diff --git a/.eslintrc.js b/.eslintrc.js index 349495a99..177dd8e5e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,7 @@ module.exports = { "SharedArrayBuffer": "readonly" }, "parserOptions": { - "ecmaVersion": 2018, + "ecmaVersion": 2020, "sourceType": "module" }, "rules": { @@ -60,6 +60,10 @@ module.exports = { "no-use-before-define": "off", // [ "error", { "variables": false, "functions": false } ], "lines-between-class-members": [ "error", "never" ], "no-var": "error", - "no-unused-vars": "error" + "no-unused-vars": "error", + "object-shorthand": 0, + "multiline-ternary": "off", + "max-len": [ "error", { "code": 100, "tabWidth": 4 } ], + "max-lines-per-function": [ "error", { "max": 200, "skipBlankLines": false } ] } }; diff --git a/.github/SECURITY.md b/.github/SECURITY.md index ecc86ee7e..8e28c985c 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -9,7 +9,7 @@ Please refer to the [security policy](https://skale.network/security). IMA Proxy contracts are periodically audited by third parties, and have been audited independently by [Solidified](https://solidified.io/), [Quantstamp](https://www.quantstamp.com), [Bramah Systems](https://www.bramah.systems/), and [Code4rena](https://code4rena.com/). - Nov 2020 -- Jun 2021 +- Jun 2021 [Bramah Audit](../audits/SKALE_Audit_Bramah.pdf) - Feb 2022 - Nov 2022 diff --git a/.github/workflows/comprehensive.yml b/.github/workflows/comprehensive.yml new file mode 100644 index 000000000..55a2da702 --- /dev/null +++ b/.github/workflows/comprehensive.yml @@ -0,0 +1,442 @@ + +name: Comprehensive test + +on: + push: + branches-ignore: + - 'docs-v*' + pull_request: + branches-ignore: + - 'docs-v*' + +jobs: + + test-comprehensive: + + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v2 + + - name: INFO - github environment variable checks + run: | + echo ------------ GIT_CURRENT_BRANCH + export GIT_CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + echo $GIT_CURRENT_BRANCH + echo ------------ GIT_SYMBOLIC_BRANCH + export GIT_SYMBOLIC_BRANCH=$(git symbolic-ref --short HEAD) + echo $GIT_SYMBOLIC_BRANCH + echo ------------ GITHUB_WORKFLOW + echo $GITHUB_WORKFLOW + echo ------------ GITHUB_RUN_ID + echo $GITHUB_RUN_ID + echo ------------ GITHUB_RUN_NUMBER + echo $GITHUB_RUN_NUMBER + echo ------------ GITHUB_ACTION + echo $GITHUB_ACTION + echo ------------ GITHUB_ACTIONS + echo $GITHUB_ACTIONS + echo ------------ GITHUB_ACTOR + echo $GITHUB_ACTOR + echo ------------ GITHUB_REPOSITORY + echo $GITHUB_REPOSITORY + echo ------------ GITHUB_EVENT_NAME + echo $GITHUB_EVENT_NAME + echo ------------ GITHUB_EVENT_PATH + echo $GITHUB_EVENT_PATH + echo ------------ GITHUB_WORKSPACE + echo $GITHUB_WORKSPACE + echo ------------ GITHUB_SHA + echo $GITHUB_SHA + echo ------------ GITHUB_REF + echo $GITHUB_REF + echo ------------ GITHUB_HEAD_REF + echo $GITHUB_HEAD_REF + echo ------------ GITHUB_BASE_REF + echo $GITHUB_BASE_REF + + - name: INFO - user information checks + run: | + echo ------------ user + echo $USER + echo ------------ home + echo $HOME + echo ------------ path + echo $PATH + + - name: INFO - system information checks + run: | + echo ------------ pwd + pwd + echo ------------ unix name - a + uname -a || true + echo ------------ unix name - r + uname -r || true + echo ------------ lsb_release - cat + cat /etc/lsb-release + echo ------------ lsb_release - a + lsb_release -a || true + echo ------------ hostnamectl + hostnamectl || true + echo ------------ /etc/os-release + cat /etc/os-release || true + echo ------------ /proc/version + cat /proc/version || true + echo ------------ lscpu + lscpu || true + + - name: UPDATE - system deps and install libc6, net-tools, btrfs-progs, zip, unzip, bash, procps + run: | + sudo apt-get update + sudo apt-get install libc6 net-tools btrfs-progs zip unzip + sudo apt-get install bash + sudo apt-get install procps + + - name: INIT - install docker with compose + run: | + echo " --------------------------- remove old packages ------------------------------------------------------------------------------------------------------ " + sudo apt-get remove docker* containerd* || true + echo " --------------------------- install containerd.io ---------------------------------------------------------------------------------------------------- " + sudo apt-get install containerd.io + echo " --------------------------- install docker.io -------------------------------------------------------------------------------------------------------- " + echo " --------------------------- install docker-compose --------------------------------------------------------------------------------------------------- " + sudo apt-get install docker-compose + + - name: INIT - reconfigure docker and restart its daemon + run: | + sudo systemctl unmask docker + sudo groupadd docker || true + sudo gpasswd -a username docker || true + sudo service docker restart || true + + - name: INIT - uninstall old Node JS if any + run: | + sudo npm cache clean -f || true &> /dev/null + sudo apt-get remove nodejs npm node -y || true &> /dev/null + sudo apt-get purge nodejs -y || true &> /dev/null + sudo apt-get autoremove -y || true &> /dev/null + sudo rm -rf /usr/bin/node || true &> /dev/null + sudo rm -rf /usr/include/node || true &> /dev/null + sudo rm -rf /usr/lib/node_modules || true &> /dev/null + sudo rm -rf /usr/local/bin/npm || true &> /dev/null + sudo rm -rf /usr/local/share/man/man1/node* || true &> /dev/null + sudo rm -rf /usr/local/lib/dtrace/node.d || true &> /dev/null + sudo rm -rf ~/.npm || true &> /dev/null + sudo rm -rf ~/.node-gyp || true &> /dev/null + sudo rm -rf /opt/local/bin/node || true &> /dev/null + sudo rm -rf /opt/local/include/node || true &> /dev/null + sudo rm -rf /opt/local/lib/node_modules || true &> /dev/null + sudo rm -rf /usr/local/lib/node* || true &> /dev/null + sudo rm -rf /usr/local/include/node* || true &> /dev/null + sudo rm -rf /usr/local/bin/node* || true &> /dev/null + + - name: INIT - install Node JS + run: | + curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - + sudo apt-get install -y nodejs + sudo ln -s /usr/bin/node /usr/local/bin/node + sudo npm install --global npm + sudo npm install --global color-support + sudo npm install --global yarn + sudo npm install --global node-gyp + + - name: INIT - version checks of Node JS and its utilities + run: | + which node + node --version + which npm + npm --version + which yarn + yarn --version + which node-gyp + node-gyp --version + + - name: INIT - Download comprehensive-test + working-directory: ${{env.working-directory}} + run: | + export IMA_ROOT_DIR=$(pwd) + echo IMA_ROOT_DIR = $IMA_ROOT_DIR + git clone https://github.com/skalenetwork/comprehensive-test.git --recursive + + - name: INIT - install Ethereum Main Net emulation + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + pwd + cd cli-hh + ./clean.sh + ./init.sh + cd ../.. + + - name: INIT - startup Ethereum Main Net emulation + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd cli-hh + ./run.sh &> ../local_mainnet_output_log.txt & + cd ../.. + + - name: INIT - Install PYTHON + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: INIT - Install everything in IMA + working-directory: ${{env.working-directory}} + run: | + ./npms/scrypt/get_scrypt_npm.sh + yarn install + + - name: INIT - initialize comprehensive test tokens + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test/test_tokens/scrypt + ./get_scrypt_npm.sh + cd .. + yarn install + cd ../.. + + - name: INIT - initialize S-Chain configuration creator + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd s_chain_gen + yarn install + cd .. + cd .. + + - name: INIT - initialize S-Chain configuration creator + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd s_chain_gen + yarn install + cd .. + cd .. + + - name: INIT - check skaled can run + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + export DETECTED_UBUNTU_VERSION=$(lsb_release -r | cut -f2) + export TRYING_SKALED_AT_PATH=./app_cache/bin_$DETECTED_UBUNTU_VERSION/skaled + $TRYING_SKALED_AT_PATH --colors --version + $TRYING_SKALED_AT_PATH --help + cd .. + + - name: INIT - generate configuration files for S-Chain nodes + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd s_chain_gen + ./init.sh + cd ../.. + + - name: INIT - download Skale Manager + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + git clone https://github.com/skalenetwork/skale-manager.git --recursive + cd .. + + - name: INIT - install Skale Manager dependencies + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd skale-manager + yarn install + cd ../.. + + - name: INIT - install comprehensive engine dependencies + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd engine + yarn install + cd ../.. + + - name: SELF-TEST 1 A - use IMA to discover chain ID via node 00-00 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --discover-cid --url-main-net=http://127.0.0.1:2164 || true + + - name: SELF-TEST 1 B - use IMA to discover chain ID via node 00-01 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --discover-cid --url-main-net=http://127.0.0.2:2264 || true + + - name: SELF-TEST 1 C - use IMA to discover chain ID via node 01-00 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --discover-cid --url-main-net=http://127.0.0.3:2364 || true + + - name: SELF-TEST 1 D - use IMA to discover chain ID via node 01-01 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --discover-cid --url-main-net=http://127.0.0.4:2464 || true + + - name: SELF-TEST 2 A - use IMA to browse S-Chain via node 00-00 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --browse-s-chain --url-s-chain=http://127.0.0.1:2164 || true + + - name: SELF-TEST 2 B - use IMA to browse S-Chain via node 00-01 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --browse-s-chain --url-s-chain=http://127.0.0.2:2264 || true + + - name: SELF-TEST 2 C - use IMA to browse S-Chain via node 01-00 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --browse-s-chain --url-s-chain=http://127.0.0.3:2364 || true + + - name: SELF-TEST 2 D - use IMA to browse S-Chain via node 01-01 and test last is alive + working-directory: ${{env.working-directory}} + run: | + node ./agent/main.mjs --colors --no-gathered --browse-s-chain --url-s-chain=http://127.0.0.4:2464 || true + + - name: INIT - download SGX Wallet + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + git clone https://github.com/skalenetwork/sgxwallet.git --recursive + cd sgxwallet + git checkout develop + git fetch + git pull + git branch + git status + cd .. + cd .. + + - name: INIT - update docker image SGX Wallet in the emulation mode + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd sgxwallet/run_sgx_sim + rm -rf ../../local_sgxwallet_output_log.txt &> /dev/null + echo " --------------------------- stopping sgx wallet ------------------------------------------------------------------------------------------------------ " + docker-compose down + echo " --------------------------- fixing sgx wallets docker config ----------------------------------------------------------------------------------------- " + mv docker-compose.yml docker-compose.yml.old-previous || true + echo "version: '3'" > docker-compose.yml + echo 'services:' >> docker-compose.yml + echo ' sgxwallet:' >> docker-compose.yml + echo ' image: skalenetwork/sgxwallet_sim:1.83.0-develop.19' >> docker-compose.yml + echo ' restart: unless-stopped' >> docker-compose.yml + echo ' ports:' >> docker-compose.yml + echo ' - "1026:1026"' >> docker-compose.yml + echo ' - "1027:1027"' >> docker-compose.yml + echo ' - "1028:1028"' >> docker-compose.yml + echo ' - "1029:1029"' >> docker-compose.yml + echo ' - "1030:1030"' >> docker-compose.yml + echo ' - "1031:1031"' >> docker-compose.yml + echo ' volumes:' >> docker-compose.yml + echo ' - ./sgx_data:/usr/src/sdk/sgx_data' >> docker-compose.yml + echo ' - /dev/urandom:/dev/random' >> docker-compose.yml + echo ' logging:' >> docker-compose.yml + echo ' driver: json-file' >> docker-compose.yml + echo ' options:' >> docker-compose.yml + echo ' max-size: "10m"' >> docker-compose.yml + echo ' max-file: "4"' >> docker-compose.yml + echo ' command: -s -y -V -d' >> docker-compose.yml + echo " --------------------------- pulling sgx wallet ------------------------------------------------------------------------------------------------------- " + docker-compose pull + cd ../.. + cd .. + + - name: INIT - start SGX Wallet + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd sgxwallet/run_sgx_sim + docker-compose up &> ../../local_sgxwallet_output_log.txt & + sleep 90 + cd ../.. + cd .. + + - name: INIT - check SGX Wallet has listening ports + working-directory: ${{env.working-directory}} + run: | + echo "sleeping 45 seconds..." + sleep 45 + echo "checking port 1026 commonly used by SGX Wallet for HTTPS..." + sudo netstat -tulpn | grep 1026 + echo "...Done" + echo "checking port 1027 commonly used by SGX Wallet for HTTP..." + sudo netstat -tulpn | grep 1027 + echo "...Done" + + - name: INIT - download transaction manager + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + rm -rf transaction-manager || true + git clone https://github.com/skalenetwork/transaction-manager + cd .. + + - name: INIT - start transaction manager and redis + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd transaction-manager + export SGX_SERVER_URL=http://127.0.0.1:1027 + export ENDPOINT=http://127.0.0.1:8545 + export ETH_PRIVATE_KEY=23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC + ./scripts/run-test-containers.sh + cd .. + echo "------------------------------------------------------------------------------------" + docker ps + echo "------------------------------------------------------------------------------------" + export TM_CONTAINER_ID=$(docker ps | grep transaction-manager | awk '{print $1;}') + echo "Transaction manager docker container ID:" $TM_CONTAINER_ID + docker logs $TM_CONTAINER_ID -f &> engine/tm.log & + echo "------------------------------------------------------------------------------------" + export REDIS_CONTAINER_ID=$(docker ps | grep redis | awk '{print $1;}') + echo "Redis container ID:" $REDIS_CONTAINER_ID + docker logs $REDIS_CONTAINER_ID -f &> engine/redis.log & + cd .. + + - name: INIT - prepare ulimit + working-directory: ${{env.working-directory}} + run: | + ulimit -n 65535 > /dev/null + echo "ulimit is now set to" $(ulimit -n) + + - name: RUN - create certificates + working-directory: ${{env.working-directory}} + run: | + cd comprehensive-test + cd engine/create_pems + ./create_pems.sh + cd ../.. + cd .. + + - name: RUN - main engine steps + working-directory: ${{env.working-directory}} + run: | + export IMA_ROOT_DIR=$(pwd) + echo IMA_ROOT_DIR = $IMA_ROOT_DIR + cd comprehensive-test/engine + export ALL_SKALE_TEST_CLOUD_RUN=1 + node ./index.js + cd ../.. + + - name: SHUTDOWN - stop SGX Wallet + run: | + cd comprehensive-test + cd sgxwallet/run_sgx_sim + docker-compose down + cd ../.. + cd .. + + - name: SHUTDOWN - stop transaction manager and redis + run: | + docker stop $TM_CONTAINER_ID $REDIS_CONTAINER_ID || true + docker rm $TM_CONTAINER_ID $REDIS_CONTAINER_ID || true + + - name: SHUTDOWN - zombie cleanup, if any + run: | + killall -9 skaled node npx python python3 || true + pkill -9 -f skaled || true diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1b431ed07..3ea00a1ca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -231,9 +231,6 @@ jobs: cat /proc/version || true echo ------------ lscpu lscpu || true - # echo ------------ lsusb - # sudo apt-get install usbutils || true &> /dev/null - # lsusb -t || echo "No lsusb available" || true - name: ESLINT run: | @@ -268,8 +265,9 @@ jobs: echo ------------ py3 wheel - pip pip3 install wheel echo ------------ slither analyzer install - # pip3 install slither-analyzer - pip3 install slither-analyzer==0.6.8 + #pip3 install slither-analyzer==0.8.3 + pip3 install -r proxy/scripts/requirements.txt + echo ------------ slither search attempt sudo find / -name slither || true echo ------------ slither location detection - after install @@ -327,7 +325,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '16' - name: Set up Python uses: actions/setup-python@v2 @@ -350,7 +348,7 @@ jobs: - name: Start background ganache run: | cd proxy - NODE_OPTIONS="--max_old_space_size=3072" npx ganache-cli --gasLimit 12000000 --quiet --allowUnlimitedContractSize --acctKeys ../test/accounts.json & + NODE_OPTIONS="--max_old_space_size=3072" npx ganache-cli --gasLimit 12000000 --quiet --allowUnlimitedContractSize --defaultBalanceEther 2000000 --acctKeys ../test/accounts.json & - name: Prepare test (PY part) working-directory: ${{env.working-directory}} diff --git a/.gitignore b/.gitignore index d6174759c..aab782f62 100644 --- a/.gitignore +++ b/.gitignore @@ -100,7 +100,7 @@ ima_data.json test/working test/config.json - +test/accounts.json .vscode diff --git a/Dockerfile b/Dockerfile index e91b786c6..903d8f361 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,17 @@ -FROM node:16 +FROM ubuntu:jammy RUN apt-get update -RUN apt-get install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget +RUN apt-get install --no-install-recommends -yq software-properties-common=0.99 +RUN apt-get update +RUN apt-get install --no-install-recommends -y build-essential=12 zlib1g-dev=1 libncurses5-dev=6 libgdbm-dev=1 libnss3-dev=2 libssl-dev=3 libreadline-dev=8 libffi-dev=3 wget=1 curl=7 sudo=1 git=1 + +RUN curl -sL https://deb.nodesource.com/setup_16.x | bash +RUN apt-get install --no-install-recommends -y nodejs=16 +RUN npm install npm --global +RUN npm install --global yarn +RUN npm --version +RUN yarn --version + RUN curl -O https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz RUN tar -xf Python-3.7.3.tar.xz RUN cd Python-3.7.3; ./configure --enable-optimizations; make -j 4 build_all; make altinstall; cd .. @@ -30,11 +40,10 @@ RUN chmod +x /ima/bls_binaries/verify_bls RUN npm install -g node-gyp RUN which node-gyp RUN node-gyp --version -RUN npms/scrypt/get_scrypt_npm.sh +WORKDIR /ima/npms/scrypt +RUN ./get_scrypt_npm.sh -RUN cd proxy && yarn install && cd .. -RUN cd npms/skale-owasp && yarn install && cd ../.. -RUN cd npms/skale-ima && yarn install && cd ../.. -RUN cd agent && yarn install && cd .. +WORKDIR /ima +RUN yarn install CMD ["bash", "/ima/agent/run.sh"] diff --git a/agent/CLI.md b/agent/CLI.md index 4a8f572b7..cc77726d1 100644 --- a/agent/CLI.md +++ b/agent/CLI.md @@ -6,288 +6,255 @@ IMA operates with 3 types of chains: -- **Ethereum(Main Net)** -- **S-Chain**, source **S-Chain** -- **T-Chain**, target **S-Chain** + - **Ethereum(Main Net)** + - **S-Chain**, source **S-Chain** + - **T-Chain**, target **S-Chain** In the most of use cases only **Ethereum(Main Net)** and source **S-Chain** are needed. **IMA** supports the following groups of operations: -- Run message loop. -- Perform **S-Chain** registration and initialization. -- Confiure and change gas reimbursement. -- Do **ETH**, **ERC20**, **ERC721**, **ERC1155**, batch **ERC1155** payments between chains. -- View amount of **ETH** can be received on Main Net. -- Mint **ERC20**, **ERC721**, **ERC1155** tokens. -- Show **ETH**, **ERC20**, **ERC721**, **ERC1155** balances. -- Browse **SKALE network**. -- Download source **S-Chain** information. -- Discover set of **S-Chains** connected to specifed **S-Chains**. -- Discover chain ID of specified chain with `--discover-cid`. -- Run monitoring service and expose its JSON RPC, the `--monitoring-port=number` option turns on monitoring web socket RPC server on specified port. By default monitoring server is disabled. + - Run message loop. + - Perform **S-Chain** registration and initialization. + - Configure and change gas reimbursement. + - Do **ETH**, **ERC20**, **ERC721**, **ERC1155**, batch **ERC1155** payments between chains. + - View amount of **ETH** can be received on Main Net. + - Mint **ERC20**, **ERC721**, **ERC1155** tokens. + - Show **ETH**, **ERC20**, **ERC721**, **ERC1155** balances. + - Browse **SKALE network**. + - Download source **S-Chain** information. + - Discover set of **S-Chains** connected to specified **S-Chains**. + - Discover chain ID of specified chain with `--discover-cid`. + - Run monitoring service and expose its JSON RPC, the `--monitoring-port=number` option turns on monitoring web socket RPC server on specified port. By default monitoring server is disabled. Here is list of options running operations described above: -``` ---show-config...................Show configuration values and exit. ---show-balance..................Show ETH and/or token balances on Main-net and/or S-Chain and exit. ---m2s-payment...................Do one payment from Main-net user account to S-chain user account. ---s2m-payment...................Do one payment from S-chain user account to Main-net user account. ---s2m-receive...................Receive one payment from S-chain user account to Main-net user account(ETH only, receives all the ETH pending in transfer). ---s2m-view......................View money amount user can receive as payment from S-chain user account to Main-net user account(ETH only, receives all the ETH pending in transfer). ---s2s-payment...................Do one payment from S-chain user account to other S-chain user account. ---s2s-forward...................Indicates S<->S transfer direction is forward. I.e. source S-chain is token minter and instantiator. This is default mode. ---s2s-reverse...................Indicates S<->S transfer direction is reverse. I.e. destination S-chain is token minter and instantiator. ---m2s-transfer..................Do single money transfer loop from Main-net to S-chain. ---s2m-transfer..................Do single money transfer loop from S-chain to Main-net. ---s2s-transfer..................Do single money transfer loop from S-chain to S-chain. ---with-metadata.................Makes ERC721 transfer using special version of Token Manager to transfer token metadata. ---transfer......................Run single M<->S and, optionally, S->S transfer loop iteration. ---loop..........................Run M<->S and, optionally, S->S transfer loop. ---browse-s-chain................Download own S-Chain network information. ---browse-skale-network..........Download entire SKALE network description. ---browse-connected-schains......Download S-Chains conected to S-Chain with name specified in id-s-chain command line parameter. ---mint-erc20....................Mint ERC20 tokens. ---mint-erc721...................Mint ERC721 tokens. ---mint-erc1155..................Mint ERC1155 tokens. ---burn-erc20....................Burn ERC20 tokens. ---burn-erc721...................Burn ERC721 tokens. ---burn-erc1155..................Burn ERC1155 tokens. -``` + --show-config - Show configuration values and exit. + --show-balance - Show ETH and/or token balances on Main-net and/or S-Chain and exit. + --m2s-payment - Do one payment from Main-net user account to S-chain user account. + --s2m-payment - Do one payment from S-chain user account to Main-net user account. + --s2m-receive - Receive one payment from S-chain user account to Main-net user account(ETH only, receives all the ETH pending in transfer). + --s2m-view - View money amount user can receive as payment from S-chain user account to Main-net user account(ETH only, receives all the ETH pending in transfer). + --s2s-payment - Do one payment from S-chain user account to other S-chain user account. + --s2s-forward - Indicates S<->S transfer direction is forward. I.e. source S-chain is token minter and instantiator. This is default mode. + --s2s-reverse - Indicates S<->S transfer direction is reverse. I.e. destination S-chain is token minter and instantiator. + --m2s-transfer - Do single money transfer loop from Main-net to S-chain. + --s2m-transfer - Do single money transfer loop from S-chain to Main-net. + --s2s-transfer - Do single money transfer loop from S-chain to S-chain. + --with-metadata - Makes ERC721 transfer using special version of Token Manager to transfer token metadata. + --transfer - Run single M<->S and, optionally, S->S transfer loop iteration. + --loop - Run M<->S and, optionally, S->S transfer loop. + --browse-s-chain - Download own S-Chain network information. + --browse-skale-network - Download entire SKALE network description. + --browse-connected-schains - Download S-Chains connected to S-Chain with name specified in id-s-chain command line parameter. + --mint-erc20 - Mint ERC20 tokens. + --mint-erc721 - Mint ERC721 tokens. + --mint-erc1155 - Mint ERC1155 tokens. + --burn-erc20 - Burn ERC20 tokens. + --burn-erc721 - Burn ERC721 tokens. + --burn-erc1155 - Burn ERC1155 tokens. Please notice, token testing commands require `--tm-url-t-chain`, `cid-t-chain`, `erc20-t-chain` or `erc721-t-chain` or `erc1155-t-chain`, account information (like private key `key-t-chain`) command line arguments specified. Token amounts are specified via amount command line arguments specified. Token IDs are specified via tid or tids command line arguments. One or more of the following URL, chain name and chain ID parameters are needed for most of **IMA** operations: -``` ---url-main-net=URL..............Main-net URL. Value is automatically loaded from the URL_W3_ETHEREUM environment variable if not specified. ---url-s-chain=URL...............S-chain URL. Value is automatically loaded from the URL_W3_S_CHAIN environment variable if not specified. ---url-t-chain=URL...............S<->S Target S-chain URL. Value is automatically loaded from the URL_W3_S_CHAIN_TARGET environment variable if ---id-main-net=number............Main-net Ethereum network name.. Value is automatically loaded from the CHAIN_NAME_ETHEREUM environment variable if not specified. Default value is "Mainnet". ---id-s-chain=number.............S-chain Ethereum network name.. Value is automatically loaded from the CHAIN_NAME_SCHAIN environment variable if not specified. Default value is "id-S-chain". ---id-t-chain=number.............S<->S Target S-chain Ethereum network name.. Value is automatically loaded from the CHAIN_NAME_SCHAIN_TARET environment variable if not specified. Default value is "id-T-chain". ---cid-main-net=number...........Main-net Ethereum chain ID. Value is automatically loaded from the CID_ETHEREUM environment variable if not specified. Default value is -4. ---cid-s-chain=number............S-chain Ethereum chain ID. Value is automatically loaded from the CID_SCHAIN environment variable if not specified. Default value is -4. ---cid-t-chain=number............S<->S Target S-chain Ethereum chain ID. Value is automatically loaded from the CID_SCHAIN_TARGET environment variable if not specified. Default value is -4. -``` - -For most of operatons, **IMA** needs ABIs of **Skale Manager**, **Ethereum(Main Net)**, **S-Chain(s)**: - -``` ---abi-skale-manager=path........Path to JSON file containing Skale Manager ABI. Optional parameter. It's needed for S-Chain to S-Chain transfers. ---abi-main-net=path.............Path to JSON file containing IMA ABI for Main-net. ---abi-s-chain=path..............Path to JSON file containing IMA ABI for S-chain. ---abi-t-chain=path..............Path to JSON file containing IMA ABI for S<->S Target S-chain. -``` - -Token transfer commands require token APIs on approproate chains. + --url-main-net=URL..............Main-net URL. Value is automatically loaded from the URL_W3_ETHEREUM environment variable if not specified. + --url-s-chain=URL...............S-chain URL. Value is automatically loaded from the URL_W3_S_CHAIN environment variable if not specified. + --url-t-chain=URL...............S<->S Target S-chain URL. Value is automatically loaded from the URL_W3_S_CHAIN_TARGET environment variable if + --id-main-net=number............Main-net Ethereum network name.. Value is automatically loaded from the CHAIN_NAME_ETHEREUM environment variable if not specified. Default value is "Mainnet". + --id-s-chain=number.............S-chain Ethereum network name.. Value is automatically loaded from the CHAIN_NAME_SCHAIN environment variable if not specified. Default value is "id-S-chain". + --id-t-chain=number.............S<->S Target S-chain Ethereum network name.. Value is automatically loaded from the CHAIN_NAME_SCHAIN_TARGET environment variable if not specified. Default value is "id-T-chain". + --cid-main-net=number...........Main-net Ethereum chain ID. Value is automatically loaded from the CID_ETHEREUM environment variable if not specified. Default value is -4. + --cid-s-chain=number............S-chain Ethereum chain ID. Value is automatically loaded from the CID_SCHAIN environment variable if not specified. Default value is -4. + --cid-t-chain=number............S<->S Target S-chain Ethereum chain ID. Value is automatically loaded from the CID_SCHAIN_TARGET environment variable if not specified. Default value is -4. + +For most of operations, **IMA** needs ABIs of **Skale Manager**, **Ethereum(Main Net)**, **S-Chain(s)**: + + --abi-skale-manager=path........Path to JSON file containing Skale Manager ABI. Optional parameter. It's needed for S-Chain to S-Chain transfers. + --abi-main-net=path.............Path to JSON file containing IMA ABI for Main-net. + --abi-s-chain=path..............Path to JSON file containing IMA ABI for S-chain. + --abi-t-chain=path..............Path to JSON file containing IMA ABI for S<->S Target S-chain. + +Token transfer commands require token APIs on appropriate chains. **ERC20** options: -``` ---erc20-main-net=path...........Path to JSON file containing ERC20 ABI for Main-net. ---erc20-s-chain=path............Path to JSON file containing ERC20 ABI for S-chain. ---addr-erc20-s-chain=address....Explicit ERC20 address in S-chain. ---erc20-t-chain=path............Path to JSON file containing ERC20 ABI for S<->S Target S-chain. ---addr-erc20-t-chain=address....Explicit ERC20 address in S<->S Target S-chain. -``` + --erc20-main-net=path...........Path to JSON file containing ERC20 ABI for Main-net. + --erc20-s-chain=path............Path to JSON file containing ERC20 ABI for S-chain. + --addr-erc20-s-chain=address....Explicit ERC20 address in S-chain. + --erc20-t-chain=path............Path to JSON file containing ERC20 ABI for S<->S Target S-chain. + --addr-erc20-t-chain=address....Explicit ERC20 address in S<->S Target S-chain. **ERC721** options: -``` ---erc721-main-net=path..........Path to JSON file containing ERC721 ABI for Main-net. ---erc721-s-chain=path...........Path to JSON file containing ERC721 ABI for S-chain. ---addr-erc721-s-chain=address...Explicit ERC721 address in S-chain. ---erc721-t-chain=path...........Path to JSON file containing ERC721 ABI for S<->S S-chain. ---addr-erc721-t-chain=address...Explicit ERC721 address in S<->S S-chain. -``` + --erc721-main-net=path..........Path to JSON file containing ERC721 ABI for Main-net. + --erc721-s-chain=path...........Path to JSON file containing ERC721 ABI for S-chain. + --addr-erc721-s-chain=address...Explicit ERC721 address in S-chain. + --erc721-t-chain=path...........Path to JSON file containing ERC721 ABI for S<->S S-chain. + --addr-erc721-t-chain=address...Explicit ERC721 address in S<->S S-chain. **ERC1155** options: -``` ---erc1155-main-net=path.........Path to JSON file containing ERC1155 ABI for Main-net. ---erc1155-s-chain=path..........Path to JSON file containing ERC1155 ABI for S-chain. ---addr-erc1155-s-chain=address..Explicit ERC1155 address in S-chain. ---erc1155-t-chain=path..........Path to JSON file containing ERC1155 ABI for S<->S S-chain. ---addr-erc1155-t-chain=address..Explicit ERC1155 address in S<->S S-chain. -``` + --erc1155-main-net=path.........Path to JSON file containing ERC1155 ABI for Main-net. + --erc1155-s-chain=path..........Path to JSON file containing ERC1155 ABI for S-chain. + --addr-erc1155-s-chain=address..Explicit ERC1155 address in S-chain. + --erc1155-t-chain=path..........Path to JSON file containing ERC1155 ABI for S<->S S-chain. + --addr-erc1155-t-chain=address..Explicit ERC1155 address in S<->S S-chain. **IMA** can sign transactions using one of following ways: -- Using **Transaction Manager** JSON RPC -- Using **SGX wallet** JSON RPC -- Using explicitly specified private key -- Using wallet address, for read only operations only - -The folllowing parameters needed to use **Transaction Manager**: - -``` ---tm-url-main-net=URL...........Transaction Manager server URL for Main-net. Value is automatically loaded from the TRANSACTION_MANAGER_URL_ETHEREUM environment variable if not specified. Example: redis://@127.0.0.1:6379 ---tm-url-s-chain=URL............Transaction Manager server URL for S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_URL_S_CHAIN environment variable if not specified. ---tm-url-t-chain=URL............Transaction Manager server URL for S<->S Target S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_URL_S_CHAIN_TARGET environment variable if not specified. ---tm-priority-main-net=URL......Transaction Manager priority for Main-net. Value is automatically loaded from the TRANSACTION_MANAGER_PRIORITY_ETHEREUM environment variable if not specified. Default is 5. ---tm-priority-s-chain=URL.......Transaction Manager priority for S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_PRIORITY_S_CHAIN environment variable if not specified. Default is 5. ---tm-priority-t-chain=URL.......Transaction Manager priority for S<->S Target S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_PRIORITY_S_CHAIN_TARGET environment variable if not specified. Default is 5. -``` - -The folllowing parameters needed to use **SGX wallet**: - -``` ---sgx-url-main-net=URL..........SGX server URL for Main-net. Value is automatically loaded from the SGX_URL_ETHEREUM environment variable if not specified. ---sgx-url-s-chain=URL...........SGX server URL for S-chain. Value is automatically loaded from the SGX_URL_S_CHAIN environment variable if not specified. ---sgx-url-t-chain=URL...........SGX server URL for S<->S Target S-chain. Value is automatically loaded from the SGX_URL_S_CHAIN_TARGET environment variable if not specified. ---sgx-ecdsa-key-main-net=name...SGX/ECDSA key name for Main-net. Value is automatically loaded from the SGX_KEY_ETHEREUM environment variable if not specified. ---sgx-ecdsa-key-s-chain=name....SGX/ECDSA key name for S-chain. Value is automatically loaded from the SGX_KEY_S_CHAIN environment variable if not specified. ---sgx-ecdsa-key-t-chain=name....SGX/ECDSA key name for S<->S Target S-chain. Value is automatically loaded from the SGX_KEY_S_CHAIN_TARGET environment variable if not specified. ---sgx-ssl-key-main-net=path.....Path to SSL key file for SGX wallet of Main-net. Value is automatically loaded from the SGX_SSL_KEY_FILE_ETHEREUM environment variable if not specified. ---sgx-ssl-key-s-chain=path......Path to SSL key file for SGX wallet of S-chain. Value is automatically loaded from the SGX_SSL_KEY_FILE_S_CHAIN environment variable if not specified. ---sgx-ssl-key-t-chain=path......Path to SSL key file for SGX wallet of S<->S Target S-chain. Value is automatically loaded from the SGX_SSL_KEY_FILE_S_CHAIN_TARGET environment variable if not specified. ---sgx-ssl-cert-main-net=path....Path to SSL certificate file for SGX wallet of Main-net. Value is automatically loaded from the SGX_SSL_CERT_FILE_ETHEREUM environment variable if not specified. ---sgx-ssl-cert-s-chain=path.....Path to SSL certificate file for SGX wallet of S-chain. Value is automatically loaded from the SGX_SSL_CERT_FILE_S_CHAIN environment variable if not specified. ---sgx-ssl-cert-t-chain=path.....Path to SSL certificate file for SGX wallet of S<->S Target S-chain. Value is automatically loaded from the SGX_SSL_CERT_FILE_S_CHAIN_TARGET environment variable if not specified. -``` + - Using **Transaction Manager** JSON RPC + - Using **SGX wallet** JSON RPC + - Using explicitly specified private key + - Using wallet address, for read only operations only + +The following parameters needed to use **Transaction Manager**: + + --tm-url-main-net=URL...........Transaction Manager server URL for Main-net. Value is automatically loaded from the TRANSACTION_MANAGER_URL_ETHEREUM environment variable if not specified. Example: redis://@127.0.0.1:6379 + --tm-url-s-chain=URL............Transaction Manager server URL for S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_URL_S_CHAIN environment variable if not specified. + --tm-url-t-chain=URL............Transaction Manager server URL for S<->S Target S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_URL_S_CHAIN_TARGET environment variable if not specified. + --tm-priority-main-net=URL......Transaction Manager priority for Main-net. Value is automatically loaded from the TRANSACTION_MANAGER_PRIORITY_ETHEREUM environment variable if not specified. Default is 5. + --tm-priority-s-chain=URL.......Transaction Manager priority for S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_PRIORITY_S_CHAIN environment variable if not specified. Default is 5. + --tm-priority-t-chain=URL.......Transaction Manager priority for S<->S Target S-chain. Value is automatically loaded from the TRANSACTION_MANAGER_PRIORITY_S_CHAIN_TARGET environment variable if not specified. Default is 5. + +The following parameters needed to use **SGX wallet**: + + --sgx-url-main-net=URL..........SGX server URL for Main-net. Value is automatically loaded from the SGX_URL_ETHEREUM environment variable if not specified. + --sgx-url-s-chain=URL...........SGX server URL for S-chain. Value is automatically loaded from the SGX_URL_S_CHAIN environment variable if not specified. + --sgx-url-t-chain=URL...........SGX server URL for S<->S Target S-chain. Value is automatically loaded from the SGX_URL_S_CHAIN_TARGET environment variable if not specified. + --sgx-ecdsa-key-main-net=name...SGX/ECDSA key name for Main-net. Value is automatically loaded from the SGX_KEY_ETHEREUM environment variable if not specified. + --sgx-ecdsa-key-s-chain=name....SGX/ECDSA key name for S-chain. Value is automatically loaded from the SGX_KEY_S_CHAIN environment variable if not specified. + --sgx-ecdsa-key-t-chain=name....SGX/ECDSA key name for S<->S Target S-chain. Value is automatically loaded from the SGX_KEY_S_CHAIN_TARGET environment variable if not specified. + --sgx-ssl-key-main-net=path.....Path to SSL key file for SGX wallet of Main-net. Value is automatically loaded from the SGX_SSL_KEY_FILE_ETHEREUM environment variable if not specified. + --sgx-ssl-key-s-chain=path......Path to SSL key file for SGX wallet of S-chain. Value is automatically loaded from the SGX_SSL_KEY_FILE_S_CHAIN environment variable if not specified. + --sgx-ssl-key-t-chain=path......Path to SSL key file for SGX wallet of S<->S Target S-chain. Value is automatically loaded from the SGX_SSL_KEY_FILE_S_CHAIN_TARGET environment variable if not specified. + --sgx-ssl-cert-main-net=path....Path to SSL certificate file for SGX wallet of Main-net. Value is automatically loaded from the SGX_SSL_CERT_FILE_ETHEREUM environment variable if not specified. + --sgx-ssl-cert-s-chain=path.....Path to SSL certificate file for SGX wallet of S-chain. Value is automatically loaded from the SGX_SSL_CERT_FILE_S_CHAIN environment variable if not specified. + --sgx-ssl-cert-t-chain=path.....Path to SSL certificate file for SGX wallet of S<->S Target S-chain. Value is automatically loaded from the SGX_SSL_CERT_FILE_S_CHAIN_TARGET environment variable if not specified. Using explicitly specified private key: -``` ---address-main-net=value........Main-net user account address. Value is automatically loaded from the ACCOUNT_FOR_ETHEREUM environment variable if not specified. ---address-s-chain=value.........S-chain user account address. Value is automatically loaded from the ACCOUNT_FOR_SCHAIN environment variable if not specified. ---address-t-chain=value.........S<->S Target S-chain user account address. Value is automatically loaded from the ACCOUNT_FOR_SCHAIN_TARGET environment variable if not specified. -``` + --address-main-net=value........Main-net user account address. Value is automatically loaded from the ACCOUNT_FOR_ETHEREUM environment variable if not specified. + --address-s-chain=value.........S-chain user account address. Value is automatically loaded from the ACCOUNT_FOR_SCHAIN environment variable if not specified. + --address-t-chain=value.........S<->S Target S-chain user account address. Value is automatically loaded from the ACCOUNT_FOR_SCHAIN_TARGET environment variable if not specified. For read only operations, only wallet address can be specified: -``` ---key-main-net=value............Private key for Main-net user account address. Value is automatically loaded from the PRIVATE_KEY_FOR_ETHEREUM environment variable if not specified. ---key-s-chain=value.............Private key for S-Chain user account address. Value is automatically loaded from the PRIVATE_KEY_FOR_SCHAIN environment variable if not specified. ---key-t-chain=value.............Private key for S<->S Target S-Chain user account address. Value is automatically loaded from the PRIVATE_KEY_FOR_SCHAIN_TARGET environment variable if not specified. -``` + --key-main-net=value............Private key for Main-net user account address. Value is automatically loaded from the PRIVATE_KEY_FOR_ETHEREUM environment variable if not specified. + --key-s-chain=value.............Private key for S-Chain user account address. Value is automatically loaded from the PRIVATE_KEY_FOR_SCHAIN environment variable if not specified. + --key-t-chain=value.............Private key for S<->S Target S-Chain user account address. Value is automatically loaded from the PRIVATE_KEY_FOR_SCHAIN_TARGET environment variable if not specified. Please notice, **IMA** prefer to use transaction manager to sign blockchain transactions if `--tm-url-main-net`/`--tm-url-s-chain` command line values or `TRANSACTION_MANAGER_URL_ETHEREUM`/`TRANSACTION_MANAGER_URL_S_CHAIN` shell variables were specified. Next preferred option is **SGX wallet** which is used if `--sgx-url-main-net`/`--sgx-url-s-chain` command line values or `SGX_URL_ETHEREUM`/`SGX_URL_S_CHAIN` shell variables were specified. SGX signing also needs key name, key and certificate files. Finally, **IMA** attempts to use explicitly provided private key to sign blockchain transactions if `--key-main-net`/`--key-s-chain` command line values or `PRIVATE_KEY_FOR_ETHEREUM`/`PRIVATE_KEY_FOR_SCHAIN` shell variables were specified. -**ETH** transfers operations require amout of **ETH** to be specied with one of the following options: +**ETH** transfers operations require amount of **ETH** to be specified with one of the following options: -``` ---value=numberunitName..........Amount of unitName to transfer, where unitName is well known Ethereum unit name like ether or wei. ---wei=number....................Amount of wei to transfer. ---babbage=number................Amount of babbage(wei*1000) to transfer. ---lovelace=number...............Amount of lovelace(wei*1000*1000) to transfer. ---shannon=number................Amount of shannon(wei*1000*1000*1000) to transfer. ---szabo=number..................Amount of szabo(wei*1000*1000*1000*1000) to transfer. ---finney=number.................Amount of finney(wei*1000*1000*1000*1000*1000) to transfer. ---ether=number..................Amount of ether(wei*1000*1000*1000*1000*1000*1000) to transfer. -``` + --value=numberUnitName..........Amount of unitName to transfer, where unitName is well known Ethereum unit name like ether or wei. + --wei=number....................Amount of wei to transfer. + --babbage=number................Amount of babbage(wei*1000) to transfer. + --lovelace=number...............Amount of lovelace(wei*1000*1000) to transfer. + --shannon=number................Amount of shannon(wei*1000*1000*1000) to transfer. + --szabo=number..................Amount of szabo(wei*1000*1000*1000*1000) to transfer. + --finney=number.................Amount of finney(wei*1000*1000*1000*1000*1000) to transfer. + --ether=number..................Amount of ether(wei*1000*1000*1000*1000*1000*1000) to transfer. Token transfer operations require token amounts and/or token IDs: -``` ---amount=number.................Amount of tokens to transfer. ---tid=number....................ERC721 or ERC1155 token id to transfer. ---amounts=array of numbers......ERC1155 token id to transfer in batch. ---tids=array of numbers.........ERC1155 token amount to transfer in batch. ---sleep-between-tx=number.......Sleep time (in milliseconds) between transactions during complex operations. ---wait-next-block...............Wait for next block between transactions during complex operations. -``` + --amount=number.................Amount of tokens to transfer. + --tid=number....................ERC721 or ERC1155 token id to transfer. + --amounts=array of numbers......ERC1155 token id to transfer in batch. + --tids=array of numbers.........ERC1155 token amount to transfer in batch. + --sleep-between-tx=number.......Sleep time (in milliseconds) between transactions during complex operations. + --wait-next-block...............Wait for next block between transactions during complex operations. -**Gas reumbursement** can be configure with the following options: +**Gas reimbursement** can be configure with the following options: -``` ---reimbursement-chain=name......Specifies chain name. ---reimbursement-recharge=vu.....Recharge user wallet with specified value v, unit name u is well known Ethereum unit name like ether or wei. ---reimbursement-withdraw=vu.....Withdraw user wallet with specified value v, unit name u is well known Ethereum unit name like ether or wei. ---reimbursement-balance.........Show wallet balance. ---reimbursement-range=number....Sets minimal time interval between transfers from S-Chain to Main Net. -``` + --reimbursement-chain=name......Specifies chain name. + --reimbursement-recharge=vu.....Recharge user wallet with specified value v, unit name u is well known Ethereum unit name like ether or wei. + --reimbursement-withdraw=vu.....Withdraw user wallet with specified value v, unit name u is well known Ethereum unit name like ether or wei. + --reimbursement-balance.........Show wallet balance. + --reimbursement-range=number....Sets minimal time interval between transfers from S-Chain to Main Net. -**Gas reumbursement** can be **Oracle**-based if the following options are specified: +**Gas reimbursement** can be **Oracle**-based if the following options are specified: ---enable-oracle.................Enable call to Oracle to compute gas price for gas reimbursement. Default mode. ---disable-oracle................Disable call to Oracle to compute gas price for gas reimbursement. + --enable-oracle.................Enable call to Oracle to compute gas price for gas reimbursement. Default mode. + --disable-oracle................Disable call to Oracle to compute gas price for gas reimbursement. **IMA** must be initialized and its **S-Chain** must be registered once after creation with the following options: -``` ---register......................Register(perform all steps). ---check-registration............Perform registration status check(perform all steps). -``` + --register......................Register(perform all steps). + --check-registration............Perform registration status check(perform all steps). **S-Chain** to **S-Chain** transfers must be turned on and require periodic **SKALE network re-discovery**: -``` ---s2s-enable....................Enables S-Chain to S-Chain transfers. Default mode. The abi-skale-manager path must be provided. ---s2s-disable...................Disables S-Chain to S-Chain transfers. ---net-rediscover=number.........SKALE NETWORK re-discovery interval(in seconds). Default is 3600 seconds or 1 hour, specify 0 to disable SKALE NETWORK re-discovery. -``` - -**IMA** loop can optionally use dry run, group **IMA** messages and supports varuous customizations: - -``` ---no-wait-s-chain...............Do not wait until S-Chain is started. ---max-wait-attempts=value.......Max number of S-Chain call attempts to do while it became alive and sane. ---skip-dry-run..................Skip dry run contract method calls. ---ignore-dry-run................Ignore result of dry run contract method calls and continue execute. ---dry-run.......................Use error results of dry run contract method calls as actual errors and stop execute. ---m2s-transfer-block-size.......Number of transactions in one block to use in money transfer loop from Main-net to S-chain. ---s2m-transfer-block-size.......Number of transactions in one block to use in money transfer loop from S-chain to Main-net. ---s2s-transfer-block-size.......Number of transactions in one block to use in money transfer loop from S-chain to S-chain. ---transfer-block-size...........Number of transactions in one block to use in both money transfer loops. ---m2s-max-transactions..........Maximal number of transactions to do in money transfer loop from Main-net to S-chain(0 is unlimited). ---s2m-max-transactions..........Maximal number of transactions to do in money transfer loop from S-chain to Main-net(0 is unlimited). ---s2s-max-transactions..........Maximal number of transactions to do in money transfer loop from S-chain to S-chain(0 is unlimited). ---max-transactions..............Maximal number of transactions to do in both money transfer loops(0 is unlimited). ---m2s-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from Main-net to S-chain(0 is no wait). ---s2m-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to Main-net(0 is no wait). ---s2s-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to S-chain(0 is no wait). ---await-blocks..................Maximal number of blocks to wait to appear in blockchain before transaction between both S-chain and Main-net(0 is no wait). ---m2s-await-time................Minimal age of transaction message(in seconds) before it will be transferred from Main-net to S-chain(0 is no wait). ---s2m-await-time................Minimal age of transaction message(in seconds) before it will be transferred from S-chain to Main-net(0 is no wait). ---s2s-await-time................Minimal age of transaction message(in seconds) before it will be transferred from S-chain to S-chain(0 is no wait). ---await-time....................Minimal age of transaction message(in seconds) before it will be transferred between both S-chain and Main-net(0 is no wait). ---period........................Transfer loop period(in seconds). ---node-number=value.............S-Chain node number(0-based). ---nodes-count=value.............S-Chain nodes count. ---time-framing=value............Specifies period(in seconds) for time framing(0 to disable time framing). ---time-gap=value................Specifies gap(in seconds) before next time frame. -``` + --s2s-enable....................Enables S-Chain to S-Chain transfers. Default mode. The abi-skale-manager path must be provided. + --s2s-disable...................Disables S-Chain to S-Chain transfers. + --net-rediscover=number.........SKALE NETWORK re-discovery interval(in seconds). Default is 3600 seconds or 1 hour, specify 0 to disable SKALE NETWORK re-discovery. + +**IMA** loop can optionally use dry run, group **IMA** messages and supports various customizations: + + --no-wait-s-chain...............Do not wait until S-Chain is started. + --max-wait-attempts=value.......Max number of S-Chain call attempts to do while it became alive and sane. + --skip-dry-run..................Skip dry run contract method calls. + --dry-run.......................Use error results of dry run contract method calls as actual errors and stop execute. + --m2s-transfer-block-size.......Number of transactions in one block to use in money transfer loop from Main-net to S-chain. + --s2m-transfer-block-size.......Number of transactions in one block to use in money transfer loop from S-chain to Main-net. + --s2s-transfer-block-size.......Number of transactions in one block to use in money transfer loop from S-chain to S-chain. + --transfer-block-size...........Number of transactions in one block to use in both money transfer loops. + --m2s-max-transactions..........Maximal number of transactions to do in money transfer loop from Main-net to S-chain(0 is unlimited). + --s2m-max-transactions..........Maximal number of transactions to do in money transfer loop from S-chain to Main-net(0 is unlimited). + --s2s-max-transactions..........Maximal number of transactions to do in money transfer loop from S-chain to S-chain(0 is unlimited). + --max-transactions..............Maximal number of transactions to do in both money transfer loops(0 is unlimited). + --m2s-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from Main-net to S-chain(0 is no wait). + --s2m-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to Main-net(0 is no wait). + --s2s-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to S-chain(0 is no wait). + --await-blocks..................Maximal number of blocks to wait to appear in blockchain before transaction between both S-chain and Main-net(0 is no wait). + --m2s-await-time................Minimal age of transaction message(in seconds) before it will be transferred from Main-net to S-chain(0 is no wait). + --s2m-await-time................Minimal age of transaction message(in seconds) before it will be transferred from S-chain to Main-net(0 is no wait). + --s2s-await-time................Minimal age of transaction message(in seconds) before it will be transferred from S-chain to S-chain(0 is no wait). + --await-time....................Minimal age of transaction message(in seconds) before it will be transferred between both S-chain and Main-net(0 is no wait). + --period........................Transfer loop period(in seconds). + --node-number=value.............S-Chain node number(0-based). + --nodes-count=value.............S-Chain nodes count. + --time-framing=value............Specifies period(in seconds) for time framing(0 to disable time framing). + --time-gap=value................Specifies gap(in seconds) before next time frame. **IMA** transfer loop must **BLS**-sign messages and needs paths to **BLS** command line utilities: -``` ---sign-messages.................Sign transferred messages. ---bls-glue=path.................Specifies path to bls_glue application. ---hash-g1=path..................Specifies path to hash_g1 application. ---bls-verify=path...............Optional parameter, specifies path to verify_bls application. -``` + --sign-messages.................Sign transferred messages. + --bls-glue=path.................Specifies path to bls_glue application. + --hash-g1=path..................Specifies path to hash_g1 application. + --bls-verify=path...............Optional parameter, specifies path to verify_bls application. **IMA** transfer loop needs to scan **IMA smart contract** events, scanning can be customized with the following options: -``` ---bs-step-size=number...........Specifies step block range size to search iterative past events step by step. 0 to disable iterative search. ---bs-max-all-range=number.......Specifies max number of steps to allow to search as [0...latest] range. 0 to disable iterative search. ---bs-progressive-enable.........Enables progressive block scan to search past events. ---bs-progressive-disable........Disables progressive block scan to search past events. -``` + --bs-step-size=number...........Specifies step block range size to search iterative past events step by step. 0 to disable iterative search. + --bs-max-all-range=number.......Specifies max number of steps to allow to search as [0...latest] range. 0 to disable iterative search. + --bs-progressive-enable.........Enables progressive block scan to search past events. + --bs-progressive-disable........Disables progressive block scan to search past events. + +**IMA** pending work analysis subsystem allows to detect busy state of previous **IMA Agent** running long work outside its time frame: + + --pwa...........................Enable pending work analysis to avoid transaction conflicts. Default mode. + --no-pwa........................Disable pending work analysis. Not recommended for slow and overloaded blockchains. + --pwa-timeout=seconds...........Node state timeout during pending work analysis. Default is 60 seconds. Like any command line application, **IMA** produces various command line output and supports logging. Logging can be customized with the following options: -``` ---expose........................Expose low-level log details after successful operations. By default details exposed only on errors. ---no-expose.....................Expose low-level log details only after errors. Default expose mode. ---verbose=value.................Set level of output details. ---verbose-list..................List available verbose levels and exit. ---log=path......................Write program output to specified log file(multiple files can be specified). ---log-size=value................Max size(in bytes) of one log file(affects to log log rotation). ---log-files=value...............Maximum number of log files for log rotation. ---gathered......................Print details of gathering data from command line arguments. Default mode. ---no-gathered...................Do not print details of gathering data from command line arguments. ---expose-security-info..........Expose security-related values in log output. This mode is needed for debugging purposes only. ---no-expose-security-info.......Do not expose security-related values in log output. Default mode. -``` - -Command line output and loggging can be plain or ANSI-colorized: - -``` ---colors........................Use ANSI-colorized logging. ---no-colors.....................Use monochrome logging. -``` \ No newline at end of file + --expose........................Expose low-level log details after successful operations. By default details exposed only on errors. + --no-expose.....................Expose low-level log details only after errors. Default expose mode. + --verbose=value.................Set level of output details. + --verbose-list..................List available verbose levels and exit. + --log=path......................Write program output to specified log file(multiple files can be specified). + --log-size=value................Max size(in bytes) of one log file(affects to log log rotation). + --log-files=value...............Maximum number of log files for log rotation. + --gathered......................Print details of gathering data from command line arguments. Default mode. + --no-gathered...................Do not print details of gathering data from command line arguments. + --expose-security-info..........Expose security-related values in log output. This mode is needed for debugging purposes only. + --no-expose-security-info.......Do not expose security-related values in log output. Default mode. + --expose-pwa....................Expose IMA agent pending work analysis information + --no-expose-pwa.................Do not expose IMA agent pending work analysis information. Default mode. + +Command line output and logging can be plain or ANSI-colorized: + + --colors........................Use ANSI-colorized logging. + --no-colors.....................Use monochrome logging. diff --git a/agent/README.md b/agent/README.md index b1e72a0d4..fc031ac9b 100644 --- a/agent/README.md +++ b/agent/README.md @@ -8,9 +8,9 @@ This article refers to **SKALE Interchain Messaging Agent** as **IMA**. **IMA** consists of the following parts: -- Contracts on Mainnet -- Contracts on a SKALE Chain -- NodeJS based app + - Contracts on Mainnet + - Contracts on a SKALE Chain + - NodeJS based app ## Contracts installation @@ -28,23 +28,23 @@ cd ./IMA Install required **Node JS** packages everywhere: ```shell -export IMA_ROOT=..... -cd $IMA_ROOT -yarn install + export IMA_ROOT=..... + cd $IMA_ROOT + yarn install ``` Export required environment variables: ```shell -export NETWORK_FOR_ETHEREUM="mainnet" -export PRIVATE_KEY_FOR_ETHEREUM="" -export NETWORK_FOR_SCHAIN="schain" -export PRIVATE_KEY_FOR_SCHAIN="" -export CHAIN_NAME_SCHAIN="Bob" -export URL_W3_ETHEREUM="http://127.0.0.1:8545" -export URL_W3_S_CHAIN="http://127.0.0.1:15000" -export ACCOUNT_FOR_ETHEREUM="" -export ACCOUNT_FOR_SCHAIN=""" + export NETWORK_FOR_ETHEREUM="mainnet" + export PRIVATE_KEY_FOR_ETHEREUM="" + export NETWORK_FOR_SCHAIN="schain" + export PRIVATE_KEY_FOR_SCHAIN="" + export CHAIN_NAME_SCHAIN="Bob" + export URL_W3_ETHEREUM="http://127.0.0.1:8545" + export URL_W3_S_CHAIN="http://127.0.0.1:15000" + export ACCOUNT_FOR_ETHEREUM="" + export ACCOUNT_FOR_SCHAIN=""" ``` Notice: `ACCOUNT_FOR_ETHEREUM` address corresponds to `PRIVATE_KEY_FOR_ETHEREUM` private key, `ACCOUNT_FOR_SCHAIN` address corresponds to `PRIVATE_KEY_FOR_SCHAIN` private key. @@ -52,8 +52,8 @@ Notice: `ACCOUNT_FOR_ETHEREUM` address corresponds to `PRIVATE_KEY_FOR_ETHEREUM` Rebuild all the contracts once to ensure everything initialized OK: ```shell -cd $IMA_ROOT/proxy -npx hardhat clean && npx hardhat compile + cd $IMA_ROOT/proxy + npx hardhat clean && npx hardhat compile ``` ### Contracts pre-installation on Mainnet and SKALE Chain @@ -61,9 +61,9 @@ npx hardhat clean && npx hardhat compile For mainnet, invoke: ```shell -cd $IMA_ROOT/proxy -yarn run deploy-to-mainnet -ls -1 ./data/ + cd $IMA_ROOT/proxy + yarn run deploy-to-mainnet + ls -1 ./data/ ``` You should see **proxyMainnet.json** file listed. @@ -71,9 +71,9 @@ You should see **proxyMainnet.json** file listed. For SKALE chain, invoke: ```shell -cd $IMA_ROOT/proxy -yarn run deploy-to-schain -ls -1 ./data/ + cd $IMA_ROOT/proxy + yarn run deploy-to-schain + ls -1 ./data/ ``` You should see **proxySchain_*s-chain-name-here*.json** file listed. @@ -83,53 +83,53 @@ You should see **proxySchain_*s-chain-name-here*.json** file listed. **IMA** supports two ways of signing transactions: ```shell -- Direct private key -- SGX Wallet + - Direct private key + - SGX Wallet ``` Private keys can be specified directly in **IMA** command line: ```shell ---key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ ---key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` If **IMA** action needs to sign only **Main Net** transaction(s) and do read-only actions on **S-Chain**: ```shell ---key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ ---address-s-chain=0x66c5a87f4a49dd75e970055a265e8dd5c3f8f852 + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --address-s-chain=0x66c5a87f4a49dd75e970055a265e8dd5c3f8f852 ``` If **IMA** action needs to sign only **S-Chain** transaction(s) and do read-only actions on **Main Net**: ```shell ---address-main-net=$ACCOUNT_FOR_ETHEREUM \ ---key-s-chain=$PRIVATE_KEY_FOR_SCHAIN \ + --address-main-net=$ACCOUNT_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN \ ``` If **IMA** should use **SGX Wallet** to sign transactions, then the parameters above should be replaced with: ```shell ---sgx-url-main-net=...\ ---sgx-url-s-chain=...\ ---sgx-ecdsa-key-main-net=...\ ---sgx-ecdsa-key-s-chain=...\ ---sgx-ssl-key-main-net=...\ ---sgx-ssl-key-s-chain=...\ ---sgx-ssl-cert-main-net=...\ ---sgx-ssl-cert-s-chain=...\ ---address-main-net=...\ ---address-s-chain=... + --sgx-url-main-net=...\ + --sgx-url-s-chain=...\ + --sgx-ecdsa-key-main-net=...\ + --sgx-ecdsa-key-s-chain=...\ + --sgx-ssl-key-main-net=...\ + --sgx-ssl-key-s-chain=...\ + --sgx-ssl-cert-main-net=...\ + --sgx-ssl-cert-s-chain=...\ + --address-main-net=...\ + --address-s-chain=... ``` If **IMA** should use **Transaction Manager** to sign transactions, then the parameters above should be replaced with: ```shell ---tm-url-main-net=...\ ---tm-url-s-chain=... \ ---address-main-net=...\ ---address-s-chain=... + --tm-url-main-net=...\ + --tm-url-s-chain=... \ + --address-main-net=...\ + --address-s-chain=... ``` **IMA** can use different ways of signing messages for **Main Net** and **S-Chain** by mixing connectivity parameters specified above. @@ -145,35 +145,35 @@ It's possible to mix **SGX Wallet** and direct private key usage. I.e. **Main Ne You can check whether **IMA** is already bound with: ```shell -node ./main.js --verbose=9 --expose --colors \ - --check-registration \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --check-registration \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` **IMA** works as S-Chain extension. It should be registered on Main-net before performing any money transfers between blockchains: ```shell -node ./main.js --verbose=9 --expose --colors \ - --register \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --register \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` ### Run IMA transfer loop for particular S-Chain @@ -181,18 +181,18 @@ node ./main.js --verbose=9 --expose --colors \ Performed with the **--loop** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --loop \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --loop \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` Notice: the command above can be run in forever while loop of shell script or became a part of daemon service file. @@ -204,86 +204,86 @@ IMA transfers from **S-Chain** back to **Main Net** needs to be payed. Gas reimb Show balance: ```shell -node ./main.js --verbose=9 --expose --colors \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --reimbursement-chain=Bob \ - --reimbursement-balance - --receiver=$ADDRESS_FOR_ETHEREUM + node ./main.js --verbose=9 --expose --colors \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --reimbursement-chain=Bob \ + --reimbursement-balance + --receiver=$ADDRESS_FOR_ETHEREUM ``` Estimate amount: ```shell -node ./main.js --verbose=9 --expose --colors \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --reimbursement-chain=Bob \ - --reimbursement-estimate \ - --receiver=$ADDRESS_FOR_ETHEREUM + node ./main.js --verbose=9 --expose --colors \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --reimbursement-chain=Bob \ + --reimbursement-estimate \ + --receiver=$ADDRESS_FOR_ETHEREUM ``` Recharge balance with 1 ETH: ```shell -node ./main.js --verbose=9 --expose --colors \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --reimbursement-chain=Bob \ - --reimbursement-recharge=1eth + node ./main.js --verbose=9 --expose --colors \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --reimbursement-chain=Bob \ + --reimbursement-recharge=1eth ``` Withdraw 1 ETH: ```shell -node ./main.js --verbose=9 --expose --colors \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --reimbursement-chain=Bob \ - --reimbursement-withdraw=1eth + node ./main.js --verbose=9 --expose --colors \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --reimbursement-chain=Bob \ + --reimbursement-withdraw=1eth ``` Set minimal time range in seconds between **S-Chain** back to **Main Net** messages to `0` seconds(default value is `5` minutes): ```shell -node ./main.js --verbose=9 --expose --colors \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_S_CHAIN \ - --reimbursement-range=0 + node ./main.js --verbose=9 --expose --colors \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_S_CHAIN \ + --reimbursement-range=0 ``` ## Other IMA tasks @@ -291,19 +291,19 @@ node ./main.js --verbose=9 --expose --colors \ ### Getting command line help ```shell -node ./main.js --colors --help + node ./main.js --colors --help ``` ### Displaying run-time variables and arguments ```shell -node ./main.js --colors --show-config + node ./main.js --colors --show-config ``` ### Listing available output detail options ```shell -node ./main.js --colors --verbose-list + node ./main.js --colors --verbose-list ``` ### Specifying logging options @@ -319,19 +319,19 @@ By default mirrored log file grows with no limit and no log rotation is performe Performed with the **--m2s-payment** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --m2s-payment \ - --ether=1 \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --address-s-chain=$ACCOUNT_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --m2s-payment \ + --ether=1 \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --address-s-chain=$ACCOUNT_FOR_SCHAIN ``` Notice: The command above does payment from Main-net and that is why we need to specify private key for source account inside Main-net blockchain using the **--key-main-net** command line argument. Target S-chain account is specified as address with the **--address-s-chain** command line argument. We don't need to specify private key for target account. @@ -341,19 +341,19 @@ Notice: The command above does payment from Main-net and that is why we need to Performed with the **--s2m-payment** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --s2m-payment \ - --ether=1 \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --address-main-net=$ACCOUNT_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --s2m-payment \ + --ether=1 \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --address-main-net=$ACCOUNT_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` Notice: The command above does payment from Main-net and that is why we need to specify private key for source account inside S-chain blockchain using the **--key-s-chain** command line argument. Target Main-net account is specified as address with the **--address-main-net** command line argument. We don't need to specify private key for target account. @@ -363,17 +363,17 @@ Notice: The command above does payment from Main-net and that is why we need to Performed with the **--s2m-view** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --s2m-view \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --id-s-chain=Bob \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM + node ./main.js --verbose=9 --expose --colors \ + --s2m-view \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --id-s-chain=Bob \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM ``` Notice: this operation is related to ETH transfers only. @@ -383,17 +383,17 @@ Notice: this operation is related to ETH transfers only. Performed with the **--s2m-receive** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --s2m-receive \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM + node ./main.js --verbose=9 --expose --colors \ + --s2m-receive \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM ``` Notice: this operation is related to ETH transfers only. @@ -422,18 +422,18 @@ Single transfer operations are similar to the **--loop** normal mode but perform Performed with the **--m2s-transfer** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --m2s-transfer \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --m2s-transfer \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` #### Single transfer iteration from S-chain to Main-net @@ -441,18 +441,18 @@ node ./main.js --verbose=9 --expose --colors \ Performed with the **--s2m-transfer** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --s2m-transfer \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --s2m-transfer \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` #### Single bidirectional transfer iteration between Main-net and S-chain @@ -460,50 +460,42 @@ node ./main.js --verbose=9 --expose --colors \ Performed with the **--transfer** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --transfer \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --transfer \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` ### Transfer loop parameters -```shell ---skip-dry-run..................Skip dry run contract method calls. ---ignore-dry-run................Ignore result of dry run contract method calls and continue execute. ---dry-run.......................Use error results of dry run contract method calls as actual errors and stop execute. - ---m2s-transfer-block-size.......Number of transactions in one block to use in money transfer loop from Main-net to S-chain. ---s2m-transfer-block-size.......Number of transactions in one block to use in money transfer loop from S-chain to Main-net. ---s2s-transfer-block-size.......Number of transactions in one block to use in money transfer loop from S-chain to S-chain. ---transfer-block-size...........Number of transactions in one block to use in both money transfer loops. - ---m2s-max-transactions..........Maximal number of transactions to do in money transfer loop from Main-net to S-chain (0 is unlimited). ---s2m-max-transactions..........Maximal number of transactions to do in money transfer loop from S-chain to Main-net (0 is unlimited). ---s2s-max-transactions..........Maximal number of transactions to do in money transfer loop from S-chain to S-chain (0 is unlimited). ---max-transactions..............Maximal number of transactions to do in both money transfer loops (0 is unlimited). - ---m2s-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from Main-net to S-chain (0 is no wait). ---s2m-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to Main-net (0 is no wait). ---s2s-await-blocks..............Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to S-chain (0 is no wait). ---await-blocks..................Maximal number of blocks to wait to appear in blockchain before transaction between both S-chain and Main-net (0 is no wait). - ---period........................Transfer loop period(seconds). ---node-number=value.............S-Chain node number(zero based). ---nodes-count=value.............S-Chain nodes count. ---time-framing=value............Specifies period(in seconds) for time framing. Zero means disable time framing. ---time-gap=value................Specifies gap(in seconds) before next time frame. ---ptx...........................Enable pending transaction analysis to avoid transaction conflicts. ---no-ptx........................Disable pending transaction analysis. Not recommended for slow and overloaded blockchains. -``` + - --skip-dry-run - Skip dry run contract method calls. + - --ignore-dry-run - Ignore result of dry run contract method calls and continue execute. + - --dry-run - Use error results of dry run contract method calls as actual errors and stop execute. + - --m2s-transfer-block-size - Number of transactions in one block to use in money transfer loop from Main-net to S-chain. + - --s2m-transfer-block-size - Number of transactions in one block to use in money transfer loop from S-chain to Main-net. + - --s2s-transfer-block-size - Number of transactions in one block to use in money transfer loop from S-chain to S-chain. + - --transfer-block-size - Number of transactions in one block to use in both money transfer loops. + - --m2s-max-transactions - Maximal number of transactions to do in money transfer loop from Main-net to S-chain (0 is unlimited). + - --s2m-max-transactions - Maximal number of transactions to do in money transfer loop from S-chain to Main-net (0 is unlimited). + - --s2s-max-transactions - Maximal number of transactions to do in money transfer loop from S-chain to S-chain (0 is unlimited). + - --max-transactions - Maximal number of transactions to do in both money transfer loops (0 is unlimited). + - --m2s-await-blocks - Maximal number of blocks to wait to appear in blockchain before transaction from Main-net to S-chain (0 is no wait). + - --s2m-await-blocks - Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to Main-net (0 is no wait). + - --s2s-await-blocks - Maximal number of blocks to wait to appear in blockchain before transaction from S-chain to S-chain (0 is no wait). + - --await-blocks - Maximal number of blocks to wait to appear in blockchain before transaction between both S-chain and Main-net (0 is no wait). + - --period - Transfer loop period(seconds). + - --node-number=value - S-Chain node number(zero based). + - --nodes-count=value - S-Chain nodes count. + - --time-framing=value - Specifies period(in seconds) for time framing. Zero means disable time framing. + - --time-gap=value - Specifies gap(in seconds) before next time frame. ### S-Chain specific configuration for more then one node S-Chains @@ -514,21 +506,21 @@ The **--node-number** and **--nodes-count** must me used for **IMA** instances r Performed with the **--m2s-payment** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --m2s-payment \ - --amount=1 \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --erc20-main-net=../../SkaleExperimental/skaled-tests/saved-Artem-scripts/Zhelcoin/data-mn.json \ - --erc20-s-chain=../../SkaleExperimental/skaled-tests/saved-Artem-scripts/Zhelcoin/data-sc.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --address-s-chain=0x66c5a87f4a49dd75e970055a265e8dd5c3f8f852 + node ./main.js --verbose=9 --expose --colors \ + --m2s-payment \ + --amount=1 \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --erc20-main-net=...path.../data-mn.json \ + --erc20-s-chain=...path.../data-sc.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --address-s-chain=0x66c5a87f4a49dd75e970055a265e8dd5c3f8f852 ``` Notice: The command above does payment from Main-net and that is why we need to specify private key for source account inside Main-net blockchain using the **--key-main-net** command line argument. Target S-chain account is specified as address with the **--address-s-chain** command line argument. We don't need to specify private key for target account. @@ -550,22 +542,22 @@ Similar to ERC1155 single token transfer.Use **--tids** to specify ERC1155 token Performed with the **--s2m-payment** command line option: ```shell -node ./main.js --verbose=9 --expose --colors \ - --s2m-payment \ - --amount=1 \ - --sleep-between-tx=5000 \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --erc20-main-net=../../SkaleExperimental/skaled-tests/saved-Artem-scripts/Zhelcoin/data-mn.json \ - --erc20-s-chain=../../SkaleExperimental/skaled-tests/saved-Artem-scripts/Zhelcoin/data-sc.json \ - --address-main-net=$ACCOUNT_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN + node ./main.js --verbose=9 --expose --colors \ + --s2m-payment \ + --amount=1 \ + --sleep-between-tx=5000 \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --erc20-main-net=...path.../data-mn.json \ + --erc20-s-chain=...path.../data-sc.json \ + --address-main-net=$ACCOUNT_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN ``` Notice: The command above does payment from Main-net and that is why we need to specify private key for source account inside S-chain blockchain using the **--key-s-chain** command line argument. Target Main-net account is specified as address with the **--address-main-net** command line argument. We don't need to specify private key for target account. @@ -589,25 +581,25 @@ Similar to ERC1155 single token transfer.Use **--tids** to specify ERC1155 token You can asl **IMA Agent** to show ETH and, optionally, various token balances and/or ERC721 token owners: ```shell -node ./main.js --verbose=9 --expose --colors \ - --show-balance \ - --tids="[1,2,3] \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --address-main-net=$ACCOUNT_FOR_ETHEREUM \ - --address-s-chain=$ACCOUNT_FOR_SCHAIN \ - --erc20-main-net=.....path-to.....ERC20.abi.mn.json \ - --erc20-s-chain=.....path-to.....ERC20.abi.sc00.json \ - --erc721-main-net=.....path-to.....ERC721.abi.mn.json \ - --erc721-s-chain=.....path-to.....ERC721.abi.sc00.json \ - --erc1155-main-net=.....path-to.....ERC1155.abi.mn.json \ - --erc1155-s-chain=.....path-to.....ERC1155.abi.sc00.json + node ./main.js --verbose=9 --expose --colors \ + --show-balance \ + --tids="[1,2,3] \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --address-main-net=$ACCOUNT_FOR_ETHEREUM \ + --address-s-chain=$ACCOUNT_FOR_SCHAIN \ + --erc20-main-net=.....path-to.....ERC20.abi.mn.json \ + --erc20-s-chain=.....path-to.....ERC20.abi.sc00.json \ + --erc721-main-net=.....path-to.....ERC721.abi.mn.json \ + --erc721-s-chain=.....path-to.....ERC721.abi.sc00.json \ + --erc1155-main-net=.....path-to.....ERC1155.abi.mn.json \ + --erc1155-s-chain=.....path-to.....ERC1155.abi.sc00.json ``` Example command above will always show: real ETH on Main Net, ETH user can receive on Main Net, real ETH on S-Chain, stored as ERC20 and local S-Chain ETH. @@ -619,8 +611,8 @@ The token balances and owners display is optional and depends on set of ABI and You can ask agent app to scan **S-Chain** network information and parameters, print it and exit: ```shell -node ./main.js --verbose=9 --expose --colors \ - --url-s-chain=$URL_W3_S_CHAIN -- browse-s-chain + node ./main.js --verbose=9 --expose --colors \ + --url-s-chain=$URL_W3_S_CHAIN --browse-s-chain ``` This information is used to sign messages on all **S-Chain** nodes. @@ -643,8 +635,8 @@ The **--hash-g1** command line parameter must be used to specify path to the **h Message signing will work only on **S-Chain** where each **skaled** node configured properly and able to: -- provide brows information for entire **S-Chain** network -- provide **IMA** signing APIs and parameters + - provide brows information for entire **S-Chain** network + - provide **IMA** signing APIs and parameters Here is example of correct **config.json** file for **skaled** node: @@ -699,39 +691,39 @@ Here is example of correct **config.json** file for **skaled** node: Here is example of IMA message processing loop invocation with BLS support: ```shell -reset; node ./main.js --verbose=9 --expose --colors \ - --loop \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN \ - --sign-messages \ - --bls-glue=/Users/l_sergiy/Work/skaled/build/libconsensus/libBLS/bls_glue \ - --hash-g1=/Users/l_sergiy/Work/skaled/build/libconsensus/libBLS/hash_g1 \ - --bls-verify=/Users/l_sergiy/Work/skaled/build/libconsensus/libBLS/verify_bls - -reset; node ./main.js --verbose=9 --expose --colors \ - --loop \ - --url-main-net=$URL_W3_ETHEREUM \ - --url-s-chain=$URL_W3_S_CHAIN \ - --id-main-net=Mainnet \ - --id-s-chain=Bob \ - --cid-main-net=-4 \ - --cid-s-chain=-4 \ - --abi-main-net=../proxy/data/proxyMainnet.json \ - --abi-s-chain=../proxy/data/proxySchain_Bob.json \ - --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ - --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN \ - --sign-messages \ - --bls-glue=/home/serge/Work/skaled/build/libconsensus/libBLS/bls_glue \ - --hash-g1=/home/serge/Work/skaled/build/libconsensus/libBLS/hash_g1 \ - --bls-verify=/home/serge/Work/skaled/build/libconsensus/libBLS/verify_bls + reset; node ./main.js --verbose=9 --expose --colors \ + --loop \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN \ + --sign-messages \ + --bls-glue=...path.../bls_glue \ + --hash-g1=...path.../hash_g1 \ + --bls-verify=...path.../verify_bls + + reset; node ./main.js --verbose=9 --expose --colors \ + --loop \ + --url-main-net=$URL_W3_ETHEREUM \ + --url-s-chain=$URL_W3_S_CHAIN \ + --id-main-net=Mainnet \ + --id-s-chain=Bob \ + --cid-main-net=-4 \ + --cid-s-chain=-4 \ + --abi-main-net=../proxy/data/proxyMainnet.json \ + --abi-s-chain=../proxy/data/proxySchain_Bob.json \ + --key-main-net=$PRIVATE_KEY_FOR_ETHEREUM \ + --key-s-chain=$PRIVATE_KEY_FOR_SCHAIN \ + --sign-messages \ + --bls-glue=/home/serge/Work/skaled/build/libconsensus/libBLS/bls_glue \ + --hash-g1=/home/serge/Work/skaled/build/libconsensus/libBLS/hash_g1 \ + --bls-verify=/home/serge/Work/skaled/build/libconsensus/libBLS/verify_bls ``` ### Gas computation and transaction customization diff --git a/agent/bls.js b/agent/bls.js deleted file mode 100644 index 187138a33..000000000 --- a/agent/bls.js +++ /dev/null @@ -1,1636 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file bls.js - * @copyright SKALE Labs 2019-Present - */ - -// const fs = require( "fs" ); -// const path = require( "path" ); -// const url = require( "url" ); -// const os = require( "os" ); -const child_process = require( "child_process" ); -const shell = require( "shelljs" ); -const { Keccak } = require( "sha3" ); - -function init() { - owaspUtils.owaspAddUsageRef(); -} - -const sleep = ( milliseconds ) => { return new Promise( resolve => setTimeout( resolve, milliseconds ) ); }; - -const g_secondsMessageVerifySendTimeout = 2 * 60; - -async function with_timeout( strDescription, promise, seconds ) { - strDescription = strDescription || "with_timeout()"; - let result_err = null, isComplete = false; - promise.catch( function( err ) { - isComplete = true; - result_err = new Error( strDescription + "error: " + err.toString() ); - } ).finally( function() { - isComplete = true; - } ); - for( let idxWaitStep = 0; idxWaitStep < seconds; ++ idxWaitStep ) { - if( isComplete ) - break; - await sleep( 1000 ); - } - if( result_err ) - throw result_err; - if( ! isComplete ) - throw new Error( strDescription + " reached limit of " + seconds + " second(s)" ); -}; - -function discover_bls_threshold( joSChainNetworkInfo ) { - joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; - const jarrNodes = joSChainNetworkInfo.network; - for( let i = 0; i < jarrNodes.length; ++i ) { - const joNode = jarrNodes[i]; - if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && - "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" && - joNode.imaInfo.t > 0 - ) - return joNode.imaInfo.t; - } - return -1; -} - -function discover_bls_participants( joSChainNetworkInfo ) { - joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; - const jarrNodes = joSChainNetworkInfo.network; - for( let i = 0; i < jarrNodes.length; ++i ) { - const joNode = jarrNodes[i]; - if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && - "n" in joNode.imaInfo && typeof joNode.imaInfo.n === "number" && - joNode.imaInfo.n > 0 - ) - return joNode.imaInfo.n; - } - return -1; -} - -function discover_public_key_by_index( nNodeIndex, joSChainNetworkInfo ) { - joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; - const jarrNodes = joSChainNetworkInfo.network; - const joNode = jarrNodes[nNodeIndex]; - if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && - "BLSPublicKey0" in joNode.imaInfo && typeof joNode.imaInfo.BLSPublicKey0 === "string" && joNode.imaInfo.BLSPublicKey0.length > 0 && - "BLSPublicKey1" in joNode.imaInfo && typeof joNode.imaInfo.BLSPublicKey1 === "string" && joNode.imaInfo.BLSPublicKey1.length > 0 && - "BLSPublicKey2" in joNode.imaInfo && typeof joNode.imaInfo.BLSPublicKey2 === "string" && joNode.imaInfo.BLSPublicKey2.length > 0 && - "BLSPublicKey3" in joNode.imaInfo && typeof joNode.imaInfo.BLSPublicKey3 === "string" && joNode.imaInfo.BLSPublicKey3.length > 0 - ) { - return { - BLSPublicKey0: joNode.imaInfo.BLSPublicKey0, - BLSPublicKey1: joNode.imaInfo.BLSPublicKey1, - BLSPublicKey2: joNode.imaInfo.BLSPublicKey2, - BLSPublicKey3: joNode.imaInfo.BLSPublicKey3 - }; - } - return null; -} - -function discover_common_public_key( joSChainNetworkInfo ) { - joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; - const jarrNodes = joSChainNetworkInfo.network; - for( let i = 0; i < jarrNodes.length; ++i ) { - const joNode = jarrNodes[i]; - if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && - "commonBLSPublicKey0" in joNode.imaInfo && typeof joNode.imaInfo.commonBLSPublicKey0 === "string" && joNode.imaInfo.commonBLSPublicKey0.length > 0 && - "commonBLSPublicKey1" in joNode.imaInfo && typeof joNode.imaInfo.commonBLSPublicKey1 === "string" && joNode.imaInfo.commonBLSPublicKey1.length > 0 && - "commonBLSPublicKey2" in joNode.imaInfo && typeof joNode.imaInfo.commonBLSPublicKey2 === "string" && joNode.imaInfo.commonBLSPublicKey2.length > 0 && - "commonBLSPublicKey3" in joNode.imaInfo && typeof joNode.imaInfo.commonBLSPublicKey3 === "string" && joNode.imaInfo.commonBLSPublicKey3.length > 0 - ) { - return { - commonBLSPublicKey0: joNode.imaInfo.commonBLSPublicKey0, - commonBLSPublicKey1: joNode.imaInfo.commonBLSPublicKey1, - commonBLSPublicKey2: joNode.imaInfo.commonBLSPublicKey2, - commonBLSPublicKey3: joNode.imaInfo.commonBLSPublicKey3 - }; - } - } - return null; -} - -let g_w3 = null; - -function get_w3() { - if( ! g_w3 ) - g_w3 = global.g_w3mod || require( "web3" ); - return g_w3; -} - -function hexPrepare( strHex, isInvertBefore, isInvertAfter ) { - if( isInvertBefore == undefined ) - isInvertBefore = true; - if( isInvertAfter == undefined ) - isInvertAfter = true; - let arrBytes = imaUtils.hexToBytes( strHex ); - if( isInvertBefore ) - arrBytes = imaUtils.invertArrayItemsLR( arrBytes ); - arrBytes = imaUtils.bytesAlignLeftWithZeroes( arrBytes, 32 ); - if( isInvertAfter ) - arrBytes = imaUtils.invertArrayItemsLR( arrBytes ); - return arrBytes; -} - -function s2ha( s ) { - const str_u256 = get_w3().utils.soliditySha3( s ); - return hexPrepare( str_u256, true, true ); -} - -// function n2ha( n ) { -// const str_u256 = "0x" + get_w3().utils.toBN( n ).toString( 16 ); -// return hexPrepare( str_u256, true, false ); -// } - -function a2ha( arrBytes ) { - const k = new Keccak( 256 ); - k.update( imaUtils.toBuffer( arrBytes ) ); - const h = k.digest( "hex" ); - return imaUtils.hexToBytes( "0x" + h ); -} - -function keccak256_message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) { - let arrBytes = s2ha( strFromChainName ); - // arrBytes = imaUtils.bytesConcat( arrBytes, n2ha( nIdxCurrentMsgBlockStart ) ); - arrBytes = imaUtils.bytesConcat( arrBytes, hexPrepare( "0x" + nIdxCurrentMsgBlockStart.toString( 16 ), false, false ) ); - // console.log( "1 ---------------", "0x" + imaUtils.bytesToHex( arrBytes, false ) ); - arrBytes = a2ha( arrBytes ); - // console.log( "2 ---------------", "0x" + imaUtils.bytesToHex( arrBytes, false ) ); - let i = 0; const cnt = jarrMessages.length; - for( i = 0; i < cnt; ++i ) { - const joMessage = jarrMessages[i]; - // - let bytesSender = imaUtils.hexToBytes( joMessage.sender ); - // bytesSender = imaUtils.invertArrayItemsLR( bytesSender ); - bytesSender = imaUtils.bytesAlignLeftWithZeroes( bytesSender, 32 ); - // bytesSender = imaUtils.invertArrayItemsLR( bytesSender ); - arrBytes = imaUtils.bytesConcat( arrBytes, bytesSender ); - // - let bytesDestinationContract = imaUtils.hexToBytes( joMessage.destinationContract ); - // bytesDestinationContract = imaUtils.invertArrayItemsLR( bytesDestinationContract ); - bytesDestinationContract = imaUtils.bytesAlignLeftWithZeroes( bytesDestinationContract, 32 ); - // bytesDestinationContract = imaUtils.invertArrayItemsLR( bytesDestinationContract ); - arrBytes = imaUtils.bytesConcat( arrBytes, bytesDestinationContract ); - // - const bytesData = imaUtils.hexToBytes( joMessage.data ); - // bytesData = imaUtils.bytesAlignLeftWithZeroes( bytesData, 32 ); - // bytesData = imaUtils.invertArrayItemsLR( bytesData ); // do not invert byte order data field (see SKALE-3554 for details) - arrBytes = imaUtils.bytesConcat( arrBytes, bytesData ); - // console.log( "3 ---------------", "0x" + imaUtils.bytesToHex( arrBytes, false ) ); - // - // arrBytes = imaUtils.invertArrayItemsLR( arrBytes ); - arrBytes = a2ha( arrBytes ); - // console.log( "4 ---------------", "0x" + imaUtils.bytesToHex( arrBytes, false ) ); - } - return "0x" + imaUtils.bytesToHex( arrBytes, false ); -} - -// const strHashExpected = "0x3094d655630537e78650506931ca36191bc2d4a85ab3216632f5bf107265c8ea".toLowerCase(), strHashComputed = -// keccak256_message( -// [ { -// "sender": "0x0000000000000000000000000000000000000001", -// "destinationContract": "0x0000000000000000000000000000000000000002", -// "data": "0x030405" // 0x010203" -// } ], -// 6, -// "d2" -// ).toLowerCase(); -// console.log( "----------------- computed.....", strHashComputed ); -// console.log( "----------------- expected.....", strHashExpected ); -// console.log( "----------------- equal........", ( strHashComputed == strHashExpected ) ? "yes" : "no" ); -// process.exit( 0 ); - -// const strHashComputed = keccak256_message( [ -// { -// sender: "0xAe79233541427BC70Bd3Bfe452ca4B1c69d5a82e", -// destinationContract: "0xd2AaA00400000000000000000000000000000000", -// data: "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000007aa5e36aa15e93d10f4f26357c30f052dacdde5f00000000000000000000000000000000000000000000006c6b935b8bbd400000" -// } -// ], 1, "Mainnet" ).toLowerCase(); -// console.log( "----------------- computed.....", strHashComputed ); -// process.exit( 0 ); - -function keccak256_u256( u256, isHash ) { - let arrBytes = new Uint8Array(); - // - let bytes_u256 = imaUtils.hexToBytes( u256 ); - bytes_u256 = imaUtils.invertArrayItemsLR( bytes_u256 ); - bytes_u256 = imaUtils.bytesAlignLeftWithZeroes( bytes_u256, 32 ); - bytes_u256 = imaUtils.invertArrayItemsLR( bytes_u256 ); - arrBytes = imaUtils.bytesConcat( arrBytes, bytes_u256 ); - // - let strMessageHash = ""; - if( isHash ) { - const hash = new Keccak( 256 ); - hash.update( imaUtils.toBuffer( arrBytes ) ); - strMessageHash = hash.digest( "hex" ); - } else - strMessageHash = "0x" + imaUtils.bytesToHex( arrBytes ); - return strMessageHash; -} - -function split_signature_share( signatureShare ) { - const jarr = signatureShare.split( ":" ); - return { - X: jarr[0], - Y: jarr[1] - }; -} - -function get_bls_glue_tmp_dir() { - // NOTE: uncomment require( "path" ); at top of this file when using local tmp folder - // const strTmpDir = path.resolve( __dirname ) + "/tmp"; - const strTmpDir = "/tmp/ima-bls-glue"; - shell.mkdir( "-p", strTmpDir ); - return strTmpDir; -} - -function alloc_bls_tmp_action_dir() { - const strActionDir = get_bls_glue_tmp_dir() + "/" + imaUtils.replaceAll( imaUtils.uuid(), "-", "" ); - shell.mkdir( "-p", strActionDir ); - return strActionDir; -} - -function perform_bls_glue( - details, - strDirection, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - arrSignResults -) { - const strLogPrefix = cc.bright( strDirection ) + cc.debug( "/" ) + cc.info( "BLS" ) + cc.debug( "/" ) + cc.attention( "Glue" ) + cc.debug( ":" ) + " "; - let joGlueResult = null; - // const jarrNodes = imaState.joSChainNetworkInfo.network; - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - details.write( strLogPrefix + cc.debug( "Discovered BLS threshold is " ) + cc.info( nThreshold ) + cc.debug( "." ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + cc.info( nParticipants ) + cc.debug( "." ) + "\n" ); - const strMessageHash = owaspUtils.remove_starting_0x( keccak256_message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) ); - details.write( strLogPrefix + cc.debug( "Message hash to sign is " ) + cc.info( strMessageHash ) + "\n" ); - const strPWD = shell.pwd(); - const strActionDir = alloc_bls_tmp_action_dir(); - details.write( strLogPrefix + cc.debug( "perform_bls_glue will work in " ) + cc.info( strActionDir ) + cc.debug( " director with " ) + cc.info( arrSignResults.length ) + cc.debug( " sign results..." ) + "\n" ); - const fnShellRestore = function() { - shell.cd( strPWD ); - shell.rm( "-rf", strActionDir ); - }; - let strOutput = ""; - try { - shell.cd( strActionDir ); - let strInput = ""; - let i = 0; const cnt = arrSignResults.length; - for( i = 0; i < cnt; ++i ) { - const jo = arrSignResults[i]; - const strPath = strActionDir + "/sign-result" + jo.index + ".json"; - details.write( strLogPrefix + cc.normal( "Saving " ) + cc.notice( strPath ) + cc.debug( " file containing " ) + cc.j( jo ) + "\n" ); - imaUtils.jsonFileSave( strPath, jo ); - strInput += " --input " + strPath; - } - const strGlueCommand = - imaState.strPathBlsGlue + - " --t " + nThreshold + - " --n " + nParticipants + - strInput + - " --output " + strActionDir + "/glue-result.json"; - details.write( strLogPrefix + cc.debug( "Will execute BLS glue command:\n" ) + cc.notice( strGlueCommand ) + "\n" ); - strOutput = child_process.execSync( strGlueCommand ); - details.write( strLogPrefix + cc.debug( "BLS glue output is:\n" ) + cc.notice( strOutput ) + "\n" ); - joGlueResult = imaUtils.jsonFileLoad( strActionDir + "/glue-result.json" ); - details.write( strLogPrefix + cc.debug( "BLS glue result is: " ) + cc.j( joGlueResult ) + "\n" ); - if( "X" in joGlueResult.signature && "Y" in joGlueResult.signature ) { - details.write( strLogPrefix + cc.success( "BLS glue success" ) + "\n" ); - joGlueResult.hashSrc = strMessageHash; - // - // - // - details.write( strLogPrefix + cc.debug( "Computing " ) + cc.info( "G1" ) + cc.debug( " hash point..." ) + "\n" ); - const strPath = strActionDir + "/hash.json"; - details.write( strLogPrefix + cc.normal( "Saving " ) + cc.notice( strPath ) + cc.debug( " file..." ) + "\n" ); - imaUtils.jsonFileSave( strPath, { message: strMessageHash } ); - const strHasG1Command = - imaState.strPathHashG1 + - " --t " + nThreshold + - " --n " + nParticipants; - details.write( strLogPrefix + cc.normal( "Will execute HashG1 command:\n" ) + cc.notice( strHasG1Command ) + "\n" ); - strOutput = child_process.execSync( strHasG1Command ); - details.write( strLogPrefix + cc.normal( "HashG1 output is:\n" ) + cc.notice( strOutput ) + "\n" ); - const joResultHashG1 = imaUtils.jsonFileLoad( strActionDir + "/g1.json" ); - details.write( strLogPrefix + cc.normal( "HashG1 result is: " ) + cc.j( joResultHashG1 ) + "\n" ); - // - // - // - if( "g1" in joResultHashG1 && "hint" in joResultHashG1.g1 && "hashPoint" in joResultHashG1.g1 && - "X" in joResultHashG1.g1.hashPoint && "Y" in joResultHashG1.g1.hashPoint ) { - joGlueResult.hashPoint = joResultHashG1.g1.hashPoint; - joGlueResult.hint = joResultHashG1.g1.hint; - } else { - joGlueResult = null; - throw new Error( "malformed HashG1 result: " + JSON.stringify( joResultHashG1 ) ); - } - } else { - const joSavedGlueResult = joGlueResult; - joGlueResult = null; - throw new Error( "malformed BLS glue result: " + JSON.stringify( joSavedGlueResult ) ); - } - // - // typical glue result is: - // { - // "signature": { - // "X": "2533808148583356869465588922364792219279924240245650719832918161014673583859", - // "Y": "2900553917645502192745899163584745093808998719667605626180761629013549672201" - // } - // } - // - fnShellRestore(); - } catch ( err ) { - const s1 = strLogPrefix + cc.fatal( "BLS glue CRITICAL ERROR:" ) + cc.error( " error description is: " ) + cc.warning( err.toString() ) + "\n"; - const s2 = strLogPrefix + cc.error( "BLS glue output is:\n" ) + cc.notice( strOutput ) + "\n"; - log.write( s1 ); - details.write( s1 ); - log.write( s2 ); - details.write( s2 ); - fnShellRestore(); - joGlueResult = null; - } - return joGlueResult; -} - -function perform_bls_glue_u256( details, u256, arrSignResults ) { - const strLogPrefix = cc.info( "BLS" ) + cc.debug( "/" ) + cc.attention( "Glue" ) + cc.debug( ":" ) + " "; - let joGlueResult = null; - // const jarrNodes = imaState.joSChainNetworkInfo.network; - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - details.write( strLogPrefix + cc.debug( "Discovered BLS threshold is " ) + cc.info( nThreshold ) + cc.debug( "." ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + cc.info( nParticipants ) + cc.debug( "." ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Original long message is " ) + cc.info( keccak256_u256( u256, false ) ) + "\n" ); - const strMessageHash = keccak256_u256( u256, true ); - details.write( strLogPrefix + cc.debug( "Message hash to sign is " ) + cc.info( strMessageHash ) + "\n" ); - const strPWD = shell.pwd(); - const strActionDir = alloc_bls_tmp_action_dir(); - details.write( strLogPrefix + cc.debug( "perform_bls_glue_u256 will work in " ) + cc.info( strActionDir ) + cc.debug( " director with " ) + cc.info( arrSignResults.length ) + cc.debug( " sign results..." ) + "\n" ); - const fnShellRestore = function() { - shell.cd( strPWD ); - shell.rm( "-rf", strActionDir ); - }; - let strOutput = ""; - try { - shell.cd( strActionDir ); - let strInput = ""; - let i = 0; const cnt = arrSignResults.length; - for( i = 0; i < cnt; ++i ) { - const jo = arrSignResults[i]; - const strPath = strActionDir + "/sign-result" + jo.index + ".json"; - details.write( strLogPrefix + cc.normal( "Saving " ) + cc.notice( strPath ) + cc.debug( " file..." ) + "\n" ); - imaUtils.jsonFileSave( strPath, jo ); - strInput += " --input " + strPath; - } - const strGlueCommand = - imaState.strPathBlsGlue + - " --t " + nThreshold + - " --n " + nParticipants + - strInput + - " --output " + strActionDir + "/glue-result.json"; - details.write( strLogPrefix + cc.normal( "Will execute BLS glue command:\n" ) + cc.notice( strGlueCommand ) + "\n" ); - strOutput = child_process.execSync( strGlueCommand ); - details.write( strLogPrefix + cc.normal( "BLS glue output is:\n" ) + cc.notice( strOutput ) + "\n" ); - joGlueResult = imaUtils.jsonFileLoad( strActionDir + "/glue-result.json" ); - details.write( strLogPrefix + cc.normal( "BLS glue result is: " ) + cc.j( joGlueResult ) + "\n" ); - if( "X" in joGlueResult.signature && "Y" in joGlueResult.signature ) { - details.write( strLogPrefix + cc.success( "BLS glue success" ) + "\n" ); - joGlueResult.hashSrc = strMessageHash; - // - // - // - details.write( strLogPrefix + cc.debug( "Computing " ) + cc.info( "G1" ) + cc.debug( " hash point..." ) + "\n" ); - const strPath = strActionDir + "/hash.json"; - details.write( strLogPrefix + cc.normal( "Saving " ) + cc.notice( strPath ) + cc.debug( " file..." ) + "\n" ); - imaUtils.jsonFileSave( strPath, { message: strMessageHash } ); - const strHasG1Command = - imaState.strPathHashG1 + - " --t " + nThreshold + - " --n " + nParticipants; - details.write( strLogPrefix + cc.normal( "Will execute HashG1 command:\n" ) + cc.notice( strHasG1Command ) + "\n" ); - strOutput = child_process.execSync( strHasG1Command ); - details.write( strLogPrefix + cc.normal( "HashG1 output is:\n" ) + cc.notice( strOutput ) + "\n" ); - const joResultHashG1 = imaUtils.jsonFileLoad( strActionDir + "/g1.json" ); - details.write( strLogPrefix + cc.normal( "HashG1 result is: " ) + cc.j( joResultHashG1 ) + "\n" ); - // - // - // - if( "g1" in joResultHashG1 && "hint" in joResultHashG1.g1 && "hashPoint" in joResultHashG1.g1 && - "X" in joResultHashG1.g1.hashPoint && "Y" in joResultHashG1.g1.hashPoint ) { - joGlueResult.hashPoint = joResultHashG1.g1.hashPoint; - joGlueResult.hint = joResultHashG1.g1.hint; - } else { - joGlueResult = null; - throw new Error( "malformed HashG1 result: " + JSON.stringify( joResultHashG1 ) ); - } - } else { - const joSavedGlueResult = joGlueResult; - joGlueResult = null; - throw new Error( "malformed BLS glue result: " + JSON.stringify( joSavedGlueResult ) ); - } - // - // typical glue result is: - // { - // "signature": { - // "X": "2533808148583356869465588922364792219279924240245650719832918161014673583859", - // "Y": "2900553917645502192745899163584745093808998719667605626180761629013549672201" - // } - // } - // - fnShellRestore(); - } catch ( err ) { - const s1 = strLogPrefix + cc.fatal( "BLS glue CRITICAL ERROR:" ) + cc.error( " error description is: " ) + cc.warning( err.toString() ) + "\n"; - const s2 = strLogPrefix + cc.error( "BLS glue output is:\n" ) + cc.notice( strOutput ) + "\n"; - log.write( s1 ); - details.write( s1 ); - log.write( s2 ); - details.write( s2 ); - fnShellRestore(); - joGlueResult = null; - } - return joGlueResult; -} - -function perform_bls_verify_i( - details, - strDirection, - nZeroBasedNodeIndex, - joResultFromNode, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joPublicKey -) { - if( !joResultFromNode ) - return true; - const strLogPrefix = cc.bright( strDirection ) + cc.debug( "/" ) + cc.info( "BLS" ) + cc.debug( "/" ) + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + cc.debug( ":" ) + " "; - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - const strPWD = shell.pwd(); - const strActionDir = alloc_bls_tmp_action_dir(); - const fnShellRestore = function() { - shell.cd( strPWD ); - shell.rm( "-rf", strActionDir ); - }; - let strOutput = ""; - try { - shell.cd( strActionDir ); - details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - first message nonce is " ) + cc.info( nIdxCurrentMsgBlockStart ) + "\n" ); - details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - first source chain name is " ) + cc.info( strFromChainName ) + "\n" ); - details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - messages array " ) + cc.j( jarrMessages ) + "\n" ); - const strMessageHash = owaspUtils.remove_starting_0x( keccak256_message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) ); - details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - hashed verify message is " ) + cc.info( strMessageHash ) + "\n" ); - const joMsg = { - message: strMessageHash - }; - details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - composed " ) + cc.j( joMsg ) + cc.debug( " composed from " ) + cc.j( jarrMessages ) + cc.debug( " using glue " ) + cc.j( joResultFromNode ) + cc.debug( " and public key " ) + cc.j( joPublicKey ) + "\n" ); - const strSignResultFileName = strActionDir + "/sign-result" + nZeroBasedNodeIndex + ".json"; - // console.log( "--- joResultFromNode ---", JSON.stringify( joResultFromNode ) ); - // console.log( "--- joMsg ---", JSON.stringify( joMsg ) ); - // console.log( "--- joPublicKey ---", JSON.stringify( joPublicKey ) ); - imaUtils.jsonFileSave( strSignResultFileName, joResultFromNode ); - imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); - imaUtils.jsonFileSave( strActionDir + "/BLS_keys" + nZeroBasedNodeIndex + ".json", joPublicKey ); - const strVerifyCommand = "" + - imaState.strPathBlsVerify + - " --t " + nThreshold + - " --n " + nParticipants + - " --j " + nZeroBasedNodeIndex + - " --input " + strSignResultFileName - ; - details.write( strLogPrefix + cc.normal( "Will execute node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.normal( " BLS verify command:\n" ) + cc.notice( strVerifyCommand ) + "\n" ); - strOutput = child_process.execSync( strVerifyCommand ); - details.write( strLogPrefix + cc.normal( "BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.normal( " verify output is:\n" ) + cc.notice( strOutput ) + "\n" ); - details.write( strLogPrefix + cc.success( "BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.success( " verify success" ) + "\n" ); - fnShellRestore(); - return true; - } catch ( err ) { - const s1 = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.error( " verify error:" ) + cc.normal( " error description is: " ) + cc.warning( err.toString() ) + "\n"; - const s2 = strLogPrefix + cc.error( "CRITICAL ERROR:" ) + cc.error( " BLS node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.error( " verify output is:\n" ) + cc.notice( strOutput ) + "\n"; - log.write( s1 ); - details.write( s1 ); - log.write( s2 ); - details.write( s2 ); - fnShellRestore(); - } - return false; -} - -function perform_bls_verify_i_u256( details, nZeroBasedNodeIndex, joResultFromNode, u256, joPublicKey ) { - if( !joResultFromNode ) - return true; - const strLogPrefix = cc.info( "BLS" ) + cc.debug( "/" ) + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + cc.debug( ":" ) + " "; - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - const strPWD = shell.pwd(); - const strActionDir = alloc_bls_tmp_action_dir(); - const fnShellRestore = function() { - shell.cd( strPWD ); - shell.rm( "-rf", strActionDir ); - }; - let strOutput = ""; - try { - shell.cd( strActionDir ); - const joMsg = { message: keccak256_u256( u256, true ) }; - details.write( strLogPrefix + cc.debug( "BLS u256 node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.debug( " verify message " ) + cc.j( joMsg ) + cc.debug( " composed from " ) + cc.j( u256 ) + cc.debug( " using glue " ) + cc.j( joResultFromNode ) + cc.debug( " and public key " ) + cc.j( joPublicKey ) + "\n" ); - const strSignResultFileName = strActionDir + "/sign-result" + nZeroBasedNodeIndex + ".json"; - // console.log( "--- joResultFromNode ---", JSON.stringify( joResultFromNode ) ); - // console.log( "--- joMsg ---", JSON.stringify( joMsg ) ); - // console.log( "--- joPublicKey ---", JSON.stringify( joPublicKey ) ); - imaUtils.jsonFileSave( strSignResultFileName, joResultFromNode ); - imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); - imaUtils.jsonFileSave( strActionDir + "/BLS_keys" + nZeroBasedNodeIndex + ".json", joPublicKey ); - const strVerifyCommand = "" + - imaState.strPathBlsVerify + - " --t " + nThreshold + - " --n " + nParticipants + - " --j " + nZeroBasedNodeIndex + - " --input " + strSignResultFileName - ; - details.write( strLogPrefix + cc.normal( "Will execute node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.normal( " BLS u256 verify command:\n" ) + cc.notice( strVerifyCommand ) + "\n" ); - strOutput = child_process.execSync( strVerifyCommand ); - details.write( strLogPrefix + cc.normal( "BLS u256 node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.normal( " verify output is:\n" ) + cc.notice( strOutput ) + "\n" ); - details.write( strLogPrefix + cc.success( "BLS u256 node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.success( " verify success" ) + "\n" ); - fnShellRestore(); - return true; - } catch ( err ) { - const s1 = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " BLS u256 node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.error( " verify error:" ) + cc.normal( " error description is: " ) + cc.warning( err.toString() ) + "\n"; - const s2 = strLogPrefix + cc.error( "CRITICAL ERROR:" ) + cc.error( " BLS u256 node " ) + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.error( " verify output is:\n" ) + cc.notice( strOutput ) + "\n"; - log.write( s1 ); - details.write( s1 ); - log.write( s2 ); - details.write( s2 ); - fnShellRestore(); - } - return false; -} - -function perform_bls_verify( - details, - strDirection, - joGlueResult, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joCommonPublicKey -) { - if( !joGlueResult ) - return true; - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - const strPWD = shell.pwd(); - const strActionDir = alloc_bls_tmp_action_dir(); - const fnShellRestore = function() { - shell.cd( strPWD ); - shell.rm( "-rf", strActionDir ); - }; - let strOutput = ""; - const strLogPrefix = cc.bright( strDirection ) + cc.debug( "/" ) + cc.info( "BLS" ) + cc.debug( "/" ) + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; - try { - shell.cd( strActionDir ); - log.write( strLogPrefix + cc.debug( "BLS/summary verify message - first message nonce is " ) + cc.info( nIdxCurrentMsgBlockStart ) + "\n" ); - log.write( strLogPrefix + cc.debug( "BLS/summary verify message - first source chain name is " ) + cc.info( strFromChainName ) + "\n" ); - log.write( strLogPrefix + cc.debug( "BLS/summary verify message - messages array " ) + cc.j( jarrMessages ) + "\n" ); - const strMessageHash = owaspUtils.remove_starting_0x( keccak256_message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) ); - details.write( strLogPrefix + cc.debug( "BLS/summary verify message - hashed verify message is " ) + cc.info( strMessageHash ) + "\n" ); - const joMsg = { message: strMessageHash }; - details.write( strLogPrefix + cc.debug( "BLS/summary verify message - composed JSON " ) + cc.j( joMsg ) + cc.debug( " from messages array " ) + cc.j( jarrMessages ) + cc.debug( " using glue " ) + cc.j( joGlueResult ) + cc.debug( " and common public key " ) + cc.j( joCommonPublicKey ) + "\n" ); - imaUtils.jsonFileSave( strActionDir + "/glue-result.json", joGlueResult ); - imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); - // let joCommonPublicKey_for_O = joCommonPublicKey; - // const joCommonPublicKey_for_O = { - // commonBLSPublicKey0: joCommonPublicKey.commonBLSPublicKey1, - // commonBLSPublicKey1: joCommonPublicKey.commonBLSPublicKey0, - // commonBLSPublicKey2: joCommonPublicKey.commonBLSPublicKey3, - // commonBLSPublicKey3: joCommonPublicKey.commonBLSPublicKey2 - // }; - const joCommonPublicKey_for_O = { - commonBLSPublicKey0: joCommonPublicKey.commonBLSPublicKey0, - commonBLSPublicKey1: joCommonPublicKey.commonBLSPublicKey1, - commonBLSPublicKey2: joCommonPublicKey.commonBLSPublicKey2, - commonBLSPublicKey3: joCommonPublicKey.commonBLSPublicKey3 - }; - imaUtils.jsonFileSave( strActionDir + "/common_public_key.json", joCommonPublicKey_for_O ); - details.write( strLogPrefix + cc.normal( "BLS common public key for verification is:\n" ) + cc.j( joCommonPublicKey ) + "\n" ); - const strVerifyCommand = "" + - imaState.strPathBlsVerify + - " --t " + nThreshold + - " --n " + nParticipants + - " --input " + "./glue-result.json" - ; - details.write( strLogPrefix + cc.normal( "Will execute BLS/summary verify command:\n" ) + cc.notice( strVerifyCommand ) + "\n" ); - strOutput = child_process.execSync( strVerifyCommand ); - details.write( strLogPrefix + cc.normal( "BLS/summary verify output is:\n" ) + cc.notice( strOutput ) + "\n" ); - details.write( strLogPrefix + cc.success( "BLS/summary verify success" ) + "\n" ); - fnShellRestore(); - return true; - } catch ( err ) { - const s1 = strLogPrefix + cc.fatal( "BLS/summary verify CRITICAL ERROR:" ) + cc.normal( " error description is: " ) + cc.warning( err.toString() ) + "\n"; - const s2 = strLogPrefix + cc.error( "BLS/summary verify output is:\n" ) + cc.notice( strOutput ) + "\n"; - log.write( s1 ); - details.write( s1 ); - log.write( s2 ); - details.write( s2 ); - fnShellRestore(); - } - return false; -} - -function perform_bls_verify_u256( details, joGlueResult, u256, joCommonPublicKey ) { - if( !joGlueResult ) - return true; - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - const strPWD = shell.pwd(); - const strActionDir = alloc_bls_tmp_action_dir(); - const fnShellRestore = function() { - shell.cd( strPWD ); - shell.rm( "-rf", strActionDir ); - }; - let strOutput = ""; - const strLogPrefix = cc.info( "BLS u256" ) + cc.debug( "/" ) + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; - try { - shell.cd( strActionDir ); - const joMsg = { message: keccak256_u256( u256, true ) }; - details.write( strLogPrefix + cc.debug( "BLS u256/summary verify message " ) + cc.j( joMsg ) + cc.debug( " composed from " ) + cc.j( u256 ) + cc.debug( " using glue " ) + cc.j( joGlueResult ) + cc.debug( " and common public key " ) + cc.j( joCommonPublicKey ) + "\n" ); - imaUtils.jsonFileSave( strActionDir + "/glue-result.json", joGlueResult ); - imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); - // let joCommonPublicKey_for_O = joCommonPublicKey; - // const joCommonPublicKey_for_O = { - // commonBLSPublicKey0: joCommonPublicKey.commonBLSPublicKey1, - // commonBLSPublicKey1: joCommonPublicKey.commonBLSPublicKey0, - // commonBLSPublicKey2: joCommonPublicKey.commonBLSPublicKey3, - // commonBLSPublicKey3: joCommonPublicKey.commonBLSPublicKey2 - // }; - const joCommonPublicKey_for_O = { - commonBLSPublicKey0: joCommonPublicKey.commonBLSPublicKey0, - commonBLSPublicKey1: joCommonPublicKey.commonBLSPublicKey1, - commonBLSPublicKey2: joCommonPublicKey.commonBLSPublicKey2, - commonBLSPublicKey3: joCommonPublicKey.commonBLSPublicKey3 - }; - imaUtils.jsonFileSave( strActionDir + "/common_public_key.json", joCommonPublicKey_for_O ); - details.write( strLogPrefix + cc.normal( "BLS u256 common public key for verification is:\n" ) + cc.j( joCommonPublicKey ) + "\n" ); - const strVerifyCommand = "" + - imaState.strPathBlsVerify + - " --t " + nThreshold + - " --n " + nParticipants + - " --input " + "./glue-result.json" - ; - details.write( strLogPrefix + cc.normal( "Will execute BLS u256/summary verify command:\n" ) + cc.notice( strVerifyCommand ) + "\n" ); - strOutput = child_process.execSync( strVerifyCommand ); - details.write( strLogPrefix + cc.normal( "BLS u256/summary verify output is:\n" ) + cc.notice( strOutput ) + "\n" ); - details.write( strLogPrefix + cc.success( "BLS u256/summary verify success" ) + "\n" ); - fnShellRestore(); - return true; - } catch ( err ) { - const s1 = strLogPrefix + cc.fatal( "BLS u256/summary verify CRITICAL ERROR:" ) + cc.normal( " error description is: " ) + cc.warning( err.toString() ) + "\n"; - const s2 = strLogPrefix + cc.error( "BLS u256/summary verify output is:\n" ) + cc.notice( strOutput ) + "\n"; - log.write( s1 ); - details.write( s1 ); - log.write( s2 ); - details.write( s2 ); - fnShellRestore(); - } - return false; -} - -async function check_correctness_of_messages_to_sign( details, strLogPrefix, strDirection, jarrMessages, nIdxCurrentMsgBlockStart, joExtraSignOpts ) { - let w3 = null; let joMessageProxy = null; let joAccount = null; let joChainName = null; - if( strDirection == "M2S" ) { - w3 = imaState.w3_main_net; - joMessageProxy = imaState.jo_message_proxy_main_net; - joAccount = imaState.joAccount_main_net; - joChainName = imaState.strChainName_s_chain; - } else if( strDirection == "S2M" ) { - w3 = imaState.w3_s_chain; - joMessageProxy = imaState.jo_message_proxy_s_chain; - joAccount = imaState.joAccount_s_chain; - joChainName = imaState.strChainName_main_net; - } else if( strDirection == "S2S" ) { - w3 = joExtraSignOpts.w3_src; - joMessageProxy = new w3.eth.Contract( imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, imaState.joAbiPublishResult_s_chain.message_proxy_chain_address ); - joAccount = imaState.joAccount_s_chain; - joChainName = joExtraSignOpts.chain_id_dst; - } else - throw new Error( "CRITICAL ERROR: Failed check_correctness_of_messages_to_sign() with unknown directon \"" + strDirection + "\"" ); - - const strCallerAccountAddress = joAccount.address( w3 ); - details.write( strLogPrefix + cc.sunny( strDirection ) + cc.debug( " message correctness validation through call to " ) + - cc.notice( "verifyOutgoingMessageData" ) + cc.debug( " method of " ) + cc.bright( "MessageProxy" ) + - cc.debug( " contract with address " ) + cc.notice( joMessageProxy.options.address ) + - cc.debug( ", caller account address is " ) + cc.info( joMessageProxy.options.address ) + - cc.debug( ", message(s) count is " ) + cc.info( jarrMessages.length ) + - cc.debug( ", message(s) to process: " ) + cc.j( jarrMessages ) + - cc.debug( ", first real message index is: " ) + cc.info( nIdxCurrentMsgBlockStart ) + - "\n" ); - let cntBadMessages = 0, i = 0; - const cnt = jarrMessages.length; - if( strDirection == "S2M" || strDirection == "S2S" ) { - for( i = 0; i < cnt; ++i ) { - const joMessage = jarrMessages[i]; - const idxMessage = nIdxCurrentMsgBlockStart + i; - try { - details.write( - cc.debug( "Will validate message " ) + cc.info( i ) + cc.debug( " of " ) + cc.info( cnt ) + - cc.debug( ", real message index is: " ) + cc.info( idxMessage ) + - "\n" ); - // const strHexAmount = "0x" + w3.utils.toBN( joMessage.amount ).toString( 16 ); - const outgoingMessageData = { - dstChainHash: w3.utils.soliditySha3( joChainName ), // dstChainHash - msgCounter: 0 + idxMessage, - srcContract: joMessage.sender, - dstContract: joMessage.destinationContract, - // to: joMessage.to, - // amount: strHexAmount, - data: joMessage.data - }; - details.write( - cc.debug( "Outgoing message data is " ) + cc.j( outgoingMessageData ) + - cc.debug( ", real message index is: " ) + cc.info( idxMessage ) + - cc.debug( ", saved msgCounter is: " ) + cc.info( outgoingMessageData.msgCounter ) + - "\n" ); - const m = joMessageProxy.methods.verifyOutgoingMessageData( - outgoingMessageData - ); - const isValidMessage = await m.call( { from: strCallerAccountAddress } ); - details.write( - cc.debug( "Got verification call result " ) + cc.tf( isValidMessage ) + - cc.debug( ", real message index is: " ) + cc.info( idxMessage ) + - cc.debug( ", saved msgCounter is: " ) + cc.info( outgoingMessageData.msgCounter ) + - "\n" ); - if( !isValidMessage ) - throw new Error( "Bad message detected, message is: " + JSON.stringify( joMessage ) ); - } catch ( err ) { - ++cntBadMessages; - const s = - strLogPrefix + cc.fatal( "BAD ERROR:" ) + - cc.error( " Correctness validation failed for message " ) + cc.info( idxMessage ) + - cc.error( " sent to " ) + cc.info( joChainName ) + - cc.error( ", message is: " ) + cc.j( joMessage ) + - cc.error( ", error information: " ) + cc.warning( err.toString() ) + - "\n"; - log.write( s ); - details.write( s ); - } - } // for( i = 0; i < cnt; ++i ) - } // if( strDirection == "S2M" || strDirection == "S2S" ) - // TODO: M2S - check events - if( cntBadMessages > 0 ) { - const s = - strLogPrefix + cc.fatal( "BAD ERROR:" ) + - cc.error( " Correctness validation failed for " ) + cc.info( cntBadMessages ) + - cc.error( " of " ) + cc.info( cnt ) + cc.error( " message(s)" ) + "\n"; - log.write( s ); - details.write( s ); - } else - details.write( strLogPrefix + cc.success( "Correctness validation passed for " ) + cc.info( cnt ) + cc.success( " message(s)" ) + "\n" ); -} - -async function do_sign_messages_impl( - nTransferLoopCounter, - strDirection, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joExtraSignOpts, - fn -) { - let bHaveResultReportCalled = false; - const strLogPrefix = cc.bright( strDirection ) + " " + cc.info( "Sign msgs:" ) + " "; - const joGatheringTracker = { - nCountReceived: 0, // including errors - nCountErrors: 0, - nCountSkipped: 0, - nWaitIntervalStepMilliseconds: 100, - nWaitIntervalStepsDone: 0, - nWaitIntervalMaxSteps: 10 * 60 * 3 // 10 is 1 second - }; - const arrSignResults = []; - let cntSuccess = 0; - let details = log.createMemoryStream( true ); - const strGatheredDetailsName = strDirection + "-" + "do_sign_messages_impl-#" + nTransferLoopCounter + - "-" + strFromChainName + "-msg#" + nIdxCurrentMsgBlockStart; - try { - log.write( strLogPrefix + cc.debug( " Invoking " ) + cc.bright( strDirection ) + cc.debug( " signing messages procedure " ) + "\n" ); - details.write( strLogPrefix + cc.debug( " Invoking " ) + cc.bright( strDirection ) + cc.debug( " signing messages procedure " ) + "\n" ); - fn = fn || function() {}; - if( !( imaState.bSignMessages && imaState.strPathBlsGlue.length > 0 && imaState.joSChainNetworkInfo ) ) { - bHaveResultReportCalled = true; - details.write( strLogPrefix + cc.debug( "BLS message signing is " ) + cc.error( "turned off" ) + - cc.debug( ", first real message index is: " ) + cc.info( nIdxCurrentMsgBlockStart ) + - cc.debug( ", have " ) + cc.info( jarrMessages.length ) + - cc.debug( " message(s) to process: " ) + cc.j( jarrMessages ) + - "\n" ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - details.close(); - await check_correctness_of_messages_to_sign( details, strLogPrefix, strDirection, jarrMessages, nIdxCurrentMsgBlockStart, joExtraSignOpts ); - await fn( null, jarrMessages, null ); - return; - } - await check_correctness_of_messages_to_sign( details, strLogPrefix, strDirection, jarrMessages, nIdxCurrentMsgBlockStart, joExtraSignOpts ); - // - // each message in array looks like: - // { - // "amount": joValues.amount, - // "data": joValues.data, - // "destinationContract": joValues.dstContract, - // "sender": joValues.srcContract, - // "to": joValues.to - // } - // - // sign result looks like: - // { - // "id": 1, "jsonrpc": "2.0", "result": { - // "signResult": { - // "errorMessage": "", - // "signatureShare": "13888409666804046853490114813821624491836407617931905586112520275264817002720:9871589266312476278322587556340871982939135237123140475925975407511373249165:0", - // "status": 0 - // } - // } - // } - // - const sequence_id = owaspUtils.remove_starting_0x( get_w3().utils.soliditySha3( log.generate_timestamp_string( null, false ) ) ); - details.write( strLogPrefix + - cc.debug( "Will sign " ) + cc.info( jarrMessages.length ) + cc.debug( " message(s)" ) + - cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + cc.attention( sequence_id ) + - cc.debug( "..." ) + "\n" ); - log.write( strLogPrefix + - cc.debug( "Will sign " ) + cc.j( jarrMessages ) + cc.debug( " message(s)" ) + - cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + cc.attention( sequence_id ) + - cc.debug( "..." ) + "\n" ); - const jarrNodes = imaState.joSChainNetworkInfo.network; - details.write( strLogPrefix + cc.debug( "Will query to sign " ) + cc.info( jarrNodes.length ) + cc.debug( " skaled node(s)..." ) + "\n" ); - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - details.write( strLogPrefix + cc.debug( "Discovered BLS threshold is " ) + cc.info( nThreshold ) + cc.debug( "." ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + cc.info( nParticipants ) + cc.debug( "." ) + "\n" ); - if( nThreshold <= 0 ) { - bHaveResultReportCalled = true; - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - details.close(); - await fn( "signature error(1), S-Chain information was not discovered properly and BLS threshold is unknown", jarrMessages, null ); - return; - } - const nCountOfBlsPartsToCollect = 0 + nThreshold; - // if( nThreshold <= 1 && nParticipants > 1 ) { - // details.write( strLogPrefix + cc.warning( "Minimal BLS parts number for dicovery was increased." ) + "\n" ); - // nCountOfBlsPartsToCollect = 2; - // } - log.write( strLogPrefix + - cc.debug( "Will collect " ) + cc.info( nCountOfBlsPartsToCollect ) + cc.debug( " signature(s)" ) + - cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + cc.attention( sequence_id ) + - "\n" ); - details.write( strLogPrefix + - cc.debug( "Will collect " ) + cc.info( nCountOfBlsPartsToCollect ) + cc.debug( " from " ) + - cc.info( jarrNodes.length ) + cc.debug( " nodes" ) + - cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + cc.attention( sequence_id ) + - "\n" ); - for( let i = 0; i < jarrNodes.length; ++i ) { - cntSuccess = joGatheringTracker.nCountReceived - joGatheringTracker.nCountErrors; - if( cntSuccess >= nCountOfBlsPartsToCollect ) { - details.write( - strLogPrefix + log.generate_timestamp_string( null, true ) + " " + - cc.debug( "Stop invoking " ) + cc.info( "skale_imaVerifyAndSign" ) + - cc.debug( " for transfer from chain " ) + cc.info( fromChainName ) + - cc.debug( " at #" ) + cc.info( i ) + - cc.debug( " because successfully gathered count is reached " ) + cc.j( cntSuccess ) + - "\n" ); - break; - } - const joNode = jarrNodes[i]; - const strNodeURL = imaUtils.compose_schain_node_url( joNode ); - const strNodeDescColorized = cc.u( strNodeURL ) + " " + - cc.normal( "(" ) + cc.bright( i ) + cc.normal( "/" ) + cc.bright( jarrNodes.length ) + cc.normal( ", ID " ) + cc.info( joNode.nodeID ) + cc.normal( ")" ) + - cc.normal( ", " ) + cc.notice( "sequence ID" ) + cc.normal( " is " ) + cc.attention( sequence_id ); - const rpcCallOpts = null; - /*await*/ rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - ++joGatheringTracker.nCountReceived; // including errors - ++joGatheringTracker.nCountErrors; - const strErrorMessage = - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + - cc.error( " failed, RPC call was not created, error: " ) + cc.warning( err ) + - cc.error( ", " ) + cc.notice( "sequence ID" ) + cc.error( " is " ) + cc.attention( sequence_id ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - return; - } - let targetChainName = ""; - let fromChainName = ""; - // let targetChainURL = ""; - // let fromChainURL = ""; - if( strDirection == "M2S" ) { - targetChainName = "" + ( imaState.strChainName_s_chain ? imaState.strChainName_s_chain : "" ); - fromChainName = "" + ( imaState.strChainName_main_net ? imaState.strChainName_main_net : "" ); - // targetChainURL = strNodeURL; - // fromChainURL = owaspUtils.w3_2_url( imaState.w3_main_net ); - } else if( strDirection == "S2M" ) { - targetChainName = "" + ( imaState.strChainName_main_net ? imaState.strChainName_main_net : "" ); - fromChainName = "" + ( imaState.strChainName_s_chain ? imaState.strChainName_s_chain : "" ); - // targetChainURL = owaspUtils.w3_2_url( imaState.w3_main_net ); - // fromChainURL = strNodeURL; - } else if( strDirection == "S2S" ) { - targetChainName = "" + joExtraSignOpts.chain_id_dst; - fromChainName = "" + joExtraSignOpts.chain_id_src; - // targetChainURL = owaspUtils.w3_2_url( joExtraSignOpts.w3_dst ); - // fromChainURL = owaspUtils.w3_2_url( joExtraSignOpts.w3_src ); - } else - throw new Error( "CRITICAL ERROR: Failed do_sign_messages_impl() with unknown directon \"" + strDirection + "\"" ); - - const joParams = { - direction: "" + strDirection, - startMessageIdx: nIdxCurrentMsgBlockStart, - dstChainName: targetChainName, - srcChainName: fromChainName, - messages: jarrMessages, - // fromChainURL: fromChainURL, - // targetChainURL: targetChainURL, - qa: { - skaled_no: 0 + i, - sequence_id: "" + sequence_id, - ts: "" + log.generate_timestamp_string( null, false ) - } - }; - details.write( - strLogPrefix + log.generate_timestamp_string( null, true ) + " " + - cc.debug( "Will invoke " ) + cc.info( "skale_imaVerifyAndSign" ) + - cc.debug( " for transfer from chain " ) + cc.info( fromChainName ) + - cc.debug( " to chain " ) + cc.info( targetChainName ) + - cc.debug( " with params " ) + cc.j( joParams ) + - cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + cc.attention( sequence_id ) + - "\n" ); - /*await*/ joCall.call( { - method: "skale_imaVerifyAndSign", - params: joParams - }, async function( joIn, joOut, err ) { - ++joGatheringTracker.nCountReceived; // including errors - if( err ) { - ++joGatheringTracker.nCountErrors; - const strErrorMessage = - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + - cc.error( " failed, RPC call reported error: " ) + cc.warning( err ) + - cc.error( ", " ) + cc.notice( "sequence ID" ) + cc.error( " is " ) + cc.attention( sequence_id ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - return; - } - details.write( - strLogPrefix + log.generate_timestamp_string( null, true ) + " " + - cc.debug( "Got answer from " ) + cc.info( "skale_imaVerifyAndSign" ) + - cc.debug( " for transfer from chain " ) + cc.info( fromChainName ) + - cc.debug( " to chain " ) + cc.info( targetChainName ) + - cc.debug( " with params " ) + cc.j( joParams ) + - cc.debug( ", answer is " ) + cc.j( joOut ) + - cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + cc.attention( sequence_id ) + - "\n" ); - if( joOut.result == null || joOut.result == undefined || ( !typeof joOut.result == "object" ) ) { - ++joGatheringTracker.nCountErrors; - if( "error" in joOut && "message" in joOut.error ) { - const strErrorMessage = - strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + - cc.error( "S-Chain node " ) + strNodeDescColorized + - cc.error( " reported wallet error: " ) + cc.warning( joOut.error.message ) + - cc.error( ", " ) + cc.notice( "sequence ID" ) + cc.error( " is " ) + cc.attention( sequence_id ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } else { - const strErrorMessage = - strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + - cc.error( "JSON RPC call to S-Chain node " ) + strNodeDescColorized + - cc.error( " failed with " ) + cc.warning( "unknown wallet error" ) + - cc.error( ", " ) + cc.notice( "sequence ID" ) + cc.error( " is " ) + cc.attention( sequence_id ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - return; - } - details.write( strLogPrefix + cc.normal( "Node " ) + cc.info( joNode.nodeID ) + cc.normal( " sign result: " ) + cc.j( joOut.result ? joOut.result : null ) + "\n" ); - try { - if( joOut.result.signResult.signatureShare.length > 0 && joOut.result.signResult.status === 0 ) { - const nZeroBasedNodeIndex = joNode.imaInfo.thisNodeIndex - 1; - // - // partial BLS verification for one participant - // - let bNodeSignatureOKay = false; // initially assume signature is wrong - const strLogPrefixA = cc.bright( strDirection ) + cc.debug( "/" ) + cc.info( "BLS" ) + cc.debug( "/" ) + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + cc.debug( ":" ) + " "; - try { - const cntSuccess = joGatheringTracker.nCountReceived - joGatheringTracker.nCountErrors; - if( cntSuccess > nCountOfBlsPartsToCollect ) { - ++joGatheringTracker.nCountSkipped; - details.write( strLogPrefixA + - cc.debug( "Will ignore sign result for node " ) + cc.info( nZeroBasedNodeIndex ) + - cc.debug( " because " ) + cc.info( nThreshold ) + cc.debug( "/" ) + cc.info( nCountOfBlsPartsToCollect ) + - cc.debug( " threshold number of BLS signature parts already gathered" ) + - "\n" ); - return; - } - const arrTmp = joOut.result.signResult.signatureShare.split( ":" ); - const joResultFromNode = { - index: "" + nZeroBasedNodeIndex, - signature: { - X: arrTmp[0], - Y: arrTmp[1] - } - }; - details.write( strLogPrefixA + cc.info( "Will verify sign result for node " ) + cc.info( nZeroBasedNodeIndex ) + "\n" ); - const joPublicKey = discover_public_key_by_index( nZeroBasedNodeIndex, imaState.joSChainNetworkInfo ); - if( perform_bls_verify_i( - details, - strDirection, - nZeroBasedNodeIndex, - joResultFromNode, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joPublicKey - ) ) { - details.write( strLogPrefixA + cc.success( "Got successful BLS verification result for node " ) + cc.info( joNode.nodeID ) + cc.success( " with index " ) + cc.info( nZeroBasedNodeIndex ) + "\n" ); - bNodeSignatureOKay = true; // node verification passed - } else { - const strError = "BLS verify failed"; - details.write( strLogPrefixA + cc.fatal( "CRITICAL ERROR:" ) + " " + cc.error( strError ) + "\n" ); - } - } catch ( err ) { - const strErrorMessage = - strLogPrefixA + cc.error( "S-Chain node " ) + strNodeDescColorized + cc.error( " sign " ) + - cc.error( " CRITICAL ERROR:" ) + cc.error( " partial signature fail from with index " ) + cc.info( nZeroBasedNodeIndex ) + - cc.error( ", error is " ) + cc.warning( err.toString() ) + - cc.error( ", " ) + cc.notice( "sequence ID" ) + cc.error( " is " ) + cc.attention( sequence_id ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - // - // sign result for bls_glue should look like: - // { - // "index": "1", - // "signature": { - // "X": "8184471694634630119550127539973704769190648951089883109386639469590492862134", - // "Y": "4773775435244318964726085856452691379381914783621253742616578726383405809710" - // } - // } - // - if( bNodeSignatureOKay ) { - arrSignResults.push( { - index: "" + nZeroBasedNodeIndex, - signature: split_signature_share( joOut.result.signResult.signatureShare ), - fromNode: joNode, // extra, not needed for bls_glue - signResult: joOut.result.signResult - } ); - } else - ++joGatheringTracker.nCountErrors; - } - } catch ( err ) { - ++nCountErrors; - const strErrorMessage = - strLogPrefix + cc.error( "S-Chain node " ) + strNodeDescColorized + " " + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " signature fail from node " ) + cc.info( joNode.nodeID ) + - cc.error( ", error is " ) + cc.warning( err.toString() ) + - cc.error( ", " ) + cc.notice( "sequence ID" ) + cc.error( " is " ) + cc.attention( sequence_id ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - } ); // joCall.call ... - } ); // rpcCall.create ... - } // for( let i = 0; i < jarrNodes.length; ++i ) - - log.write( strLogPrefix + cc.debug( "Waiting for BLS glue result " ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Waiting for BLS glue result " ) + "\n" ); - let errGathering = null; - const promise_gathering_complete = new Promise( ( resolve, reject ) => { - const iv = setInterval( function() { - ++ joGatheringTracker.nWaitIntervalStepsDone; - cntSuccess = joGatheringTracker.nCountReceived - joGatheringTracker.nCountErrors; - if( cntSuccess >= nCountOfBlsPartsToCollect ) { - const strLogPrefixB = cc.bright( strDirection ) + cc.debug( "/" ) + cc.info( "BLS" ) + cc.debug( "/" ) + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; - clearInterval( iv ); - let strError = null, strSuccessfulResultDescription = null; - const joGlueResult = perform_bls_glue( - details, - strDirection, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - arrSignResults - ); - if( joGlueResult ) { - details.write( strLogPrefixB + cc.success( "Got BLS glue result: " ) + cc.j( joGlueResult ) + "\n" ); - if( imaState.strPathBlsVerify.length > 0 ) { - const joCommonPublicKey = discover_common_public_key( imaState.joSChainNetworkInfo ); - // console.log(joCommonPublicKey); - if( perform_bls_verify( - details, - strDirection, - joGlueResult, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joCommonPublicKey - ) ) { - strSuccessfulResultDescription = "Got successful summary BLS verification result"; - details.write( strLogPrefixB + cc.success( strSuccessfulResultDescription ) + "\n" ); - } else { - strError = "BLS verify failed"; - log.write( strLogPrefixB + cc.fatal( "CRITICAL ERROR:" ) + cc.error( strError ) + "\n" ); - details.write( strLogPrefixB + cc.fatal( "CRITICAL ERROR:" ) + cc.error( strError ) + "\n" ); - } - } - } else { - strError = "BLS glue failed, no glue result arrived"; - const strErrorMessage = - strLogPrefixB + cc.error( "Problem(1) in BLS sign result handler: " ) + cc.warning( strError ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - log.write( cc.debug( "Will call sending function (fn)" ) + "\n" ); - details.write( cc.debug( "Will call sending function (fn) for " ) + "\n" ); - /*await*/ fn( strError, jarrMessages, joGlueResult ).catch( ( err ) => { - const strErrorMessage = cc.error( "Problem(2) in BLS sign result handler: " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - errGathering = "Problem(2) in BLS sign result handler: " + err.toString(); - return; - } ); - bHaveResultReportCalled = true; - if( strError ) { - errGathering = strError; - reject( new Error( errGathering ) ); - } else - resolve(); - return; - } - if( joGatheringTracker.nCountReceived >= jarrNodes.length ) { - clearInterval( iv ); - /*await*/ fn( "signature error(2), got " + joGatheringTracker.nCountErrors + " errors(s) for " + jarrNodes.length + " node(s)", jarrMessages, null ).catch( ( err ) => { - const strErrorMessage = - cc.error( "Problem(3) in BLS sign result handler, not enough successful BLS signature parts(" ) + - cc.info( cntSuccess ) + cc.error( " when all attempts done, error details: " ) + cc.warning( err.toString() ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - errGathering = - "Problem(3) in BLS sign result handler, not enough successful BLS signature parts(" + - cntSuccess + " when all attempts done, error details: " + err.toString(); - reject( new Error( errGathering ) ); - } ); - bHaveResultReportCalled = true; - return; - } - if( joGatheringTracker.nWaitIntervalStepsDone >= joGatheringTracker.nWaitIntervalMaxSteps ) { - clearInterval( iv ); - /*await*/ fn( "signature error(3), got " + joGatheringTracker.nCountErrors + " errors(s) for " + jarrNodes.length + " node(s)", jarrMessages, null ).catch( ( err ) => { - const strErrorMessage = - cc.error( "Problem(4) in BLS sign result handler, not enough successful BLS signature parts(" ) + - cc.info( cntSuccess ) + cc.error( ") and timeout reached, error details: " ) + - cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - errGathering = - "Problem(4) in BLS sign result handler, not enough successful BLS signature parts(" + - cntSuccess + ") and timeout reached, error details: " + err.toString(); - reject( new Error( errGathering ) ); - } ); - bHaveResultReportCalled = true; - return; - } - }, joGatheringTracker.nWaitIntervalStepMilliseconds ); - } ); - log.write( cc.debug( "Will await for message BLS verification and sending..." ) + "\n" ); - details.write( cc.debug( "Will await for message BLS verification and sending..." ) + "\n" ); - await with_timeout( "BLS verification and sending", promise_gathering_complete, g_secondsMessageVerifySendTimeout ).then( strSuccessfulResultDescription => { - details.write( cc.success( "BLS verification and sending promise awaited." ) + "\n" ); - log.write( cc.success( "BLS verification and sending promise awaited." ) + "\n" ); - } ).catch( err => { - const strErrorMessage = cc.error( "Failed to verify BLS and send message : " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } ); - if( errGathering ) { - const strErrorMessage = cc.error( "Failed BLS sign result awaiting(1): " ) + cc.warning( errGathering.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - if( ! bHaveResultReportCalled ) { - bHaveResultReportCalled = true; - await fn( - "Failed to gather BLS signatures in " + jarrNodes.length + " node(s), trakcer data is: " + - JSON.stringify( joGatheringTracker ) + ", error: " + errGathering.toString(), - jarrMessages, - null - ).catch( ( err ) => { - const strErrorMessage = - cc.error( "Problem(5) in BLS sign result handler, not enough successful BLS signature parts(" ) + - cc.info( cntSuccess ) + cc.error( ") and timeout reached, error details: " ) + - cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - details.close(); - details = null; - } ); - } - return; - } - if( ! bHaveResultReportCalled ) { - const strErrorMessage = cc.error( "Failed BLS sign result awaiting(2): " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - bHaveResultReportCalled = true; - await fn( "Failed to gather BLS signatures in " + jarrNodes.length + " node(s), trakcer data is: " + JSON.stringify( joGatheringTracker ), jarrMessages, null ).catch( ( err ) => { - const strErrorMessage = - cc.error( "Problem(6) in BLS sign result handler, not enough successful BLS signature parts(" ) + - cc.info( cntSuccess ) + cc.error( ") and timeout reached, error details: " ) + - cc.warning( err ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - details.close(); - details = null; - } ); - } - } catch ( err ) { - const strErrorMessage = cc.error( "Failed BLS sign due to generic flow exception: " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - if( details ) - details.write( strErrorMessage ); - if( ! bHaveResultReportCalled ) { - bHaveResultReportCalled = true; - await fn( "Failed BLS sign due to exception: " + err.toString(), jarrMessages, null ).catch( ( err ) => { - const strErrorMessage = cc.error( "Failed BLS sign due to error-erporting callback exception: " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - if( details ) { - details.write( strErrorMessage ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - details.close(); - } - } ); - } - } - log.write( strGatheredDetailsName + " completed" ); - details.write( strGatheredDetailsName + " completed" ); - if( details ) { - details.exposeDetailsTo( log, strGatheredDetailsName, true ); - details.close(); - } -} - -async function do_sign_messages_m2s( - nTransferLoopCounter, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joExtraSignOpts, - fn -) { - return await do_sign_messages_impl( - nTransferLoopCounter, - "M2S", - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joExtraSignOpts, - fn - ); -} - -async function do_sign_messages_s2m( - nTransferLoopCounter, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joExtraSignOpts, - fn -) { - return await do_sign_messages_impl( - nTransferLoopCounter, - "S2M", - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joExtraSignOpts, - fn - ); -} - -async function do_sign_messages_s2s( - nTransferLoopCounter, - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joExtraSignOpts, - fn -) { - return await do_sign_messages_impl( - nTransferLoopCounter, - "S2S", - jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, - joExtraSignOpts, - fn - ); -} - -async function do_sign_u256( u256, details, fn ) { - const strLogPrefix = cc.info( "Sign u256:" ) + " "; - log.write( strLogPrefix + cc.debug( "Invoking signing u256 procedure " ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Invoking signing u256 procedure " ) + "\n" ); - fn = fn || function() {}; - if( !( /*imaState.bSignMessages &&*/ imaState.strPathBlsGlue.length > 0 && imaState.joSChainNetworkInfo ) ) { - details.write( strLogPrefix + cc.debug( "BLS u256 signing is " ) + cc.error( "unavailable" ) + "\n" ); - await fn( "BLS u256 signing is unavailable", u256, null ); - return; - } - // - // sign result looks like: - // { - // "id": 1, "jsonrpc": "2.0", "result": { - // "signResult": { - // "errorMessage": "", - // "signatureShare": "13888409666804046853490114813821624491836407617931905586112520275264817002720:9871589266312476278322587556340871982939135237123140475925975407511373249165:0", - // "status": 0 - // } - // } - // } - // - details.write( strLogPrefix + cc.debug( "Will sign " ) + cc.info( u256 ) + cc.debug( " value..." ) + "\n" ); - log.write( strLogPrefix + cc.debug( "Will sign " ) + cc.info( u256 ) + cc.debug( " value..." ) + "\n" ); - const joGatheringTracker = { - nCountReceived: 0, // including errors - nCountErrors: 0, - nCountSkipped: 0, - nWaitIntervalStepMilliseconds: 100, - nWaitIntervalStepsDone: 0, - nWaitIntervalMaxSteps: 10 * 60 * 3 // 10 is 1 second - }; - const arrSignResults = []; - const jarrNodes = imaState.joSChainNetworkInfo.network; - details.write( strLogPrefix + cc.debug( "Will query to sign " ) + cc.info( jarrNodes.length ) + cc.debug( " skaled node(s)..." ) + "\n" ); - const nThreshold = discover_bls_threshold( imaState.joSChainNetworkInfo ); - const nParticipants = discover_bls_participants( imaState.joSChainNetworkInfo ); - details.write( strLogPrefix + cc.debug( "Discovered BLS threshold is " ) + cc.info( nThreshold ) + cc.debug( "." ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + cc.info( nParticipants ) + cc.debug( "." ) + "\n" ); - if( nThreshold <= 0 ) { - await fn( "signature error(1, u256), S-Chain information was not discovered properly and BLS threshold is unknown", u256, null ); - return; - } - const nCountOfBlsPartsToCollect = 0 + nThreshold; - // if( nThreshold <= 1 && nParticipants > 1 ) { - // details.write( strLogPrefix + cc.warning( "Minimal BLS parts number for dicovery was increased." ) + "\n" ); - // nCountOfBlsPartsToCollect = 2; - // } - log.write( strLogPrefix + cc.debug( "Will(u256) collect " ) + cc.info( nCountOfBlsPartsToCollect ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Will(u256) collect " ) + cc.info( nCountOfBlsPartsToCollect ) + cc.debug( " from " ) + cc.info( jarrNodes.length ) + cc.debug( " nodes" ) + "\n" ); - for( let i = 0; i < jarrNodes.length; ++i ) { - const joNode = jarrNodes[i]; - const strNodeURL = imaUtils.compose_schain_node_url( joNode ); - const strNodeDescColorized = cc.u( strNodeURL ) + " " + - cc.normal( "(" ) + cc.bright( i ) + cc.normal( "/" ) + cc.bright( jarrNodes.length ) + cc.normal( ", ID " ) + cc.info( joNode.nodeID ) + cc.normal( ")" ); - const rpcCallOpts = null; - await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - ++joGatheringTracker.nCountReceived; // including errors - ++joGatheringTracker.nCountErrors; - const strErrorMessage = - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + - cc.error( " failed, RPC call was not created, error: " ) + cc.warning( err ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - return; - } - details.write( - strLogPrefix + cc.debug( "Will invoke " ) + cc.info( "skale_imaBSU256" ) + - cc.debug( " for to sign value " ) + cc.info( u256.toString() ) + - "\n" ); - await joCall.call( { - method: "skale_imaBSU256", - params: { - valueToSign: u256 - } - }, async function( joIn, joOut, err ) { - ++joGatheringTracker.nCountReceived; // including errors - if( err ) { - ++joGatheringTracker.nCountErrors; - const strErrorMessage = - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + - cc.error( " failed, RPC call reported error: " ) + cc.warning( err ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - return; - } - details.write( - strLogPrefix + cc.debug( "Did invoked " ) + cc.info( "skale_imaBSU256" ) + - cc.debug( " for to sign value " ) + cc.info( u256.toString() ) + - cc.debug( ", answer is: " ) + cc.j( joOut ) + - "\n" ); - if( joOut.result == null || joOut.result == undefined || ( !typeof joOut.result == "object" ) ) { - ++joGatheringTracker.nCountErrors; - if( "error" in joOut && "message" in joOut.error ) { - const strErrorMessage = - strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + - cc.error( "S-Chain node " ) + strNodeDescColorized + - cc.error( " reported wallet error: " ) + cc.warning( joOut.error.message ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } else { - const strErrorMessage = - strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + - cc.error( "JSON RPC call to S-Chain node " ) + strNodeDescColorized + - cc.error( " failed with " ) + cc.warning( "unknown wallet error" ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - return; - } - details.write( strLogPrefix + cc.normal( "Node " ) + cc.info( joNode.nodeID ) + cc.normal( " sign result: " ) + cc.j( joOut.result ? joOut.result : null ) + "\n" ); - try { - if( joOut.result.signResult.signatureShare.length > 0 && joOut.result.signResult.status === 0 ) { - const nZeroBasedNodeIndex = joNode.imaInfo.thisNodeIndex - 1; - // - // partial BLS verification for one participant - // - let bNodeSignatureOKay = false; // initially assume signature is wrong - const strLogPrefixA = cc.info( "BLS" ) + cc.debug( "/" ) + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + cc.debug( ":" ) + " "; - try { - const cntSuccess = joGatheringTracker.nCountReceived - joGatheringTracker.nCountErrors; - if( cntSuccess > nCountOfBlsPartsToCollect ) { - ++joGatheringTracker.nCountSkipped; - details.write( strLogPrefixA + - cc.debug( "Will ignore sign result for node " ) + cc.info( nZeroBasedNodeIndex ) + - cc.debug( " because " ) + cc.info( nThreshold ) + cc.debug( "/" ) + cc.info( nCountOfBlsPartsToCollect ) + - cc.debug( " threshold number of BLS signature parts already gathered" ) + - "\n" ); - return; - } - const arrTmp = joOut.result.signResult.signatureShare.split( ":" ); - const joResultFromNode = { - index: "" + nZeroBasedNodeIndex, - signature: { - X: arrTmp[0], - Y: arrTmp[1] - } - }; - details.write( strLogPrefixA + cc.info( "Will verify sign result for node " ) + cc.info( nZeroBasedNodeIndex ) + "\n" ); - const joPublicKey = discover_public_key_by_index( nZeroBasedNodeIndex, imaState.joSChainNetworkInfo ); - if( perform_bls_verify_i_u256( details, nZeroBasedNodeIndex, joResultFromNode, u256, joPublicKey ) ) { - details.write( strLogPrefixA + cc.success( "Got successful BLS verification result for node " ) + cc.info( joNode.nodeID ) + cc.success( " with index " ) + cc.info( nZeroBasedNodeIndex ) + "\n" ); - bNodeSignatureOKay = true; // node verification passed - } else { - const strError = "BLS u256 one node verify failed"; - details.write( strLogPrefixA + cc.fatal( "CRITICAL ERROR:" ) + " " + cc.error( strError ) + "\n" ); - } - } catch ( err ) { - const strErrorMessage = - strLogPrefixA + cc.error( "S-Chain node " ) + strNodeDescColorized + cc.error( " sign " ) + - cc.error( " CRITICAL ERROR:" ) + cc.error( " partial signature fail from with index " ) + cc.info( nZeroBasedNodeIndex ) + - cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - // - // sign result for bls_glue should look like: - // { - // "index": "1", - // "signature": { - // "X": "8184471694634630119550127539973704769190648951089883109386639469590492862134", - // "Y": "4773775435244318964726085856452691379381914783621253742616578726383405809710" - // } - // } - // - if( bNodeSignatureOKay ) { - arrSignResults.push( { - index: "" + nZeroBasedNodeIndex, - signature: split_signature_share( joOut.result.signResult.signatureShare ), - fromNode: joNode, // extra, not needed for bls_glue - signResult: joOut.result.signResult - } ); - } else - ++joGatheringTracker.nCountErrors; - } - } catch ( err ) { - ++nCountErrors; - const strErrorMessage = - strLogPrefix + cc.error( "S-Chain node " ) + strNodeDescColorized + " " + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " signature fail from node " ) + cc.info( joNode.nodeID ) + - cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - } ); // joCall.call ... - } ); // rpcCall.create ... - } - - log.write( strLogPrefix + cc.debug( "Waiting for BLS glue result " ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Waiting for BLS glue result " ) + "\n" ); - errGathering = null; - const promise_gathering_complete = new Promise( ( resolve, reject ) => { - const iv = setInterval( function() { - ++ joGatheringTracker.nWaitIntervalStepsDone; - const cntSuccess = joGatheringTracker.nCountReceived - joGatheringTracker.nCountErrors; - if( cntSuccess >= nCountOfBlsPartsToCollect ) { - const strLogPrefixB = cc.info( "BLS u256" ) + cc.debug( "/" ) + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; - clearInterval( iv ); - let strError = null, strSuccessfulResultDescription = null; - const joGlueResult = perform_bls_glue_u256( details, u256, arrSignResults ); - if( joGlueResult ) { - details.write( strLogPrefixB + cc.success( "Got BLS glue u256 result: " ) + cc.j( joGlueResult ) + "\n" ); - if( imaState.strPathBlsVerify.length > 0 ) { - const joCommonPublicKey = discover_common_public_key( imaState.joSChainNetworkInfo ); - // console.log(joCommonPublicKey); - if( perform_bls_verify_u256( details, joGlueResult, u256, joCommonPublicKey ) ) { - strSuccessfulResultDescription = "Got successful summary BLS u256 verification result"; - details.write( strLogPrefixB + cc.success( strSuccessfulResultDescription ) + "\n" ); - } else { - strError = "BLS verify failed"; - log.write( strLogPrefixB + cc.fatal( "CRITICAL ERROR:" ) + cc.error( strError ) + "\n" ); - details.write( strLogPrefixB + cc.fatal( "CRITICAL ERROR:" ) + cc.error( strError ) + "\n" ); - } - } - } else { - strError = "BLS u256 glue failed, no glue result arrived"; - const strErrorMessage = - strLogPrefixB + cc.error( "Problem(1) in BLS u256 sign result handler: " ) + cc.warning( strError ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } - log.write( cc.debug( "Will call sending function (fn)" ) + "\n" ); - details.write( cc.debug( "Will call sending function (fn) for " ) + "\n" ); - /*await*/ fn( strError, u256, joGlueResult ).catch( ( err ) => { - const strErrorMessage = cc.error( "Problem(2) in BLS u256 sign result handler: " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - errGathering = "Problem(2) in BLS u256 sign result handler: " + err.toString(); - } ); - if( strError ) { - errGathering = strError; - reject( new Error( errGathering ) ); - } else - resolve(); - return; - } - if( joGatheringTracker.nCountReceived >= jarrNodes.length ) { - clearInterval( iv ); - /*await*/ fn( "signature error(2, u256), got " + joGatheringTracker.nCountErrors + " errors(s) for " + jarrNodes.length + " node(s)", u256, null ).catch( ( err ) => { - const strErrorMessage = - cc.error( "Problem(3) in BLS u256 sign result handler, not enough successful BLS signature parts(" ) + - cc.info( cntSuccess ) + cc.error( " when all attempts done, error details: " ) + cc.warning( err.toString() ) + - "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - errGathering = - "Problem(3) in BLS u256 sign result handler, not enough successful BLS signature parts(" + - cntSuccess + " when all attempts done, error details: " + err.toString(); - reject( new Error( errGathering ) ); - } ); - return; - } - if( joGatheringTracker.nWaitIntervalStepsDone >= joGatheringTracker.nWaitIntervalMaxSteps ) { - clearInterval( iv ); - /*await*/ fn( "signature error(3, u256), got " + joGatheringTracker.nCountErrors + " errors(s) for " + jarrNodes.length + " node(s)", u256, null ).catch( ( err ) => { - const strErrorMessage = - cc.error( "Problem(4) in BLS u256 sign result handler, not enough successful BLS signature parts(" ) + - cc.info( cntSuccess ) + cc.error( ") and timeout reached, error details: " ) + - cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - errGathering = - "Problem(4) in BLS u256 sign result handler, not enough successful BLS signature parts(" + - cntSuccess + ") and timeout reached, error details: " + err.toString(); - reject( new Error( errGathering ) ); - } ); - return; - } - }, joGatheringTracker.nWaitIntervalStepMilliseconds ); - } ); - details.write( cc.debug( "Will await BLS u256 sign result..." ) + "\n" ); - log.write( cc.debug( "Will await BLS u256 sign result..." ) + "\n" ); - await with_timeout( "BLS u256 sign", promise_gathering_complete, g_secondsMessageVerifySendTimeout ).then( strSuccessfulResultDescription => { - details.write( cc.info( "BLS u256 sign promise awaited." ) + "\n" ); - log.write( cc.info( "BLS u256 sign promise awaited." ) + "\n" ); - } ).catch( err => { - const strErrorMessage = cc.error( "Failed to verify BLS and send message : " ) + cc.warning( err.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - } ); - if( errGathering ) { - const strErrorMessage = cc.error( "Failed BLS u256 sign result awaiting: " ) + cc.warning( errGathering.toString() ) + "\n"; - log.write( strErrorMessage ); - details.write( strErrorMessage ); - return; - } - log.write( strLogPrefix + cc.debug( "Completed signing u256 procedure " ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Completed signing u256 procedure " ) + "\n" ); -} - -module.exports = { - init: init, - do_sign_messages_m2s: do_sign_messages_m2s, - do_sign_messages_s2m: do_sign_messages_s2m, - do_sign_messages_s2s: do_sign_messages_s2s, - do_sign_u256: do_sign_u256 -}; // module.exports diff --git a/agent/bls.mjs b/agent/bls.mjs new file mode 100644 index 000000000..0feaa2174 --- /dev/null +++ b/agent/bls.mjs @@ -0,0 +1,3130 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file bls.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as fs from "fs"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as childProcessModule from "child_process"; +import * as rpcCall from "./rpcCall.mjs"; +import * as shellModule from "shelljs"; +import * as imaUtils from "./utils.mjs"; +import * as sha3Module from "sha3"; +import * as skaleObserver from "../npms/skale-observer/observer.mjs"; + +import * as state from "./state.mjs"; +import { randomCallID } from "../npms/skale-cool-socket/socketUtils.mjs"; + +const shell = shellModule.default; + +const Keccak = sha3Module.Keccak; + +const sleep = + ( milliseconds ) => { return new Promise( resolve => setTimeout( resolve, milliseconds ) ); }; + +const gSecondsMessageVerifySendTimeout = 2 * 60; + +async function withTimeout( strDescription, promise, seconds ) { + strDescription = strDescription || "withTimeout()"; + let resultError = null, isComplete = false; + promise.catch( function( err ) { + isComplete = true; + resultError = + new Error( strDescription + "error: " + owaspUtils.extractErrorMessage( err ) ); + } ).finally( function() { + isComplete = true; + } ); + for( let idxWaitStep = 0; idxWaitStep < seconds; ++ idxWaitStep ) { + if( isComplete ) + break; + await sleep( 1000 ); + } + if( resultError ) + throw resultError; + if( ! isComplete ) + throw new Error( strDescription + " reached limit of " + seconds + " second(s)" ); +}; + +function discoverBlsThreshold( joSChainNetworkInfo ) { + const imaState = state.get(); + joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; + if( ! joSChainNetworkInfo ) + return -1; + const jarrNodes = joSChainNetworkInfo.network; + for( let i = 0; i < jarrNodes.length; ++i ) { + const joNode = jarrNodes[i]; + if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && + "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" && + joNode.imaInfo.t > 0 + ) + return joNode.imaInfo.t; + } + return -1; +} + +function discoverBlsParticipants( joSChainNetworkInfo ) { + const imaState = state.get(); + joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; + if( ! joSChainNetworkInfo ) + return -1; + const jarrNodes = joSChainNetworkInfo.network; + for( let i = 0; i < jarrNodes.length; ++i ) { + const joNode = jarrNodes[i]; + if( joNode && "imaInfo" in joNode && + typeof joNode.imaInfo === "object" && + "n" in joNode.imaInfo && + typeof joNode.imaInfo.n === "number" && + joNode.imaInfo.n > 0 + ) + return joNode.imaInfo.n; + } + return -1; +} + +function discoverPublicKeyByIndex( nNodeIndex, joSChainNetworkInfo ) { + const imaState = state.get(); + joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; + const jarrNodes = joSChainNetworkInfo.network; + const joNode = jarrNodes[nNodeIndex]; + if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && + "BLSPublicKey0" in joNode.imaInfo && + typeof joNode.imaInfo.BLSPublicKey0 === "string" && + joNode.imaInfo.BLSPublicKey0.length > 0 && + "BLSPublicKey1" in joNode.imaInfo && + typeof joNode.imaInfo.BLSPublicKey1 === "string" && + joNode.imaInfo.BLSPublicKey1.length > 0 && + "BLSPublicKey2" in joNode.imaInfo && + typeof joNode.imaInfo.BLSPublicKey2 === "string" && + joNode.imaInfo.BLSPublicKey2.length > 0 && + "BLSPublicKey3" in joNode.imaInfo && + typeof joNode.imaInfo.BLSPublicKey3 === "string" && + joNode.imaInfo.BLSPublicKey3.length > 0 + ) { + return { + BLSPublicKey0: joNode.imaInfo.BLSPublicKey0, + BLSPublicKey1: joNode.imaInfo.BLSPublicKey1, + BLSPublicKey2: joNode.imaInfo.BLSPublicKey2, + BLSPublicKey3: joNode.imaInfo.BLSPublicKey3 + }; + } + return null; +} + +function discoverCommonPublicKey( joSChainNetworkInfo ) { + const imaState = state.get(); + joSChainNetworkInfo = joSChainNetworkInfo || imaState.joSChainNetworkInfo; + const jarrNodes = joSChainNetworkInfo.network; + for( let i = 0; i < jarrNodes.length; ++i ) { + const joNode = jarrNodes[i]; + if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && + "commonBLSPublicKey0" in joNode.imaInfo && + typeof joNode.imaInfo.commonBLSPublicKey0 === "string" && + joNode.imaInfo.commonBLSPublicKey0.length > 0 && + "commonBLSPublicKey1" in joNode.imaInfo && + typeof joNode.imaInfo.commonBLSPublicKey1 === "string" && + joNode.imaInfo.commonBLSPublicKey1.length > 0 && + "commonBLSPublicKey2" in joNode.imaInfo && + typeof joNode.imaInfo.commonBLSPublicKey2 === "string" && + joNode.imaInfo.commonBLSPublicKey2.length > 0 && + "commonBLSPublicKey3" in joNode.imaInfo && + typeof joNode.imaInfo.commonBLSPublicKey3 === "string" && + joNode.imaInfo.commonBLSPublicKey3.length > 0 + ) { + return { + commonBLSPublicKey0: joNode.imaInfo.commonBLSPublicKey0, + commonBLSPublicKey1: joNode.imaInfo.commonBLSPublicKey1, + commonBLSPublicKey2: joNode.imaInfo.commonBLSPublicKey2, + commonBLSPublicKey3: joNode.imaInfo.commonBLSPublicKey3 + }; + } + } + return null; +} + +function hexPrepare( strHex, isInvertBefore, isInvertAfter ) { + if( isInvertBefore == undefined ) + isInvertBefore = true; + if( isInvertAfter == undefined ) + isInvertAfter = true; + let arrBytes = imaUtils.hexToBytes( strHex ); + if( isInvertBefore ) + arrBytes = arrBytes.reverse(); + arrBytes = imaUtils.bytesAlignLeftWithZeroes( arrBytes, 32 ); + if( isInvertAfter ) + arrBytes = arrBytes.reverse(); + return arrBytes; +} + +function stringToKeccak256( s ) { + const strU256 = owaspUtils.ethersMod.ethers.utils.id( s ); + return hexPrepare( strU256, true, true ); +} + +function arrayToKeccak256( arrBytes ) { + const k = new Keccak( 256 ); + k.update( imaUtils.toBuffer( arrBytes ) ); + const h = k.digest( "hex" ); + return imaUtils.hexToBytes( "0x" + h ); +} + +function keccak256Message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) { + let arrBytes = stringToKeccak256( strFromChainName ); + arrBytes = imaUtils.bytesConcat( + arrBytes, + hexPrepare( + owaspUtils.ensureStartsWith0x( nIdxCurrentMsgBlockStart.toString( 16 ) ), + false, + false + ) + ); + arrBytes = arrayToKeccak256( arrBytes ); + const cnt = jarrMessages.length; + for( let i = 0; i < cnt; ++i ) { + const joMessage = jarrMessages[i]; + + let bytesSender = imaUtils.hexToBytes( joMessage.sender.toString() ); + bytesSender = imaUtils.bytesAlignLeftWithZeroes( bytesSender, 32 ); + arrBytes = imaUtils.bytesConcat( arrBytes, bytesSender ); + + let bytesDestinationContract = + imaUtils.hexToBytes( joMessage.destinationContract ); + bytesDestinationContract = + imaUtils.bytesAlignLeftWithZeroes( bytesDestinationContract, 32 ); + arrBytes = imaUtils.bytesConcat( arrBytes, bytesDestinationContract ); + + const bytesData = imaUtils.hexToBytes( joMessage.data ); + arrBytes = imaUtils.bytesConcat( arrBytes, bytesData ); + arrBytes = arrayToKeccak256( arrBytes ); + } + return owaspUtils.ensureStartsWith0x( imaUtils.bytesToHex( arrBytes, false ) ); +} + +export function keccak256U256( u256, isHash ) { + let arrBytes = new Uint8Array(); + + let bytesU256 = imaUtils.hexToBytes( u256 ); + bytesU256 = bytesU256.reverse(); + bytesU256 = imaUtils.bytesAlignLeftWithZeroes( bytesU256, 32 ); + bytesU256 = bytesU256.reverse(); + arrBytes = imaUtils.bytesConcat( arrBytes, bytesU256 ); + + let strMessageHash = ""; + if( isHash ) { + const hash = new Keccak( 256 ); + hash.update( imaUtils.toBuffer( arrBytes ) ); + strMessageHash = hash.digest( "hex" ); + } else + strMessageHash = "0x" + imaUtils.bytesToHex( arrBytes ); + return strMessageHash; +} + +export function keccak256ForPendingWorkAnalysis( nNodeNumber, strLoopWorkType, isStart, ts ) { + let arrBytes = new Uint8Array(); + + let bytesU256 = imaUtils.hexToBytes( nNodeNumber ); + bytesU256 = bytesU256.reverse(); + bytesU256 = imaUtils.bytesAlignLeftWithZeroes( bytesU256, 32 ); + bytesU256 = bytesU256.reverse(); + arrBytes = imaUtils.bytesConcat( arrBytes, bytesU256 ); + + arrBytes = imaUtils.bytesConcat( arrBytes, stringToKeccak256( strLoopWorkType ) ); + + bytesU256 = imaUtils.hexToBytes( isStart ? 1 : 0 ); + bytesU256 = bytesU256.reverse(); + bytesU256 = imaUtils.bytesAlignLeftWithZeroes( bytesU256, 32 ); + bytesU256 = bytesU256.reverse(); + arrBytes = imaUtils.bytesConcat( arrBytes, bytesU256 ); + + bytesU256 = imaUtils.hexToBytes( ts ); + bytesU256 = bytesU256.reverse(); + bytesU256 = imaUtils.bytesAlignLeftWithZeroes( bytesU256, 32 ); + bytesU256 = bytesU256.reverse(); + arrBytes = imaUtils.bytesConcat( arrBytes, bytesU256 ); + + const hash = new Keccak( 256 ); + hash.update( imaUtils.toBuffer( arrBytes ) ); + const strMessageHash = hash.digest( "hex" ); + return strMessageHash; +} + +function splitSignatureShare( signatureShare ) { + const jarr = signatureShare.split( ":" ); + return { + X: jarr[0], + Y: jarr[1] + }; +} + +function getBlsGlueTmpDir() { + const strTmpDir = "/tmp/ima-bls-glue"; + shell.mkdir( "-p", strTmpDir ); + return strTmpDir; +} + +function allocBlsTmpActionDir() { + const strActionDir = + getBlsGlueTmpDir() + "/" + imaUtils.replaceAll( imaUtils.uuid(), "-", "" ); + if( ! fs.existsSync( strActionDir ) ) + fs.mkdirSync( strActionDir , { recursive: true } ); + return strActionDir; +} + +function performBlsGlue( + details, + strDirection, + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + arrSignResults +) { + const imaState = state.get(); + const strLogPrefix = + cc.bright( strDirection ) + cc.debug( "/" ) + + cc.info( "BLS" ) + cc.debug( "/" ) + + cc.attention( "Glue" ) + cc.debug( ":" ) + " "; + let joGlueResult = null; + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "Discovered BLS threshold is " ) + + cc.info( nThreshold ) + cc.debug( "." ) + "\n" ); + details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + + cc.info( nParticipants ) + cc.debug( "." ) + "\n" ); + } + const strMessageHash = + owaspUtils.removeStarting0x( + keccak256Message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) + ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "Message hash to sign is " ) + + cc.info( strMessageHash ) + "\n" ); + } + const strActionDir = allocBlsTmpActionDir(); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "performBlsGlue will work in " ) + + cc.info( strActionDir ) + cc.debug( " director with " ) + + cc.info( arrSignResults.length ) + cc.debug( " sign results..." ) + "\n" ); + } + const fnShellRestore = function() { + shell.rm( "-rf", strActionDir ); + }; + let strOutput = ""; + try { + let strInput = ""; + const cnt = arrSignResults.length; + for( let i = 0; i < cnt; ++i ) { + const jo = arrSignResults[i]; + const strPath = strActionDir + "/sign-result" + jo.index + ".json"; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Saving " ) + cc.notice( strPath ) + + cc.debug( " file containing " ) + cc.j( jo ) + "\n" ); + } + imaUtils.jsonFileSave( strPath, jo ); + strInput += " --input " + strPath; + } + const strGlueCommand = + imaState.strPathBlsGlue + + " --t " + nThreshold + + " --n " + nParticipants + + strInput + + " --output " + strActionDir + "/glue-result.json"; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute BLS glue command:\n" ) + + cc.notice( strGlueCommand ) + "\n" ); + } + strOutput = childProcessModule.execSync( strGlueCommand, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS glue output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + joGlueResult = imaUtils.jsonFileLoad( strActionDir + "/glue-result.json" ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS glue result is: " ) + + cc.j( joGlueResult ) + "\n" ); + } + if( "X" in joGlueResult.signature && "Y" in joGlueResult.signature ) { + if( log.verboseGet() >= log.verboseReversed().debug ) + details.write( strLogPrefix + cc.success( "BLS glue success" ) + "\n" ); + joGlueResult.hashSrc = strMessageHash; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Computing " ) + cc.info( "G1" ) + + cc.debug( " hash point..." ) + "\n" ); + } + const strPath = strActionDir + "/hash.json"; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Saving " ) + cc.notice( strPath ) + + cc.debug( " file..." ) + "\n" ); + } + imaUtils.jsonFileSave( strPath, { "message": strMessageHash } ); + const strHasG1Command = + imaState.strPathHashG1 + + " --t " + nThreshold + + " --n " + nParticipants; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute HashG1 command:\n" ) + + cc.notice( strHasG1Command ) + "\n" ); + } + strOutput = childProcessModule.execSync( strHasG1Command, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "HashG1 output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + const joResultHashG1 = imaUtils.jsonFileLoad( strActionDir + "/g1.json" ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "HashG1 result is: " ) + + cc.j( joResultHashG1 ) + "\n" ); + } + if( "g1" in joResultHashG1 && + "hint" in joResultHashG1.g1 && + "hashPoint" in joResultHashG1.g1 && + "X" in joResultHashG1.g1.hashPoint && + "Y" in joResultHashG1.g1.hashPoint + ) { + joGlueResult.hashPoint = joResultHashG1.g1.hashPoint; + joGlueResult.hint = joResultHashG1.g1.hint; + } else { + joGlueResult = null; + throw new Error( "malformed HashG1 result: " + JSON.stringify( joResultHashG1 ) ); + } + } else { + const joSavedGlueResult = joGlueResult; + joGlueResult = null; + throw new Error( "malformed BLS glue result: " + JSON.stringify( joSavedGlueResult ) ); + } + fnShellRestore(); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s1 = strLogPrefix + + cc.fatal( "BLS glue CRITICAL ERROR:" ) + cc.error( " error description is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + const s2 = strLogPrefix + + cc.error( "BLS glue output is:\n" ) + cc.notice( strOutput ) + + "\n"; + details.write( s1 ); + details.write( s2 ); + } + fnShellRestore(); + joGlueResult = null; + } + return joGlueResult; +} + +function performBlsGlueU256( details, u256, arrSignResults ) { + const imaState = state.get(); + const strLogPrefix = + cc.info( "BLS" ) + cc.debug( "/" ) + cc.attention( "Glue" ) + + cc.debug( ":" ) + " "; + let joGlueResult = null; + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "Discovered BLS threshold is " ) + + cc.info( nThreshold ) + cc.debug( "." ) + "\n" ); + details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + + cc.info( nParticipants ) + cc.debug( "." ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Original long message is " ) + + cc.info( keccak256U256( u256, false ) ) + "\n" ); + } + const strMessageHash = keccak256U256( u256, true ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Message hash to sign is " ) + + cc.info( strMessageHash ) + "\n" ); + } + const strActionDir = allocBlsTmpActionDir(); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "performBlsGlueU256 will work in " ) + + cc.info( strActionDir ) + cc.debug( " director with " ) + + cc.info( arrSignResults.length ) + cc.debug( " sign results..." ) + "\n" ); + } + const fnShellRestore = function() { + shell.rm( "-rf", strActionDir ); + }; + let strOutput = ""; + try { + let strInput = ""; + const cnt = arrSignResults.length; + for( let i = 0; i < cnt; ++i ) { + const jo = arrSignResults[i]; + const strPath = strActionDir + "/sign-result" + jo.index + ".json"; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Saving " ) + cc.notice( strPath ) + + cc.debug( " file..." ) + "\n" ); + } + imaUtils.jsonFileSave( strPath, jo ); + strInput += " --input " + strPath; + } + const strGlueCommand = + imaState.strPathBlsGlue + + " --t " + nThreshold + + " --n " + nParticipants + + strInput + + " --output " + strActionDir + "/glue-result.json"; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute BLS glue command:\n" ) + + cc.notice( strGlueCommand ) + "\n" ); + } + strOutput = childProcessModule.execSync( strGlueCommand, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS glue output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + joGlueResult = imaUtils.jsonFileLoad( strActionDir + "/glue-result.json" ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS glue result is: " ) + + cc.j( joGlueResult ) + "\n" ); + } + if( "X" in joGlueResult.signature && "Y" in joGlueResult.signature ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + details.write( strLogPrefix + cc.success( "BLS glue success" ) + "\n" ); + joGlueResult.hashSrc = strMessageHash; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Computing " ) + cc.info( "G1" ) + + cc.debug( " hash point..." ) + "\n" ); + } + const strPath = strActionDir + "/hash.json"; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Saving " ) + cc.notice( strPath ) + + cc.debug( " file..." ) + "\n" ); + } + imaUtils.jsonFileSave( strPath, { "message": strMessageHash } ); + const strHasG1Command = + imaState.strPathHashG1 + + " --t " + nThreshold + + " --n " + nParticipants; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute HashG1 command:\n" ) + + cc.notice( strHasG1Command ) + "\n" ); + } + strOutput = childProcessModule.execSync( strHasG1Command, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "HashG1 output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + const joResultHashG1 = imaUtils.jsonFileLoad( strActionDir + "/g1.json" ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "HashG1 result is: " ) + + cc.j( joResultHashG1 ) + "\n" ); + } + if( "g1" in joResultHashG1 && + "hint" in joResultHashG1.g1 && + "hashPoint" in joResultHashG1.g1 && + "X" in joResultHashG1.g1.hashPoint && + "Y" in joResultHashG1.g1.hashPoint + ) { + joGlueResult.hashPoint = joResultHashG1.g1.hashPoint; + joGlueResult.hint = joResultHashG1.g1.hint; + } else { + joGlueResult = null; + throw new Error( "malformed HashG1 result: " + JSON.stringify( joResultHashG1 ) ); + } + } else { + const joSavedGlueResult = joGlueResult; + joGlueResult = null; + throw new Error( "malformed BLS glue result: " + JSON.stringify( joSavedGlueResult ) ); + } + fnShellRestore(); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s1 = strLogPrefix + + cc.fatal( "BLS glue CRITICAL ERROR:" ) + cc.error( " error description is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n" + + cc.error( ", stack is: " ) + cc.stack( err.stack ) + + "\n"; + const s2 = strLogPrefix + + cc.error( "BLS glue output is:\n" ) + cc.notice( strOutput ) + + "\n"; + details.write( s1 ); + details.write( s2 ); + } + fnShellRestore(); + joGlueResult = null; + } + return joGlueResult; +} + +function performBlsVerifyI( + details, + strDirection, + nZeroBasedNodeIndex, + joResultFromNode, + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joPublicKey +) { + if( !joResultFromNode ) + return true; + const imaState = state.get(); + const strLogPrefix = + cc.bright( strDirection ) + cc.debug( "/" ) + cc.info( "BLS" ) + cc.debug( "/" ) + + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + cc.debug( ":" ) + " "; + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + const strActionDir = allocBlsTmpActionDir(); + const fnShellRestore = function() { + shell.rm( "-rf", strActionDir ); + }; + let strOutput = ""; + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - first message nonce is " ) + + cc.info( nIdxCurrentMsgBlockStart ) + "\n" ); + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - first source chain name is " ) + + cc.info( strFromChainName ) + "\n" ); + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - messages array " ) + + cc.j( jarrMessages ) + "\n" ); + } + const strMessageHash = + owaspUtils.removeStarting0x( + keccak256Message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - hashed verify message is " ) + + cc.info( strMessageHash ) + "\n" ); + } + const joMsg = { "message": strMessageHash }; + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - composed " ) + cc.j( joMsg ) + + cc.debug( " composed from " ) + cc.j( jarrMessages ) + cc.debug( " using glue " ) + + cc.j( joResultFromNode ) + cc.debug( " and public key " ) + cc.j( joPublicKey ) + + "\n" ); + } + const strSignResultFileName = strActionDir + "/sign-result" + nZeroBasedNodeIndex + ".json"; + imaUtils.jsonFileSave( strSignResultFileName, joResultFromNode ); + imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); + imaUtils.jsonFileSave( + strActionDir + "/BLS_keys" + nZeroBasedNodeIndex + ".json", joPublicKey ); + const strVerifyCommand = "" + + imaState.strPathBlsVerify + + " --t " + nThreshold + + " --n " + nParticipants + + " --j " + nZeroBasedNodeIndex + + " --input " + strSignResultFileName + ; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " BLS verify command:\n" ) + + cc.notice( strVerifyCommand ) + "\n" ); + } + strOutput = childProcessModule.execSync( strVerifyCommand, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " verify output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.success( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.success( " verify success" ) + "\n" ); + } + fnShellRestore(); + return true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s1 = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " BLS node " ) + + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.error( " verify error:" ) + + cc.warning( " error description is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + const s2 = strLogPrefix + + cc.error( "CRITICAL ERROR:" ) + cc.error( " BLS node " ) + + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + + cc.error( " verify output is:\n" ) + cc.notice( strOutput ) + + "\n"; + details.write( s1 ); + details.write( s2 ); + } + fnShellRestore(); + } + return false; +} + +function performBlsVerifyIU256( + details, + nZeroBasedNodeIndex, + joResultFromNode, + u256, + joPublicKey +) { + if( ! joResultFromNode ) + return true; + const imaState = state.get(); + const strLogPrefix = + cc.info( "BLS" ) + cc.debug( "/" ) + + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + + cc.debug( ":" ) + " "; + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + const strActionDir = allocBlsTmpActionDir(); + const fnShellRestore = function() { + shell.rm( "-rf", strActionDir ); + }; + let strOutput = ""; + try { + const joMsg = { "message": keccak256U256( u256, true ) }; + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "BLS u256 node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " verify message " ) + cc.j( joMsg ) + + cc.debug( " composed from " ) + cc.j( u256 ) + cc.debug( " using glue " ) + + cc.j( joResultFromNode ) + cc.debug( " and public key " ) + cc.j( joPublicKey ) + + "\n" ); + } + const strSignResultFileName = strActionDir + "/sign-result" + nZeroBasedNodeIndex + ".json"; + imaUtils.jsonFileSave( strSignResultFileName, joResultFromNode ); + imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); + imaUtils.jsonFileSave( + strActionDir + "/BLS_keys" + nZeroBasedNodeIndex + ".json", joPublicKey ); + const strVerifyCommand = "" + + imaState.strPathBlsVerify + + " --t " + nThreshold + + " --n " + nParticipants + + " --j " + nZeroBasedNodeIndex + + " --input " + strSignResultFileName + ; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " BLS u256 verify command:\n" ) + + cc.notice( strVerifyCommand ) + "\n" ); + } + strOutput = childProcessModule.execSync( strVerifyCommand, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS u256 node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " verify output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.success( "BLS u256 node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.success( " verify success" ) + "\n" ); + } + fnShellRestore(); + return true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s1 = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " BLS u256 node " ) + + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + + cc.error( " verify error:" ) + + cc.warning( " error description is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + const s2 = strLogPrefix + + cc.error( "CRITICAL ERROR:" ) + cc.error( " BLS u256 node " ) + + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + + cc.error( " verify output is:\n" ) + cc.notice( strOutput ) + + "\n"; + details.write( s1 ); + details.write( s2 ); + } + fnShellRestore(); + } + return false; +} + +function performBlsVerify( + details, + strDirection, + joGlueResult, + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joCommonPublicKey +) { + if( !joGlueResult ) + return true; + const imaState = state.get(); + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + const strActionDir = allocBlsTmpActionDir(); + const fnShellRestore = function() { + shell.rm( "-rf", strActionDir ); + }; + let strOutput = ""; + const strLogPrefix = + cc.bright( strDirection ) + cc.debug( "/" ) + + cc.info( "BLS" ) + cc.debug( "/" ) + + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS/summary verify message - " + + "first message nonce is " ) + cc.info( nIdxCurrentMsgBlockStart ) + "\n" ); + details.write( strLogPrefix + cc.debug( "BLS/summary verify message - " + + "first source chain name is " ) + cc.info( strFromChainName ) + "\n" ); + details.write( strLogPrefix + cc.debug( "BLS/summary verify message - " + + "messages array " ) + cc.j( jarrMessages ) + "\n" ); + } + const strMessageHash = + owaspUtils.removeStarting0x( + keccak256Message( jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName ) + ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS/summary verify message - " + + "hashed verify message is " ) + cc.info( strMessageHash ) + "\n" ); + } + const joMsg = { "message": strMessageHash }; + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "BLS/summary verify message - " + + "composed JSON " ) + cc.j( joMsg ) + cc.debug( " from messages array " ) + + cc.j( jarrMessages ) + cc.debug( " using glue " ) + cc.j( joGlueResult ) + + cc.debug( " and common public key " ) + cc.j( joCommonPublicKey ) + "\n" ); + } + imaUtils.jsonFileSave( strActionDir + "/glue-result.json", joGlueResult ); + imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); + const joCommonPublicKeyToSave = { + commonBLSPublicKey0: joCommonPublicKey.commonBLSPublicKey0, + commonBLSPublicKey1: joCommonPublicKey.commonBLSPublicKey1, + commonBLSPublicKey2: joCommonPublicKey.commonBLSPublicKey2, + commonBLSPublicKey3: joCommonPublicKey.commonBLSPublicKey3 + }; + imaUtils.jsonFileSave( strActionDir + "/common_public_key.json", joCommonPublicKeyToSave ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS common public key " + + "for verification is:\n" ) + cc.j( joCommonPublicKey ) + "\n" ); + } + const strVerifyCommand = "" + + imaState.strPathBlsVerify + + " --t " + nThreshold + + " --n " + nParticipants + + " --input " + "./glue-result.json" + ; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute BLS/summary verify command:\n" ) + + cc.notice( strVerifyCommand ) + "\n" ); + } + strOutput = childProcessModule.execSync( strVerifyCommand, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS/summary verify output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().debug ) + details.write( strLogPrefix + cc.success( "BLS/summary verify success" ) + "\n" ); + fnShellRestore(); + return true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s1 = strLogPrefix + + cc.fatal( "BLS/summary verify CRITICAL ERROR:" ) + + cc.error( " error description is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + const s2 = strLogPrefix + + cc.error( "BLS/summary verify output is:\n" ) + cc.notice( strOutput ) + "\n"; + details.write( s1 ); + details.write( s2 ); + } + fnShellRestore(); + } + return false; +} + +function performBlsVerifyU256( details, joGlueResult, u256, joCommonPublicKey ) { + if( !joGlueResult ) + return true; + const imaState = state.get(); + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + const strActionDir = allocBlsTmpActionDir(); + const fnShellRestore = function() { + shell.rm( "-rf", strActionDir ); + }; + let strOutput = ""; + const strLogPrefix = + cc.info( "BLS u256" ) + cc.debug( "/" ) + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; + try { + const joMsg = { "message": keccak256U256( u256, true ) }; + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "BLS u256/summary verify message " ) + + cc.j( joMsg ) + cc.debug( " composed from " ) + cc.j( u256 ) + + cc.debug( " using glue " ) + cc.j( joGlueResult ) + + cc.debug( " and common public key " ) + cc.j( joCommonPublicKey ) + "\n" ); + } + imaUtils.jsonFileSave( strActionDir + "/glue-result.json", joGlueResult ); + imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); + const joCommonPublicKeyToSave = { + commonBLSPublicKey0: joCommonPublicKey.commonBLSPublicKey0, + commonBLSPublicKey1: joCommonPublicKey.commonBLSPublicKey1, + commonBLSPublicKey2: joCommonPublicKey.commonBLSPublicKey2, + commonBLSPublicKey3: joCommonPublicKey.commonBLSPublicKey3 + }; + imaUtils.jsonFileSave( strActionDir + "/common_public_key.json", joCommonPublicKeyToSave ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS u256 common public key " + + "for verification is:\n" ) + cc.j( joCommonPublicKey ) + "\n" ); + } + const strVerifyCommand = "" + + imaState.strPathBlsVerify + + " --t " + nThreshold + + " --n " + nParticipants + + " --input " + "./glue-result.json" + ; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute BLS u256/summary " + + "verify command:\n" ) + cc.notice( strVerifyCommand ) + "\n" ); + } + strOutput = childProcessModule.execSync( strVerifyCommand, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS u256/summary verify output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().debug ) + details.write( strLogPrefix + cc.success( "BLS u256/summary verify success" ) + "\n" ); + fnShellRestore(); + return true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s1 = strLogPrefix + + cc.fatal( "BLS u256/summary verify CRITICAL ERROR:" ) + + cc.error( " error description is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + const s2 = strLogPrefix + + cc.error( "BLS u256/summary verify output is:\n" ) + + cc.notice( strOutput ) + + "\n"; + details.write( s1 ); + details.write( s2 ); + } + fnShellRestore(); + } + return false; +} + +async function checkCorrectnessOfMessagesToSign( + details, + strLogPrefix, + strDirection, + jarrMessages, + nIdxCurrentMsgBlockStart, + joExtraSignOpts +) { + const imaState = state.get(); + let joMessageProxy = null, joAccount = null, joChainName = null; + if( strDirection == "M2S" ) { + joMessageProxy = imaState.joMessageProxyMainNet; + joAccount = imaState.chainProperties.mn.joAccount; + joChainName = imaState.chainProperties.sc.strChainName; + } else if( strDirection == "S2M" ) { + joMessageProxy = imaState.joMessageProxySChain; + joAccount = imaState.chainProperties.sc.joAccount; + joChainName = imaState.chainProperties.mn.strChainName; + } else if( strDirection == "S2S" ) { + joAccount = imaState.chainProperties.sc.joAccount; + joChainName = joExtraSignOpts.chainNameDst; + const ethersProvider = + ( "ethersProviderSrc" in joExtraSignOpts && + joExtraSignOpts.ethersProviderSrc ) + ? joExtraSignOpts.ethersProviderSrc + : null + ; + if( ! ethersProvider ) { + throw new Error( + "CRITICAL ERROR: No provider specified in " + + "extra signing options for checking messages of direction \"" + + strDirection + "\"" ); + } + joMessageProxy = + new owaspUtils.ethersMod.ethers.Contract( + imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_address, + imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_abi, + ethersProvider + ); + } else { + throw new Error( + "CRITICAL ERROR: Failed checkCorrectnessOfMessagesToSign() " + + "with unknown direction \"" + strDirection + "\"" ); + } + + const strCallerAccountAddress = joAccount.address(); + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.bright( strDirection ) + + cc.debug( " message correctness validation through call to " ) + + cc.notice( "verifyOutgoingMessageData" ) + cc.debug( " method of " ) + + cc.bright( "MessageProxy" ) + cc.debug( " contract with address " ) + + cc.notice( joMessageProxy.address ) + cc.debug( ", caller account address is " ) + + cc.info( joMessageProxy.address ) + cc.debug( ", message(s) count is " ) + + cc.debug( ", have " ) + cc.info( jarrMessages.length ) + + cc.debug( " message(s) to process " ) + cc.j( jarrMessages ) + + cc.debug( ", first real message index is " ) + cc.info( nIdxCurrentMsgBlockStart ) + + cc.debug( ", messages will be sent to chain name " ) + cc.info( joChainName ) + + cc.debug( ", caller address is " ) + cc.info( strCallerAccountAddress ) + "\n" ); + } + let cntBadMessages = 0, i = 0; + const cnt = jarrMessages.length; + if( strDirection == "S2M" || strDirection == "S2S" ) { + for( i = 0; i < cnt; ++i ) { + const joMessage = jarrMessages[i]; + const idxMessage = nIdxCurrentMsgBlockStart + i; + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.bright( strDirection ) + + cc.debug( " Will validate message " ) + cc.info( i ) + cc.debug( " of " ) + + cc.info( cnt ) + cc.debug( ", real message index is " ) + + cc.info( idxMessage ) + cc.debug( ", source contract is " ) + + cc.info( joMessage.sender ) + cc.debug( ", destination contract is " ) + + cc.info( joMessage.destinationContract ) + + cc.debug( ", message data is " ) + cc.j( joMessage.data ) + "\n" ); + } + const outgoingMessageData = { + "dstChainHash": owaspUtils.ethersMod.ethers.utils.id( joChainName ), + "msgCounter": 0 + idxMessage, + "srcContract": joMessage.sender, + "dstContract": joMessage.destinationContract, + "data": joMessage.data + }; + const isValidMessage = await joMessageProxy.callStatic.verifyOutgoingMessageData( + outgoingMessageData, + { from: strCallerAccountAddress } + ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.bright( strDirection ) + + cc.debug( " Got verification call result " ) + cc.tf( isValidMessage ) + + cc.debug( ", real message index is: " ) + cc.info( idxMessage ) + + cc.debug( ", saved msgCounter is: " ) + + cc.info( outgoingMessageData.msgCounter ) + "\n" ); + } + if( !isValidMessage ) { + throw new Error( + "Bad message detected, message is: " + JSON.stringify( joMessage ) ); + } + } catch ( err ) { + ++cntBadMessages; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + strLogPrefix + cc.fatal( "BAD ERROR:" ) + " " + + cc.bright( strDirection ) + + cc.error( " Correctness validation failed for message " ) + + cc.info( idxMessage ) + + cc.error( " sent to " ) + cc.info( joChainName ) + + cc.error( ", message is: " ) + cc.j( joMessage ) + + cc.error( ", error information: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.id != details.id ) + log.write( strErrorMessage ); + details.write( strErrorMessage ); + } + } + } + } + // TODO: M2S - check events + if( cntBadMessages > 0 ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s = + strLogPrefix + cc.fatal( "BAD ERROR:" ) + + cc.error( " Correctness validation failed for " ) + cc.info( cntBadMessages ) + + cc.error( " of " ) + cc.info( cnt ) + cc.error( " message(s)" ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + } else { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.success( "Correctness validation passed for " ) + + cc.info( cnt ) + cc.success( " message(s)" ) + "\n" ); + } + } +} + +async function prepareSignMessagesImpl( optsSignOperation ) { + optsSignOperation.fn = optsSignOperation.fn || function() {}; + optsSignOperation.sequenceId = + owaspUtils.removeStarting0x( + owaspUtils.ethersMod.ethers.utils.id( log.generateTimestampString( null, false ) ) + ); + optsSignOperation.jarrNodes = + ( optsSignOperation.imaState.bSignMessages && + "joSChainNetworkInfo" in optsSignOperation.imaState && + typeof optsSignOperation.imaState.joSChainNetworkInfo == "object" && + "network" in optsSignOperation.imaState.joSChainNetworkInfo && + typeof optsSignOperation.imaState.joSChainNetworkInfo.network == "object" + ) + ? optsSignOperation.imaState.joSChainNetworkInfo.network + : []; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + cc.debug( " Invoking " ) + + cc.bright( optsSignOperation.strDirection ) + + cc.debug( " signing messages procedure, message signing is " ) + + cc.onOff( optsSignOperation.imaState.bSignMessages ) + "\n" ); + } + if( !( optsSignOperation.imaState.bSignMessages && + optsSignOperation.imaState.strPathBlsGlue.length > 0 && + optsSignOperation.imaState.joSChainNetworkInfo + ) ) { + optsSignOperation.bHaveResultReportCalled = true; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + cc.debug( "BLS message signing is " ) + cc.error( "turned off" ) + + cc.debug( ", first real message index is: " ) + + cc.info( optsSignOperation.nIdxCurrentMsgBlockStart ) + cc.debug( ", have " ) + + cc.info( optsSignOperation.jarrMessages.length ) + + cc.debug( " message(s) to process " ) + cc.j( optsSignOperation.jarrMessages ) + + "\n" ); + } + optsSignOperation.details.exposeDetailsTo( + log, optsSignOperation.strGatheredDetailsName, false ); + optsSignOperation.details.close(); + await checkCorrectnessOfMessagesToSign( + optsSignOperation.details, optsSignOperation.strLogPrefix, + optsSignOperation.strDirection, + optsSignOperation.jarrMessages, + optsSignOperation.nIdxCurrentMsgBlockStart, + optsSignOperation.joExtraSignOpts + ); + await optsSignOperation.fn( null, optsSignOperation.jarrMessages, null ); + return; + } + await checkCorrectnessOfMessagesToSign( + optsSignOperation.details, optsSignOperation.strLogPrefix, + optsSignOperation.strDirection, + optsSignOperation.jarrMessages, optsSignOperation.nIdxCurrentMsgBlockStart, + optsSignOperation.joExtraSignOpts + ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + cc.debug( "Will sign " ) + + cc.info( optsSignOperation.jarrMessages.length ) + cc.debug( " message(s)" ) + + cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + + cc.attention( optsSignOperation.sequenceId ) + cc.debug( "..." ) + "\n" ); + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + cc.debug( "Will query to sign " ) + cc.info( optsSignOperation.jarrNodes.length ) + + cc.debug( " skaled node(s)..." ) + "\n" ); + } + optsSignOperation.nThreshold = + discoverBlsThreshold( optsSignOperation.imaState.joSChainNetworkInfo ); + optsSignOperation.nParticipants = + discoverBlsParticipants( optsSignOperation.imaState.joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + cc.debug( "Discovered BLS threshold is " ) + cc.info( optsSignOperation.nThreshold ) + + cc.debug( "." ) + "\n" ); + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + cc.debug( "Discovered number of BLS participants is " ) + + cc.info( optsSignOperation.nParticipants ) + cc.debug( "." ) + "\n" ); + } + if( optsSignOperation.nThreshold <= 0 ) { + optsSignOperation.bHaveResultReportCalled = true; + optsSignOperation.details.exposeDetailsTo( + log, optsSignOperation.strGatheredDetailsName, false ); + optsSignOperation.details.close(); + await optsSignOperation.fn( + "signature error(1), S-Chain information " + + "was not discovered properly and BLS threshold is unknown", + optsSignOperation.jarrMessages, + null + ); + return; + } + optsSignOperation.nCountOfBlsPartsToCollect = 0 + optsSignOperation.nThreshold; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + cc.debug( "Will collect " ) + cc.info( optsSignOperation.nCountOfBlsPartsToCollect ) + + cc.debug( " from " ) + cc.info( optsSignOperation.jarrNodes.length ) + + cc.debug( " nodes" ) + cc.debug( ", " ) + cc.notice( "sequence ID" ) + + cc.debug( " is " ) + cc.attention( optsSignOperation.sequenceId ) + "\n" ); + } +} + +async function gatherSigningStartImpl( optsSignOperation ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + cc.debug( "Waiting for BLS glue result " ) + "\n" ); + } + optsSignOperation.errGathering = null; + optsSignOperation.promiseCompleteGathering = new Promise( ( resolve, reject ) => { + const iv = setInterval( function() { + ++ optsSignOperation.joGatheringTracker.nWaitIntervalStepsDone; + optsSignOperation.cntSuccess = + optsSignOperation.joGatheringTracker.nCountReceived - + optsSignOperation.joGatheringTracker.nCountErrors; + if( optsSignOperation.cntSuccess >= optsSignOperation.nCountOfBlsPartsToCollect ) { + optsSignOperation.strLogPrefixB = + cc.bright( optsSignOperation.strDirection ) + cc.debug( "/" ) + + cc.attention( "#" ) + cc.sunny( optsSignOperation.nTransferLoopCounter ) + + cc.debug( "/" ) + cc.info( "BLS" ) + + cc.debug( "/" ) + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; + clearInterval( iv ); + let strError = null, strSuccessfulResultDescription = null; + const joGlueResult = performBlsGlue( + optsSignOperation.details, optsSignOperation.strDirection, + optsSignOperation.jarrMessages, + optsSignOperation.nIdxCurrentMsgBlockStart, + optsSignOperation.strFromChainName, + optsSignOperation.arrSignResults + ); + if( joGlueResult ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefixB + + cc.success( "Got BLS glue result: " ) + cc.j( joGlueResult ) + "\n" ); + } + if( optsSignOperation.imaState.strPathBlsVerify.length > 0 ) { + const joCommonPublicKey = + discoverCommonPublicKey( + optsSignOperation.imaState.joSChainNetworkInfo ); + if( performBlsVerify( + optsSignOperation.details, optsSignOperation.strDirection, + joGlueResult, optsSignOperation.jarrMessages, + optsSignOperation.nIdxCurrentMsgBlockStart, + optsSignOperation.strFromChainName, + joCommonPublicKey + ) ) { + strSuccessfulResultDescription = + "Got successful summary BLS verification result"; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefixB + + cc.success( strSuccessfulResultDescription ) + "\n" ); + } + } else { + strError = "BLS verification failed"; + if( log.verboseGet() >= log.verboseReversed().error ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefixB + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( strError ) + "\n" ); + } + } + } + } else { + strError = "BLS glue failed, no glue result arrived"; + const strErrorMessage = optsSignOperation.strLogPrefixB + + cc.error( "Problem(1) in BLS sign result handler: " ) + + cc.warning( strError ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + optsSignOperation.details.write( strErrorMessage ); + if( log.id != details.id ) + log.write( strErrorMessage ); + } + } + const strCallbackCallDescription = + cc.debug( "Will call signed-hash answer-sending callback " ) + + ( strError ? ( cc.debug( " with error " ) + cc.j( strError ) ) : "" ) + + cc.debug( ", optsSignOperation.jarrMessages is " ) + + cc.j( optsSignOperation.jarrMessages ) + + cc.debug( ", glue result is " ) + cc.j( joGlueResult ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().trace ) + optsSignOperation.details.write( strCallbackCallDescription ); + optsSignOperation.fn( // NOTICE: no await here, executed async + strError, optsSignOperation.jarrMessages, joGlueResult ) + .catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Problem(2) in BLS sign result handler: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + optsSignOperation.errGathering = + "Problem(2) in BLS sign result handler: " + + owaspUtils.extractErrorMessage( err ); + return; + } ); + optsSignOperation.bHaveResultReportCalled = true; + if( strError ) { + optsSignOperation.errGathering = strError; + reject( new Error( optsSignOperation.errGathering ) ); + } else + resolve(); + return; + } + if( optsSignOperation.joGatheringTracker.nCountReceived >= + optsSignOperation.jarrNodes.length ) { + clearInterval( iv ); + optsSignOperation.fn( // NOTICE: no await here, executed async + "signature error(2), got " + + optsSignOperation.joGatheringTracker.nCountErrors + + " errors(s) for " + optsSignOperation.jarrNodes.length + + " node(s)", optsSignOperation.jarrMessages, + null + ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Problem(3) in BLS sign result handler, " + + "not enough successful BLS signature parts(" ) + + cc.info( optsSignOperation.cntSuccess ) + + cc.error( " when all attempts done, " + + "error optsSignOperation.details: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + optsSignOperation.details.write( strErrorMessage ); + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + } + optsSignOperation.errGathering = + "Problem(3) in BLS sign result handler," + + " not enough successful BLS signature parts(" + + optsSignOperation.cntSuccess + + " when all attempts done, error optsSignOperation.details: " + + owaspUtils.extractErrorMessage( err ); + reject( new Error( optsSignOperation.errGathering ) ); + } ); + optsSignOperation.bHaveResultReportCalled = true; + return; + } + if( optsSignOperation.joGatheringTracker.nWaitIntervalStepsDone >= + optsSignOperation.joGatheringTracker.nWaitIntervalMaxSteps + ) { + clearInterval( iv ); + optsSignOperation.fn( // NOTICE: no await here, executed async + "signature error(3), got " + + optsSignOperation.joGatheringTracker.nCountErrors + + " errors(s) for " + optsSignOperation.jarrNodes.length + " node(s)", + optsSignOperation.jarrMessages, + null + ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( + "Problem(4) in BLS sign result handler, " + + "not enough successful BLS signature parts(" ) + + cc.info( optsSignOperation.cntSuccess ) + + cc.error( ") and timeout reached, " + + "error optsSignOperation.details: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + optsSignOperation.details.write( strErrorMessage ); + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + } + optsSignOperation.errGathering = + "Problem(4) in BLS sign result handler, " + + "not enough successful BLS signature parts(" + + optsSignOperation.cntSuccess + + ") and timeout reached, error optsSignOperation.details: " + + owaspUtils.extractErrorMessage( err ); + reject( new Error( optsSignOperation.errGathering ) ); + } ); + optsSignOperation.bHaveResultReportCalled = true; + return; + } + }, optsSignOperation.joGatheringTracker.nWaitIntervalStepMilliseconds ); + } ); +} + +async function gatherSigningFinishImpl( optsSignOperation ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + cc.debug( "Will await for message BLS verification and sending..." ) + "\n" ); + } + await withTimeout( + "BLS verification and sending", + optsSignOperation.promiseCompleteGathering, + gSecondsMessageVerifySendTimeout ) + .then( strSuccessfulResultDescription => { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( + cc.success( "BLS verification and sending promise awaited." ) + "\n" ); + } + } ).catch( err => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Failed to verify BLS and send message : " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + } + } ); + if( optsSignOperation.errGathering ) { + const strErrorMessage = + cc.error( "Failed BLS sign result awaiting(1): " ) + + cc.warning( optsSignOperation.errGathering.toString() ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + if( ! optsSignOperation.bHaveResultReportCalled ) { + optsSignOperation.bHaveResultReportCalled = true; + await optsSignOperation.fn( + "Failed to gather BLS signatures in " + optsSignOperation.jarrNodes.length + + " node(s), tracker data is: " + + JSON.stringify( optsSignOperation.joGatheringTracker ) + + ", error is: " + optsSignOperation.errGathering.toString(), + optsSignOperation.jarrMessages, + null + ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Problem(5) in BLS sign result handler, " + + "not enough successful BLS signature parts(" ) + + cc.info( optsSignOperation.cntSuccess ) + + cc.error( ") and timeout reached, error optsSignOperation.details: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + } + optsSignOperation.details.exposeDetailsTo( + log, optsSignOperation.strGatheredDetailsName, false ); + optsSignOperation.details.close(); + optsSignOperation.details = null; + } ); + } + return; + } + if( ! optsSignOperation.bHaveResultReportCalled ) { + const strErrorMessage = cc.error( "Failed BLS sign result awaiting(2): " ) + + cc.warning( "No reports were arrived" ) + + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + optsSignOperation.bHaveResultReportCalled = true; + await optsSignOperation.fn( + "Failed to gather BLS signatures in " + optsSignOperation.jarrNodes.length + + " node(s), tracker data is: " + + JSON.stringify( optsSignOperation.joGatheringTracker ), + optsSignOperation.jarrMessages, null + ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Problem(6) in BLS sign result handler, " + + "not enough successful BLS signature parts(" ) + + cc.info( optsSignOperation.cntSuccess ) + + cc.error( ") and timeout reached, error optsSignOperation.details: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n"; + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + optsSignOperation.details.exposeDetailsTo( + log, optsSignOperation.strGatheredDetailsName, false ); + optsSignOperation.details.close(); + optsSignOperation.details = null; + } ); + } +} + +async function doSignConfigureChainAccessParams( optsSignOperation ) { + optsSignOperation.targetChainName = ""; + optsSignOperation.fromChainName = ""; + optsSignOperation.targetChainID = -4; + optsSignOperation.fromChainID = -4; + if( optsSignOperation.strDirection == "M2S" ) { + optsSignOperation.targetChainName = "" + + ( optsSignOperation.imaState.chainProperties.sc.strChainName + ? optsSignOperation.imaState.chainProperties.sc.strChainName + : "" ); + optsSignOperation.fromChainName = "" + + ( optsSignOperation.imaState.chainProperties.mn.strChainName + ? optsSignOperation.imaState.chainProperties.mn.strChainName + : "" ); + optsSignOperation.targetChainID = optsSignOperation.imaState.chainProperties.sc.chainId; + optsSignOperation.fromChainID = optsSignOperation.imaState.chainProperties.mn.chainId; + } else if( optsSignOperation.strDirection == "S2M" ) { + optsSignOperation.targetChainName = "" + + ( optsSignOperation.imaState.chainProperties.mn.strChainName + ? optsSignOperation.imaState.chainProperties.mn.strChainName + : "" ); + optsSignOperation.fromChainName = "" + + ( optsSignOperation.imaState.chainProperties.sc.strChainName + ? optsSignOperation.imaState.chainProperties.sc.strChainName + : "" ); + optsSignOperation.targetChainID = optsSignOperation.imaState.chainProperties.mn.chainId; + optsSignOperation.fromChainID = optsSignOperation.imaState.chainProperties.sc.chainId; + } else if( optsSignOperation.strDirection == "S2S" ) { + optsSignOperation.targetChainName = + "" + optsSignOperation.joExtraSignOpts.chainNameDst; + optsSignOperation.fromChainName = "" + optsSignOperation.joExtraSignOpts.chainNameSrc; + optsSignOperation.targetChainID = optsSignOperation.joExtraSignOpts.chainIdDst; + optsSignOperation.fromChainID = optsSignOperation.joExtraSignOpts.chainIdSrc; + } else { + await joCall.disconnect(); + throw new Error( + "CRITICAL ERROR: " + + "Failed doSignMessagesImpl() with unknown direction \"" + + optsSignOperation.strDirection + "\"" + ); + } +} + +async function doSignProcessHandleCall( + optsSignOperation, + joNode, joParams, + joIn, joOut, err +) { + ++optsSignOperation.joGatheringTracker.nCountReceived; // including errors + if( err ) { + ++optsSignOperation.joGatheringTracker.nCountErrors; + const strErrorMessage = + optsSignOperation.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + + cc.error( " failed, RPC call reported error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", " ) + cc.notice( "sequence ID" ) + + cc.error( " is " ) + cc.attention( optsSignOperation.sequenceId ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + await joCall.disconnect(); + return; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + log.generateTimestampString( null, true ) + " " + + cc.debug( "Got answer from " ) + cc.info( "skale_imaVerifyAndSign" ) + + cc.debug( " for transfer from chain " ) + cc.info( optsSignOperation.fromChainName ) + + cc.debug( " to chain " ) + cc.info( optsSignOperation.targetChainName ) + + cc.debug( " with params " ) + cc.j( joParams ) + cc.debug( ", answer is " ) + + cc.j( joOut ) + cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + + cc.attention( optsSignOperation.sequenceId ) + "\n" ); + } + if( joOut.result == null || + joOut.result == undefined || + ( !typeof joOut.result == "object" ) + ) { + ++optsSignOperation.joGatheringTracker.nCountErrors; + const strErrorMessage = optsSignOperation.strLogPrefix + + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + + cc.error( "S-Chain node " ) + strNodeDescColorized + + cc.error( " reported wallet error: " ) + + cc.warning( + owaspUtils.extractErrorMessage( joOut, "unknown wallet error(1)" ) + ) + + cc.error( ", " ) + cc.notice( "sequence ID" ) + + cc.error( " is " ) + cc.attention( optsSignOperation.sequenceId ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + await joCall.disconnect(); + return; + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + cc.debug( "Node " ) + + cc.info( joNode.nodeID ) + cc.debug( " sign result: " ) + + cc.j( joOut.result ? joOut.result : null ) + "\n" ); + } + try { + if( joOut.result.signResult.signatureShare.length > 0 && + joOut.result.signResult.status === 0 + ) { + const nZeroBasedNodeIndex = joNode.imaInfo.thisNodeIndex - 1; + // partial BLS verification for one participant + let bNodeSignatureOKay = false; // initially assume signature is wrong + optsSignOperation.strLogPrefixA = + cc.bright( optsSignOperation.strDirection ) + cc.debug( "/" ) + + cc.info( "BLS" ) + cc.debug( "/" ) + + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + + cc.debug( ":" ) + " "; + try { + optsSignOperation.cntSuccess = + optsSignOperation.joGatheringTracker.nCountReceived - + optsSignOperation.joGatheringTracker.nCountErrors; + if( optsSignOperation.cntSuccess > + optsSignOperation.nCountOfBlsPartsToCollect ) { + ++optsSignOperation.joGatheringTracker.nCountSkipped; + if( log.verboseGet() >= log.verboseReversed().notice ) { + optsSignOperation.details.write( + optsSignOperation.strLogPrefixA + + cc.debug( "Will ignore sign result for node " ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " because " ) + + cc.info( optsSignOperation.nThreshold ) + cc.debug( "/" ) + + cc.info( optsSignOperation.nCountOfBlsPartsToCollect ) + + cc.debug( " threshold number of BLS signature " + + "parts already gathered" ) + "\n" ); + } + await joCall.disconnect(); + return; + } + const arrTmp = joOut.result.signResult.signatureShare.split( ":" ); + const joResultFromNode = { + index: "" + nZeroBasedNodeIndex, + signature: { + X: arrTmp[0], + Y: arrTmp[1] + } + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefixA + + cc.info( "Will verify sign result for node " ) + + cc.info( nZeroBasedNodeIndex ) + "\n" ); + } + const joPublicKey = + discoverPublicKeyByIndex( + nZeroBasedNodeIndex, + optsSignOperation.imaState.joSChainNetworkInfo + ); + if( performBlsVerifyI( + optsSignOperation.details, optsSignOperation.strDirection, + nZeroBasedNodeIndex, joResultFromNode, + optsSignOperation.jarrMessages, + optsSignOperation.nIdxCurrentMsgBlockStart, + optsSignOperation.strFromChainName, + joPublicKey + ) ) { + if( log.verboseGet() >= log.verboseReversed().notice ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefixA + + cc.success( "Got successful BLS verification result for node " ) + + cc.info( joNode.nodeID ) + cc.success( " with index " ) + + cc.info( nZeroBasedNodeIndex ) + "\n" ); + } + bNodeSignatureOKay = true; // node verification passed + } else { + if( log.verboseGet() >= log.verboseReversed().error ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefixA + + cc.fatal( "CRITICAL ERROR:" ) + " " + + cc.error( "BLS verification failed" ) + "\n" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + optsSignOperation.strLogPrefixA + cc.error( "S-Chain node " ) + + strNodeDescColorized + cc.error( " sign " ) + + cc.error( " CRITICAL ERROR:" ) + + cc.error( " partial signature fail from with index " ) + + cc.info( nZeroBasedNodeIndex ) + + cc.error( ", error is " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", " ) + cc.notice( "sequence ID" ) + + cc.error( " is " ) + cc.attention( optsSignOperation.sequenceId ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + } + if( bNodeSignatureOKay ) { + optsSignOperation.arrSignResults.push( { + index: "" + nZeroBasedNodeIndex, + signature: + splitSignatureShare( + joOut.result.signResult.signatureShare + ), + fromNode: joNode, // extra, not needed for bls_glue + signResult: joOut.result.signResult + } ); + } else + ++optsSignOperation.joGatheringTracker.nCountErrors; + } + } catch ( err ) { + ++optsSignOperation.joGatheringTracker.nCountErrors; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + optsSignOperation.strLogPrefix + cc.error( "S-Chain node " ) + + strNodeDescColorized + " " + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " signature fail from node " ) + cc.info( joNode.nodeID ) + + cc.error( ", error is " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", " ) + cc.notice( "sequence ID" ) + + cc.error( " is " ) + cc.attention( optsSignOperation.sequenceId ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + } + await joCall.disconnect(); +} + +async function doSignProcessOneImpl( i, optsSignOperation ) { + const joNode = optsSignOperation.jarrNodes[i]; + const strNodeURL = optsSignOperation.imaState.isCrossImaBlsMode + ? imaUtils.composeImaAgentNodeUrl( joNode ) + : imaUtils.composeSChainNodeUrl( joNode ); + const strNodeDescColorized = cc.u( strNodeURL ) + " " + + cc.debug( "(" ) + cc.bright( i ) + cc.debug( "/" ) + + cc.bright( optsSignOperation.jarrNodes.length ) + + cc.debug( ", ID " ) + cc.info( joNode.nodeID ) + cc.debug( ")" ) + + cc.debug( ", " ) + cc.notice( "sequence ID" ) + cc.debug( " is " ) + + cc.attention( optsSignOperation.sequenceId ); + const rpcCallOpts = null; + rpcCall.create( // NOTICE: no await here, executed async + strNodeURL, rpcCallOpts, async function( joCall, err ) { + if( err ) { + ++optsSignOperation.joGatheringTracker.nCountReceived; // including errors + ++optsSignOperation.joGatheringTracker.nCountErrors; + const strErrorMessage = + optsSignOperation.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + + cc.error( " failed, RPC call was not created, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", " ) + cc.notice( "sequence ID" ) + + cc.error( " is " ) + cc.attention( optsSignOperation.sequenceId ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + optsSignOperation.details.write( strErrorMessage ); + } + if( joCall ) + await joCall.disconnect(); + return; + } + await doSignConfigureChainAccessParams( optsSignOperation ); + const joParams = { + "direction": "" + optsSignOperation.strDirection, + "startMessageIdx": optsSignOperation.nIdxCurrentMsgBlockStart, + "dstChainName": optsSignOperation.targetChainName, + "srcChainName": optsSignOperation.fromChainName, + "dstChainID": optsSignOperation.targetChainID, + "srcChainID": optsSignOperation.fromChainID, + "messages": optsSignOperation.jarrMessages, + "qa": { + "skaledNumber": 0 + i, + "optsSignOperation.sequenceId": "" + optsSignOperation.sequenceId, + "ts": "" + log.generateTimestampString( null, false ) + } + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + log.generateTimestampString( null, true ) + " " + cc.debug( "Will invoke " ) + + cc.info( "skale_imaVerifyAndSign" ) + cc.debug( " for transfer from chain " ) + + cc.info( optsSignOperation.fromChainName ) + cc.debug( " to chain " ) + + cc.info( optsSignOperation.targetChainName ) + cc.debug( " with params " ) + + cc.j( joParams ) + cc.debug( ", " ) + cc.notice( "sequence ID" ) + + cc.debug( " is " ) + cc.attention( optsSignOperation.sequenceId ) + "\n" ); + } + await joCall.call( { + "method": "skale_imaVerifyAndSign", + "params": joParams + }, async function( joIn, joOut, err ) { + await doSignProcessHandleCall( + optsSignOperation, + joNode, joParams, + joIn, joOut, err + ); + } ); // joCall.call ... + } ); // rpcCall.create ... +} + +async function doSignMessagesImpl( + nTransferLoopCounter, strDirection, + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, fn +) { + const optsSignOperation = { + imaState: state.get(), + nTransferLoopCounter: nTransferLoopCounter, + strDirection: strDirection, + jarrMessages: jarrMessages, + nIdxCurrentMsgBlockStart: nIdxCurrentMsgBlockStart, + strFromChainName: strFromChainName, + joExtraSignOpts: joExtraSignOpts, + fn: fn, + bHaveResultReportCalled: false, + strLogPrefix: "", + strLogPrefixA: "", + strLogPrefixB: "", + joGatheringTracker: {}, + arrSignResults: [], + cntSuccess: 0, + details: log, + strGatheredDetailsName: "", + sequenceId: "", + jarrNodes: [], + nThreshold: 1, + nParticipants: 1, + nCountOfBlsPartsToCollect: 1, + errGathering: null, + promiseCompleteGathering: null, + targetChainName: "", + fromChainName: "", + targetChainID: -4, + fromChainID: -4 + }; + optsSignOperation.strLogPrefix = + cc.bright( optsSignOperation.strDirection ) + cc.debug( "/" ) + + cc.attention( "#" ) + cc.sunny( optsSignOperation.nTransferLoopCounter ) + " " + + cc.info( "Sign msgs via " ) + + cc.attention( optsSignOperation.imaState.isCrossImaBlsMode ? "IMA agent" : "skaled" ) + + cc.info( ":" ) + " "; + optsSignOperation.joGatheringTracker = { + nCountReceived: 0, // including errors + nCountErrors: 0, + nCountSkipped: 0, + nWaitIntervalStepMilliseconds: 100, + nWaitIntervalStepsDone: 0, + nWaitIntervalMaxSteps: 10 * 60 * 3 // 10 is 1 second + }; + optsSignOperation.details = + optsSignOperation.imaState.isDynamicLogInBlsSigner + ? log : log.createMemoryStream( true ); + optsSignOperation.strGatheredDetailsName = optsSignOperation.strDirection + "-" + + "doSignMessagesImpl-#" + optsSignOperation.nTransferLoopCounter + + "-" + optsSignOperation.strFromChainName + "-msg#" + + optsSignOperation.nIdxCurrentMsgBlockStart; + try { + await prepareSignMessagesImpl( optsSignOperation ); + for( let i = 0; i < optsSignOperation.jarrNodes.length; ++i ) { + optsSignOperation.cntSuccess = + optsSignOperation.joGatheringTracker.nCountReceived - + optsSignOperation.joGatheringTracker.nCountErrors; + if( optsSignOperation.cntSuccess >= optsSignOperation.nCountOfBlsPartsToCollect ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignOperation.details.write( optsSignOperation.strLogPrefix + + log.generateTimestampString( null, true ) + " " + + cc.debug( "Stop invoking " ) + cc.info( "skale_imaVerifyAndSign" ) + + cc.debug( " for transfer from chain " ) + cc.info( fromChainName ) + + cc.debug( " at #" ) + cc.info( i ) + + cc.debug( " because successfully gathered count is reached " ) + + cc.j( optsSignOperation.cntSuccess ) + "\n" ); + } + break; + } + await doSignProcessOneImpl( i, optsSignOperation ); + } + await gatherSigningStartImpl( optsSignOperation ); + await gatherSigningFinishImpl( optsSignOperation ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Failed BLS sign due to generic flow exception: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( ( !optsSignOperation.details ) || log.id != optsSignOperation.details.id ) + log.write( strErrorMessage ); + if( optsSignOperation.details ) + optsSignOperation.details.write( strErrorMessage ); + } + if( ! optsSignOperation.bHaveResultReportCalled ) { + optsSignOperation.bHaveResultReportCalled = true; + await optsSignOperation.fn( + "Failed BLS sign due to exception: " + + owaspUtils.extractErrorMessage( err ), + optsSignOperation.jarrMessages, + null + ).catch( ( err ) => { + let strErrorMessage = null; + if( log.verboseGet() >= log.verboseReversed().critical ) { + strErrorMessage = + cc.error( "Failed BLS sign due to " + + "error-reporting callback exception: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + log.write( strErrorMessage ); + } + if( optsSignOperation.details ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( strErrorMessage ) + optsSignOperation.details.write( strErrorMessage ); + } + optsSignOperation.details.exposeDetailsTo( + log, optsSignOperation.strGatheredDetailsName, false ); + optsSignOperation.details.close(); + } + } ); + } + } + if( log.verboseGet() >= log.verboseReversed().information ) { + const strFinalMessage = cc.info( optsSignOperation.strGatheredDetailsName ) + + cc.success( " completed" ) + "\n"; + optsSignOperation.details.write( strFinalMessage ); + } + if( optsSignOperation.details ) { + optsSignOperation.details.exposeDetailsTo( + log, optsSignOperation.strGatheredDetailsName, true ); + optsSignOperation.details.close(); + } +} + +export async function doSignMessagesM2S( + nTransferLoopCounter, + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, + fn +) { + return await doSignMessagesImpl( + nTransferLoopCounter, + "M2S", + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, + fn + ); +} + +export async function doSignMessagesS2M( + nTransferLoopCounter, + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, + fn +) { + return await doSignMessagesImpl( + nTransferLoopCounter, + "S2M", + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, + fn + ); +} + +export async function doSignMessagesS2S( + nTransferLoopCounter, + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, + fn +) { + return await doSignMessagesImpl( + nTransferLoopCounter, + "S2S", + jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, + fn + ); +} + +async function prepareSignU256( optsSignU256 ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + cc.debug( "Will sign " ) + + cc.info( optsSignU256.u256 ) + cc.debug( " value..." ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + cc.debug( "Will query to sign " ) + + cc.info( optsSignU256.jarrNodes.length ) + cc.debug( " skaled node(s)..." ) + "\n" ); + } + optsSignU256.nThreshold = + discoverBlsThreshold( optsSignU256.imaState.joSChainNetworkInfo ); + optsSignU256.nParticipants = + discoverBlsParticipants( optsSignU256.imaState.joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + + cc.debug( "Discovered BLS threshold is " ) + cc.info( optsSignU256.nThreshold ) + + cc.debug( "." ) + "\n" ); + optsSignU256.details.write( optsSignU256.strLogPrefix + + cc.debug( "Discovered number of BLS participants is " ) + + cc.info( optsSignU256.nParticipants ) + cc.debug( "." ) + "\n" ); + } + if( optsSignU256.nThreshold <= 0 ) { + await optsSignU256.fn( + "signature error(1, u256), S-Chain information " + + "was not discovered properly and BLS threshold is unknown", + optsSignU256.u256, + null + ); + return; + } + optsSignU256.nCountOfBlsPartsToCollect = 0 + optsSignU256.nThreshold; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + + cc.debug( "Will(optsSignU256.u256) collect " ) + + cc.info( optsSignU256.nCountOfBlsPartsToCollect ) + + cc.debug( " from " ) + cc.info( optsSignU256.jarrNodes.length ) + + cc.debug( " nodes" ) + "\n" ); + } +} + +async function doSignU256OneImpl( optsSignU256 ) { + const joNode = optsSignU256.jarrNodes[i]; + const strNodeURL = optsSignU256.imaState.isCrossImaBlsMode + ? imaUtils.composeImaAgentNodeUrl( joNode ) : imaUtils.composeSChainNodeUrl( joNode ); + const strNodeDescColorized = cc.u( strNodeURL ) + " " + cc.debug( "(" ) + cc.bright( i ) + + cc.debug( "/" ) + cc.bright( optsSignU256.jarrNodes.length ) + + cc.debug( ", ID " ) + cc.info( joNode.nodeID ) + cc.debug( ")" ); + const rpcCallOpts = null; + await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { + if( err ) { + ++optsSignU256.joGatheringTracker.nCountReceived; // including errors + ++optsSignU256.joGatheringTracker.nCountErrors; + const strErrorMessage = + optsSignU256.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + + cc.error( " failed, RPC call was not created, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + if( joCall ) + await joCall.disconnect(); + return; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + cc.debug( "Will invoke " ) + + cc.info( "skale_imaBSU256" ) + cc.debug( " for to sign value " ) + + cc.info( optsSignU256.u256.toString() ) + "\n" ); + } + await joCall.call( { + "method": "skale_imaBSU256", + "params": { + "valueToSign": optsSignU256.u256 // must be 0x string, came from outside 0x string + } + }, async function( joIn, joOut, err ) { + ++optsSignU256.joGatheringTracker.nCountReceived; // including errors + if( err ) { + ++optsSignU256.joGatheringTracker.nCountErrors; + const strErrorMessage = + optsSignU256.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + + cc.error( " failed, RPC call reported error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + await joCall.disconnect(); + return; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + cc.debug( "Did invoked " ) + + cc.info( "skale_imaBSU256" ) + cc.debug( " for to sign value " ) + + cc.info( optsSignU256.u256.toString() ) + cc.debug( ", answer is: " ) + + cc.j( joOut ) + "\n" ); + } + if( joOut.result == null || + joOut.result == undefined || + ( !typeof joOut.result == "object" ) + ) { + ++optsSignU256.joGatheringTracker.nCountErrors; + const strErrorMessage = + optsSignU256.strLogPrefix + cc.fatal( "Wallet CRITICAL ERROR:" ) + " " + + cc.error( "S-Chain node " ) + strNodeDescColorized + + cc.error( " reported wallet error: " ) + cc.warning( + owaspUtils.extractErrorMessage( joOut, "unknown wallet error(2)" ) ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + await joCall.disconnect(); + return; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + cc.debug( "Node " ) + + cc.info( joNode.nodeID ) + cc.debug( " sign result: " ) + + cc.j( joOut.result ? joOut.result : null ) + "\n" ); + } + try { + if( joOut.result.signResult.signatureShare.length > 0 && + joOut.result.signResult.status === 0 + ) { + const nZeroBasedNodeIndex = joNode.imaInfo.thisNodeIndex - 1; + // partial BLS verification for one participant + let bNodeSignatureOKay = false; // initially assume signature is wrong + const strLogPrefixA = cc.info( "BLS" ) + cc.debug( "/" ) + cc.notice( "#" ) + + cc.bright( nZeroBasedNodeIndex ) + cc.debug( ":" ) + " "; + try { + const cntSuccess = optsSignU256.joGatheringTracker.nCountReceived - + optsSignU256.joGatheringTracker.nCountErrors; + if( cntSuccess > optsSignU256.nCountOfBlsPartsToCollect ) { + ++optsSignU256.joGatheringTracker.nCountSkipped; + if( log.verboseGet() >= log.verboseReversed().notice ) { + optsSignU256.details.write( strLogPrefixA + + cc.debug( "Will ignore sign result for node " ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " because " ) + + cc.info( optsSignU256.nThreshold ) + cc.debug( "/" ) + + cc.info( optsSignU256.nCountOfBlsPartsToCollect ) + + cc.debug( " threshold number of BLS signature " + + "parts already gathered" ) + "\n" ); + } + return; + } + const arrTmp = joOut.result.signResult.signatureShare.split( ":" ); + const joResultFromNode = { + index: "" + nZeroBasedNodeIndex, + signature: { X: arrTmp[0], Y: arrTmp[1] } + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( strLogPrefixA + + cc.info( "Will verify sign result for node " ) + + cc.info( nZeroBasedNodeIndex ) + "\n" ); + } + const joPublicKey = + discoverPublicKeyByIndex( + nZeroBasedNodeIndex, optsSignU256.imaState.joSChainNetworkInfo ); + if( performBlsVerifyIU256( + optsSignU256.details, nZeroBasedNodeIndex, joResultFromNode, + optsSignU256.u256, joPublicKey ) ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + optsSignU256.details.write( strLogPrefixA + + cc.success( "Got successful BLS " + + "verification result for node " ) + + cc.info( joNode.nodeID ) + cc.success( " with index " ) + + cc.info( nZeroBasedNodeIndex ) + "\n" ); + } + bNodeSignatureOKay = true; // node verification passed + } else { + const strError = "BLS u256 one node verify failed"; + if( log.verboseGet() >= log.verboseReversed().error ) { + optsSignU256.details.write( strLogPrefixA + + cc.fatal( "CRITICAL ERROR:" ) + " " + + cc.error( strError ) + "\n" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + strLogPrefixA + cc.error( "S-Chain node " ) + + strNodeDescColorized + cc.error( " sign " ) + + cc.error( " CRITICAL ERROR:" ) + + cc.error( " partial signature fail from with index " ) + + cc.info( nZeroBasedNodeIndex ) + cc.error( ", error is " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + } + } + if( bNodeSignatureOKay ) { + optsSignU256.arrSignResults.push( { + index: "" + nZeroBasedNodeIndex, + signature: + splitSignatureShare( joOut.result.signResult.signatureShare ), + fromNode: joNode, // extra, not needed for bls_glue + signResult: joOut.result.signResult + } ); + } else + ++optsSignU256.joGatheringTracker.nCountErrors; + } + } catch ( err ) { + ++optsSignU256.joGatheringTracker.nCountErrors; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + optsSignU256.strLogPrefix + cc.error( "S-Chain node " ) + + strNodeDescColorized + " " + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " signature fail from node " ) + cc.info( joNode.nodeID ) + + cc.error( ", error is " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + } + await joCall.disconnect(); + } ); // joCall.call ... + } ); // rpcCall.create ... +} + +async function doSignU256Gathering( optsSignU256 ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + + cc.debug( "Waiting for BLS glue result " ) + + "\n" ); + optsSignU256.errGathering = null; + optsSignU256.promiseCompleteGathering = new Promise( ( resolve, reject ) => { + const iv = setInterval( function() { + ++ optsSignU256.joGatheringTracker.nWaitIntervalStepsDone; + const cntSuccess = + optsSignU256.joGatheringTracker.nCountReceived - + optsSignU256.joGatheringTracker.nCountErrors; + if( cntSuccess >= optsSignU256.nCountOfBlsPartsToCollect ) { + const strLogPrefixB = cc.info( "BLS u256" ) + + cc.debug( "/" ) + cc.sunny( "Summary" ) + cc.debug( ":" ) + " "; + clearInterval( iv ); + let strError = null, strSuccessfulResultDescription = null; + const joGlueResult = + performBlsGlueU256( + optsSignU256.details, optsSignU256.u256, optsSignU256.arrSignResults ); + if( joGlueResult ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( strLogPrefixB + + cc.success( "Got BLS glue u256 result: " ) + cc.j( joGlueResult ) + + "\n" ); + } + if( optsSignU256.imaState.strPathBlsVerify.length > 0 ) { + const joCommonPublicKey = + discoverCommonPublicKey( + optsSignU256.imaState.joSChainNetworkInfo ); + if( performBlsVerifyU256( + optsSignU256.details, + joGlueResult, + optsSignU256.u256, + joCommonPublicKey + ) + ) { + strSuccessfulResultDescription = + "Got successful summary BLS u256 verification result"; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( strLogPrefixB + + cc.success( strSuccessfulResultDescription ) + "\n" ); + } + } else { + strError = "BLS verification failed"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) { + log.write( strLogPrefixB + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( strError ) + "\n" ); + } + optsSignU256.details.write( strLogPrefixB + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( strError ) + "\n" ); + } + } + } + } else { + strError = "BLS u256 glue failed, no glue result arrived"; + const strErrorMessage = strLogPrefixB + + cc.error( "Problem(1) in BLS u256 sign result handler: " ) + + cc.warning( strError ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + } + const strCallbackCallDescription = + cc.debug( "Will call signed-256 answer-sending callback " ) + + ( strError ? ( cc.debug( " with error " ) + cc.j( strError ) ) : "" ) + + cc.debug( ", u256 is " ) + cc.j( optsSignU256.u256 ) + + cc.debug( ", glue result is " ) + cc.j( joGlueResult ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().trace ) + optsSignU256.details.write( strCallbackCallDescription ); + optsSignU256.fn( // NOTICE: no await here, executed async + strError, optsSignU256.u256, joGlueResult ) + .catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Problem(2) in BLS u256 sign result handler: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + } + optsSignU256.errGathering = + "Problem(2) in BLS u256 sign result handler: " + + owaspUtils.extractErrorMessage( err ); + } ); + if( strError ) { + optsSignU256.errGathering = strError; + reject( new Error( optsSignU256.errGathering ) ); + } else + resolve(); + return; + } + if( optsSignU256.joGatheringTracker.nCountReceived >= + optsSignU256.jarrNodes.length ) { + clearInterval( iv ); + optsSignU256.fn( // NOTICE: no await here, executed async + "signature error(2, u256), got " + + optsSignU256.joGatheringTracker.nCountErrors + + " errors(s) for " + optsSignU256.jarrNodes.length + " node(s)", + optsSignU256.u256, + null + ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Problem(3) in BLS u256 sign result handler, " + + "not enough successful BLS signature parts(" ) + cc.info( cntSuccess ) + + cc.error( " when all attempts done, error optsSignU256.details: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + } + optsSignU256.errGathering = + "Problem(3) in BLS u256 sign result handler, " + + "not enough successful BLS signature parts(" + + cntSuccess + " when all attempts done, error optsSignU256.details: " + + owaspUtils.extractErrorMessage( err ); + reject( new Error( optsSignU256.errGathering ) ); + } ); + return; + } + if( optsSignU256.joGatheringTracker.nWaitIntervalStepsDone >= + optsSignU256.joGatheringTracker.nWaitIntervalMaxSteps + ) { + clearInterval( iv ); + optsSignU256.fn( // NOTICE: no await here, executed async + "signature error(3, u256), got " + + optsSignU256.joGatheringTracker.nCountErrors + + " errors(s) for " + optsSignU256.jarrNodes.length + " node(s)", + optsSignU256.u256, + null + ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Problem(4) in BLS u256 sign result handler, " + + "not enough successful BLS signature parts(" ) + + cc.info( cntSuccess ) + + cc.error( ") and timeout reached, error optsSignU256.details: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n"; + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + optsSignU256.errGathering = + "Problem(4) in BLS u256 sign result handler, " + + "not enough successful BLS signature parts(" + + cntSuccess + ") and timeout reached, error optsSignU256.details: " + + owaspUtils.extractErrorMessage( err ); + reject( new Error( optsSignU256.errGathering ) ); + } ); + return; + } + }, optsSignU256.joGatheringTracker.nWaitIntervalStepMilliseconds ); + } ); +} + +export async function doSignU256( u256, details, fn ) { + const optsSignU256 = { + u256: u256, + fn: fn, + details: details, + imaState: state.get(), + strLogPrefix: cc.info( "Sign u256:" ) + " ", + joGatheringTracker: { + nCountReceived: 0, // including errors + nCountErrors: 0, + nCountSkipped: 0, + nWaitIntervalStepMilliseconds: 100, + nWaitIntervalStepsDone: 0, + nWaitIntervalMaxSteps: 10 * 60 * 3 // 10 is 1 second + }, + arrSignResults: [], + jarrNodes: {}, + nThreshold: 1, + nParticipants: 1, + nCountOfBlsPartsToCollect: 1, + errGathering: null, + promiseCompleteGathering: null + }; + optsSignU256.jarrNodes = optsSignU256.imaState.joSChainNetworkInfo.network; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + + cc.debug( "Invoking signing u256 procedure " ) + "\n" ); + } + optsSignU256.fn = optsSignU256.fn || function() {}; + if( !( + optsSignU256.imaState.strPathBlsGlue.length > 0 && + optsSignU256.imaState.joSChainNetworkInfo + ) ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + + cc.debug( "BLS u256 signing is " ) + cc.error( "unavailable" ) + "\n" ); + } + await optsSignU256.fn( "BLS u256 signing is unavailable", optsSignU256.u256, null ); + return; + } + await prepareSignU256( optsSignU256 ); + for( let i = 0; i < optsSignU256.jarrNodes.length; ++i ) + await doSignU256OneImpl( optsSignU256 ); + + await doSignU256Gathering( optsSignU256 ); + if( log.verboseGet() >= log.verboseReversed().trace ) + optsSignU256.details.write( cc.debug( "Will await BLS u256 sign result..." ) + "\n" ); + await withTimeout( + "BLS u256 sign", + optsSignU256.promiseCompleteGathering, + gSecondsMessageVerifySendTimeout + ).then( strSuccessfulResultDescription => { + if( log.verboseGet() >= log.verboseReversed().trace ) + optsSignU256.details.write( cc.info( "BLS u256 sign promise awaited." ) + "\n" ); + } ).catch( err => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + cc.error( "Failed to verify BLS and send message : " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + } + } ); + if( optsSignU256.errGathering ) { + const strErrorMessage = + cc.error( "Failed BLS u256 sign result awaiting: " ) + + cc.warning( optsSignU256.errGathering.toString() ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsSignU256.details.id ) + log.write( strErrorMessage ); + optsSignU256.details.write( strErrorMessage ); + } + return; + } + if( log.verboseGet() >= log.verboseReversed().information ) { + optsSignU256.details.write( optsSignU256.strLogPrefix + + cc.debug( "Completed signing u256 procedure " ) + "\n" ); + } +} + +export async function doVerifyReadyHash( + strMessageHash, + nZeroBasedNodeIndex, + signature, + isExposeOutput +) { + const imaState = state.get(); + const strDirection = "RAW"; + const strLogPrefix = + cc.bright( strDirection ) + cc.debug( "/" ) + + cc.info( "BLS" ) + cc.debug( "/" ) + + cc.notice( "#" ) + cc.bright( nZeroBasedNodeIndex ) + + cc.debug( ":" ) + " "; + const details = log.createMemoryStream(); + let isSuccess = false; + const joPublicKey = + discoverPublicKeyByIndex( nZeroBasedNodeIndex, imaState.joSChainNetworkInfo ); + const arrTmp = signature.signatureShare.split( ":" ); + const joResultFromNode = { + index: "" + nZeroBasedNodeIndex, + signature: { + X: arrTmp[0], + Y: arrTmp[1] + } + }; + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + const strActionDir = allocBlsTmpActionDir(); + const fnShellRestore = function() { + shell.rm( "-rf", strActionDir ); + }; + let strOutput = ""; + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - hashed verify message is " ) + + cc.info( strMessageHash ) + "\n" ); + } + const joMsg = { + "message": strMessageHash + }; + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " - composed " ) + cc.j( joMsg ) + + cc.debug( " using hash " ) + cc.j( strMessageHash ) + cc.debug( " and glue " ) + + cc.j( joResultFromNode ) + cc.debug( " and public key " ) + cc.j( joPublicKey ) + + "\n" ); + } + const strSignResultFileName = strActionDir + "/sign-result" + nZeroBasedNodeIndex + ".json"; + imaUtils.jsonFileSave( strSignResultFileName, joResultFromNode ); + imaUtils.jsonFileSave( strActionDir + "/hash.json", joMsg ); + imaUtils.jsonFileSave( + strActionDir + "/BLS_keys" + nZeroBasedNodeIndex + ".json", joPublicKey ); + const strVerifyCommand = "" + + imaState.strPathBlsVerify + + " --t " + nThreshold + + " --n " + nParticipants + + " --j " + nZeroBasedNodeIndex + + " --input " + strSignResultFileName + ; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will execute node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " BLS verify command:\n" ) + + cc.notice( strVerifyCommand ) + "\n" ); + } + strOutput = childProcessModule.execSync( strVerifyCommand, { cwd: strActionDir } ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.debug( " verify output is:\n" ) + + cc.notice( strOutput ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.success( "BLS node " ) + cc.notice( "#" ) + + cc.info( nZeroBasedNodeIndex ) + cc.success( " verify success" ) + "\n" ); + } + fnShellRestore(); + isSuccess = true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s1 = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " BLS node " ) + + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + cc.error( " verify error:" ) + + cc.warning( " error description is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + const s2 = strLogPrefix + cc.error( "CRITICAL ERROR:" ) + cc.error( " BLS node " ) + + cc.notice( "#" ) + cc.info( nZeroBasedNodeIndex ) + + cc.error( " verify output is:\n" ) + cc.warning( strOutput ) + "\n"; + if( log.id != details.id ) { + log.write( s1 ); + log.write( s2 ); + } + details.write( s1 ); + details.write( s2 ); + } + fnShellRestore(); + isSuccess = false; + } + if( isExposeOutput || ( !isSuccess ) ) + details.exposeDetailsTo( log, "BLS-raw-verifier", isSuccess ); + details.close(); + return isSuccess; +} + +export async function doSignReadyHash( strMessageHash, isExposeOutput ) { + const imaState = state.get(); + const strLogPrefix = ""; + const details = log.createMemoryStream(); + let joSignResult = null; + try { + const nThreshold = discoverBlsThreshold( imaState.joSChainNetworkInfo ); + const nParticipants = discoverBlsParticipants( imaState.joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().debug ) + details.write( strLogPrefix + cc.debug( "Will BLS-sign ready hash." ) + "\n" ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Discovered BLS threshold is " ) + + cc.info( nThreshold ) + cc.debug( "." ) + "\n" ); + details.write( strLogPrefix + cc.debug( "Discovered number of BLS participants is " ) + + cc.info( nParticipants ) + cc.debug( "." ) + "\n" ); + details.write( strLogPrefix + cc.debug( "hash value to sign is " ) + + cc.info( strMessageHash ) + "\n" ); + } + let joAccount = imaState.chainProperties.sc.joAccount; + if( ! joAccount.strURL ) { + joAccount = imaState.chainProperties.mn.joAccount; + if( ! joAccount.strSgxURL ) + throw new Error( "SGX URL is unknown, cannot sign U256" ); + if( ! joAccount.strBlsKeyName ) + throw new Error( "BLS keys name is unknown, cannot sign U256" ); + } + let rpcCallOpts = null; + if( "strPathSslKey" in joAccount && typeof joAccount.strPathSslKey == "string" && + joAccount.strPathSslKey.length > 0 && "strPathSslCert" in joAccount && + typeof joAccount.strPathSslCert == "string" && joAccount.strPathSslCert.length > 0 + ) { + rpcCallOpts = { + "cert": fs.readFileSync( joAccount.strPathSslCert, "utf8" ), + "key": fs.readFileSync( joAccount.strPathSslKey, "utf8" ) + }; + } else { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( cc.warning( "Will sign via SGX" ) + " " + + cc.error( "without SSL options" ) + "\n" ); + } + } + const signerIndex = imaState.nNodeNumber; + await rpcCall.create( joAccount.strSgxURL, rpcCallOpts, async function( joCall, err ) { + if( err ) { + const strErrorMessage = + strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to SGX failed, " + + "RPC call was not created, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != details.id ) + log.write( strErrorMessage ); + details.write( strErrorMessage ); + } + if( joCall ) + await joCall.disconnect(); + throw new Error( + "JSON RPC call to SGX failed, RPC call was not created, error is: " + + owaspUtils.extractErrorMessage( err ) + ); + } + const joCallSGX = { + "jsonrpc": "2.0", + "id": randomCallID(), + "method": "blsSignMessageHash", + "params": { + "keyShareName": joAccount.strBlsKeyName, + "messageHash": strMessageHash, + "n": nParticipants, + "t": nThreshold, + "signerIndex": signerIndex + 0 // 1-based + } + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will invoke " ) + cc.info( "SGX" ) + + cc.debug( " with call data " ) + cc.j( joCallSGX ) + "\n" ); + } + await joCall.call( joCallSGX, async function( joIn, joOut, err ) { + if( err ) { + const jsErrorObject = new Error( + "JSON RPC call to SGX failed, RPC call reported error: " + + owaspUtils.extractErrorMessage( err ) + ); + const strErrorMessage = + strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to SGX failed, RPC call reported error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( jsErrorObject.stack ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != details.id ) + log.write( strErrorMessage ); + details.write( strErrorMessage ); + } + await joCall.disconnect(); + throw jsErrorObject; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Call to " ) + cc.info( "SGX" ) + + cc.debug( " done, answer is: " ) + cc.j( joOut ) + "\n" ); + } + joSignResult = joOut; + if( joOut.result != null && joOut.result != undefined && + typeof joOut.result == "object" ) + joSignResult = joOut.result; + if( joOut.signResult != null && joOut.signResult != undefined && + typeof joOut.signResult == "object" ) + joSignResult = joOut.signResult; + if( "errorMessage" in joSignResult && + typeof joSignResult.errorMessage == "string" && + joSignResult.errorMessage.length > 0 + ) { + const strError = + "BLS signing finished with error: " + joSignResult.errorMessage; + joRetVal.error = strError; + const strErrorMessage = + strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " BLS signing(1) finished with error: " ) + + cc.warning( joSignResult.errorMessage ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != details.id ) + log.write( strErrorMessage ); + details.write( strErrorMessage ); + } + await joCall.disconnect(); + throw new Error( strError ); + } + joSignResult.error = null; + await joCall.disconnect(); + } ); // joCall.call ... + } ); // rpcCall.create ... + } catch ( err ) { + const strError = owaspUtils.extractErrorMessage( err ); + joSignResult = { }; + joSignResult.error = strError; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + " " + + cc.error( "BLS-raw-signer error: " ) + cc.warning( strError ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != details.id ) + log.write( strErrorMessage ); + details.write( strErrorMessage ); + } + } + } + const isSuccess = ( + joSignResult && typeof joSignResult == "object" && ( !joSignResult.error ) ) + ? true : false; + if( isExposeOutput || ( !isSuccess ) ) + details.exposeDetailsTo( log, "BLS-raw-signer", isSuccess ); + details.close(); + return joSignResult; +} + +async function prepareHandlingOfSkaleImaVerifyAndSign( optsHandleVerifyAndSign ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.debug( "Will verify and sign " ) + cc.j( optsHandleVerifyAndSign.joCallData ) + + "\n" ); + } + optsHandleVerifyAndSign.nIdxCurrentMsgBlockStart = + optsHandleVerifyAndSign.joCallData.params.startMessageIdx; + optsHandleVerifyAndSign.strFromChainName = + optsHandleVerifyAndSign.joCallData.params.srcChainName; + optsHandleVerifyAndSign.strToChainName = + optsHandleVerifyAndSign.joCallData.params.dstChainName; + optsHandleVerifyAndSign.strFromChainID = + optsHandleVerifyAndSign.joCallData.params.srcChainID; + optsHandleVerifyAndSign.strToChainID = + optsHandleVerifyAndSign.joCallData.params.dstChainID; + optsHandleVerifyAndSign.strDirection = + optsHandleVerifyAndSign.joCallData.params.direction; + optsHandleVerifyAndSign.jarrMessages = + optsHandleVerifyAndSign.joCallData.params.messages; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " verification algorithm will work for transfer from chain " ) + + cc.info( optsHandleVerifyAndSign.strFromChainName ) + cc.debug( "/" ) + + cc.notice( optsHandleVerifyAndSign.strFromChainID ) + cc.debug( " to chain" ) + + cc.info( optsHandleVerifyAndSign.strToChainName ) + cc.debug( "/" ) + + cc.notice( optsHandleVerifyAndSign.strToChainID ) + + cc.debug( " and work with array of message(s) " ) + + cc.j( optsHandleVerifyAndSign.jarrMessages ) + "\n" ); + } + optsHandleVerifyAndSign.nThreshold = + discoverBlsThreshold( optsHandleVerifyAndSign.imaState.joSChainNetworkInfo ); + optsHandleVerifyAndSign.nParticipants = + discoverBlsParticipants( optsHandleVerifyAndSign.imaState.joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " verification algorithm discovered BLS threshold is " ) + + cc.info( optsHandleVerifyAndSign.nThreshold ) + cc.debug( "." ) + "\n" ); + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " verification algorithm discovered number of BLS participants is " ) + + cc.info( optsHandleVerifyAndSign.nParticipants ) + cc.debug( "." ) + "\n" ); + } + optsHandleVerifyAndSign.strMessageHash = + owaspUtils.removeStarting0x( + keccak256Message( + optsHandleVerifyAndSign.jarrMessages, + optsHandleVerifyAndSign.nIdxCurrentMsgBlockStart, + optsHandleVerifyAndSign.strFromChainName + ) + ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " verification algorithm message hash to sign is " ) + + cc.info( optsHandleVerifyAndSign.strMessageHash ) + + "\n" ); + } +} + +async function prepareS2sOfSkaleImaVerifyAndSign( optsHandleVerifyAndSign ) { + const strSChainNameSrc = optsHandleVerifyAndSign.joCallData.params.srcChainName; + const strSChainNameDst = optsHandleVerifyAndSign.joCallData.params.dstChainName; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " verification algorithm will use for source chain name " ) + + cc.info( strSChainNameSrc ) + cc.debug( " and destination chain name " ) + + cc.info( strSChainNameDst ) + "\n" ); + } + const arrSChainsCached = skaleObserver.getLastCachedSChains(); + if( ( !arrSChainsCached ) || arrSChainsCached.length == 0 ) { + throw new Error( + "Could not handle " + optsHandleVerifyAndSign.strDirection + + " skale_imaVerifyAndSign(1), no S-Chains in SKALE NETWORK " + + "observer cached yet, try again later" + ); + } + + let joSChainSrc = null, strUrlSrcSChain = null; + for( let idxSChain = 0; idxSChain < arrSChainsCached.length; ++ idxSChain ) { + const joSChain = arrSChainsCached[idxSChain]; + if( joSChain.data.name.toString() == strSChainNameSrc.toString() ) { + joSChainSrc = joSChain; + strUrlSrcSChain = skaleObserver.pickRandomSChainUrl( joSChain ); + break; + } + } + if( joSChainSrc == null || strUrlSrcSChain == null || strUrlSrcSChain.length == 0 ) { + throw new Error( + "Could not handle " + optsHandleVerifyAndSign.strDirection + + " skale_imaVerifyAndSign(2), failed to discover source " + + "chain access parameters, try again later" ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " verification algorithm discovered source chain URL is " ) + + cc.u( strUrlSrcSChain ) + cc.debug( ", chain name is " ) + + cc.info( joSChainSrc.data.computed.computedSChainId ) + cc.debug( ", chain id is " ) + + cc.info( joSChainSrc.data.computed.chainId ) + "\n" ); + } + optsHandleVerifyAndSign.joExtraSignOpts = { + skaleObserver: skaleObserver, + ethersProviderSrc: owaspUtils.getEthersProviderFromURL( strUrlSrcSChain ), + chainNameSrc: optsHandleVerifyAndSign.strFromChainName, + chainNameDst: optsHandleVerifyAndSign.strToChainName, + chainIdSrc: optsHandleVerifyAndSign.strFromChainID, + chainIdDst: optsHandleVerifyAndSign.strToChainID + }; +} + +export async function handleSkaleImaVerifyAndSign( joCallData ) { + const optsHandleVerifyAndSign = { + joCallData: joCallData, + imaState: state.get(), + strLogPrefix: "", + details: log.createMemoryStream(), + joRetVal: {}, + isSuccess: false, + nIdxCurrentMsgBlockStart: 0, + strFromChainName: "", + strToChainName: "", + strFromChainID: "", + strToChainID: "", + strDirection: "", + jarrMessages: [], + strMessageHash: "", + joExtraSignOpts: null, + nThreshold: 1, + nParticipants: 1 + }; + try { + await prepareHandlingOfSkaleImaVerifyAndSign( optsHandleVerifyAndSign ); + optsHandleVerifyAndSign.joExtraSignOpts = null; + if( optsHandleVerifyAndSign.strDirection == "S2S" ) + await prepareS2sOfSkaleImaVerifyAndSign( optsHandleVerifyAndSign ); + + await checkCorrectnessOfMessagesToSign( + optsHandleVerifyAndSign.details, optsHandleVerifyAndSign.strLogPrefix, + optsHandleVerifyAndSign.strDirection, optsHandleVerifyAndSign.jarrMessages, + optsHandleVerifyAndSign.nIdxCurrentMsgBlockStart, + optsHandleVerifyAndSign.joExtraSignOpts + ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.debug( "Will BLS-sign verified messages." ) + "\n" ); + } + let joAccount = optsHandleVerifyAndSign.imaState.chainProperties.sc.joAccount; + if( ! joAccount.strURL ) { + joAccount = optsHandleVerifyAndSign.imaState.chainProperties.mn.joAccount; + if( ! joAccount.strSgxURL ) + throw new Error( "SGX URL is unknown, cannot sign IMA message(s)" ); + if( ! joAccount.strBlsKeyName ) + throw new Error( "BLS keys name is unknown, cannot sign IMA message(s)" ); + } + let rpcCallOpts = null; + if( "strPathSslKey" in joAccount && typeof joAccount.strPathSslKey == "string" && + joAccount.strPathSslKey.length > 0 && "strPathSslCert" in joAccount && + typeof joAccount.strPathSslCert == "string" && joAccount.strPathSslCert.length > 0 + ) { + rpcCallOpts = { + "cert": fs.readFileSync( joAccount.strPathSslCert, "utf8" ), + "key": fs.readFileSync( joAccount.strPathSslKey, "utf8" ) + }; + } else { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsHandleVerifyAndSign.details.write( cc.warning( "Will sign via SGX" ) + + " " + cc.error( "without SSL options" ) + "\n" ); + } + } + const signerIndex = optsHandleVerifyAndSign.imaState.nNodeNumber; + await rpcCall.create( joAccount.strSgxURL, rpcCallOpts, async function( joCall, err ) { + if( err ) { + const strErrorMessage = optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + " " + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to SGX failed, " + + "RPC call was not created, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsHandleVerifyAndSign.details.id ) + log.write( strErrorMessage ); + optsHandleVerifyAndSign.details.write( strErrorMessage ); + } + if( joCall ) + await joCall.disconnect(); + throw new Error( + "JSON RPC call to SGX failed, RPC call was not created, error is: " + + owaspUtils.extractErrorMessage( err ) + ); + } + const joCallSGX = { + "jsonrpc": "2.0", + "id": randomCallID(), + "method": "blsSignMessageHash", + "params": { + "keyShareName": joAccount.strBlsKeyName, + "messageHash": optsHandleVerifyAndSign.strMessageHash, + "n": optsHandleVerifyAndSign.nParticipants, + "t": optsHandleVerifyAndSign.nThreshold, + "signerIndex": signerIndex + 0 // 1-based + } + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " verification algorithm will invoke " ) + cc.info( "SGX" ) + " " + + cc.debug( "with call data" ) + " " + cc.j( joCallSGX ) + "\n" ); + } + await joCall.call( joCallSGX, async function( joIn, joOut, err ) { + if( err ) { + const strError = + "JSON RPC call to SGX failed, RPC call reported error: " + + owaspUtils.extractErrorMessage( err ); + optsHandleVerifyAndSign.joRetVal.error = strError; + const jsErrorObject = new Error( strError ); + const strErrorMessage = optsHandleVerifyAndSign.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to SGX failed, " + + "RPC call reported error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( jsErrorObject.stack ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsHandleVerifyAndSign.details.id ) + log.write( strErrorMessage ); + optsHandleVerifyAndSign.details.write( strErrorMessage ); + } + await joCall.disconnect(); + throw jsErrorObject; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsHandleVerifyAndSign.details.write( optsHandleVerifyAndSign.strLogPrefix + + cc.bright( optsHandleVerifyAndSign.strDirection ) + + cc.debug( " Call to " ) + cc.info( "SGX" ) + + cc.debug( " done, answer is: " ) + cc.j( joOut ) + "\n" ); + } + let joSignResult = joOut; + if( joOut.result != null && joOut.result != undefined && + typeof joOut.result == "object" ) + joSignResult = joOut.result; + if( joOut.signResult != null && joOut.signResult != undefined && + typeof joOut.signResult == "object" ) + joSignResult = joOut.signResult; + if( "qa" in optsHandleVerifyAndSign.joCallData ) + optsHandleVerifyAndSign.joRetVal.qa = optsHandleVerifyAndSign.joCallData.qa; + if( "errorMessage" in joSignResult && + typeof joSignResult.errorMessage == "string" && + joSignResult.errorMessage.length > 0 + ) { + optsHandleVerifyAndSign.isSuccess = false; + const strError = + "BLS signing finished with error: " + joSignResult.errorMessage; + optsHandleVerifyAndSign.joRetVal.error = strError; + const strErrorMessage = optsHandleVerifyAndSign.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " BLS signing(2) finished with error: " ) + + cc.warning( joSignResult.errorMessage ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsHandleVerifyAndSign.details.id ) + log.write( strErrorMessage ); + optsHandleVerifyAndSign.details.write( strErrorMessage ); + } + await joCall.disconnect(); + throw new Error( strError ); + } + optsHandleVerifyAndSign.isSuccess = true; + optsHandleVerifyAndSign.joRetVal.result = { signResult: joSignResult }; + if( "qa" in optsHandleVerifyAndSign.joCallData ) + optsHandleVerifyAndSign.joRetVal.qa = optsHandleVerifyAndSign.joCallData.qa; + await joCall.disconnect(); + } ); // joCall.call ... + } ); // rpcCall.create ... + } catch ( err ) { + optsHandleVerifyAndSign.isSuccess = false; + const strError = owaspUtils.extractErrorMessage( err ); + optsHandleVerifyAndSign.joRetVal.error = strError; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + optsHandleVerifyAndSign.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + " " + + cc.error( "IMA messages verifier/signer error: " ) + cc.warning( strError ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.id != optsHandleVerifyAndSign.details.id ) + log.write( strErrorMessage ); + optsHandleVerifyAndSign.details.write( strErrorMessage ); + } + } + optsHandleVerifyAndSign.details.exposeDetailsTo( + log, "IMA messages verifier/signer", optsHandleVerifyAndSign.isSuccess ); + optsHandleVerifyAndSign.details.close(); + return optsHandleVerifyAndSign.joRetVal; +} + +async function handleSkaleImaBSU256Prepare( optsBSU256 ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsBSU256.details.write( optsBSU256.strLogPrefix + + cc.debug( "Will U256-BLS-sign " ) + cc.j( optsBSU256.joCallData ) + "\n" ); + } + optsBSU256.nThreshold = + discoverBlsThreshold( optsBSU256.imaState.joSChainNetworkInfo ); + optsBSU256.nParticipants = + discoverBlsParticipants( optsBSU256.imaState.joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsBSU256.details.write( optsBSU256.strLogPrefix + + cc.debug( "Discovered BLS threshold is " ) + + cc.info( optsBSU256.nThreshold ) + cc.debug( "." ) + "\n" ); + optsBSU256.details.write( optsBSU256.strLogPrefix + + cc.debug( "Discovered number of BLS participants is " ) + + cc.info( optsBSU256.nParticipants ) + cc.debug( "." ) + "\n" ); + } + optsBSU256.u256 = optsBSU256.joCallData.params.valueToSign; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsBSU256.details.write( optsBSU256.strLogPrefix + + cc.debug( "U256 original value is " ) + cc.info( optsBSU256.u256 ) + "\n" ); + } + optsBSU256.strMessageHash = keccak256U256.u256( optsBSU256.u256, true ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsBSU256.details.write( optsBSU256.strLogPrefix + + cc.debug( "hash of U256 value to sign is " ) + cc.info( optsBSU256.strMessageHash ) + + "\n" ); + optsBSU256.details.write( optsBSU256.strLogPrefix + cc.debug( "Will BLS-sign U256." ) + + "\n" ); + } + optsBSU256.joAccount = optsBSU256.imaState.chainProperties.sc.optsBSU256.joAccount; + if( ! optsBSU256.joAccount.strURL ) { + optsBSU256.joAccount = optsBSU256.imaState.chainProperties.mn.optsBSU256.joAccount; + if( ! optsBSU256.joAccount.strSgxURL ) + throw new Error( "SGX URL is unknown, cannot sign U256" ); + if( ! optsBSU256.joAccount.strBlsKeyName ) + throw new Error( "BLS keys name is unknown, cannot sign U256" ); + } +} + +export async function handleSkaleImaBSU256( joCallData ) { + const optsBSU256 = { + joCallData: joCallData, + imaState: state.get(), + strLogPrefix: "", + details: log.createMemoryStream(), + joRetVal: {}, + isSuccess: false, + nThreshold: 1, + nParticipants: 1, + u256: null, + strMessageHash: "", + joAccount: null + }; + try { + await handleSkaleImaBSU256Prepare( optsBSU256 ); + let rpcCallOpts = null; + if( "strPathSslKey" in optsBSU256.joAccount && + typeof optsBSU256.joAccount.strPathSslKey == "string" && + optsBSU256.joAccount.strPathSslKey.length > 0 && + "strPathSslCert" in optsBSU256.joAccount && + typeof optsBSU256.joAccount.strPathSslCert == "string" && + optsBSU256.joAccount.strPathSslCert.length > 0 + ) { + rpcCallOpts = { + "cert": fs.readFileSync( optsBSU256.joAccount.strPathSslCert, "utf8" ), + "key": fs.readFileSync( optsBSU256.joAccount.strPathSslKey, "utf8" ) + }; + } else { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsBSU256.details.write( cc.warning( "Will sign via SGX" ) + " " + + cc.error( "without SSL options" ) + "\n" ); + } + } + const signerIndex = optsBSU256.imaState.nNodeNumber; + await rpcCall.create( optsBSU256.joAccount.strSgxURL, rpcCallOpts, + async function( joCall, err ) { + if( err ) { + const strErrorMessage = + optsBSU256.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to SGX failed, " + + "RPC call was not created, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsBSU256.details.id ) + log.write( strErrorMessage ); + optsBSU256.details.write( strErrorMessage ); + } + if( joCall ) + await joCall.disconnect(); + throw new Error( "JSON RPC call to SGX failed, " + + "RPC call was not created, error is: " + + owaspUtils.extractErrorMessage( err ) ); + } + const joCallSGX = { + "jsonrpc": "2.0", + "id": randomCallID(), + "method": "blsSignMessageHash", + "params": { + "keyShareName": optsBSU256.joAccount.strBlsKeyName, + "messageHash": optsBSU256.strMessageHash, + "n": optsBSU256.nParticipants, + "t": optsBSU256.nThreshold, + "signerIndex": signerIndex + 0 // 1-based + } + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsBSU256.details.write( optsBSU256.strLogPrefix + cc.debug( "Will invoke " ) + + cc.info( "SGX" ) + cc.debug( " with call data " ) + cc.j( joCallSGX ) + + "\n" ); + } + await joCall.call( joCallSGX, async function( joIn, joOut, err ) { + if( err ) { + const jsErrorObject = new Error( + "JSON RPC call to SGX failed, RPC call reported error: " + + owaspUtils.extractErrorMessage( err ) ); + const strErrorMessage = + optsBSU256.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to SGX failed, " + + "RPC call reported error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( jsErrorObject.stack ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsBSU256.details.id ) + log.write( strErrorMessage ); + optsBSU256.details.write( strErrorMessage ); + } + await joCall.disconnect(); + throw jsErrorObject; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsBSU256.details.write( optsBSU256.strLogPrefix + cc.debug( "Call to " ) + + cc.info( "SGX" ) + cc.debug( " done, answer is: " ) + cc.j( joOut ) + + "\n" ); + } + let joSignResult = joOut; + if( joOut.result != null && joOut.result != undefined && + typeof joOut.result == "object" ) + joSignResult = joOut.result; + if( joOut.signResult != null && joOut.signResult != undefined && + typeof joOut.signResult == "object" ) + joSignResult = joOut.signResult; + if( "errorMessage" in joSignResult && + typeof joSignResult.errorMessage == "string" && + joSignResult.errorMessage.length > 0 ) { + optsBSU256.isSuccess = false; + const strError = + "BLS signing finished with error: " + joSignResult.errorMessage; + optsBSU256.joRetVal.error = strError; + const strErrorMessage = optsBSU256.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " BLS signing(3) finished with error: " ) + + cc.warning( joSignResult.errorMessage ) + "\n"; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.id != optsBSU256.details.id ) + log.write( strErrorMessage ); + optsBSU256.details.write( strErrorMessage ); + } + await joCall.disconnect(); + throw new Error( strError ); + } + optsBSU256.isSuccess = true; + optsBSU256.joRetVal.result = { signResult: joSignResult }; + if( "qa" in optsBSU256.joCallData ) + optsBSU256.joRetVal.qa = optsBSU256.joCallData.qa; + await joCall.disconnect(); + } ); // joCall.call ... + } ); // rpcCall.create ... + } catch ( err ) { + optsBSU256.isSuccess = false; + const strError = owaspUtils.extractErrorMessage( err ); + optsBSU256.joRetVal.error = strError; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strErrorMessage = + optsBSU256.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + " " + + cc.error( "U256-BLS-signer error: " ) + cc.warning( strError ) + + cc.error( ", stack is:" ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.id != optsBSU256.details.id ) + log.write( strErrorMessage ); + optsBSU256.details.write( strErrorMessage ); + } + } + optsBSU256.details.exposeDetailsTo( log, "U256-BLS-signer", optsBSU256.isSuccess ); + optsBSU256.details.close(); + return optsBSU256.joRetVal; +} diff --git a/agent/cli.js b/agent/cli.js deleted file mode 100644 index 0070a1ff3..000000000 --- a/agent/cli.js +++ /dev/null @@ -1,2268 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file cli.js - * @copyright SKALE Labs 2019-Present - */ - -const fs = require( "fs" ); -const { cc } = require( "./utils" ); -// const path = require( "path" ); -// const url = require( "url" ); -const os = require( "os" ); -// const shell = require( "shelljs" ); - -function init() { - rpcCall.rpcCallAddUsageRef(); - owaspUtils.owaspAddUsageRef(); -} - -const g_strAppName = "IMA AGENT"; -const g_strVersion = "1.0"; - -function print_about( isLog ) { - isLog = isLog || false; - const strMsg = cc.attention( g_strAppName ) + cc.normal( " version " ) + cc.sunny( g_strVersion ); - if( isLog ) - log.write( strMsg + "\n" ); - else - console.log( strMsg ); - return true; -} - -function parse_command_line_argument( s ) { - const joArg = { - name: "", - value: "" - }; - try { - if( !s ) - return joArg; - s = "" + s; - while( s.length > 0 && s[0] == "-" ) - s = s.substring( 1 ); - const n = s.indexOf( "=" ); - if( n < 0 ) { - joArg.name = s; - return joArg; - } - joArg.name = s.substring( 0, n ); - joArg.value = s.substring( n + 1 ); - } catch ( e ) {} - return joArg; -} - -// -// -// check correctness of command line arguments -function ensure_have_value( name, value, isExitIfEmpty, isPrintValue, fnNameColorizer, fnValueColorizer ) { - isExitIfEmpty = isExitIfEmpty || false; - isPrintValue = isPrintValue || false; - fnNameColorizer = fnNameColorizer || ( ( x ) => { - return cc.info( x ); - } ); - fnValueColorizer = fnValueColorizer || ( ( x ) => { - return cc.notice( x ); - } ); - let retVal = true; - value = value ? value.toString() : ""; - if( value.length === 0 ) { - retVal = false; - if( ! isPrintValue ) - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " missing value for " ) + fnNameColorizer( name ) ); - if( isExitIfEmpty ) - process.exit( 126 ); - } - let strDots = "..."; - let n = 50 - name.length; - for( ; n > 0; --n ) - strDots += "."; - if( isPrintValue ) - log.write( fnNameColorizer( name ) + cc.debug( strDots ) + fnValueColorizer( value ) + "\n" ); // just print value - return retVal; -} - -function ensure_have_chain_credentials( strFriendlyChainName, joAccount, isExitIfEmpty, isPrintValue ) { - strFriendlyChainName = strFriendlyChainName || ""; - if( ! ( typeof joAccount == "object" ) ) { - log.write( cc.error( "ARGUMENTS VALIDATION WARNING:" ) + - cc.warning( " bad account specified for " ) + cc.info( strFriendlyChainName ) + - cc.warning( " chain" ) + "\n" - ); - if( isExitIfEmpty ) - process.exit( 126 ); - } - if( "strTransactionManagerURL" in joAccount && typeof joAccount.strTransactionManagerURL == "string" && joAccount.strTransactionManagerURL.length > 0 ) - ensure_have_value( "" + strFriendlyChainName + "/TM/URL", joAccount.strTransactionManagerURL, isExitIfEmpty, isPrintValue ); - else if( "strSgxURL" in joAccount && typeof joAccount.strSgxURL == "string" && joAccount.strSgxURL.length > 0 && - "strSgxKeyName" in joAccount && typeof joAccount.strSgxKeyName == "string" && joAccount.strSgxKeyName.length > 0 - ) { - ensure_have_value( "" + strFriendlyChainName + "/SGX/URL", joAccount.strSgxURL, isExitIfEmpty, isPrintValue ); - ensure_have_value( "" + strFriendlyChainName + "/SGX/keyName", joAccount.strSgxKeyName, isExitIfEmpty, isPrintValue ); - if( "strPathSslKey" in joAccount && typeof joAccount.strPathSslKey == "string" && joAccount.strPathSslKey.length > 0 ) - ensure_have_value( "" + strFriendlyChainName + "/SGX/SSL/keyPath", joAccount.strPathSslKey, isExitIfEmpty, isPrintValue ); - if( "strPathSslCert" in joAccount && typeof joAccount.strPathSslCert == "string" && joAccount.strPathSslCert.length > 0 ) - ensure_have_value( "" + strFriendlyChainName + "/SGX/SSL/certPath", joAccount.strPathSslCert, isExitIfEmpty, isPrintValue ); - } else if( "privateKey" in joAccount && typeof joAccount.privateKey == "string" && joAccount.privateKey.length > 0 ) - ensure_have_value( "" + strFriendlyChainName + "/privateKey", joAccount.privateKey, isExitIfEmpty, isPrintValue ); - else if( "address_" in joAccount && typeof joAccount.address_ == "string" && joAccount.address_.length > 0 ) - ensure_have_value( "" + strFriendlyChainName + "/walletAddress", joAccount.address_, isExitIfEmpty, isPrintValue ); - else { - log.write( cc.error( "ARGUMENTS VALIDATION WARNING:" ) + - cc.warning( " bad credentials information specified for " ) + cc.info( strFriendlyChainName ) + - cc.warning( " chain, no explicit SGX, no explicit private key, no wallet address found" ) + "\n" - ); - if( isExitIfEmpty ) - process.exit( 126 ); - } - return true; -} - -function find_node_index( joSChainNodeConfiguration ) { - try { - const searchID = joSChainNodeConfiguration.skaleConfig.nodeInfo.nodeID; - const cnt = joSChainNodeConfiguration.skaleConfig.sChain.nodes.length; - for( let i = 0; i < cnt; ++i ) { - const joNodeDescription = joSChainNodeConfiguration.skaleConfig.sChain.nodes[i]; - if( joNodeDescription.nodeID == searchID ) - return i; - } - } catch ( e ) {} - return 0; // ??? -} - -function load_node_config( strPath ) { - const strLogPrefix = cc.info( "Node config:" ) + " "; - try { - strPath = imaUtils.normalizePath( strPath ); - // - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Loading values from S-Chain configuration JSON file " ) + cc.note( strPath ) + cc.debug( "..." ) + "\n" ); - const strJsonSChainNodeConfiguration = fs.readFileSync( strPath, "utf8" ); - const joSChainNodeConfiguration = JSON.parse( strJsonSChainNodeConfiguration ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.trace ) - log.write( strLogPrefix + cc.debug( "S-Chain configuration JSON: " ) + cc.j( joSChainNodeConfiguration ) + "\n" ); - // - imaState.nNodeNumber = find_node_index( joSChainNodeConfiguration ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.debug ) - log.write( strLogPrefix + cc.debug( "....from S-Chain configuration JSON file...." ) + cc.notice( "this node index" ) + cc.debug( " is " ) + cc.info( imaState.nNodeNumber ) + "\n" ); - imaState.nNodesCount = joSChainNodeConfiguration.skaleConfig.sChain.nodes.length; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.debug ) - log.write( strLogPrefix + cc.debug( "....from S-Chain configuration JSON file...." ) + cc.notice( "nodes count" ) + cc.debug( " is " ) + cc.info( imaState.nNodesCount ) + "\n" ); - // - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.success( "Done" ) + cc.debug( " loading values from S-Chain configuration JSON file " ) + cc.note( strPath ) + cc.debug( "." ) + "\n" ); - } catch ( e ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR: Exception in load_node_config():" ) + cc.error( e ) + "\n" ); - } -} - -function parse( joExternalHandlers, argv ) { - let idxArg; const cntArgs = argv || process.argv.length; - for( idxArg = 2; idxArg < cntArgs; ++idxArg ) { - const joArg = parse_command_line_argument( process.argv[idxArg] ); - if( joArg.name == "help" ) { - print_about(); - const soi = " "; // options indent - // - console.log( cc.sunny( "GENERAL" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "help" ) + cc.debug( ".........................." ) + cc.notice( "Show this " ) + cc.note( "help info" ) + cc.notice( " and exit." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "version" ) + cc.debug( "......................." ) + cc.notice( "Show " ) + cc.note( "version info" ) + cc.notice( " and exit." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "colors" ) + cc.debug( "........................" ) + cc.notice( "Use " ) + cc.rainbow( "ANSI-colorized logging" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-colors" ) + cc.debug( "....................." ) + cc.notice( "Use " ) + cc.normal( "monochrome logging" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "BLOCKCHAIN NETWORK" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "url-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( ".............." ) + cc.note( "Main-net" ) + cc.notice( " URL. Value is automatically loaded from the " ) + cc.warning( "URL_W3_ETHEREUM" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "url-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "..............." ) + cc.note( "S-chain" ) + cc.notice( " URL. Value is automatically loaded from the " ) + cc.warning( "URL_W3_S_CHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "url-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "..............." ) + cc.note( "S<->S Target S-chain" ) + cc.notice( " URL. Value is automatically loaded from the " ) + cc.warning( "URL_W3_S_CHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "id-main-net" ) + cc.sunny( "=" ) + cc.success( "number" ) + cc.debug( "............" ) + cc.note( "Main-net" ) + cc.notice( " Ethereum " ) + cc.note( "network name." ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "CHAIN_NAME_ETHEREUM" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default value is " ) + cc.sunny( "\"Mainnet\"" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "id-s-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + cc.debug( "............." ) + cc.note( "S-chain" ) + cc.notice( " Ethereum " ) + cc.note( "network name." ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "CHAIN_NAME_SCHAIN" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default value is " ) + cc.sunny( "\"id-S-chain\"" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "id-t-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + cc.debug( "............." ) + cc.note( "S<->S Target S-chain" ) + cc.notice( " Ethereum " ) + cc.note( "network name." ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "CHAIN_NAME_SCHAIN_TARET" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default value is " ) + cc.sunny( "\"id-T-chain\"" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "cid-main-net" ) + cc.sunny( "=" ) + cc.success( "number" ) + cc.debug( "..........." ) + cc.note( "Main-net" ) + cc.notice( " Ethereum " ) + cc.attention( "chain ID" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "CID_ETHEREUM" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default value is " ) + cc.sunny( -4 ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "cid-s-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + cc.debug( "............" ) + cc.note( "S-chain" ) + cc.notice( " Ethereum " ) + cc.attention( "chain ID" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "CID_SCHAIN" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default value is " ) + cc.sunny( -4 ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "cid-t-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + cc.debug( "............" ) + cc.note( "S<->S Target S-chain" ) + cc.notice( " Ethereum " ) + cc.attention( "chain ID" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "CID_SCHAIN_TARGET" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default value is " ) + cc.sunny( -4 ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "BLOCKCHAIN INTERFACE" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "abi-skale-manager" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "........" ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "Skale Manager" ) + cc.notice( " ABI. " ) + cc.debug( "Optional parameter. It's needed for " ) + cc.note( "S-Chain" ) + cc.debug( " to " ) + cc.note( "S-Chain" ) + cc.debug( " transfers." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "abi-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "............." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "IMA" ) + cc.notice( " ABI for " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "abi-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( ".............." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "IMA" ) + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "abi-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( ".............." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "IMA" ) + cc.notice( " ABI for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "ERC20 INTERFACE" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc20-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "..........." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC20" ) + cc.notice( " ABI for " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc20-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "............" ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC20" ) + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "addr-erc20-s-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + cc.debug( "...." ) + cc.notice( "Explicit " ) + cc.bright( "ERC20" ) + cc.notice( " address in " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc20-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "............" ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC20" ) + cc.notice( " ABI for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "addr-erc20-t-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + cc.debug( "...." ) + cc.notice( "Explicit " ) + cc.bright( "ERC20" ) + cc.notice( " address in " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "ERC721 INTERFACE" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc721-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( ".........." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC721" ) + cc.notice( " ABI for " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc721-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "..........." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC721" ) + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "addr-erc721-s-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + cc.debug( "..." ) + cc.notice( "Explicit " ) + cc.bright( "ERC721" ) + cc.notice( " address in " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc721-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "..........." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC721" ) + cc.notice( " ABI for " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "addr-erc721-t-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + cc.debug( "..." ) + cc.notice( "Explicit " ) + cc.bright( "ERC721" ) + cc.notice( " address in " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "ERC1155 INTERFACE" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc1155-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "........." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC1155" ) + cc.notice( " ABI for " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc1155-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( ".........." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC1155" ) + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "addr-erc1155-s-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + cc.debug( ".." ) + cc.notice( "Explicit " ) + cc.bright( "ERC1155" ) + cc.notice( " address in " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "erc1155-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( ".........." ) + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC1155" ) + cc.notice( " ABI for " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "addr-erc1155-t-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + cc.debug( ".." ) + cc.notice( "Explicit " ) + cc.bright( "ERC1155" ) + cc.notice( " address in " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "USER ACCOUNT" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tm-url-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "..........." ) + cc.bright( "Transaction Manager" ) + cc.notice( " server URL for " ) + cc.note( "Main-net" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "TRANSACTION_MANAGER_URL_ETHEREUM" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Example: " ) + cc.bright( "redis://@127.0.0.1:6379" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tm-url-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "............" ) + cc.bright( "Transaction Manager" ) + cc.notice( " server URL for " ) + cc.note( "S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "TRANSACTION_MANAGER_URL_S_CHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tm-url-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "............" ) + cc.bright( "Transaction Manager" ) + cc.notice( " server URL for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "TRANSACTION_MANAGER_URL_S_CHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tm-priority-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "......" ) + cc.bright( "Transaction Manager" ) + cc.notice( " priority for " ) + cc.note( "Main-net" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "TRANSACTION_MANAGER_PRIORITY_ETHEREUM" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default is " ) + cc.sunny( "5" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tm-priority-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "......." ) + cc.bright( "Transaction Manager" ) + cc.notice( " priority for " ) + cc.note( "S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "TRANSACTION_MANAGER_PRIORITY_S_CHAIN" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default is " ) + cc.sunny( "5" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tm-priority-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "......." ) + cc.bright( "Transaction Manager" ) + cc.notice( " priority for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "TRANSACTION_MANAGER_PRIORITY_S_CHAIN_TARGET" ) + cc.notice( " environment variable if not specified. " ) + cc.debug( "Default is " ) + cc.sunny( "5" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-url-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( ".........." ) + cc.sunny( "SGX server" ) + cc.notice( " URL for " ) + cc.note( "Main-net" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_URL_ETHEREUM" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-url-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "..........." ) + cc.sunny( "SGX server" ) + cc.notice( " URL for " ) + cc.note( "S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_URL_S_CHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-url-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + cc.debug( "..........." ) + cc.sunny( "SGX server" ) + cc.notice( " URL for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_URL_S_CHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ecdsa-key-main-net" ) + cc.sunny( "=" ) + cc.error( "name" ) + cc.debug( "..." ) + cc.attention( "SGX/ECDSA key name" ) + cc.notice( " for " ) + cc.note( "Main-net" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_KEY_ETHEREUM" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ecdsa-key-s-chain" ) + cc.sunny( "=" ) + cc.error( "name" ) + cc.debug( "...." ) + cc.attention( "SGX/ECDSA key name" ) + cc.notice( " for " ) + cc.note( "S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_KEY_S_CHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ecdsa-key-t-chain" ) + cc.sunny( "=" ) + cc.error( "name" ) + cc.debug( "...." ) + cc.attention( "SGX/ECDSA key name" ) + cc.notice( " for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_KEY_S_CHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - // - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ssl-key-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "....." ) + cc.notice( "Path to " ) + cc.note( "SSL key file" ) + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "Main-net" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_SSL_KEY_FILE_ETHEREUM" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ssl-key-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "......" ) + cc.notice( "Path to " ) + cc.note( "SSL key file" ) + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_SSL_KEY_FILE_S_CHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ssl-key-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "......" ) + cc.notice( "Path to " ) + cc.note( "SSL key file" ) + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_SSL_KEY_FILE_S_CHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ssl-cert-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "...." ) + cc.notice( "Path to " ) + cc.note( "SSL certificate file" ) + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "Main-net" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_SSL_CERT_FILE_ETHEREUM" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ssl-cert-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "....." ) + cc.notice( "Path to " ) + cc.note( "SSL certificate file" ) + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_SSL_CERT_FILE_S_CHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sgx-ssl-cert-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + cc.debug( "....." ) + cc.notice( "Path to " ) + cc.note( "SSL certificate file" ) + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "SGX_SSL_CERT_FILE_S_CHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - // - console.log( soi + cc.debug( "--" ) + cc.bright( "address-main-net" ) + cc.sunny( "=" ) + cc.warning( "value" ) + cc.debug( "........" ) + cc.note( "Main-net" ) + " " + cc.attention( "user account address" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "ACCOUNT_FOR_ETHEREUM" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "address-s-chain" ) + cc.sunny( "=" ) + cc.warning( "value" ) + cc.debug( "........." ) + cc.note( "S-chain" ) + " " + cc.attention( "user account address" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "ACCOUNT_FOR_SCHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "address-t-chain" ) + cc.sunny( "=" ) + cc.warning( "value" ) + cc.debug( "........." ) + cc.note( "S<->S Target S-chain" ) + " " + cc.attention( "user account address" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "ACCOUNT_FOR_SCHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "key-main-net" ) + cc.sunny( "=" ) + cc.error( "value" ) + cc.debug( "............" ) + cc.attention( "Private key" ) + cc.notice( " for " ) + cc.note( "Main-net" ) + " " + cc.attention( "user account address" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "PRIVATE_KEY_FOR_ETHEREUM" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "key-s-chain" ) + cc.sunny( "=" ) + cc.error( "value" ) + cc.debug( "............." ) + cc.attention( "Private key" ) + cc.notice( " for " ) + cc.note( "S-Chain" ) + " " + cc.attention( "user account address" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "PRIVATE_KEY_FOR_SCHAIN" ) + cc.notice( " environment variable if not specified." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "key-t-chain" ) + cc.sunny( "=" ) + cc.error( "value" ) + cc.debug( "............." ) + cc.attention( "Private key" ) + cc.notice( " for " ) + cc.note( "S<->S Target S-Chain" ) + " " + cc.attention( "user account address" ) + cc.notice( ". Value is automatically loaded from the " ) + cc.warning( "PRIVATE_KEY_FOR_SCHAIN_TARGET" ) + cc.notice( " environment variable if not specified." ) ); - // - console.log( soi + cc.debug( "Please notice, IMA prefer to use transaction manager to sign blockchain transactions if " ) + - cc.attention( "--tm-url-main-net" ) + cc.debug( "/" ) + cc.attention( "--tm-url-s-chain" ) + cc.debug( " command line values or " ) + - cc.warning( "TRANSACTION_MANAGER_URL_ETHEREUM" ) + cc.debug( "/" ) + cc.warning( "TRANSACTION_MANAGER_URL_S_CHAIN" ) + - cc.debug( " shell variables were specified. Next preferred option is SGX wallet which is used if " ) + - cc.attention( "--sgx-url-main-net" ) + cc.debug( "/" ) + cc.attention( "--sgx-url-s-chain" ) + cc.debug( " command line values or " ) + - cc.warning( "SGX_URL_ETHEREUM" ) + cc.debug( "/" ) + cc.warning( "SGX_URL_S_CHAIN" ) + - cc.debug( " shell variables were specified. SGX signing also needs key name, key and certificate files. " ) + - cc.debug( "Finally, IMA attempts to use explicitly provided private key to sign blockchain transactions if " ) + - cc.attention( "--key-main-net" ) + cc.debug( "/" ) + cc.attention( "--key-s-chain" ) + cc.debug( " command line values or " ) + - cc.warning( "PRIVATE_KEY_FOR_ETHEREUM" ) + cc.debug( "/" ) + cc.warning( "PRIVATE_KEY_FOR_SCHAIN" ) + - cc.debug( " shell variables were specified. " ) - ); - // - console.log( cc.sunny( "GENERAL TRANSFER" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "value" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.warning( "unitName" ) + cc.debug( ".........." ) + cc.notice( "Amount of " ) + cc.attention( "unitName" ) + cc.notice( " to transfer, where " ) + cc.attention( "unitName" ) + cc.notice( " is well known Ethereum unit name like " ) + cc.attention( "ether" ) + cc.notice( " or " ) + cc.attention( "wei" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "wei" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "...................." ) + cc.notice( "Amount of " ) + cc.attention( "wei" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "babbage" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "................" ) + cc.notice( "Amount of " ) + cc.attention( "babbage" ) + cc.info( "(wei*1000)" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "lovelace" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "..............." ) + cc.notice( "Amount of " ) + cc.attention( "lovelace" ) + cc.info( "(wei*1000*1000)" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "shannon" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "................" ) + cc.notice( "Amount of " ) + cc.attention( "shannon" ) + cc.info( "(wei*1000*1000*1000)" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "szabo" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( ".................." ) + cc.notice( "Amount of " ) + cc.attention( "szabo" ) + cc.info( "(wei*1000*1000*1000*1000)" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "finney" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "................." ) + cc.notice( "Amount of " ) + cc.attention( "finney" ) + cc.info( "(wei*1000*1000*1000*1000*1000)" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "ether" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( ".................." ) + cc.notice( "Amount of " ) + cc.attention( "ether" ) + cc.info( "(wei*1000*1000*1000*1000*1000*1000)" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "amount" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "................." ) + cc.notice( "Amount of " ) + cc.attention( "tokens" ) + cc.notice( " to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tid" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "...................." ) + cc.bright( "ERC721" ) + cc.notice( " or " ) + cc.bright( "ERC1155" ) + cc.notice( " token id to transfer." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "amounts" ) + cc.sunny( "=" ) + cc.attention( "array of numbers" ) + cc.debug( "......" ) + cc.bright( "ERC1155" ) + cc.notice( " token id to transfer in batch." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "tids" ) + cc.sunny( "=" ) + cc.attention( "array of numbers" ) + cc.debug( "........." ) + cc.bright( "ERC1155" ) + cc.notice( " token amount to transfer in batch." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sleep-between-tx" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "......." ) + cc.notice( "Sleep time " ) + cc.debug( "(in milliseconds)" ) + cc.notice( " between transactions during complex operations." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "wait-next-block" ) + cc.debug( "..............." ) + cc.notice( "Wait for next block between transactions during complex operations." ) ); - // - console.log( cc.sunny( "S-CHAIN TO S-CHAIN TRANSFER" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-enable" ) + cc.debug( "...................." ) + cc.success( "Enables" ) + " " + cc.note( "S-Chain" ) + cc.notice( " to " ) + cc.note( "S-Chain" ) + cc.notice( " transfers. " ) + cc.debug( "Default mode" ) + cc.notice( ". The " ) + cc.bright( "abi-skale-manager" ) + cc.notice( " path must be provided." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-disable" ) + cc.debug( "..................." ) + cc.error( "Disables" ) + " " + cc.note( "S-Chain" ) + cc.notice( " to " ) + cc.note( "S-Chain" ) + cc.notice( " transfers." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "net-rediscover" ) + cc.sunny( "=" ) + cc.attention( "number" ) + cc.debug( "........." ) + cc.note( "SKALE NETWORK" ) + cc.notice( " re-discovery interval" ) + cc.debug( "(in seconds)" ) + cc.notice( ". " ) + cc.debug( "Default is " ) + cc.sunny( "3600" ) + cc.debug( " seconds or " ) + cc.sunny( "1" ) + cc.debug( " hour, specify " ) + cc.sunny( "0" ) + cc.debug( " to " ) + cc.error( "disable" ) + " " + cc.note( "SKALE NETWORK" ) + cc.debug( " re-discovery" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "PAYMENT TRANSACTION" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-price-multiplier-mn" ) + cc.debug( "......." ) + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + cc.notice( " for " ) + cc.note( "Main Net" ) + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + cc.sunny( "1.25" ) + cc.notice( "." ) + cc.debug( " Specify value " ) + cc.sunny( "0.0" ) + cc.debug( " to " ) + cc.error( "disable" ) + " " + cc.attention( "Gas Price Customization" ) + cc.debug( " for " ) + cc.note( "Main Net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-price-multiplier-sc" ) + cc.debug( "......." ) + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + cc.notice( " for " ) + cc.note( "S-Chain" ) + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + cc.sunny( "0.0" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-price-multiplier-tc" ) + cc.debug( "......." ) + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + cc.notice( " for " ) + cc.note( "S<->S Target S-Chain" ) + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + cc.sunny( "0.0" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-price-multiplier" ) + cc.debug( ".........." ) + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + cc.notice( " for both " ) + cc.note( "Main Net" ) + cc.notice( " and " ) + cc.note( "S-Chain" ) + cc.debug( "(s)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-multiplier-mn" ) + cc.debug( "............." ) + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + cc.notice( " for " ) + cc.note( "Main Net" ) + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + cc.sunny( "1.25" ) + cc.notice( "." ) + cc.debug( " Specify value " ) + cc.sunny( "0.0" ) + cc.debug( " to " ) + cc.error( "disable" ) + " " + cc.attention( "Gas Price Customization" ) + cc.debug( " for " ) + cc.note( "Main Net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-multiplier-sc" ) + cc.debug( "............." ) + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + cc.notice( " for " ) + cc.note( "S-Chain" ) + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + cc.sunny( "1.25" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-multiplier-tc" ) + cc.debug( "............." ) + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + cc.notice( " for " ) + cc.note( "S<->S Target S-Chain" ) + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + cc.sunny( "1.25" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gas-multiplier" ) + cc.debug( "................" ) + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + cc.notice( " for both " ) + cc.note( "Main Net" ) + cc.notice( " and " ) + cc.note( "S-Chain" ) + cc.debug( "(s)" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "REGISTRATION" ) + cc.info( " commands:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "register" ) + cc.debug( "......................" ) + cc.notice( "Register" ) + cc.debug( "(perform " ) + cc.sunny( "all steps" ) + cc.debug( ")" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "register1" ) + cc.debug( "....................." ) + cc.notice( "Perform registration " ) + cc.sunny( "step 1" ) + cc.notice( " - register " ) + cc.note( "S-Chain" ) + cc.notice( " on " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "check-registration" ) + cc.debug( "............" ) + cc.notice( "Perform registration status check" ) + cc.debug( "(perform " ) + cc.sunny( "all steps" ) + cc.debug( ")" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "check-registration1" ) + cc.debug( "..........." ) + cc.notice( "Perform registration status check " ) + cc.sunny( "step 1" ) + cc.notice( " - register " ) + cc.note( "S-Chain" ) + cc.notice( " on " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "check-registration2" ) + cc.debug( "..........." ) + cc.notice( "Perform registration status check " ) + cc.sunny( "step 2" ) + cc.notice( " - register " ) + cc.note( "S-Chain" ) + cc.notice( " in " ) + cc.attention( "deposit box" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "check-registration3" ) + cc.debug( "..........." ) + cc.notice( "Perform registration status check " ) + cc.sunny( "step 3" ) + cc.notice( " - register " ) + cc.note( "Main-net" ) + cc.notice( "'s " ) + cc.attention( "deposit box" ) + cc.notice( " on " ) + cc.note( "S-Chain" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "ACTION" ) + cc.info( " commands:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "show-config" ) + cc.debug( "..................." ) + cc.notice( "Show " ) + cc.note( "configuration values" ) + cc.notice( " and exit." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "show-balance" ) + cc.debug( ".................." ) + cc.notice( "Show " ) + cc.note( "ETH" ) + cc.notice( " and/or token balances on " ) + cc.note( "Main-net" ) + cc.notice( " and/or " ) + cc.note( "S-Chain" ) + cc.notice( " and exit." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "m2s-payment" ) + cc.debug( "..................." ) + cc.notice( "Do one payment from " ) + cc.note( "Main-net" ) + cc.notice( " user account to " ) + cc.note( "S-chain" ) + cc.notice( " user account." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-payment" ) + cc.debug( "..................." ) + cc.notice( "Do one payment from " ) + cc.note( "S-chain" ) + cc.notice( " user account to " ) + cc.note( "Main-net" ) + cc.notice( " user account." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-receive" ) + cc.debug( "..................." ) + cc.notice( "Receive one payment from " ) + cc.note( "S-chain" ) + cc.notice( " user account to " ) + cc.note( "Main-net" ) + cc.notice( " user account" ) + cc.debug( "(ETH only, receives all the ETH pending in transfer)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-view" ) + cc.debug( "......................" ) + cc.notice( "View money amount user can receive as payment from " ) + cc.note( "S-chain" ) + cc.notice( " user account to " ) + cc.note( "Main-net" ) + cc.notice( " user account" ) + cc.debug( "(ETH only, receives all the ETH pending in transfer)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-payment" ) + cc.debug( "..................." ) + cc.notice( "Do one payment from " ) + cc.note( "S-chain" ) + cc.notice( " user account to other " ) + cc.note( "S-chain" ) + cc.notice( " user account." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-forward" ) + cc.debug( "..................." ) + cc.notice( "Indicates " ) + cc.note( "S<->S" ) + cc.notice( " transfer direction is " ) + cc.attention( "forward" ) + cc.notice( ". I.e. source " ) + cc.note( "S-chain" ) + cc.notice( " is token minter and instantiator. " ) + cc.debug( "This is default mode" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-reverse" ) + cc.debug( "..................." ) + cc.notice( "Indicates " ) + cc.note( "S<->S" ) + cc.notice( " transfer direction is " ) + cc.attention( "reverse" ) + cc.notice( ". I.e. destination " ) + cc.note( "S-chain" ) + cc.notice( " is token minter and instantiator." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "m2s-transfer" ) + cc.debug( ".................." ) + cc.notice( "Do single " ) + cc.attention( "money transfer loop" ) + cc.notice( " from " ) + cc.note( "Main-net" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-transfer" ) + cc.debug( ".................." ) + cc.notice( "Do single " ) + cc.attention( "money transfer loop" ) + cc.notice( " from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-transfer" ) + cc.debug( ".................." ) + cc.notice( "Do single " ) + cc.attention( "money transfer loop" ) + cc.notice( " from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "with-metadata" ) + cc.debug( "................." ) + cc.notice( "Makes " ) + cc.bright( "ERC721" ) + cc.notice( " transfer using special version of " ) + cc.bright( "Token Manager" ) + cc.notice( " to transfer token metadata." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "transfer" ) + cc.debug( "......................" ) + cc.notice( "Run single " ) + cc.note( "M<->S" ) + cc.notice( " and, optionally, " ) + cc.note( "S->S" ) + cc.notice( " transfer loop iteration" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "loop" ) + cc.debug( ".........................." ) + cc.notice( "Run " ) + cc.note( "M<->S" ) + cc.notice( " and, optionally, " ) + cc.note( "S->S" ) + cc.notice( " transfer loop." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "load-node-config" ) + cc.sunny( "=" ) + cc.success( "path" ) + cc.debug( "........." ) + cc.notice( "Use specified " ) + cc.note( "S-Chain" ) + cc.notice( " node JSON configuration file to load parameters" ) + cc.debug( "(like " ) + cc.attention( "node index" ) + cc.debug( ", " ) + cc.attention( "nodes count" ) + cc.debug( ")" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "ADDITIONAL ACTION" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-wait-s-chain" ) + cc.debug( "..............." ) + cc.notice( "Do not wait until " ) + cc.note( "S-Chain" ) + cc.notice( " is started." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "max-wait-attempts" ) + cc.sunny( "=" ) + cc.info( "value" ) + cc.debug( "......." ) + cc.notice( "Max number of " ) + cc.note( "S-Chain" ) + cc.notice( " call attempts to do while it became alive and sane." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "skip-dry-run" ) + cc.debug( ".................." ) + cc.notice( "Skip " ) + cc.note( "dry run" ) + cc.notice( " contract method calls." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "ignore-dry-run" ) + cc.debug( "................" ) + cc.notice( "Ignore result of " ) + cc.note( "dry run" ) + cc.notice( " contract method calls and continue execute." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "dry-run" ) + cc.debug( "......................." ) + cc.notice( "Use error results of " ) + cc.note( "dry run" ) + cc.notice( " contract method calls as actual errors and stop execute." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "m2s-transfer-block-size" ) + cc.debug( "......." ) + cc.notice( "Number of transactions in one block to use in money transfer loop from " ) + cc.note( "Main-net" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-transfer-block-size" ) + cc.debug( "......." ) + cc.notice( "Number of transactions in one block to use in money transfer loop from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-transfer-block-size" ) + cc.debug( "......." ) + cc.notice( "Number of transactions in one block to use in money transfer loop from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "transfer-block-size" ) + cc.debug( "..........." ) + cc.notice( "Number of transactions in one block to use in both money transfer loops." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "m2s-max-transactions" ) + cc.debug( ".........." ) + cc.notice( "Maximal number of transactions to do in money transfer loop from " ) + cc.note( "Main-net" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is unlimited)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-max-transactions" ) + cc.debug( ".........." ) + cc.notice( "Maximal number of transactions to do in money transfer loop from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is unlimited)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-max-transactions" ) + cc.debug( ".........." ) + cc.notice( "Maximal number of transactions to do in money transfer loop from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is unlimited)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "max-transactions" ) + cc.debug( ".............." ) + cc.notice( "Maximal number of transactions to do in both money transfer loops" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is unlimited)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "m2s-await-blocks" ) + cc.debug( ".............." ) + cc.notice( "Maximal number of blocks to wait to appear in blockchain before transaction from " ) + cc.note( "Main-net" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-await-blocks" ) + cc.debug( ".............." ) + cc.notice( "Maximal number of blocks to wait to appear in blockchain before transaction from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-await-blocks" ) + cc.debug( ".............." ) + cc.notice( "Maximal number of blocks to wait to appear in blockchain before transaction from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "await-blocks" ) + cc.debug( ".................." ) + cc.notice( "Maximal number of blocks to wait to appear in blockchain before transaction between both " ) + cc.note( "S-chain" ) + cc.notice( " and " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + cc.sunny( "0 " ) + cc.debug( "is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "m2s-await-time" ) + cc.debug( "................" ) + cc.notice( "Minimal age of transaction message" ) + cc.debug( "(in seconds)" ) + cc.notice( " before it will be transferred from " ) + cc.note( "Main-net" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2m-await-time" ) + cc.debug( "................" ) + cc.notice( "Minimal age of transaction message" ) + cc.debug( "(in seconds)" ) + cc.notice( " before it will be transferred from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "s2s-await-time" ) + cc.debug( "................" ) + cc.notice( "Minimal age of transaction message" ) + cc.debug( "(in seconds)" ) + cc.notice( " before it will be transferred from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "await-time" ) + cc.debug( "...................." ) + cc.notice( "Minimal age of transaction message" ) + cc.debug( "(in seconds)" ) + cc.notice( " before it will be transferred between both " ) + cc.note( "S-chain" ) + cc.notice( " and " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "period" ) + cc.debug( "........................" ) + cc.notice( "Transfer " ) + cc.note( "loop period" ) + cc.debug( "(in seconds)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "node-number" ) + cc.sunny( "=" ) + cc.info( "value" ) + cc.debug( "............." ) + cc.note( "S-Chain" ) + " " + cc.bright( "node number" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( "-based)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "nodes-count" ) + cc.sunny( "=" ) + cc.info( "value" ) + cc.debug( "............." ) + cc.note( "S-Chain" ) + " " + cc.bright( "nodes count" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "time-framing" ) + cc.sunny( "=" ) + cc.note( "value" ) + cc.debug( "............" ) + cc.notice( "Specifies " ) + cc.note( "period" ) + cc.debug( "(in seconds) " ) + cc.note( "for time framing" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " to " ) + cc.error( "disable" ) + cc.debug( " time framing)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "time-gap" ) + cc.sunny( "=" ) + cc.note( "value" ) + cc.debug( "................" ) + cc.notice( "Specifies " ) + cc.note( "gap" ) + cc.debug( "(in seconds) " ) + cc.note( "before next time frame" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "auto-exit" ) + cc.sunny( "=" ) + cc.note( "seconds" ) + cc.debug( "............." ) + cc.notice( "Automatically exit " ) + cc.bright( "IMA Agent" ) + cc.notice( " after specified number of seconds" ) + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no automatic exit, " ) + cc.sunny( "3600" ) + cc.debug( " is no default)" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "TOKEN TESTING" ) + cc.info( " commands:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "mint-erc20" ) + cc.debug( "...................." ) + cc.notice( "Mint " ) + cc.note( "ERC20" ) + cc.notice( " tokens." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "mint-erc721" ) + cc.debug( "..................." ) + cc.notice( "Mint " ) + cc.note( "ERC721" ) + cc.notice( " tokens." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "mint-erc1155" ) + cc.debug( ".................." ) + cc.notice( "Mint " ) + cc.note( "ERC1155" ) + cc.notice( " tokens." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "burn-erc20" ) + cc.debug( "...................." ) + cc.notice( "Burn " ) + cc.note( "ERC20" ) + cc.notice( " tokens." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "burn-erc721" ) + cc.debug( "..................." ) + cc.notice( "Burn " ) + cc.note( "ERC721" ) + cc.notice( " tokens." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "burn-erc1155" ) + cc.debug( ".................." ) + cc.notice( "Burn " ) + cc.note( "ERC1155" ) + cc.notice( " tokens." ) ); - console.log( soi + cc.debug( "Please notice, token testing commands require " ) + - cc.attention( "--tm-url-t-chain" ) + cc.debug( ", " ) + cc.attention( "cid-t-chain" ) + cc.debug( ", " ) + - cc.attention( "erc20-t-chain" ) + cc.debug( " or " ) + cc.attention( "erc721-t-chain" ) + cc.debug( " or " ) + - cc.attention( "erc1155-t-chain" ) + cc.debug( ", account information (like private key " ) + - cc.attention( "key-t-chain" ) + cc.debug( ") command line arguments specified. Token amounts are specified via " ) + - cc.attention( "amount" ) + cc.debug( " command line arguments specified. Token IDs are specified via " ) + - cc.attention( "tid" ) + cc.debug( " or " ) + cc.attention( "tids" ) + cc.debug( " command line arguments." ) - ); - // - console.log( cc.sunny( "PENDING TRANSACTIONS ANALYSIS" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "ptx" ) + cc.debug( "..........................." ) + cc.success( "Enable" ) + " " + cc.attention( "pending transaction analysis" ) + cc.notice( " to avoid transaction conflicts." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-ptx" ) + cc.debug( "........................" ) + cc.error( "Disable" ) + " " + cc.attention( "pending transaction analysis" ) + cc.notice( ". " ) + cc.warning( "Not recommended" ) + cc.notice( " for slow and overloaded blockchains." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "ptx-attempt" ) + cc.sunny( "=" ) + cc.info( "value" ) + cc.debug( "............." ) + cc.note( "Timeout " ) + cc.debug( "(in seconds)" ) + cc.notice( " to perform secondary " ) + cc.attention( "pending transaction analysis" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "ptx-ignore" ) + cc.debug( "...................." ) + cc.error( "Ignore" ) + cc.notice( " result of " ) + cc.attention( "pending transaction analysis" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-ptx-ignore" ) + cc.debug( "................." ) + cc.success( "Do not ignore" ) + cc.notice( " result of " ) + cc.attention( "pending transaction analysis" ) + cc.notice( ". Transfer loop will be delayed until " ) + cc.attention( "pending transactions disappear" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "ptx-ignore2" ) + cc.debug( "..................." ) + cc.error( "Ignore" ) + cc.notice( " secondary result of " ) + cc.attention( "pending transaction analysis" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-ptx-ignore2" ) + cc.debug( "................" ) + cc.success( "Do not ignore" ) + cc.notice( " secondary result of " ) + cc.attention( "pending transaction analysis" ) + cc.notice( ". Transfer loop will be delayed until " ) + cc.attention( "pending transactions disappear" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "MESSAGE SIGNING" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "sign-messages" ) + cc.debug( "................." ) + cc.notice( "Sign transferred messages." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "bls-glue" ) + cc.sunny( "=" ) + cc.note( "path" ) + cc.debug( "................." ) + cc.notice( "Specifies path to " ) + cc.note( "bls_glue" ) + cc.notice( " application." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "hash-g1" ) + cc.sunny( "=" ) + cc.note( "path" ) + cc.debug( ".................." ) + cc.notice( "Specifies path to " ) + cc.note( "hash_g1" ) + cc.notice( " application." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "bls-verify" ) + cc.sunny( "=" ) + cc.note( "path" ) + cc.debug( "..............." ) + cc.debug( "Optional parameter, specifies path to " ) + cc.note( "verify_bls" ) + cc.debug( " application." ) ); - // - console.log( cc.sunny( "MONITORING" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "monitoring-port" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "........" ) + cc.notice( "Run " ) + cc.note( "monitoring web socket RPC server" ) + cc.notice( " on specified port. " ) + cc.debug( "By default monitoring server is " ) + cc.error( "disabled" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "GAS REIMBURSEMENT" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-chain" ) + cc.sunny( "=" ) + cc.note( "name" ) + cc.debug( "......" ) + cc.notice( "Specifies chain name." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-recharge" ) + cc.sunny( "=" ) + cc.note( "v" ) + cc.warning( "u" ) + cc.debug( "....." ) + cc.success( "Recharge" ) + cc.notice( " user wallet with specified value " ) + cc.attention( "v" ) + cc.notice( ", unit name " ) + cc.attention( "u" ) + cc.notice( " is well known Ethereum unit name like " ) + cc.attention( "ether" ) + cc.notice( " or " ) + cc.attention( "wei" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-withdraw" ) + cc.sunny( "=" ) + cc.note( "v" ) + cc.warning( "u" ) + cc.debug( "....." ) + cc.error( "Withdraw" ) + cc.notice( " user wallet with specified value " ) + cc.attention( "v" ) + cc.notice( ", unit name " ) + cc.attention( "u" ) + cc.notice( " is well known Ethereum unit name like " ) + cc.attention( "ether" ) + cc.notice( " or " ) + cc.attention( "wei" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-balance" ) + cc.debug( "........." ) + cc.notice( "Show wallet balance." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "reimbursement-range" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "...." ) + cc.notice( "Sets " ) + cc.note( "minimal time interval" ) + cc.notice( " between transfers from " ) + cc.note( "S-Chain" ) + cc.notice( " to " ) + cc.note( "Main Net" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "PAST EVENTS SCAN" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "bs-step-size" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "..........." ) + cc.notice( "Specifies " ) + cc.note( "step block range size" ) + cc.notice( " to search iterative past events step by step. " ) + cc.sunny( "0" ) + cc.notice( " to " ) + cc.error( "disable" ) + cc.notice( " iterative search." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "bs-max-all-range" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "......." ) + cc.notice( "Specifies " ) + cc.note( "max number of steps" ) + cc.notice( " to allow to search as [0...latest] range. " ) + cc.sunny( "0" ) + cc.notice( " to " ) + cc.error( "disable" ) + cc.notice( " iterative search." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "bs-progressive-enable" ) + cc.debug( "........." ) + cc.success( "Enables" ) + " " + cc.attention( "progressive block scan" ) + cc.notice( " to search past events." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "bs-progressive-disable" ) + cc.debug( "........" ) + cc.error( "Disables" ) + " " + cc.attention( "progressive block scan" ) + cc.notice( " to search past events." ) ); - // - console.log( cc.sunny( "ORACLE BASED GAS REIMBURSEMENT" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "enable-oracle" ) + cc.debug( "................." ) + cc.success( "Enable" ) + cc.notice( " call to " ) + cc.note( "Oracle" ) + cc.notice( " to compute " ) + cc.note( "gas price" ) + cc.notice( " for " ) + cc.attention( "gas reimbursement" ) + cc.notice( ". " ) + cc.debug( "Default mode" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "disable-oracle" ) + cc.debug( "................" ) + cc.error( "Disable" ) + cc.notice( " call to " ) + cc.note( "Oracle" ) + cc.notice( " to compute " ) + cc.note( "gas price" ) + cc.notice( " for " ) + cc.attention( "gas reimbursement" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "TEST" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "browse-s-chain" ) + cc.debug( "................" ) + cc.notice( "Download own " ) + cc.note( "S-Chain" ) + cc.notice( " network information." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "browse-skale-network" ) + cc.debug( ".........." ) + cc.notice( "Download entire " ) + cc.note( "SKALE network" ) + cc.notice( " description." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "browse-connected-schains" ) + cc.debug( "......" ) + cc.notice( "Download " ) + cc.note( "S-Chains" ) + cc.notice( " conected to " ) + cc.note( "S-Chain" ) + cc.notice( " with name specified in " ) + cc.bright( "id-s-chain" ) + cc.notice( " command line parameter." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "discover-cid" ) + cc.debug( ".................." ) + cc.notice( "Discover " ) + cc.attention( "chains ID(s)" ) + cc.notice( " from provided " ) + cc.note( "URL(s)" ) + cc.notice( "." ) + cc.debug( " This command is not executed automatically at startup" ) + cc.notice( "." ) ); - // - console.log( cc.sunny( "LOGGING" ) + cc.info( " options:" ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "expose" ) + cc.debug( "........................" ) + cc.notice( "Expose " ) + cc.note( "low-level log details" ) + cc.notice( " after " ) + cc.success( "successful operations" ) + cc.notice( ". " ) + cc.debug( "By default details exposed only " ) + cc.error( "on errors" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-expose" ) + cc.debug( "....................." ) + cc.notice( "Expose " ) + cc.note( "low-level log details" ) + cc.notice( " only after " ) + cc.error( "errors" ) + cc.notice( ". " ) + cc.debug( "Default expose mode" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "verbose" ) + cc.sunny( "=" ) + cc.bright( "value" ) + cc.debug( "................." ) + cc.notice( "Set " ) + cc.note( "level" ) + cc.notice( " of output details." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "verbose-list" ) + cc.debug( ".................." ) + cc.notice( "List available " ) + cc.note( "verbose levels" ) + cc.notice( " and exit." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "log" ) + cc.sunny( "=" ) + cc.note( "path" ) + cc.debug( "......................" ) + cc.notice( "Write program output to specified " ) + cc.note( "log file" ) + cc.debug( "(multiple files can be specified)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "log-size" ) + cc.sunny( "=" ) + cc.note( "value" ) + cc.debug( "................" ) + cc.notice( "Max size" ) + cc.debug( "(in bytes)" ) + cc.notice( " of one log file" ) + cc.debug( "(affects to log log rotation)" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "log-files" ) + cc.sunny( "=" ) + cc.note( "value" ) + cc.debug( "..............." ) + cc.notice( "Maximum number of log files for log rotation." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "gathered" ) + cc.debug( "......................" ) + cc.notice( "Print details of gathering data from command line arguments. " ) + cc.debug( "Default mode" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-gathered" ) + cc.debug( "..................." ) + cc.notice( "Do not print details of gathering data from command line arguments." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "expose-security-info" ) + cc.debug( ".........." ) + cc.notice( "Expose security-related values in log output." ) + " " + cc.debug( "This mode is needed for debugging purposes only" ) + cc.notice( "." ) ); - console.log( soi + cc.debug( "--" ) + cc.bright( "no-expose-security-info" ) + cc.debug( "......." ) + cc.notice( "Do not expose security-related values in log output." ) + " " + cc.debug( "Default mode" ) + cc.notice( "." ) ); - // - process.exit( 0 ); - } - if( joArg.name == "version" ) { - print_about(); - process.exit( 0 ); - } - if( joArg.name == "colors" ) { - cc.enable( true ); - continue; - } - if( joArg.name == "no-colors" ) { - cc.enable( false ); - continue; - } - if( joArg.name == "expose" ) { - IMA.expose_details_set( true ); - continue; - } - if( joArg.name == "no-expose" ) { - IMA.expose_details_set( false ); - continue; - } - if( joArg.name == "verbose" ) { - IMA.verbose_set( IMA.verbose_parse( joArg.value ) ); - continue; - } - if( joArg.name == "verbose-list" ) { - IMA.verbose_list(); - return 0; - } - if( joArg.name == "url-main-net" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - imaState.strURL_main_net = joArg.value; - continue; - } - if( joArg.name == "url-s-chain" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - imaState.strURL_s_chain = joArg.value; - continue; - } - if( joArg.name == "url-t-chain" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - imaState.strURL_t_chain = joArg.value; - continue; - } - if( joArg.name == "id-main-net" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strChainName_main_net = joArg.value; - continue; - } - if( joArg.name == "id-s-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strChainName_s_chain = joArg.value; - continue; - } - if( joArg.name == "id-origin-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strChainName_origin_chain = joArg.value; - continue; - } - if( joArg.name == "id-t-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strChainName_t_chain = joArg.value; - continue; - } - if( joArg.name == "cid-main-net" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.cid_main_net = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "cid-s-chain" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.cid_s_chain = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "cid-t-chain" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.cid_t_chain = owaspUtils.toInteger( joArg.value ); - continue; - } - // - // - if( joArg.name == "tm-url-main-net" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - const strURL = "" + joArg.value; - // if( strURL.indexOf( "/sign-and-send" ) < 0 ) - // strURL += "/sign-and-send"; - // strURL += "/0"; - imaState.joAccount_main_net.strTransactionManagerURL = strURL; - continue; - } - if( joArg.name == "tm-url-s-chain" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - const strURL = "" + joArg.value; - // if( strURL.indexOf( "/sign-and-send" ) < 0 ) - // strURL += "/sign-and-send"; - // strURL += "/0"; - imaState.joAccount_s_chain.strTransactionManagerURL = strURL; - continue; - } - if( joArg.name == "tm-url-t-chain" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - const strURL = "" + joArg.value; - // if( strURL.indexOf( "/sign-and-send" ) < 0 ) - // strURL += "/sign-and-send"; - // strURL += "/0"; - imaState.joAccount_t_chain.strTransactionManagerURL = strURL; - continue; - } - if( joArg.name == "tm-priority-main-net" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.joAccount_main_net.tm_priority = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "tm-priority-s-chain" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.joAccount_s_chain.tm_priority = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "tm-priority-t-chain" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.joAccount_t_chain.tm_priority = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "sgx-url-main-net" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - imaState.joAccount_main_net.strSgxURL = joArg.value; - continue; - } - if( joArg.name == "sgx-url-s-chain" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - imaState.joAccount_s_chain.strSgxURL = joArg.value; - continue; - } - if( joArg.name == "sgx-url-t-chain" ) { - owaspUtils.verifyArgumentIsURL( joArg ); - imaState.joAccount_t_chain.strSgxURL = joArg.value; - continue; - } - if( joArg.name == "sgx-ecdsa-key-main-net" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_main_net.strSgxKeyName = joArg.value; - continue; - } - if( joArg.name == "sgx-ecdsa-key-s-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_s_chain.strSgxKeyName = joArg.value; - continue; - } - if( joArg.name == "sgx-ecdsa-key-t-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_t_chain.strSgxKeyName = joArg.value; - continue; - } - // - if( joArg.name == "sgx-ssl-key-main-net" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.joAccount_main_net.strPathSslKey = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "sgx-ssl-key-s-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.joAccount_s_chain.strPathSslKey = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "sgx-ssl-key-t-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.joAccount_t_chain.strPathSslKey = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "sgx-ssl-cert-main-net" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.joAccount_main_net.strPathSslCert = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "sgx-ssl-cert-s-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.joAccount_s_chain.strPathSslCert = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "sgx-ssl-cert-t-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.joAccount_t_chain.strPathSslCert = imaUtils.normalizePath( joArg.value ); - continue; - } - // - // - if( joArg.name == "address-main-net" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_main_net.address_ = joArg.value; - continue; - } - if( joArg.name == "address-s-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_s_chain.address_ = joArg.value; - continue; - } - if( joArg.name == "address-t-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_t_chain.address_ = joArg.value; - continue; - } - if( joArg.name == "receiver" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.receiver = joArg.value; - continue; - } - if( joArg.name == "key-main-net" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_main_net.privateKey = joArg.value; - continue; - } - if( joArg.name == "key-s-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_s_chain.privateKey = joArg.value; - continue; - } - if( joArg.name == "key-t-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.joAccount_t_chain.privateKey = joArg.value; - continue; - } - if( joArg.name == "abi-skale-manager" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathAbiJson_skale_manager = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "abi-main-net" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathAbiJson_main_net = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "abi-s-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathAbiJson_s_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "abi-t-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathAbiJson_t_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - // - // - if( joArg.name == "erc20-main-net" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc20_main_net = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "erc20-s-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc20_s_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "addr-erc20-s-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strAddrErc20_explicit = joArg.value; - continue; - } - if( joArg.name == "erc20-t-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc20_t_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "addr-erc20-t-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strAddrErc20_explicit_target = joArg.value; - continue; - } - // - // - if( joArg.name == "erc721-main-net" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc721_main_net = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "erc721-s-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc721_s_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "addr-erc721-s-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strAddrErc721_explicit = joArg.value; - continue; - } - if( joArg.name == "erc721-t-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc721_t_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "addr-erc721-t-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strAddrErc721_explicit_target = joArg.value; - continue; - } - // - // - if( joArg.name == "erc1155-main-net" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc1155_main_net = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "erc1155-s-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc1155_s_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "addr-erc1155-s-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strAddrErc1155_explicit = joArg.value; - continue; - } - if( joArg.name == "erc1155-t-chain" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathJsonErc1155_t_chain = imaUtils.normalizePath( joArg.value ); - continue; - } - if( joArg.name == "addr-erc1155-t-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strAddrErc1155_explicit_target = joArg.value; - continue; - } - // - // - if( joArg.name == "sleep-between-tx" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - IMA.setSleepBetweenTransactionsOnSChainMilliseconds( joArg.value ); - continue; - } - if( joArg.name == "wait-next-block" ) { - IMA.setWaitForNextBlockOnSChain( true ); - continue; - } - if( joArg.name == "value" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value, true ); - continue; - } - if( joArg.name == "wei" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - // imaState.nAmountOfWei = joArg.value * 1; - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value + "wei", true ); - continue; - } - if( joArg.name == "babbage" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - // imaState.nAmountOfWei = joArg.value * 1000; - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value + "babbage", true ); - continue; - } - if( joArg.name == "lovelace" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - // imaState.nAmountOfWei = joArg.value * 1000 * 1000; - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value + "lovelace", true ); - continue; - } - if( joArg.name == "shannon" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - // imaState.nAmountOfWei = joArg.value * 1000 * 1000 * 1000; - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value + "shannon", true ); - continue; - } - if( joArg.name == "szabo" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - // imaState.nAmountOfWei = joArg.value * 1000 * 1000 * 1000 * 1000; - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value + "szabo", true ); - continue; - } - if( joArg.name == "finney" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - // imaState.nAmountOfWei = joArg.value * 1000 * 1000 * 1000 * 1000 * 1000; - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value + "finney", true ); - continue; - } - if( joArg.name == "ether" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - // imaState.nAmountOfWei = joArg.value * 1000 * 1000 * 1000 * 1000 * 1000 * 1000; - imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value + "ether", true ); - continue; - } - if( joArg.name == "amount" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.nAmountOfToken = joArg.value; - continue; - } - if( joArg.name == "tid" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.idToken = joArg.value; - imaState.have_idToken = true; - continue; - } - if( joArg.name == "amounts" ) { - imaState.arrAmountsOfTokens = owaspUtils.verifyArgumentIsArrayOfIntegers( joArg ); - continue; - } - if( joArg.name == "tids" ) { - imaState.idTokens = owaspUtils.verifyArgumentIsArrayOfIntegers( joArg ); - imaState.have_idTokens = true; - continue; - } - // - if( joArg.name == "gas-price-multiplier-mn" ) { - let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasPriceMultiplier < 0.0 ) - gasPriceMultiplier = 0.0; - imaState.tc_main_net.gasPriceMultiplier = gasPriceMultiplier; - continue; - } - if( joArg.name == "gas-price-multiplier-sc" ) { - let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasPriceMultiplier < 0.0 ) - gasPriceMultiplier = 0.0; - imaState.tc_s_chain.gasPriceMultiplier = gasPriceMultiplier; - continue; - } - if( joArg.name == "gas-price-multiplier-tc" ) { - let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasPriceMultiplier < 0.0 ) - gasPriceMultiplier = 0.0; - imaState.tc_t_chain.gasPriceMultiplier = gasPriceMultiplier; - continue; - } - if( joArg.name == "gas-price-multiplier" ) { - let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasPriceMultiplier < 0.0 ) - gasPriceMultiplier = 0.0; - imaState.tc_main_net.gasPriceMultiplier = - imaState.tc_s_chain.gasPriceMultiplier = - imaState.tc_t_chain.gasPriceMultiplier = - gasPriceMultiplier; - continue; - } - // - if( joArg.name == "gas-multiplier-mn" ) { - let gasMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasMultiplier < 0.0 ) - gasMultiplier = 0.0; - imaState.tc_main_net.gasMultiplier = gasMultiplier; - continue; - } - if( joArg.name == "gas-multiplier-sc" ) { - let gasMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasMultiplier < 0.0 ) - gasMultiplier = 0.0; - imaState.tc_s_chain.gasMultiplier = gasMultiplier; - continue; - } - if( joArg.name == "gas-multiplier-tc" ) { - let gasMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasMultiplier < 0.0 ) - gasMultiplier = 0.0; - imaState.tc_t_chain.gasMultiplier = gasMultiplier; - continue; - } - if( joArg.name == "gas-multiplier" ) { - let gasMultiplier = owaspUtils.toFloat( joArg.value ); - if( gasMultiplier < 0.0 ) - gasMultiplier = 0.0; - imaState.tc_main_net.gasMultiplier = - imaState.tc_s_chain.gasMultiplier = - imaState.tc_t_chain.gasMultiplier = - gasMultiplier; - continue; - } - // - if( joArg.name == "s2s-enable" ) { - imaState.s2s_opts.isEnabled = true; - continue; - } - if( joArg.name == "s2s-disable" ) { - imaState.s2s_opts.isEnabled = false; - continue; - } - if( joArg.name == "net-rediscover" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.s2s_opts.secondsToReDiscoverSkaleNetwork = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "with-metadata" ) { - imaState.isWithMetadata721 = true; - continue; - } - // - if( joArg.name == "show-config" ) { - imaState.bShowConfigMode = true; - continue; - } - if( joArg.name == "load-node-config" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - load_node_config( joArg.value ); - continue; - } - if( joArg.name == "no-wait-s-chain" ) { - imaState.bNoWaitSChainStarted = true; - continue; - } - if( joArg.name == "max-wait-attempts" ) { - imaState.nMaxWaitSChainAttempts = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "skip-dry-run" ) { - imaState.doEnableDryRun( false ); - continue; - } - if( joArg.name == "ignore-dry-run" ) { - imaState.doIgnoreDryRun( true ); - continue; - } - if( joArg.name == "dry-run" ) { - imaState.doIgnoreDryRun( false ); - continue; - } - if( joArg.name == "m2s-transfer-block-size" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nTransferBlockSizeM2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2m-transfer-block-size" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nTransferBlockSizeS2M = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2s-transfer-block-size" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nTransferBlockSizeS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "transfer-block-size" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nTransferBlockSizeM2S = imaState.nTransferBlockSizeS2M = imaState.nTransferBlockSizeS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "m2s-max-transactions" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nMaxTransactionsM2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2m-max-transactions" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nMaxTransactionsS2M = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2s-max-transactions" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nMaxTransactionsS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "max-transactions" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nMaxTransactionsM2S = imaState.nMaxTransactionsS2M = imaState.nMaxTransactionsS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "m2s-await-blocks" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAwaitDepthM2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2m-await-blocks" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAwaitDepthS2M = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2s-await-blocks" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAwaitDepthS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "await-blocks" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAwaitDepthM2S = imaState.nBlockAwaitDepthS2M = imaState.nBlockAwaitDepthS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "m2s-await-time" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAgeM2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2m-await-time" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAgeS2M = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "s2s-await-time" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAgeS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "await-time" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nBlockAgeM2S = imaState.nBlockAgeS2M = imaState.nBlockAgeS2S = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "period" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nLoopPeriodSeconds = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "node-number" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nNodeNumber = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "nodes-count" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nNodesCount = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "time-framing" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nTimeFrameSeconds = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "time-gap" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nNextFrameGap = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "auto-exit" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nAutoExitAfterSeconds = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "ptx" ) { - imaState.optsPendingTxAnalysis.isEnabled = true; - continue; - } - if( joArg.name == "no-ptx" ) { - imaState.optsPendingTxAnalysis.isEnabled = false; - continue; - } - if( joArg.name == "ptx-attempt" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.optsPendingTxAnalysis.nTimeoutSecondsBeforeSecondAttempt = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "ptx-ignore" ) { - imaState.optsPendingTxAnalysis.isIgnore = true; - continue; - } - if( joArg.name == "no-ptx-ignore" ) { - imaState.optsPendingTxAnalysis.isIgnore = false; - continue; - } - if( joArg.name == "ptx-ignore2" ) { - imaState.optsPendingTxAnalysis.isIgnore2 = true; - continue; - } - if( joArg.name == "no-ptx-ignore2" ) { - imaState.optsPendingTxAnalysis.isIgnore2 = false; - continue; - } - if( joArg.name == "log-size" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nLogMaxSizeBeforeRotation = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "log-files" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - imaState.nLogMaxFilesCount = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "gathered" ) { - imaState.isPrintGathered = true; - continue; - } - if( joArg.name == "no-gathered" ) { - imaState.isPrintGathered = false; - continue; - } - if( joArg.name == "expose-security-info" ) { - imaState.isPrintSecurityValues = true; - continue; - } - if( joArg.name == "no-expose-security-info" ) { - imaState.isPrintSecurityValues = false; - continue; - } - if( joArg.name == "log" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strLogFilePath = "" + joArg.value; - continue; - } - if( joArg.name == "sign-messages" ) { - imaState.bSignMessages = true; - continue; - } - if( joArg.name == "bls-glue" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathBlsGlue = "" + joArg.value; - continue; - } - if( joArg.name == "hash-g1" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathHashG1 = "" + joArg.value; - continue; - } - if( joArg.name == "bls-verify" ) { - owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); - imaState.strPathBlsVerify = "" + joArg.value; - continue; - } - if( joArg.name == "monitoring-port" ) { - owaspUtils.verifyArgumentIsIntegerIpPortNumber( joArg ); - imaState.nMonitoringPort = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "reimbursement-chain" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.strReimbursementChain = joArg.value.trim(); - continue; - } - if( joArg.name == "reimbursement-recharge" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.nReimbursementRecharge = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value, true ); - continue; - } - if( joArg.name == "reimbursement-withdraw" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.nReimbursementWithdraw = owaspUtils.parseMoneySpecToWei( null, "" + joArg.value, true ); - continue; - } - if( joArg.name == "reimbursement-balance" ) { - imaState.isShowReimbursementBalance = true; - continue; - } - if( joArg.name == "reimbursement-estimate" ) { - imaState.nReimbursementEstimate = true; - continue; - } - if( joArg.name == "reimbursement-range" ) { - owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); - imaState.nReimbursementRange = owaspUtils.toInteger( joArg.value ); - continue; - } - if( joArg.name == "bs-step-size" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - IMA.setBlocksCountInInIterativeStepOfEventsScan( owaspUtils.toInteger( joArg.value ) ); - continue; - } - if( joArg.name == "bs-max-all-range" ) { - owaspUtils.verifyArgumentIsInteger( joArg ); - IMA.setMaxIterationsInAllRangeEventsScan( owaspUtils.toInteger( joArg.value ) ); - continue; - } - if( joArg.name == "bs-progressive-enable" ) { - IMA.setEnabledProgressiveEventsScan( true ); - continue; - } - if( joArg.name == "bs-progressive-disable" ) { - IMA.setEnabledProgressiveEventsScan( false ); - continue; - } - if( joArg.name == "enable-oracle" ) { - IMA.setEnabledOracle( true ); - continue; - } - if( joArg.name == "disable-oracle" ) { - IMA.setEnabledOracle( false ); - continue; - } - if( joArg.name == "s2s-forward" ) { - IMA.setForwardS2S(); - continue; - } - if( joArg.name == "s2s-reverse" ) { - IMA.setReverseS2S(); - continue; - } - if( joArg.name == "register" || - joArg.name == "register1" || - joArg.name == "check-registration" || - joArg.name == "check-registration1" || - joArg.name == "check-registration2" || - joArg.name == "check-registration3" || - joArg.name == "mint-erc20" || - joArg.name == "mint-erc721" || - joArg.name == "mint-erc1155" || - joArg.name == "burn-erc20" || - joArg.name == "burn-erc721" || - joArg.name == "burn-erc1155" || - joArg.name == "show-balance" || - joArg.name == "m2s-payment" || - joArg.name == "s2m-payment" || - joArg.name == "s2m-receive" || - joArg.name == "s2m-view" || - joArg.name == "s2s-payment" | - joArg.name == "m2s-transfer" || - joArg.name == "s2m-transfer" || - joArg.name == "s2s-transfer" || - joArg.name == "transfer" || - joArg.name == "loop" || - joArg.name == "browse-s-chain" || - joArg.name == "browse-skale-network" || - joArg.name == "browse-connected-schains" || - joArg.name == "discover-cid" - ) { - joExternalHandlers[joArg.name](); - continue; - } - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " unknown command line argument " ) + cc.info( joArg.name ) ); - return 666; - } - return 0; -} - -function getWeb3FromURL( strURL, log ) { - let w3 = null; - log = log || { write: console.log }; - try { - const u = cc.safeURL( strURL ); - const strProtocol = u.protocol.trim().toLowerCase().replace( ":", "" ).replace( "/", "" ); - if( strProtocol == "ws" || strProtocol == "wss" ) { - const w3ws = new w3mod.providers.WebsocketProvider( strURL, { - // see: https://github.com/ChainSafe/web3.js/tree/1.x/packages/web3-providers-ws#usage - clientConfig: { - // // if requests are large: - // maxReceivedFrameSize: 100000000, // bytes - default: 1MiB - // maxReceivedMessageSize: 100000000, // bytes - default: 8MiB - // keep a connection alive - keepalive: true, - keepaliveInterval: 200000 // ms - }, - reconnect: { // enable auto reconnection - auto: true, - delay: 5000, // ms - maxAttempts: 10000000, // 10 million times - onTimeout: false - } - } ); - w3 = new w3mod( w3ws ); - } else { - const w3http = new w3mod.providers.HttpProvider( strURL ); - w3 = new w3mod( w3http ); - } - } catch ( err ) { - log.write( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Failed to create " ) + - cc.attention( "Web3" ) + cc.error( " connection to " ) + cc.info( strURL ) + - cc.error( ": " ) + cc.warning( err.toString() ) + "\n" ); - w3 = null; - } - return w3; -} - -async function async_check_url_at_startup( u, name ) { - const details = log.createMemoryStream( true ); - const nTimeoutMilliseconds = 10 * 1000; - try { - details.write( cc.debug( "Will check URL " ) + cc.u( u ) + cc.debug( " connectivity for " ) + cc.info( name ) + cc.debug( " at start-up..." ) + "\n" ); - const isLog = false; - const isOnLine = await rpcCall.check_url( u, nTimeoutMilliseconds, isLog ); - if( isOnLine ) - details.write( cc.success( "Done, start-up checking URL " ) + cc.u( u ) + cc.success( " connectivity for " ) + cc.info( name ) + cc.success( ", URL is on-line." ) + "\n" ); - else - details.write( cc.error( "Done, start-up checking URL " ) + cc.u( u ) + cc.error( " connectivity for " ) + cc.info( name ) + cc.error( ", URL is off-line." ) + "\n" ); - return isOnLine; - } catch ( err ) { - details.write( - cc.fatal( "ERROR:" ) + cc.error( " Failed to check URL " ) + - cc.u( u ) + cc.error( " connectivity for " ) + cc.info( name ) + cc.error( " at start-up, error is: " ) + cc.warning( err.toString() ) + - "\n" ); - } - // details.exposeDetailsTo( log, "async_check_url_at_startup( \"" + u + "\", \"" + name + "\" )", true ); - // details.close(); - return false; -} - -function ima_common_init() { - const isPrintGathered = imaState.isPrintGathered ? true : false; - if( isPrintGathered ) { - log.write( cc.debug( "This process " ) + cc.sunny( "PID" ) + cc.debug( " is " ) + cc.bright( process.pid ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "PPID" ) + cc.debug( " is " ) + cc.bright( process.ppid ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "EGID" ) + cc.debug( " is " ) + cc.bright( process.getegid() ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "EUID" ) + cc.debug( " is " ) + cc.bright( process.geteuid() ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "GID" ) + cc.debug( " is " ) + cc.bright( process.getgid() ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "UID" ) + cc.debug( " is " ) + cc.bright( process.getuid() ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "groups" ) + cc.debug( " are " ) + cc.j( process.getgroups() ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "CWD" ) + cc.debug( " is " ) + cc.bright( process.cwd() ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "platform" ) + cc.debug( " is " ) + cc.bright( process.platform ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "release" ) + cc.debug( " is " ) + cc.j( process.release ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "report" ) + cc.debug( " is " ) + cc.j( process.report ) + "\n" ); - log.write( cc.debug( "This process " ) + cc.sunny( "config" ) + cc.debug( " is " ) + cc.j( process.config ) + "\n" ); - log.write( cc.sunny( "Node JS" ) + " " + cc.bright( "detailed version information" ) + cc.debug( " is " ) + cc.j( process.versions ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "type" ) + cc.debug( " is " ) + cc.bright( os.type() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "platform" ) + cc.debug( " is " ) + cc.bright( os.platform() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "release" ) + cc.debug( " is " ) + cc.bright( os.release() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "architecture" ) + cc.debug( " is " ) + cc.bright( os.arch() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "endianness" ) + cc.debug( " is " ) + cc.bright( os.endianness() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "host name" ) + cc.debug( " is " ) + cc.bright( os.hostname() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "CPUs" ) + cc.debug( " are " ) + cc.j( os.cpus() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "network interfaces" ) + cc.debug( " are " ) + cc.j( os.networkInterfaces() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "home dir" ) + cc.debug( " is " ) + cc.bright( os.homedir() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "tmp dir" ) + cc.debug( " is " ) + cc.bright( os.tmpdir() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "uptime" ) + cc.debug( " is " ) + cc.bright( os.uptime() ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "user" ) + cc.debug( " is " ) + cc.j( os.userInfo() ) + "\n" ); - const joMemory = { total: os.totalmem(), free: os.freemem() }; - joMemory.freePercent = ( joMemory.free / joMemory.total ) * 100.0; - log.write( cc.sunny( "OS" ) + " " + cc.bright( "memory" ) + cc.debug( " is " ) + cc.j( joMemory ) + "\n" ); - log.write( cc.sunny( "OS" ) + " " + cc.bright( "average load" ) + cc.debug( " is " ) + cc.j( os.loadavg() ) + "\n" ); - } // if( isPrintGathered ) - - let n1 = 0; - let n2 = 0; - if( imaState.strPathAbiJson_skale_manager && ( typeof imaState.strPathAbiJson_skale_manager == "string" ) && imaState.strPathAbiJson_skale_manager.length > 0 ) { - imaState.joAbiPublishResult_skale_manager = imaUtils.jsonFileLoad( imaState.strPathAbiJson_skale_manager, null ); - imaState.bHaveSkaleManagerABI = true; - } else { - imaState.bHaveSkaleManagerABI = false; - log.write( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Skale Manager" ) + - cc.warning( " ABI file path is provided in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - if( imaState.strPathAbiJson_main_net && typeof imaState.strPathAbiJson_main_net == "string" && imaState.strPathAbiJson_main_net.length > 0 ) { - imaState.joAbiPublishResult_main_net = imaUtils.jsonFileLoad( imaState.strPathAbiJson_main_net, null ); - imaState.bHaveImaAbiMainNet = true; - } else { - imaState.bHaveImaAbiMainNet = false; - log.write( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Main-net" ) + - cc.warning( " IMA ABI file path is provided in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - if( imaState.strPathAbiJson_s_chain && typeof imaState.strPathAbiJson_s_chain == "string" && imaState.strPathAbiJson_s_chain.length > 0 ) { - imaState.joAbiPublishResult_s_chain = imaUtils.jsonFileLoad( imaState.strPathAbiJson_s_chain, null ); - imaState.bHaveImaAbiSchain = true; - } else { - imaState.bHaveImaAbiSchain = false; - log.write( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S-Chain" ) + - cc.warning( " IMA ABI file path is provided in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - if( imaState.strPathAbiJson_t_chain && typeof imaState.strPathAbiJson_t_chain == "string" && imaState.strPathAbiJson_t_chain.length > 0 ) { - imaState.joAbiPublishResult_t_chain = imaUtils.jsonFileLoad( imaState.strPathAbiJson_t_chain, null ); - imaState.bHaveImaAbiSchainTarget = true; - } else { - imaState.bHaveImaAbiSchainTarget = false; - log.write( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S<->S Target S-Chain" ) + - cc.warning( " IMA ABI file path is provided in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - - if( imaState.bHaveSkaleManagerABI ) { - imaUtils.check_keys_exist_in_abi( "skale-manager", imaState.strPathAbiJson_skale_manager, imaState.joAbiPublishResult_skale_manager, [ - // partial list of Skale Manager's contracts specified here: - "constants_holder_abi", - "constants_holder_address", - "nodes_abi", - "nodes_address", - "key_storage_abi", - "key_storage_address", - "schains_abi", - "schains_address", - "schains_internal_abi", - "schains_internal_address", - "skale_d_k_g_abi", - "skale_d_k_g_address", - "skale_manager_abi", - "skale_manager_address", - "skale_token_abi", - "skale_token_address", - "validator_service_abi", - "validator_service_address", - "wallets_abi", - "wallets_address" - ] ); - } else if( imaState.s2s_opts.isEnabled ) - log.write( cc.error( "WARNING:" ) + cc.warning( " Missing " ) + cc.note( "Skale Manager" ) + cc.warning( " ABI path for " ) + cc.note( "S-Chain" ) + cc.warning( " to " ) + cc.note( "S-Chain" ) + cc.warning( " transfers" ) + "\n" ); - // process.exit( 126 ); - - if( imaState.bHaveImaAbiMainNet ) { - imaUtils.check_keys_exist_in_abi( "main-net", imaState.strPathAbiJson_main_net, imaState.joAbiPublishResult_main_net, [ - "deposit_box_eth_abi", - "deposit_box_eth_address", - "message_proxy_mainnet_abi", - "message_proxy_mainnet_address", - "linker_abi", - "linker_address", - "deposit_box_erc20_abi", - "deposit_box_erc20_address", - "deposit_box_erc721_abi", - "deposit_box_erc721_address", - "deposit_box_erc1155_abi", - "deposit_box_erc1155_address", - "deposit_box_erc721_with_metadata_abi", - "deposit_box_erc721_with_metadata_address", - "community_pool_abi", - "community_pool_address" - ] ); - } - if( imaState.bHaveImaAbiSchain ) { - imaUtils.check_keys_exist_in_abi( "S-Chain", imaState.strPathAbiJson_s_chain, imaState.joAbiPublishResult_s_chain, [ - "token_manager_eth_abi", - "token_manager_eth_address", - "token_manager_erc20_abi", - "token_manager_erc20_address", - "token_manager_erc721_abi", - "token_manager_erc721_address", - "token_manager_erc1155_abi", - "token_manager_erc1155_address", - "token_manager_erc721_with_metadata_abi", - "token_manager_erc721_with_metadata_address", - "message_proxy_chain_abi", - "message_proxy_chain_address", - "token_manager_linker_abi", - "token_manager_linker_address", - "community_locker_abi", - "community_locker_address" - ] ); - } - if( imaState.bHaveImaAbiSchainTarget ) { - imaUtils.check_keys_exist_in_abi( "S<->S Target S-Chain", imaState.strPathAbiJson_t_chain, imaState.joAbiPublishResult_t_chain, [ - "token_manager_eth_abi", - "token_manager_eth_address", - "token_manager_erc20_abi", - "token_manager_erc20_address", - "token_manager_erc721_abi", - "token_manager_erc721_address", - "token_manager_erc1155_abi", - "token_manager_erc1155_address", - "token_manager_erc721_with_metadata_abi", - "token_manager_erc721_with_metadata_address", - "message_proxy_chain_abi", - "message_proxy_chain_address", - "token_manager_linker_abi", - "token_manager_linker_address", - "community_locker_abi", - "community_locker_address" - ] ); - } - - // deposit_box_eth_address --> deposit_box_eth_abi - // deposit_box_erc20_address --> deposit_box_erc20_abi - // deposit_box_erc721_address --> deposit_box_erc721_abi - // deposit_box_erc1155_address --> deposit_box_erc1155_abi - // deposit_box_erc721_with_metadata_address --> deposit_box_erc721_with_metadata_abi - // linker_address --> linker_abi - // token_manager_eth_address --> token_manager_eth_abi - // token_manager_erc20_address --> token_manager_erc20_abi - // token_manager_erc721_address --> token_manager_erc721_abi - // token_manager_erc1155_address --> token_manager_erc1155_abi - // token_manager_erc721_with_metadata_address --> token_manager_erc721_with_metdata_abi - // token_manager_linker_address --> token_manager_linker_abi - // message_proxy_mainnet_address --> message_proxy_mainnet_abi - // message_proxy_chain_address --> message_proxy_chain_abi - - // - if( imaState.strURL_main_net && typeof imaState.strURL_main_net == "string" && imaState.strURL_main_net.length > 0 ) { - const u = imaState.strURL_main_net; - async_check_url_at_startup( u, "Main-net" ); - imaState.w3_main_net = getWeb3FromURL( u, log ); - } else { - log.write( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Main-net" ) + - cc.warning( " URL specified in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - if( imaState.strURL_s_chain && typeof imaState.strURL_s_chain == "string" && imaState.strURL_s_chain.length > 0 ) { - const u = imaState.strURL_s_chain; - async_check_url_at_startup( u, "S-Chain" ); - imaState.w3_s_chain = getWeb3FromURL( u, log ); - } else { - log.write( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S-Chain" ) + - cc.warning( " URL specified in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - if( imaState.strURL_t_chain && typeof imaState.strURL_t_chain == "string" && imaState.strURL_t_chain.length > 0 ) { - const u = imaState.strURL_t_chain; - async_check_url_at_startup( u, "S<->S Target S-Chain" ); - imaState.w3_t_chain = getWeb3FromURL( u, log ); - } else { - log.write( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S<->S Target S-Chain" ) + - cc.warning( " URL specified in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - if( imaState.bHaveImaAbiMainNet ) { - imaState.jo_deposit_box_eth = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.deposit_box_eth_abi, imaState.joAbiPublishResult_main_net.deposit_box_eth_address ); // only main net - imaState.jo_deposit_box_erc20 = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.deposit_box_erc20_abi, imaState.joAbiPublishResult_main_net.deposit_box_erc20_address ); // only main net - imaState.jo_deposit_box_erc721 = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.deposit_box_erc721_abi, imaState.joAbiPublishResult_main_net.deposit_box_erc721_address ); // only main net - imaState.jo_deposit_box_erc1155 = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.deposit_box_erc1155_abi, imaState.joAbiPublishResult_main_net.deposit_box_erc1155_address ); // only main net - imaState.jo_deposit_box_erc721_with_metadata = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.deposit_box_erc721_with_metadata_abi, imaState.joAbiPublishResult_main_net.deposit_box_erc721_with_metadata_address ); // only main net - imaState.jo_community_pool = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.community_pool_abi, imaState.joAbiPublishResult_main_net.community_pool_address ); // only main net - imaState.jo_linker = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.linker_abi, imaState.joAbiPublishResult_main_net.linker_address ); // only main net - imaState.jo_message_proxy_main_net = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_main_net.message_proxy_mainnet_abi, imaState.joAbiPublishResult_main_net.message_proxy_mainnet_address ); - } - if( imaState.bHaveImaAbiSchain ) { - imaState.jo_token_manager_eth = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.token_manager_eth_abi, imaState.joAbiPublishResult_s_chain.token_manager_eth_address ); // only s-chain - imaState.jo_token_manager_erc20 = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.token_manager_erc20_abi, imaState.joAbiPublishResult_s_chain.token_manager_erc20_address ); // only s-chain - imaState.jo_token_manager_erc721 = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.token_manager_erc721_abi, imaState.joAbiPublishResult_s_chain.token_manager_erc721_address ); // only s-chain - imaState.jo_token_manager_erc1155 = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.token_manager_erc1155_abi, imaState.joAbiPublishResult_s_chain.token_manager_erc1155_address ); // only s-chain - imaState.jo_token_manager_erc721_with_metadata = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.token_manager_erc721_with_metadata_abi, imaState.joAbiPublishResult_s_chain.token_manager_erc721_with_metadata_address ); // only s-chain - imaState.jo_community_locker = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.community_locker_abi, imaState.joAbiPublishResult_s_chain.community_locker_address ); // only s-chain - imaState.jo_message_proxy_s_chain = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, imaState.joAbiPublishResult_s_chain.message_proxy_chain_address ); - imaState.jo_token_manager_linker = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.token_manager_linker_abi, imaState.joAbiPublishResult_s_chain.token_manager_linker_address ); - imaState.eth_erc20 = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.eth_erc20_abi, imaState.joAbiPublishResult_s_chain.eth_erc20_address ); // only s-chain - // imaState.eth_erc721 = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.eth_erc721_abi, imaState.joAbiPublishResult_s_chain.eth_erc721_address ); // only s-chain - // imaState.eth_erc1155 = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_s_chain.eth_erc1155_abi, imaState.joAbiPublishResult_s_chain.eth_erc721_address ); // only s-chain - } - if( imaState.bHaveImaAbiSchainTarget ) { - // imaState.jo_token_manager_eth_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.token_manager_eth_abi, imaState.joAbiPublishResult_t_chain.token_manager_eth_address ); // only s-chain - imaState.jo_token_manager_erc20_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.token_manager_erc20_abi, imaState.joAbiPublishResult_t_chain.token_manager_erc20_address ); // only s-chain - imaState.jo_token_manager_erc721_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.token_manager_erc721_abi, imaState.joAbiPublishResult_t_chain.token_manager_erc721_address ); // only s-chain - imaState.jo_token_manager_erc1155_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.token_manager_erc1155_abi, imaState.joAbiPublishResult_t_chain.token_manager_erc1155_address ); // only s-chain - imaState.jo_token_manager_erc721_with_metadata_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.token_manager_erc721_with_metadata_abi, imaState.joAbiPublishResult_t_chain.token_manager_erc721_with_metadata_address ); // only s-chain - imaState.jo_community_locker_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.community_locker_abi, imaState.joAbiPublishResult_t_chain.community_locker_address ); // only s-chain - imaState.jo_message_proxy_s_chain_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.message_proxy_chain_abi, imaState.joAbiPublishResult_t_chain.message_proxy_chain_address ); - imaState.jo_token_manager_linker_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.token_manager_linker_abi, imaState.joAbiPublishResult_t_chain.token_manager_linker_address ); - imaState.eth_erc20_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.eth_erc20_abi, imaState.joAbiPublishResult_t_chain.eth_erc20_address ); // only s-chain - // imaState.eth_erc721_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.eth_erc721_abi, imaState.joAbiPublishResult_t_chain.eth_erc721_address ); // only s-chain - // imaState.eth_erc1155_target = new imaState.w3_s_chain.eth.Contract( imaState.joAbiPublishResult_t_chain.eth_erc1155_abi, imaState.joAbiPublishResult_t_chain.eth_erc721_address ); // only s-chain - } - if( imaState.bHaveSkaleManagerABI ) { - imaState.jo_constants_holder = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.constants_holder_abi, imaState.joAbiPublishResult_skale_manager.constants_holder_address ); - // jo_contract_manager - // jo_decryption - // jo_delegation_controller - // jo_delegation_period_manager - // jo_distributor - // jo_ecdh - // jo_manager_data - // jo_monitors_functionality - imaState.jo_nodes = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.nodes_abi, imaState.joAbiPublishResult_skale_manager.nodes_address ); - // jo_pricing - // jo_punisher - imaState.jo_key_storage = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.key_storage_abi, imaState.joAbiPublishResult_skale_manager.key_storage_address ); - imaState.jo_schains = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.schains_abi, imaState.joAbiPublishResult_skale_manager.schains_address ); - imaState.jo_schains_internal = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.schains_internal_abi, imaState.joAbiPublishResult_skale_manager.schains_internal_address ); - // jo_schains_functionality - // jo_schains_functionality_internal - imaState.jo_skale_dkg = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.skale_d_k_g_abi, imaState.joAbiPublishResult_skale_manager.skale_d_k_g_address ); - imaState.jo_skale_manager = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.skale_manager_abi, imaState.joAbiPublishResult_skale_manager.skale_manager_address ); - imaState.jo_skale_token = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.skale_token_abi, imaState.joAbiPublishResult_skale_manager.skale_token_address ); - // jo_skale_verifier - // jo_slashing_table - // jo_time_helpers - // jo_time_helpers_with_debug - // jo_token_state - imaState.jo_validator_service = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.validator_service_abi, imaState.joAbiPublishResult_skale_manager.validator_service_address ); - imaState.jo_wallets = new imaState.w3_main_net.eth.Contract( imaState.joAbiPublishResult_skale_manager.wallets_abi, imaState.joAbiPublishResult_skale_manager.wallets_address ); - } // if( imaState.bHaveSkaleManagerABI ) - - const oct = function( joContract ) { // optional contract address - if( joContract && "options" in joContract && "address" in joContract.options ) - return cc.bright( joContract.options.address ); - return cc.error( "contract is not available" ); - }; - - if( isPrintGathered ) { - log.write( cc.bright( "IMA contracts(Main Net):" ) + "\n" ); - log.write( cc.sunny( "DepositBoxEth" ) + cc.debug( "...................address is....." ) + oct( imaState.jo_deposit_box_eth ) + "\n" ); - log.write( cc.sunny( "DepositBoxERC20" ) + cc.debug( ".................address is....." ) + oct( imaState.jo_deposit_box_erc20 ) + "\n" ); - log.write( cc.sunny( "DepositBoxERC721" ) + cc.debug( "................address is....." ) + oct( imaState.jo_deposit_box_erc721 ) + "\n" ); - log.write( cc.sunny( "DepositBoxERC1155" ) + cc.debug( "...............address is....." ) + oct( imaState.jo_deposit_box_erc1155 ) + "\n" ); - log.write( cc.sunny( "DepositBoxERC721WithMetadata" ) + cc.debug( "....address is....." ) + oct( imaState.jo_deposit_box_erc721_with_metadata ) + "\n" ); - log.write( cc.sunny( "CommunityPool" ) + cc.debug( "...................address is....." ) + oct( imaState.jo_community_pool ) + "\n" ); - log.write( cc.sunny( "MessageProxy" ) + cc.debug( "....................address is....." ) + oct( imaState.jo_message_proxy_main_net ) + "\n" ); - log.write( cc.sunny( "Linker" ) + cc.debug( "..........................address is....." ) + oct( imaState.jo_linker ) + "\n" ); - log.write( cc.bright( "IMA contracts(S-Chain):" ) + "\n" ); - log.write( cc.sunny( "TokenManagerEth" ) + cc.debug( ".................address is....." ) + oct( imaState.jo_token_manager_eth ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC20" ) + cc.debug( "...............address is....." ) + oct( imaState.jo_token_manager_erc20 ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC721" ) + cc.debug( "..............address is....." ) + oct( imaState.jo_token_manager_erc721 ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC1155" ) + cc.debug( ".............address is....." ) + oct( imaState.jo_token_manager_erc1155 ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC721WithMetadata" ) + cc.debug( "..address is....." ) + oct( imaState.jo_token_manager_erc721_with_metadata ) + "\n" ); - log.write( cc.sunny( "CommunityLocker" ) + cc.debug( ".................address is....." ) + oct( imaState.jo_community_locker ) + "\n" ); - log.write( cc.sunny( "MessageProxy" ) + cc.debug( "....................address is....." ) + oct( imaState.jo_message_proxy_s_chain ) + "\n" ); - log.write( cc.sunny( "TokenManagerLinker" ) + cc.debug( "..............address is....." ) + oct( imaState.jo_token_manager_linker ) + "\n" ); - log.write( cc.sunny( "ERC20" ) + cc.debug( " ..........................address is....." ) + oct( imaState.eth_erc20 ) + "\n" ); - // log.write( "S-Chain " ) + cc.sunny( "ERC721" ) + cc.debug( " ......................address is....." ) + oct( imaState.eth_erc721 ) + "\n" ); - // log.write( "S-Chain " ) + cc.sunny( "ERC1155" ) + cc.debug( " .....................address is....." ) + oct( imaState.eth_erc1155 ) + "\n" ); - log.write( cc.bright( "IMA contracts(Target S-Chain):" ) + "\n" ); - // log.write( "S-Chain " ) + cc.sunny( "TokenManagerEth" ) + cc.debug( "..............address is....." ) + oct( imaState.jo_token_manager_eth_target ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC20" ) + cc.debug( "...............address is....." ) + oct( imaState.jo_token_manager_erc20_target ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC721" ) + cc.debug( "..............address is....." ) + oct( imaState.jo_token_manager_erc721_target ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC1155" ) + cc.debug( ".............address is....." ) + oct( imaState.jo_token_manager_erc1155_target ) + "\n" ); - log.write( cc.sunny( "TokenManagerERC721WithMetadata" ) + cc.debug( "..address is....." ) + oct( imaState.jo_token_manager_erc721_with_metadata_target ) + "\n" ); - log.write( cc.sunny( "CommunityLocker" ) + cc.debug( ".................address is....." ) + oct( imaState.jo_community_locker_target ) + "\n" ); - log.write( cc.sunny( "MessageProxy" ) + cc.debug( "....................address is....." ) + oct( imaState.jo_message_proxy_s_chain_target ) + "\n" ); - log.write( cc.sunny( "TokenManagerLinker" ) + cc.debug( "..............address is....." ) + oct( imaState.jo_token_manager_linker_target ) + "\n" ); - log.write( cc.sunny( "ERC20" ) + cc.debug( " ..........................address is....." ) + oct( imaState.eth_erc20_target ) + "\n" ); - // log.write( "S-Chain " ) + cc.sunny( "ERC721" ) + cc.debug( " ......................address is....." ) + oct( imaState.eth_erc721_target ) + "\n" ); - // log.write( "S-Chain " ) + cc.sunny( "ERC1155" ) + cc.debug( " .....................address is....." ) + oct( imaState.eth_erc1155_target ) + "\n" ); - - // if( imaState.bHaveSkaleManagerABI ) { - log.write( cc.bright( "Skale Manager contracts:" ) + "\n" ); - log.write( cc.sunny( "ConstantsHolder" ) + cc.debug( ".................address is....." ) + oct( imaState.jo_constants_holder ) + "\n" ); - log.write( cc.sunny( "Nodes" ) + cc.debug( "...........................address is....." ) + oct( imaState.jo_nodes ) + "\n" ); - log.write( cc.sunny( "KeyStorage" ) + cc.debug( "......................address is....." ) + oct( imaState.jo_key_storage ) + "\n" ); - log.write( cc.sunny( "Schains" ) + cc.debug( ".........................address is....." ) + oct( imaState.jo_schains ) + "\n" ); - log.write( cc.sunny( "SchainsInternal" ) + cc.debug( ".................address is....." ) + oct( imaState.jo_schains_internal ) + "\n" ); - log.write( cc.sunny( "SkaleDKG" ) + cc.debug( "........................address is....." ) + oct( imaState.jo_skale_dkg ) + "\n" ); - log.write( cc.sunny( "SkaleManager" ) + cc.debug( "....................address is....." ) + oct( imaState.jo_skale_manager ) + "\n" ); - log.write( cc.sunny( "SkaleToken" ) + cc.debug( "......................address is....." ) + oct( imaState.jo_skale_token ) + "\n" ); - log.write( cc.sunny( "ValidatorService" ) + cc.debug( "................address is....." ) + oct( imaState.jo_validator_service ) + "\n" ); - log.write( cc.sunny( "Wallets" ) + cc.debug( ".........................address is....." ) + oct( imaState.jo_wallets ) + "\n" ); - // } else - // log.write( cc.error( "WARNING:" ) + " " + cc.warning( "no Skale Manager contracts to list, Skale Manager ABI was not provided" ) + "\n" ); - } // if( isPrintGathered ) - - // - // - // - if( imaState.strPathJsonErc20_main_net.length > 0 /* && imaState.strPathJsonErc20_s_chain.length > 0 */ ) { - n1 = 0; - n2 = 0; - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading Main-net ERC20 ABI from " ) + cc.info( imaState.strPathJsonErc20_main_net ) + "\n" ); - imaState.joErc20_main_net = imaUtils.jsonFileLoad( imaState.strPathJsonErc20_main_net, null ); - n1 = Object.keys( imaState.joErc20_main_net ).length; - if( imaState.strPathJsonErc20_s_chain.length > 0 ) { - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S-Chain ERC20 ABI from " ) + cc.info( imaState.strPathJsonErc20_s_chain ) + "\n" ); - imaState.joErc20_s_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc20_s_chain, null ); - n2 = Object.keys( imaState.joErc20_s_chain ).length; - } - if( n1 > 0 /* && n2 > 0 */ ) { - imaState.strCoinNameErc20_main_net = imaUtils.discover_in_json_coin_name( imaState.joErc20_main_net ); - if( n2 > 0 ) - imaState.strCoinNameErc20_s_chain = imaUtils.discover_in_json_coin_name( imaState.joErc20_s_chain ); - n1 = imaState.strCoinNameErc20_main_net.length; - if( n2 > 0 ) - n2 = imaState.strCoinNameErc20_s_chain.length; - if( n1 > 0 /* && n2 > 0 */ ) { - if( isPrintGathered && IMA.verbose_get() >= IMA.RV_VERBOSE.information && ( !imaState.bShowConfigMode ) ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded Main-net ERC20 ABI " ) + cc.attention( imaState.strCoinNameErc20_main_net ) + "\n" ); - if( isPrintGathered && n2 > 0 ) - log.write( cc.info( "Loaded S-Chain ERC20 ABI " ) + cc.attention( imaState.strCoinNameErc20_s_chain ) + "\n" ); - } - } else { - if( n1 === 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Main-net ERC20 token name is not discovered (malformed JSON)" ) + "\n" ); - if( n2 === 0 && imaState.strPathJsonErc20_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC20 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc20_main_net = null; - imaState.joErc20_s_chain = null; - imaState.strCoinNameErc20_main_net = ""; - imaState.strCoinNameErc20_s_chain = ""; - process.exit( 126 ); - } - } else { - if( n1 === 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Main-net ERC20 JSON is invalid" ) + "\n" ); - if( n2 === 0 && imaState.strPathJsonErc20_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC20 JSON is invalid" ) + "\n" ); - imaState.joErc20_main_net = null; - imaState.joErc20_s_chain = null; - imaState.strCoinNameErc20_main_net = ""; - imaState.strCoinNameErc20_s_chain = ""; - process.exit( 126 ); - } - } else { // if( imaState.strPathJsonErc20_main_net.length > 0 /*&& imaState.strPathJsonErc20_s_chain.length > 0*/ ) - if( imaState.strPathJsonErc20_s_chain.length > 0 ) { - n1 = 0; - n2 = 0; - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S-Chain ERC20 ABI from " ) + cc.info( imaState.strPathJsonErc20_s_chain ) + "\n" ); - imaState.joErc20_s_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc20_s_chain, null ); - n2 = Object.keys( imaState.joErc20_s_chain ).length; - if( n2 > 0 ) { - imaState.strCoinNameErc20_s_chain = imaUtils.discover_in_json_coin_name( imaState.joErc20_s_chain ); - n2 = imaState.strCoinNameErc20_s_chain.length; - if( n2 > 0 ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded S-Chain ERC20 ABI " ) + cc.attention( imaState.strCoinNameErc20_s_chain ) + "\n" ); - } else { - if( n2 === 0 && imaState.strPathJsonErc20_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC20 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc20_main_net = null; - imaState.joErc20_s_chain = null; - imaState.strCoinNameErc20_main_net = ""; - imaState.strCoinNameErc20_s_chain = ""; - process.exit( 126 ); - } - } - } - } - if( n1 !== 0 && n2 === 0 ) { - if( imaState.strAddrErc20_explicit.length === 0 ) - log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + cc.warning( "Both S-Chain ERC20 JSON and explicit ERC20 address are not specified" ) + "\n" ); - else { - if( isPrintGathered ) - log.write( cc.attention( "IMPORTANT NOTICE:" ) + " " + cc.note( "S-Chain ERC20 ABI will be auto-generated" ) + "\n" ); - imaState.strCoinNameErc20_s_chain = "" + imaState.strCoinNameErc20_main_net; // assume same - imaState.joErc20_s_chain = JSON.parse( JSON.stringify( imaState.joErc20_main_net ) ); // clone - imaState.joErc20_s_chain[imaState.strCoinNameErc20_s_chain + "_address"] = "" + imaState.strAddrErc20_explicit; // set explicit address - // if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - // log.write( cc.info("Auto-generated S-Chain ERC20 JSON is ") + cc.j(imaState.joErc20_s_chain) + "\n" ); - } - } - // - if( imaState.strPathJsonErc20_t_chain.length > 0 ) { - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S<->S Target S-Chain ERC20 ABI from " ) + cc.info( imaState.strPathJsonErc20_t_chain ) + "\n" ); - imaState.joErc20_t_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc20_t_chain, null ); - n2 = Object.keys( imaState.joErc20_t_chain ).length; - if( n2 > 0 ) { - imaState.strCoinNameErc20_t_chain = imaUtils.discover_in_json_coin_name( imaState.joErc20_t_chain ); - n2 = imaState.strCoinNameErc20_t_chain.length; - if( n2 > 0 ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded S<->S Target S-Chain ERC20 ABI " ) + cc.attention( imaState.strCoinNameErc20_t_chain ) + "\n" ); - } else { - if( n2 === 0 && imaState.strPathJsonErc20_t_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S<->S Target S-Chain ERC20 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc20_t_chain = null; - imaState.strCoinNameErc20_t_chain = ""; - process.exit( 126 ); - } - } - } // if( imaState.strPathJsonErc20_t_chain.length > 0 ) - if( isPrintGathered && - imaState.strAddrErc20_explicit_target.length === 0 && imaState.strCoinNameErc20_t_chain.length === 0 && - imaState.strCoinNameErc20_s_chain.length > 0 - ) - log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + cc.warning( "Both S<->S Target S-Chain ERC20 JSON and explicit ERC20 address are not specified" ) + "\n" ); - // - // - // - if( imaState.strPathJsonErc721_main_net.length > 0 /* && imaState.strPathJsonErc721_s_chain.length > 0 */ ) { - n1 = 0; - n2 = 0; - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading Main-net ERC721 ABI from " ) + cc.info( imaState.strPathJsonErc721_main_net ) + "\n" ); - imaState.joErc721_main_net = imaUtils.jsonFileLoad( imaState.strPathJsonErc721_main_net, null ); - n1 = Object.keys( imaState.joErc721_main_net ).length; - if( imaState.strPathJsonErc721_s_chain.length > 0 ) { - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S-Chain ERC721 ABI from " ) + cc.info( imaState.strPathJsonErc721_s_chain ) + "\n" ); - imaState.joErc721_s_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc721_s_chain, null ); - n2 = Object.keys( imaState.joErc721_s_chain ).length; - } - if( n1 > 0 /* && n2 > 0 */ ) { - imaState.strCoinNameErc721_main_net = imaUtils.discover_in_json_coin_name( imaState.joErc721_main_net ); - if( n2 > 0 ) - imaState.strCoinNameErc721_s_chain = imaUtils.discover_in_json_coin_name( imaState.joErc721_s_chain ); - n1 = imaState.strCoinNameErc721_main_net.length; - if( n2 > 0 ) - n2 = imaState.strCoinNameErc721_s_chain.length; - if( n1 > 0 /* && n2 > 0 */ ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information && ( !imaState.bShowConfigMode ) ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded Main-net ERC721 ABI " ) + cc.attention( imaState.strCoinNameErc721_main_net ) + "\n" ); - if( n2 > 0 && isPrintGathered ) - log.write( cc.info( "Loaded S-Chain ERC721 ABI " ) + cc.attention( imaState.strCoinNameErc721_s_chain ) + "\n" ); - } - } else { - if( n1 === 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Main-net ERC721 token name is not discovered (malformed JSON)" ) + "\n" ); - if( n2 === 0 && imaState.strPathJsonErc721_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC721 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc721_main_net = null; - imaState.joErc721_s_chain = null; - imaState.strCoinNameErc721_main_net = ""; - imaState.strCoinNameErc721_s_chain = ""; - process.exit( 126 ); - } - } else { - if( n1 === 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Main-net ERC721 JSON is invalid" ) + "\n" ); - if( n2 === 0 && imaState.strPathJsonErc721_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC721 JSON is invalid" ) + "\n" ); - imaState.joErc721_main_net = null; - imaState.joErc721_s_chain = null; - imaState.strCoinNameErc721_main_net = ""; - imaState.strCoinNameErc721_s_chain = ""; - process.exit( 126 ); - } - } else { // if( imaState.strPathJsonErc721_main_net.length > 0 /*&& imaState.strPathJsonErc721_s_chain.length > 0*/ ) - if( imaState.strPathJsonErc721_s_chain.length > 0 ) { - n1 = 0; - n2 = 0; - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S-Chain ERC721 ABI from " ) + cc.info( imaState.strPathJsonErc721_s_chain ) + "\n" ); - imaState.joErc721_s_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc721_s_chain, null ); - n2 = Object.keys( imaState.joErc721_s_chain ).length; - - if( n2 > 0 ) { - imaState.strCoinNameErc721_s_chain = imaUtils.discover_in_json_coin_name( imaState.joErc721_s_chain ); - n2 = imaState.strCoinNameErc721_s_chain.length; - if( n2 > 0 ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded S-Chain ERC721 ABI " ) + cc.attention( imaState.strCoinNameErc721_s_chain ) + "\n" ); else { - if( n2 === 0 && imaState.strPathJsonErc721_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC721 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc721_main_net = null; - imaState.joErc721_s_chain = null; - imaState.strCoinNameErc721_main_net = ""; - imaState.strCoinNameErc721_s_chain = ""; - process.exit( 126 ); - } - } - } - } - } - if( n1 !== 0 && n2 === 0 ) { - if( imaState.strAddrErc721_explicit.length === 0 ) { - if( isPrintGathered ) - log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + cc.warning( "Both S-Chain ERC721 JSON and explicit ERC721 address are not specified" ) + "\n" ); - } else { - if( isPrintGathered ) - log.write( cc.attention( "IMPORTANT NOTICE:" ) + " " + cc.note( "S-Chain ERC721 ABI will be auto-generated" ) + "\n" ); - imaState.strCoinNameErc721_s_chain = "" + imaState.strCoinNameErc721_main_net; // assume same - imaState.joErc721_s_chain = JSON.parse( JSON.stringify( imaState.joErc721_main_net ) ); // clone - imaState.joErc721_s_chain[imaState.strCoinNameErc721_s_chain + "_address"] = "" + imaState.strAddrErc721_explicit; // set explicit address - // if( IMA.verbose_get() > IMA.RV_VERBOSE.information ) - // log.write( cc.info("Auto-generated S-Chain ERC721 JSON is ") + cc.j(imaState.joErc721_s_chain) + "\n" ); - } - } - // - if( imaState.strPathJsonErc721_t_chain.length > 0 && isPrintGathered ) { - if( IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S<->S Target S-Chain ERC721 ABI from " ) + cc.info( imaState.strPathJsonErc721_t_chain ) + "\n" ); - imaState.joErc721_t_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc721_t_chain, null ); - n2 = Object.keys( imaState.joErc721_t_chain ).length; - if( n2 > 0 ) { - imaState.strCoinNameErc721_t_chain = imaUtils.discover_in_json_coin_name( imaState.joErc721_t_chain ); - n2 = imaState.strCoinNameErc721_t_chain.length; - if( n2 > 0 && isPrintGathered ) - log.write( cc.info( "Loaded S<->S Target S-Chain ERC721 ABI " ) + cc.attention( imaState.strCoinNameErc721_t_chain ) + "\n" ); - else { - if( n2 === 0 && imaState.strPathJsonErc721_t_chain.length > 0 && isPrintGathered ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S<->S Target S-Chain ERC721 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc721_t_chain = null; - imaState.strCoinNameErc721_t_chain = ""; - process.exit( 126 ); - } - } - } // if( imaState.strPathJsonErc721_t_chain.length > 0 ) - if( isPrintGathered && - imaState.strAddrErc721_explicit_target.length === 0 && imaState.strCoinNameErc721_t_chain.length === 0 && - imaState.strCoinNameErc721_s_chain.length > 0 - ) - log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + cc.warning( "Both S<->S Target S-Chain ERC721 JSON and explicit ERC721 address are not specified" ) + "\n" ); - // - // - // - if( imaState.strPathJsonErc1155_main_net.length > 0 /* && imaState.strPathJsonErc1155_s_chain.length > 0 */ ) { - n1 = 0; - n2 = 0; - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading Main-net ERC1155 ABI from " ) + cc.info( imaState.strPathJsonErc1155_main_net ) + "\n" ); - imaState.joErc1155_main_net = imaUtils.jsonFileLoad( imaState.strPathJsonErc1155_main_net, null ); - n1 = Object.keys( imaState.joErc1155_main_net ).length; - if( imaState.strPathJsonErc1155_s_chain.length > 0 ) { - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S-Chain ERC1155 ABI from " ) + cc.info( imaState.strPathJsonErc1155_s_chain ) + "\n" ); - imaState.joErc1155_s_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc1155_s_chain, null ); - n2 = Object.keys( imaState.joErc1155_s_chain ).length; - } - if( n1 > 0 /* && n2 > 0 */ ) { - imaState.strCoinNameErc1155_main_net = imaUtils.discover_in_json_coin_name( imaState.joErc1155_main_net ); - if( n2 > 0 ) - imaState.strCoinNameErc1155_s_chain = imaUtils.discover_in_json_coin_name( imaState.joErc1155_s_chain ); - n1 = imaState.strCoinNameErc1155_main_net.length; - if( n2 > 0 ) - n2 = imaState.strCoinNameErc1155_s_chain.length; - if( n1 > 0 /* && n2 > 0 */ ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information && ( !imaState.bShowConfigMode ) ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded Main-net ERC1155 ABI " ) + cc.attention( imaState.strCoinNameErc1155_main_net ) + "\n" ); - if( n2 > 0 && isPrintGathered ) - log.write( cc.info( "Loaded S-Chain ERC1155 ABI " ) + cc.attention( imaState.strCoinNameErc1155_s_chain ) + "\n" ); - } - } else { - if( n1 === 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Main-net ERC1155 token name is not discovered (malformed JSON)" ) + "\n" ); - if( n2 === 0 && imaState.strPathJsonErc1155_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC1155 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc1155_main_net = null; - imaState.joErc1155_s_chain = null; - imaState.strCoinNameErc1155_main_net = ""; - imaState.strCoinNameErc1155_s_chain = ""; - process.exit( 126 ); - } - } else { - if( n1 === 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Main-net ERC1155 JSON is invalid" ) + "\n" ); - if( n2 === 0 && imaState.strPathJsonErc1155_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC1155 JSON is invalid" ) + "\n" ); - imaState.joErc1155_main_net = null; - imaState.joErc1155_s_chain = null; - imaState.strCoinNameErc1155_main_net = ""; - imaState.strCoinNameErc1155_s_chain = ""; - process.exit( 126 ); - } - } else { // if( imaState.strPathJsonErc1155_main_net.length > 0 /*&& imaState.strPathJsonErc1155_s_chain.length > 0*/ ) - if( imaState.strPathJsonErc1155_s_chain.length > 0 ) { - n1 = 0; - n2 = 0; - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S-Chain ERC1155 ABI from " ) + cc.info( imaState.strPathJsonErc1155_s_chain ) + "\n" ); - imaState.joErc1155_s_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc1155_s_chain, null ); - n2 = Object.keys( imaState.joErc1155_s_chain ).length; - - if( n2 > 0 ) { - imaState.strCoinNameErc1155_s_chain = imaUtils.discover_in_json_coin_name( imaState.joErc1155_s_chain ); - n2 = imaState.strCoinNameErc1155_s_chain.length; - if( n2 > 0 ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded S-Chain ERC1155 ABI " ) + cc.attention( imaState.strCoinNameErc1155_s_chain ) + "\n" ); - } else { - if( n2 === 0 && imaState.strPathJsonErc1155_s_chain.length > 0 ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S-Chain ERC1155 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc1155_main_net = null; - imaState.joErc1155_s_chain = null; - imaState.strCoinNameErc1155_main_net = ""; - imaState.strCoinNameErc1155_s_chain = ""; - process.exit( 126 ); - } - } - } - } - if( n1 !== 0 && n2 === 0 ) { - if( imaState.strAddrErc1155_explicit.length === 0 ) { - if( isPrintGathered ) - log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + cc.warning( "Both S-Chain ERC1155 JSON and explicit ERC1155 address are not specified" ) + "\n" ); - } else { - if( isPrintGathered ) - log.write( cc.attention( "IMPORTANT NOTICE:" ) + " " + cc.note( "S-Chain ERC1155 ABI will be auto-generated" ) + "\n" ); - imaState.strCoinNameErc1155_s_chain = "" + imaState.strCoinNameErc1155_main_net; // assume same - imaState.joErc1155_s_chain = JSON.parse( JSON.stringify( imaState.joErc1155_main_net ) ); // clone - imaState.joErc1155_s_chain[imaState.strCoinNameErc1155_s_chain + "_address"] = "" + imaState.strAddrErc1155_explicit; // set explicit address - // if( IMA.verbose_get() > IMA.RV_VERBOSE.information ) - // log.write( cc.info("Auto-generated S-Chain ERC1155 JSON is ") + cc.j(imaState.joErc1155_s_chain) + "\n" ); - } - } - // - if( imaState.strPathJsonErc1155_t_chain.length > 0 ) { - if( isPrintGathered && IMA.verbose_get() > IMA.RV_VERBOSE.information ) - log.write( cc.info( "Loading S<->S Target S-Chain ERC1155 ABI from " ) + cc.info( imaState.strPathJsonErc1155_t_chain ) + "\n" ); - imaState.joErc1155_t_chain = imaUtils.jsonFileLoad( imaState.strPathJsonErc1155_t_chain, null ); - n2 = Object.keys( imaState.joErc1155_t_chain ).length; - if( n2 > 0 ) { - imaState.strCoinNameErc1155_t_chain = imaUtils.discover_in_json_coin_name( imaState.joErc1155_t_chain ); - n2 = imaState.strCoinNameErc1155_t_chain.length; - if( n2 > 0 ) { - if( isPrintGathered ) - log.write( cc.info( "Loaded S<->S Target S-Chain ERC1155 ABI " ) + cc.attention( imaState.strCoinNameErc1155_t_chain ) + "\n" ); - } else { - if( n2 === 0 && imaState.strPathJsonErc1155_t_chain.length > 0 && isPrintGathered ) - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "S<->S Target S-Chain ERC1155 token name is not discovered (malformed JSON)" ) + "\n" ); - imaState.joErc1155_t_chain = null; - imaState.strCoinNameErc1155_t_chain = ""; - process.exit( 126 ); - } - } - } // if( imaState.strPathJsonErc1155_t_chain.length > 0 ) - if( isPrintGathered && - imaState.strAddrErc1155_explicit_target.length === 0 && imaState.strCoinNameErc1155_t_chain.length === 0 && - imaState.strCoinNameErc1155_s_chain.length > 0 - ) - log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + cc.warning( "Both S<->S Target S-Chain ERC1155 JSON and explicit ERC1155 address are not specified" ) + "\n" ); - // - // - // - - if( IMA.verbose_get() > IMA.RV_VERBOSE.information || imaState.bShowConfigMode ) { - const isPrintGathered = imaState.isPrintGathered ? true : false; - const isPrintSecurityValues = imaState.isPrintSecurityValues ? true : false; - if( isPrintGathered ) { - print_about( true ); - log.write( cc.attention( "IMA AGENT" ) + cc.normal( " is using " ) + cc.bright( "Web3" ) + cc.normal( " version " ) + cc.sunny( IMA.w3mod.version ) + "\n" ); - } - ensure_have_value( "App path", __filename, false, isPrintGathered, null, ( x ) => { - return cc.normal( x ); - } ); - ensure_have_value( "Verbose level", IMA.VERBOSE[IMA.verbose_get()], false, isPrintGathered, null, ( x ) => { - return cc.sunny( x ); - } ); - ensure_have_value( "Main-net URL", imaState.strURL_main_net, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.u( x ); - } ); - ensure_have_value( "S-chain URL", imaState.strURL_s_chain, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.u( x ); - } ); - ensure_have_value( "S<->S Target S-chain URL", imaState.strURL_t_chain, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.u( x ); - } ); - ensure_have_value( "Main-net Ethereum network name", imaState.strChainName_main_net, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S-Chain Ethereum network name", imaState.strChainName_s_chain, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S<->S Target S-Chain Ethereum network name", imaState.strChainName_t_chain, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "Main-net Ethereum chain ID", imaState.cid_main_net, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S-Chain Ethereum chain ID", imaState.cid_s_chain, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S<->S Target S-Chain Ethereum chain ID", imaState.cid_t_chain, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "Skale Manager ABI JSON file path", imaState.strPathAbiJson_skale_manager, false, isPrintGathered, null, ( x ) => { - return cc.warning( x ); - } ); - ensure_have_value( "Main-net ABI JSON file path", imaState.strPathAbiJson_main_net, false, isPrintGathered, null, ( x ) => { - return cc.warning( x ); - } ); - ensure_have_value( "S-Chain ABI JSON file path", imaState.strPathAbiJson_s_chain, false, isPrintGathered, null, ( x ) => { - return cc.warning( x ); - } ); - ensure_have_value( "S<->S Target S-Chain ABI JSON file path", imaState.strPathAbiJson_t_chain, false, isPrintGathered, null, ( x ) => { - return cc.warning( x ); - } ); - // - // - try { - ensure_have_value( "Main-net user account address", imaState.joAccount_main_net.address( imaState.w3_main_net ), false, isPrintGathered && isPrintSecurityValues ); - } catch ( err ) {} - try { - ensure_have_value( "S-chain user account address", imaState.joAccount_s_chain.address( imaState.w3_s_chain ), false, isPrintGathered && isPrintSecurityValues ); - } catch ( err ) {} - try { - ensure_have_value( "S<->S Target S-chain user account address", imaState.joAccount_t_chain.address( imaState.w3_t_chain ), false, isPrintGathered ); - } catch ( err ) {} - // - // ensure_have_value( "Private key for main-net user account address", imaState.joAccount_main_net.privateKey, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - // return cc.attention( x ); - // } ); - // ensure_have_value( "Private key for S-Chain user account address", imaState.joAccount_s_chain.privateKey, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - // return cc.attention( x ); - // } ); - // ensure_have_value( "Private key for S<->S Target S-Chain user account address", imaState.joAccount_t_chain.privateKey, false, isPrintGathered && isPrintSecurityValues, null, ( x ) => { - // return cc.attention( x ); - // } ); - // - try { - ensure_have_chain_credentials( "Main Net", imaState.joAccount_main_net, false, isPrintGathered && isPrintSecurityValues ); - } catch ( err ) {} - try { - ensure_have_chain_credentials( "S-Chain", imaState.joAccount_s_chain, false, isPrintGathered && isPrintSecurityValues ); - } catch ( err ) {} - try { - ensure_have_chain_credentials( "S<->S Target S-Chain", imaState.joAccount_t_chain, false, isPrintGathered && isPrintSecurityValues ); - } catch ( err ) {} - // - // - ensure_have_value( "Amount of wei to transfer", imaState.nAmountOfWei, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - ensure_have_value( "M->S transfer block size", imaState.nTransferBlockSizeM2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S->M transfer block size", imaState.nTransferBlockSizeS2M, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - if( imaState.bHaveSkaleManagerABI ) { - ensure_have_value( "S->S transfer block size", imaState.nTransferBlockSizeS2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - } - ensure_have_value( "M->S transactions limit", imaState.nMaxTransactionsM2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S->M transactions limit", imaState.nMaxTransactionsS2M, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - if( imaState.bHaveSkaleManagerABI ) { - ensure_have_value( "S->S transactions limit", imaState.nMaxTransactionsS2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - } - ensure_have_value( "M->S await blocks", imaState.nBlockAwaitDepthM2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S->M await blocks", imaState.nBlockAwaitDepthS2M, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - if( imaState.bHaveSkaleManagerABI ) { - ensure_have_value( "S->S await blocks", imaState.nBlockAwaitDepthS2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - } - ensure_have_value( "M->S minimal block age", imaState.nBlockAgeM2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - ensure_have_value( "S->M minimal block age", imaState.nBlockAgeS2M, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - if( imaState.bHaveSkaleManagerABI ) { - ensure_have_value( "S->S minimal block age", imaState.nBlockAgeS2S, false, isPrintGathered, null, ( x ) => { - return cc.note( x ); - } ); - } - ensure_have_value( "Transfer loop period(seconds)", imaState.nLoopPeriodSeconds, false, isPrintGathered, null, ( x ) => { - return cc.success( x ); - } ); - if( imaState.nTimeFrameSeconds > 0 ) { - ensure_have_value( "Time framing(seconds)", imaState.nTimeFrameSeconds, false, isPrintGathered ); - ensure_have_value( "Next frame gap(seconds)", imaState.nNextFrameGap, false, isPrintGathered ); - } else - ensure_have_value( "Time framing", cc.error( "disabled" ), false, isPrintGathered ); - ensure_have_value( "S-Chain node number(zero based)", imaState.nNodeNumber, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - ensure_have_value( "S-Chain nodes count", imaState.nNodesCount, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - - ensure_have_value( "Automatic exit(seconds)", imaState.nAutoExitAfterSeconds, false, isPrintGathered && isPrintSecurityValues ); - - if( imaState.strLogFilePath.length > 0 ) { - ensure_have_value( "Log file path", imaState.strLogFilePath, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - ensure_have_value( "Max size of log file path", imaState.nLogMaxSizeBeforeRotation, false, isPrintGathered, null, ( x ) => { - return ( x <= 0 ) ? cc.warning( "unlimited" ) : cc.note( x ); - } ); - ensure_have_value( "Max rotated count of log files", imaState.nLogMaxFilesCount, false, isPrintGathered, null, ( x ) => { - return ( x <= 1 ) ? cc.warning( "not set" ) : cc.note( x ); - } ); - } - if( imaState.strCoinNameErc20_main_net.length > 0 /* && imaState.strCoinNameErc20_s_chain.length > 0 */ ) { - ensure_have_value( "Loaded Main-net ERC20 ABI ", imaState.strCoinNameErc20_main_net, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - ensure_have_value( "Loaded S-Chain ERC20 ABI ", imaState.strCoinNameErc20_s_chain, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - ensure_have_value( "Amount of tokens to transfer", imaState.nAmountOfToken, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - if( isPrintGathered ) - log.write( cc.info( "ERC20 explicit S-Chain address is " ) + cc.attention( imaState.strAddrErc20_explicit ) + "\n" ); - } - if( imaState.strCoinNameErc20_t_chain.length > 0 ) { - ensure_have_value( "Loaded S<->S Target S-Chain ERC20 ABI ", imaState.strCoinNameErc20_t_chain, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - } - if( imaState.strCoinNameErc721_main_net.length > 0 /* && imaState.strCoinNameErc721_s_chain.length > 0 */ ) { - ensure_have_value( "Loaded Main-net ERC721 ABI ", imaState.strCoinNameErc721_main_net, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - ensure_have_value( "Loaded S-Chain ERC721 ABI ", imaState.strCoinNameErc721_s_chain, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - ensure_have_value( "ERC721 token id ", imaState.idToken, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - if( isPrintGathered ) - log.write( cc.info( "ERC721 explicit S-Chain address is " ) + cc.attention( imaState.strAddrErc721_explicit ) + "\n" ); - } - if( imaState.strCoinNameErc721_t_chain.length > 0 ) { - ensure_have_value( "Loaded S<->S Target S-Chain ERC721 ABI ", imaState.strCoinNameErc721_t_chain, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - } - if( imaState.strCoinNameErc1155_main_net.length > 0 /* && imaState.strCoinNameErc1155_s_chain.length > 0 */ ) { - ensure_have_value( "Loaded Main-net ERC1155 ABI ", imaState.strCoinNameErc1155_main_net, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - ensure_have_value( "Loaded S-Chain ERC1155 ABI ", imaState.strCoinNameErc1155_s_chain, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - try { - ensure_have_value( "ERC1155 token id ", imaState.idToken, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - ensure_have_value( "ERC1155 token amount ", imaState.nAmountOfToken, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - } catch ( e1 ) { - try { - ensure_have_value( "ERC1155 batch of token ids ", imaState.idTokens, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - ensure_have_value( "ERC1155 batch of token amounts ", imaState.arrAmountsOfTokens, false, isPrintGathered, null, ( x ) => { - return cc.info( x ); - } ); - } catch ( e2 ) { - log.write( cc.warning( "Please check your params in ERC1155 transfer \n" ) ); - log.write( cc.warning( "Error 1" ) + cc.sunny( e1 ) + "\n" ); - log.write( cc.warning( "Error 2" ) + cc.sunny( e2 ) + "\n" ); - process.exit( 126 ); - } - } - if( isPrintGathered ) - log.write( cc.info( "ERC1155 explicit S-Chain address is " ) + cc.attention( imaState.strAddrErc1155_explicit ) + "\n" ); - } - if( imaState.strCoinNameErc1155_t_chain.length > 0 ) { - ensure_have_value( "Loaded S<->S Target S-Chain ERC1155 ABI ", imaState.strCoinNameErc1155_t_chain, false, isPrintGathered, null, ( x ) => { - return cc.attention( x ); - } ); - } - if( isPrintGathered ) { - log.write( cc.info( "Main Net Gas Price Multiplier is" ) + cc.debug( "....................." ) + ( imaState.tc_main_net.gasPriceMultiplier ? cc.info( imaState.tc_main_net.gasPriceMultiplier.toString() ) : cc.error( "disabled" ) ) + "\n" ); - log.write( cc.info( "S-Chain Gas Price Multiplier is" ) + cc.debug( "......................" ) + ( imaState.tc_s_chain.gasPriceMultiplier ? cc.info( imaState.tc_s_chain.gasPriceMultiplier.toString() ) : cc.error( "disabled" ) ) + "\n" ); - log.write( cc.info( "Target S-Chain Gas Price Multiplier is" ) + cc.debug( "..............." ) + ( imaState.tc_t_chain.gasPriceMultiplier ? cc.info( imaState.tc_t_chain.gasPriceMultiplier.toString() ) : cc.error( "disabled" ) ) + "\n" ); - log.write( cc.info( "Main Net Gas Value Multiplier is" ) + cc.debug( "....................." ) + ( imaState.tc_main_net.gasMultiplier ? cc.info( imaState.tc_main_net.gasMultiplier.toString() ) : cc.notice( "default" ) ) + "\n" ); - log.write( cc.info( "S-Chain Gas Value Multiplier is" ) + cc.debug( "......................" ) + ( imaState.tc_s_chain.gasMultiplier ? cc.info( imaState.tc_s_chain.gasMultiplier.toString() ) : cc.notice( "default" ) ) + "\n" ); - log.write( cc.info( "Target S-Chain Gas Value Multiplier is" ) + cc.debug( "..............." ) + ( imaState.tc_t_chain.gasMultiplier ? cc.info( imaState.tc_t_chain.gasMultiplier.toString() ) : cc.notice( "default" ) ) + "\n" ); - log.write( cc.info( "Pending transaction analysis(PTX) is" ) + cc.debug( "................." ) + ( imaState.optsPendingTxAnalysis.isEnabled ? cc.success( "enabled" ) : cc.error( "disabled" ) ) + "\n" ); - log.write( cc.info( "Pending transaction analysis 2nd attempt after" ) + cc.debug( "......." ) + cc.bright( imaState.optsPendingTxAnalysis.nTimeoutSecondsBeforeSecondAttempt ) + "\n" ); - log.write( cc.info( "Ignore result of PTX is" ) + cc.debug( ".............................." ) + ( imaState.optsPendingTxAnalysis.isIgnore ? cc.success( "yes" ) : cc.error( "no" ) ) + "\n" ); - log.write( cc.info( "Ignore secondary result of PTX is" ) + cc.debug( "...................." ) + ( imaState.optsPendingTxAnalysis.isIgnore2 ? cc.success( "yes" ) : cc.error( "no" ) ) + "\n" ); - log.write( cc.info( "Oracle based gas reimbursement is" ) + cc.debug( "...................." ) + ( IMA.getEnabledOracle() ? cc.success( "enabled" ) : cc.error( "disabled" ) ) + "\n" ); - log.write( cc.info( "S-Chain to S-Chain transferring is" ) + cc.debug( "..................." ) + ( imaState.s2s_opts.isEnabled ? cc.success( "enabled" ) : cc.error( "disabled" ) ) + "\n" ); - log.write( cc.info( "SKALE network re-discovery interval is" ) + cc.debug( "..............." ) + ( imaState.s2s_opts.secondsToReDiscoverSkaleNetwork ? cc.info( imaState.s2s_opts.secondsToReDiscoverSkaleNetwork.toString() ) : cc.error( "disabled" ) ) + "\n" ); - log.write( cc.info( "S<->S transfer mode is" ) + cc.debug( "..............................." ) + IMA.get_S2S_transfer_mode_description_colorized() + "\n" ); - } // if( isPrintGathered ) - } - // - // - // -} // ima_common_init - -module.exports = { - init: init, - print_about: print_about, - parse_command_line_argument: parse_command_line_argument, - ensure_have_value: ensure_have_value, - ensure_have_chain_credentials: ensure_have_chain_credentials, - find_node_index: find_node_index, - load_node_config: load_node_config, - parse: parse, - ima_common_init: ima_common_init, - getWeb3FromURL: getWeb3FromURL -}; // module.exports diff --git a/agent/cli.mjs b/agent/cli.mjs new file mode 100644 index 000000000..644941296 --- /dev/null +++ b/agent/cli.mjs @@ -0,0 +1,4299 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file cli.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as path from "path"; +import * as url from "url"; +import * as os from "os"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as imaUtils from "./utils.mjs"; +import * as rpcCall from "./rpcCall.mjs"; +import * as imaHelperAPIs from "../npms/skale-ima/imaHelperAPIs.mjs"; +import * as imaTransferErrorHandling from "../npms/skale-ima/imaTransferErrorHandling.mjs"; +import * as imaOracleOperations from "../npms/skale-ima/imaOracleOperations.mjs"; +import * as imaTx from "../npms/skale-ima/imaTx.mjs"; +import * as state from "./state.mjs"; + +const __dirname = path.dirname( url.fileURLToPath( import.meta.url ) ); + +const gStrAppName = "IMA AGENT"; +const gStrVersion = + imaUtils.jsonFileLoad( path.join( __dirname, "package.json" ), null ).version; + +export function printAbout( isLog ) { + isLog = isLog || false; + const strMsg = + cc.attention( gStrAppName ) + cc.normal( " version " ) + cc.sunny( gStrVersion ); + if( isLog ) + log.write( strMsg + "\n" ); + else + console.log( strMsg ); + return true; +} + +export function parseCommandLineArgument( s ) { + const joArg = { + name: "", + value: "" + }; + try { + if( !s ) + return joArg; + s = "" + s; + while( s.length > 0 && s[0] == "-" ) + s = s.substring( 1 ); + const n = s.indexOf( "=" ); + if( n < 0 ) { + joArg.name = s; + return joArg; + } + joArg.name = s.substring( 0, n ); + joArg.value = s.substring( n + 1 ); + } catch ( err ) {} + return joArg; +} + +// check correctness of command line arguments +export function ensureHaveValue( + name, value, isExitIfEmpty, + isPrintValue, fnNameColorizer, fnValueColorizer +) { + isExitIfEmpty = isExitIfEmpty || false; + isPrintValue = isPrintValue || false; + fnNameColorizer = fnNameColorizer || ( ( x ) => { + return cc.info( x ); + } ); + fnValueColorizer = fnValueColorizer || ( ( x ) => { + return cc.notice( x ); + } ); + let retVal = true; + value = value ? value.toString() : ""; + if( value.length === 0 ) { + retVal = false; + if( ! isPrintValue ) { + console.log( " " + cc.error( "IMPORTANT WARNING:" ) + + cc.warning( " missing value for " ) + fnNameColorizer( name ) ); + } + if( isExitIfEmpty ) + process.exit( 126 ); + } + let strDots = "..."; + let n = 50 - name.length; + for( ; n > 0; --n ) + strDots += "."; + if( isPrintValue ) { + log.write( fnNameColorizer( name ) + cc.debug( strDots ) + + fnValueColorizer( value ) + "\n" ); + } + return retVal; +} + +export function ensureHaveCredentials( + strFriendlyChainName, joAccount, isExitIfEmpty, isPrintValue +) { + strFriendlyChainName = strFriendlyChainName || ""; + if( ! ( typeof joAccount == "object" ) ) { + log.write( cc.error( "ARGUMENTS VALIDATION WARNING:" ) + + cc.warning( " bad account specified for " ) + cc.info( strFriendlyChainName ) + + cc.warning( " chain" ) + "\n" + ); + if( isExitIfEmpty ) + process.exit( 126 ); + } + let cntAccountVariantsSpecified = 0; + if( "strTransactionManagerURL" in joAccount && + typeof joAccount.strTransactionManagerURL == "string" && + joAccount.strTransactionManagerURL.length > 0 + ) { + ++ cntAccountVariantsSpecified; + ensureHaveValue( + "" + strFriendlyChainName + "/TM/URL", + joAccount.strTransactionManagerURL, isExitIfEmpty, isPrintValue + ); + } + if( "strSgxURL" in joAccount && + typeof joAccount.strSgxURL == "string" && + joAccount.strSgxURL.length > 0 + ) { + ++ cntAccountVariantsSpecified; + ensureHaveValue( + "" + strFriendlyChainName + "/SGX/URL", + joAccount.strSgxURL, isExitIfEmpty, isPrintValue + ); + if( "strPathSslKey" in joAccount && + typeof joAccount.strPathSslKey == "string" && + joAccount.strPathSslKey.length > 0 + ) { + ensureHaveValue( + "" + strFriendlyChainName + "/SGX/SSL/keyPath", + joAccount.strPathSslKey, isExitIfEmpty, isPrintValue + ); + } + if( "strPathSslCert" in joAccount && + typeof joAccount.strPathSslCert == "string" && + joAccount.strPathSslCert.length > 0 + ) { + ensureHaveValue( + "" + strFriendlyChainName + "/SGX/SSL/certPath", + joAccount.strPathSslCert, isExitIfEmpty, isPrintValue + ); + } + } + if( "strSgxKeyName" in joAccount && + typeof joAccount.strSgxKeyName == "string" && + joAccount.strSgxKeyName.length > 0 + ) { + ++ cntAccountVariantsSpecified; + ensureHaveValue( + "" + strFriendlyChainName + "/SGX/keyName", + joAccount.strSgxKeyName, isExitIfEmpty, isPrintValue + ); + } + if( "privateKey" in joAccount && + typeof joAccount.privateKey == "string" && + joAccount.privateKey.length > 0 + ) { + ++ cntAccountVariantsSpecified; + ensureHaveValue( + "" + strFriendlyChainName + "/privateKey", + joAccount.privateKey, isExitIfEmpty, isPrintValue + ); + } + if( "address_" in joAccount && + typeof joAccount.address_ == "string" && + joAccount.address_.length > 0 + ) { + ++ cntAccountVariantsSpecified; + ensureHaveValue( + "" + strFriendlyChainName + "/walletAddress", + joAccount.address_, isExitIfEmpty, isPrintValue + ); + } + if( cntAccountVariantsSpecified == 0 ) { + log.write( cc.error( "ARGUMENTS VALIDATION WARNING:" ) + + cc.warning( " bad credentials information specified for " ) + + cc.info( strFriendlyChainName ) + + cc.warning( " chain, no explicit SGX, no explicit private key, " + + "no wallet address found" ) + + "\n" + ); + if( isExitIfEmpty ) + process.exit( 126 ); + } + return true; +} + +export function findNodeIndex( joSChainNodeConfiguration ) { + try { + const searchID = joSChainNodeConfiguration.skaleConfig.nodeInfo.nodeID; + const cnt = joSChainNodeConfiguration.skaleConfig.sChain.nodes.length; + for( let i = 0; i < cnt; ++i ) { + const joNodeDescription = joSChainNodeConfiguration.skaleConfig.sChain.nodes[i]; + if( joNodeDescription.nodeID == searchID ) + return i; + } + } catch ( err ) {} + return 0; +} + +function printHelpGeneral( soi ) { + console.log( cc.sunny( "GENERAL" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + cc.bright( "help" ) + + cc.debug( ".................................." ) + cc.notice( "Show this " ) + + cc.note( "help info" ) + cc.notice( " and exit." ) ); + console.log( soi + cc.debug( "--" ) + cc.bright( "version" ) + + cc.debug( "..............................." ) + cc.notice( "Show " ) + + cc.note( "version info" ) + cc.notice( " and exit." ) ); + console.log( soi + cc.debug( "--" ) + cc.bright( "colors" ) + + cc.debug( "................................" ) + cc.notice( "Use " ) + + cc.rainbow( "ANSI-colorized logging" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + cc.bright( "no-colors" ) + + cc.debug( "............................." ) + cc.notice( "Use " ) + + cc.normal( "monochrome logging" ) + cc.notice( "." ) ); +} + +function printHelpBlockchainNetwork( soi ) { + console.log( cc.sunny( "BLOCKCHAIN NETWORK" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "url-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "......................" ) + cc.note( "Main-net" ) + + cc.notice( " URL. Value is automatically loaded from the " ) + + cc.warning( "URL_W3_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "url-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "......................." ) + cc.note( "S-chain" ) + + cc.notice( " URL. Value is automatically loaded from the " ) + + cc.warning( "URL_W3_S_CHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "url-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "......................." ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( " URL. Value is automatically loaded from the " ) + + cc.warning( "URL_W3_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "id-main-net" ) + cc.sunny( "=" ) + cc.success( "number" ) + + cc.debug( "...................." ) + cc.note( "Main-net" ) + + cc.notice( " Ethereum " ) + cc.note( "network name." ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "CHAIN_NAME_ETHEREUM" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default value is " ) + cc.sunny( "\"Mainnet\"" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "id-s-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + + cc.debug( "....................." ) + cc.note( "S-chain" ) + + cc.notice( " Ethereum " ) + cc.note( "network name." ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "CHAIN_NAME_SCHAIN" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default value is " ) + cc.sunny( "\"id-S-chain\"" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "id-t-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + + cc.debug( "....................." ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( " Ethereum " ) + cc.note( "network name." ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "CHAIN_NAME_SCHAIN_TARGET" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default value is " ) + cc.sunny( "\"id-T-chain\"" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "cid-main-net" ) + cc.sunny( "=" ) + cc.success( "number" ) + + cc.debug( "..................." ) + cc.note( "Main-net" ) + + cc.notice( " Ethereum " ) + cc.attention( "chain ID" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "CID_ETHEREUM" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default value is " ) + cc.sunny( -4 ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "cid-s-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + + cc.debug( "...................." ) + cc.note( "S-chain" ) + + cc.notice( " Ethereum " ) + cc.attention( "chain ID" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "CID_SCHAIN" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default value is " ) + cc.sunny( -4 ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "cid-t-chain" ) + cc.sunny( "=" ) + cc.success( "number" ) + + cc.debug( "...................." ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( " Ethereum " ) + cc.attention( "chain ID" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "CID_SCHAIN_TARGET" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default value is " ) + cc.sunny( -4 ) + cc.notice( "." ) ); +} + +function printHelpBlockchainInterface( soi ) { + console.log( cc.sunny( "BLOCKCHAIN INTERFACE" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "abi-skale-manager" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "................" ) + cc.notice( "Path to JSON file containing " ) + + cc.bright( "Skale Manager" ) + cc.notice( " ABI. " ) + + cc.debug( "Optional parameter. It's needed for " ) + cc.note( "S-Chain" ) + + cc.debug( " to " ) + cc.note( "S-Chain" ) + cc.debug( " transfers." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "abi-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "....................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "IMA" ) + + cc.notice( " ABI for " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "abi-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "......................" ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "IMA" ) + + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "abi-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "......................" ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "IMA" ) + + cc.notice( " ABI for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( "." ) ); +} + +function printHelpErcInterfaces( soi ) { + console.log( cc.sunny( "ERC20 INTERFACE" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc20-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "..................." ) + cc.notice( "Path to JSON file containing " ) + + cc.bright( "ERC20" ) + cc.notice( " ABI for " ) + + cc.note( "Main-net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc20-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "...................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC20" ) + + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "addr-erc20-s-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + + cc.debug( "............" ) + cc.notice( "Explicit " ) + cc.bright( "ERC20" ) + + cc.notice( " address in " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc20-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "...................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC20" ) + + cc.notice( " ABI for " ) + cc.note( "S<->S Target S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "addr-erc20-t-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + + cc.debug( "............" ) + cc.notice( "Explicit " ) + cc.bright( "ERC20" ) + + cc.notice( " address in " ) + + cc.note( "S<->S Target S-chain" ) + cc.notice( "." ) ); + + console.log( cc.sunny( "ERC721 INTERFACE" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc721-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( ".................." ) + cc.notice( "Path to JSON file containing " ) + + cc.bright( "ERC721" ) + cc.notice( " ABI for " ) + + cc.note( "Main-net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc721-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "..................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC721" ) + + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "addr-erc721-s-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + + cc.debug( "..........." ) + cc.notice( "Explicit " ) + cc.bright( "ERC721" ) + + cc.notice( " address in " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc721-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "..................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC721" ) + + cc.notice( " ABI for " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "addr-erc721-t-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + + cc.debug( "..........." ) + cc.notice( "Explicit " ) + cc.bright( "ERC721" ) + + cc.notice( " address in " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); + + console.log( cc.sunny( "ERC1155 INTERFACE" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc1155-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC1155" ) + + cc.notice( " ABI for " ) + cc.note( "Main-net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc1155-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( ".................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC1155" ) + + cc.notice( " ABI for " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "addr-erc1155-s-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + + cc.debug( ".........." ) + cc.notice( "Explicit " ) + cc.bright( "ERC1155" ) + + cc.notice( " address in " ) + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "erc1155-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( ".................." ) + + cc.notice( "Path to JSON file containing " ) + cc.bright( "ERC1155" ) + + cc.notice( " ABI for " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "addr-erc1155-t-chain" ) + cc.sunny( "=" ) + cc.attention( "address" ) + + cc.debug( ".........." ) + cc.notice( "Explicit " ) + cc.bright( "ERC1155" ) + + cc.notice( " address in " ) + cc.note( "S<->S S-chain" ) + cc.notice( "." ) ); +} + +function printHelpUserAccount1( soi ) { + console.log( cc.sunny( "USER ACCOUNT" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tm-url-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "..................." ) + cc.bright( "Transaction Manager" ) + + cc.notice( " server URL for " ) + cc.note( "Main-net" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "TRANSACTION_MANAGER_URL_ETHEREUM" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Example: " ) + cc.bright( "redis://@127.0.0.1:6379" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tm-url-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "...................." ) + cc.bright( "Transaction Manager" ) + + cc.notice( " server URL for " ) + cc.note( "S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "TRANSACTION_MANAGER_URL_S_CHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tm-url-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "...................." ) + cc.bright( "Transaction Manager" ) + + cc.notice( " server URL for " ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "TRANSACTION_MANAGER_URL_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tm-priority-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( ".............." ) + cc.bright( "Transaction Manager" ) + + cc.notice( " priority for " ) + cc.note( "Main-net" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "TRANSACTION_MANAGER_PRIORITY_ETHEREUM" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default is " ) + cc.sunny( "5" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tm-priority-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "..............." ) + cc.bright( "Transaction Manager" ) + + cc.notice( " priority for " ) + cc.note( "S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "TRANSACTION_MANAGER_PRIORITY_S_CHAIN" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default is " ) + cc.sunny( "5" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tm-priority-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "..............." ) + cc.bright( "Transaction Manager" ) + + cc.notice( " priority for " ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "TRANSACTION_MANAGER_PRIORITY_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified. " ) + + cc.debug( "Default is " ) + cc.sunny( "5" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-url-main-net" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( ".................." ) + cc.sunny( "SGX server" ) + + cc.notice( " URL for " ) + cc.note( "Main-net" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_URL_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-url-s-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "..................." ) + cc.sunny( "SGX server" ) + + cc.notice( " URL for " ) + cc.note( "S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_URL_S_CHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-url-t-chain" ) + cc.sunny( "=" ) + cc.attention( "URL" ) + + cc.debug( "..................." ) + cc.sunny( "SGX server" ) + + cc.notice( " URL for " ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_URL_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ecdsa-key-main-net" ) + cc.sunny( "=" ) + cc.error( "name" ) + + cc.debug( "..........." ) + cc.attention( "SGX/ECDSA key name" ) + + cc.notice( " for " ) + cc.note( "Main-net" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_KEY_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ecdsa-key-s-chain" ) + cc.sunny( "=" ) + cc.error( "name" ) + + cc.debug( "............" ) + cc.attention( "SGX/ECDSA key name" ) + + cc.notice( " for " ) + cc.note( "S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_KEY_S_CHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ecdsa-key-t-chain" ) + cc.sunny( "=" ) + cc.error( "name" ) + + cc.debug( "............" ) + cc.attention( "SGX/ECDSA key name" ) + + cc.notice( " for " ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_KEY_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-bls-key-main-net" ) + cc.sunny( "=" ) + cc.error( "name" ) + + cc.debug( "............." ) + cc.attention( "SGX/BLS key name" ) + + cc.notice( " for " ) + cc.note( "Main-net" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "BLS_KEY_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-bls-key-s-chain" ) + cc.sunny( "=" ) + cc.error( "name" ) + + cc.debug( ".............." ) + cc.attention( "SGX/BLS key name" ) + + cc.notice( " for " ) + cc.note( "S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "BLS_KEY_S_CHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-bls-key-t-chain" ) + cc.sunny( "=" ) + cc.error( "name" ) + + cc.debug( ".............." ) + cc.attention( "SGX/BLS key name" ) + + cc.notice( " for " ) + cc.note( "S<->S Target S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "BLS_KEY_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ssl-key-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "............." ) + cc.notice( "Path to " ) + cc.note( "SSL key file" ) + + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + + cc.note( "Main-net" ) + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_SSL_KEY_FILE_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ssl-key-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( ".............." ) + cc.notice( "Path to " ) + + cc.note( "SSL key file" ) + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + + cc.notice( " of " ) + cc.note( "S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_SSL_KEY_FILE_S_CHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ssl-key-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( ".............." ) + cc.notice( "Path to " ) + cc.note( "SSL key file" ) + + cc.notice( " for " ) + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + + cc.note( "S<->S Target S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_SSL_KEY_FILE_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ssl-cert-main-net" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "............" ) + cc.notice( "Path to " ) + + cc.note( "SSL certificate file" ) + cc.notice( " for " ) + + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "Main-net" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_SSL_CERT_FILE_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ssl-cert-s-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "............." ) + cc.notice( "Path to " ) + + cc.note( "SSL certificate file" ) + cc.notice( " for " ) + + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + cc.note( "S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_SSL_CERT_FILE_S_CHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sgx-ssl-cert-t-chain" ) + cc.sunny( "=" ) + cc.attention( "path" ) + + cc.debug( "............." ) + cc.notice( "Path to " ) + + cc.note( "SSL certificate file" ) + cc.notice( " for " ) + + cc.bright( "SGX wallet" ) + cc.notice( " of " ) + + cc.note( "S<->S Target S-chain" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "SGX_SSL_CERT_FILE_S_CHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "address-main-net" ) + cc.sunny( "=" ) + cc.warning( "value" ) + + cc.debug( "................" ) + cc.note( "Main-net" ) + " " + + cc.attention( "user account address" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "ACCOUNT_FOR_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "address-s-chain" ) + cc.sunny( "=" ) + cc.warning( "value" ) + + cc.debug( "................." ) + cc.note( "S-chain" ) + " " + + cc.attention( "user account address" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "ACCOUNT_FOR_SCHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "address-t-chain" ) + cc.sunny( "=" ) + cc.warning( "value" ) + + cc.debug( "................." ) + cc.note( "S<->S Target S-chain" ) + + " " + cc.attention( "user account address" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "ACCOUNT_FOR_SCHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); +} + +function printHelpUserAccount2( soi ) { + console.log( soi + cc.debug( "--" ) + + cc.bright( "key-main-net" ) + cc.sunny( "=" ) + cc.error( "value" ) + + cc.debug( "...................." ) + cc.attention( "Private key" ) + + cc.notice( " for " ) + cc.note( "Main-net" ) + " " + + cc.attention( "user account address" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "PRIVATE_KEY_FOR_ETHEREUM" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "key-s-chain" ) + cc.sunny( "=" ) + cc.error( "value" ) + + cc.debug( "....................." ) + cc.attention( "Private key" ) + + cc.notice( " for " ) + cc.note( "S-Chain" ) + " " + + cc.attention( "user account address" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "PRIVATE_KEY_FOR_SCHAIN" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "key-t-chain" ) + cc.sunny( "=" ) + cc.error( "value" ) + + cc.debug( "....................." ) + cc.attention( "Private key" ) + + cc.notice( " for " ) + cc.note( "S<->S Target S-Chain" ) + " " + + cc.attention( "user account address" ) + + cc.notice( ". Value is automatically loaded from the " ) + + cc.warning( "PRIVATE_KEY_FOR_SCHAIN_TARGET" ) + + cc.notice( " environment variable if not specified." ) ); + console.log( soi + cc.debug( "Please notice, IMA prefer to use transaction manager " + + "to sign blockchain transactions if " ) + + cc.attention( "--tm-url-main-net" ) + cc.debug( "/" ) + + cc.attention( "--tm-url-s-chain" ) + cc.debug( " command line values or " ) + + cc.warning( "TRANSACTION_MANAGER_URL_ETHEREUM" ) + cc.debug( "/" ) + + cc.warning( "TRANSACTION_MANAGER_URL_S_CHAIN" ) + + cc.debug( " shell variables were specified. " + + "Next preferred option is SGX wallet which is used if " ) + + cc.attention( "--sgx-url-main-net" ) + cc.debug( "/" ) + + cc.attention( "--sgx-url-s-chain" ) + cc.debug( " command line values or " ) + + cc.warning( "SGX_URL_ETHEREUM" ) + cc.debug( "/" ) + + cc.warning( "SGX_URL_S_CHAIN" ) + + cc.debug( " shell variables were specified. SGX signing also needs " + + "key name, key and certificate files. " ) + + cc.debug( "Finally, IMA attempts to use explicitly provided private key " + + "to sign blockchain transactions if " ) + + cc.attention( "--key-main-net" ) + cc.debug( "/" ) + + cc.attention( "--key-s-chain" ) + cc.debug( " command line values or " ) + + cc.warning( "PRIVATE_KEY_FOR_ETHEREUM" ) + cc.debug( "/" ) + + cc.warning( "PRIVATE_KEY_FOR_SCHAIN" ) + + cc.debug( " shell variables were specified. " ) + ); +} + +function printHelpTransfers( soi ) { + console.log( cc.sunny( "GENERAL TRANSFER" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "value" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.warning( "unitName" ) + cc.debug( ".................." ) + + cc.notice( "Amount of " ) + cc.attention( "unitName" ) + + cc.notice( " to transfer, where " ) + cc.attention( "unitName" ) + + cc.notice( " is well known Ethereum unit name like " ) + cc.attention( "ether" ) + + cc.notice( " or " ) + cc.attention( "wei" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "wei" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "............................" ) + cc.notice( "Amount of " ) + + cc.attention( "wei" ) + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "babbage" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "........................" ) + cc.notice( "Amount of " ) + + cc.attention( "babbage" ) + cc.info( "(wei*1000)" ) + + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "lovelace" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "......................." ) + cc.notice( "Amount of " ) + + cc.attention( "lovelace" ) + cc.info( "(wei*1000*1000)" ) + + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "shannon" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "........................" ) + cc.notice( "Amount of " ) + + cc.attention( "shannon" ) + cc.info( "(wei*1000*1000*1000)" ) + + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "szabo" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( ".........................." ) + cc.notice( "Amount of " ) + + cc.attention( "szabo" ) + cc.info( "(wei*1000*1000*1000*1000)" ) + + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "finney" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "........................." ) + cc.notice( "Amount of " ) + + cc.attention( "finney" ) + cc.info( "(wei*1000*1000*1000*1000*1000)" ) + + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "ether" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( ".........................." ) + cc.notice( "Amount of " ) + + cc.attention( "ether" ) + cc.info( "(wei*1000*1000*1000*1000*1000*1000)" ) + + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "amount" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "........................." ) + cc.notice( "Amount of " ) + + cc.attention( "tokens" ) + cc.notice( " to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tid" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "............................" ) + cc.bright( "ERC721" ) + + cc.notice( " or " ) + cc.bright( "ERC1155" ) + + cc.notice( " token id to transfer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "amounts" ) + cc.sunny( "=" ) + cc.attention( "array of numbers" ) + + cc.debug( ".............." ) + cc.bright( "ERC1155" ) + + cc.notice( " token id to transfer in batch." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "tids" ) + cc.sunny( "=" ) + cc.attention( "array of numbers" ) + + cc.debug( "................." ) + cc.bright( "ERC1155" ) + + cc.notice( " token amount to transfer in batch." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sleep-between-tx" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "..............." ) + cc.notice( "Sleep time " ) + + cc.debug( "(in milliseconds)" ) + + cc.notice( " between transactions during complex operations." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "wait-next-block" ) + + cc.debug( "......................." ) + + cc.notice( "Wait for next block between transactions " + + "during complex operations." ) ); + + console.log( cc.sunny( "S-CHAIN TO S-CHAIN TRANSFER" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-enable" ) + cc.debug( "............................" ) + + cc.success( "Enables" ) + " " + cc.note( "S-Chain" ) + cc.notice( " to " ) + + cc.note( "S-Chain" ) + cc.notice( " transfers. " ) + cc.debug( "Default mode" ) + + cc.notice( ". The " ) + cc.bright( "abi-skale-manager" ) + + cc.notice( " path must be provided." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-disable" ) + cc.debug( "..........................." ) + + cc.error( "Disables" ) + " " + cc.note( "S-Chain" ) + cc.notice( " to " ) + + cc.note( "S-Chain" ) + cc.notice( " transfers." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "net-rediscover" ) + cc.sunny( "=" ) + cc.attention( "number" ) + + cc.debug( "................." ) + cc.note( "SKALE NETWORK" ) + + cc.notice( " re-discovery interval" ) + cc.debug( "(in seconds)" ) + + cc.notice( ". " ) + cc.debug( "Default is " ) + cc.sunny( "3600" ) + + cc.debug( " seconds or " ) + cc.sunny( "1" ) + cc.debug( " hour, specify " ) + + cc.sunny( "0" ) + cc.debug( " to " ) + cc.error( "disable" ) + " " + + cc.note( "SKALE NETWORK" ) + cc.debug( " re-discovery" ) + cc.notice( "." ) ); +} + +function printHelpPaymentTransaction( soi ) { + console.log( cc.sunny( "PAYMENT TRANSACTION" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-price-multiplier-mn" ) + cc.debug( "..............." ) + + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + + cc.notice( " for " ) + cc.note( "Main Net" ) + cc.notice( " transactions, " ) + + cc.debug( "Default value is " ) + cc.sunny( "1.25" ) + cc.notice( "." ) + + cc.debug( " Specify value " ) + cc.sunny( "0.0" ) + cc.debug( " to " ) + + cc.error( "disable" ) + " " + cc.attention( "Gas Price Customization" ) + + cc.debug( " for " ) + cc.note( "Main Net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-price-multiplier-sc" ) + cc.debug( "..............." ) + + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + + cc.notice( " for " ) + cc.note( "S-Chain" ) + cc.notice( " transactions, " ) + + cc.debug( "Default value is " ) + cc.sunny( "0.0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-price-multiplier-tc" ) + cc.debug( "..............." ) + + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + + cc.notice( " for " ) + cc.note( "S<->S Target S-Chain" ) + + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + + cc.sunny( "0.0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-price-multiplier" ) + cc.debug( ".................." ) + + cc.notice( "Sets " ) + cc.attention( "Gas Price Multiplier" ) + + cc.notice( " for both " ) + cc.note( "Main Net" ) + cc.notice( " and " ) + + cc.note( "S-Chain" ) + cc.debug( "(s)" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-multiplier-mn" ) + cc.debug( "....................." ) + + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + + cc.notice( " for " ) + cc.note( "Main Net" ) + cc.notice( " transactions, " ) + + cc.debug( "Default value is " ) + cc.sunny( "1.25" ) + cc.notice( "." ) + + cc.debug( " Specify value " ) + cc.sunny( "0.0" ) + cc.debug( " to " ) + + cc.error( "disable" ) + " " + cc.attention( "Gas Price Customization" ) + + cc.debug( " for " ) + cc.note( "Main Net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-multiplier-sc" ) + cc.debug( "....................." ) + + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + + cc.notice( " for " ) + cc.note( "S-Chain" ) + cc.notice( " transactions, " ) + + cc.debug( "Default value is " ) + cc.sunny( "1.25" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-multiplier-tc" ) + cc.debug( "....................." ) + + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + + cc.notice( " for " ) + cc.note( "S<->S Target S-Chain" ) + + cc.notice( " transactions, " ) + cc.debug( "Default value is " ) + + cc.sunny( "1.25" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gas-multiplier" ) + cc.debug( "........................" ) + + cc.notice( "Sets " ) + cc.attention( "Gas Value Multiplier" ) + + cc.notice( " for both " ) + cc.note( "Main Net" ) + cc.notice( " and " ) + + cc.note( "S-Chain" ) + cc.debug( "(s)" ) + cc.notice( "." ) ); +} + +function printHelpRegistration( soi ) { + console.log( cc.sunny( "REGISTRATION" ) + cc.info( " commands:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "register" ) + cc.debug( ".............................." ) + + cc.notice( "Register" ) + cc.debug( "(perform " ) + cc.sunny( "all steps" ) + + cc.debug( ")" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "register1" ) + cc.debug( "............................." ) + + cc.notice( "Perform registration " ) + cc.sunny( "step 1" ) + + cc.notice( " - register " ) + cc.note( "S-Chain" ) + cc.notice( " on " ) + + cc.note( "Main-net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "check-registration" ) + cc.debug( "...................." ) + + cc.notice( "Perform registration status check" ) + cc.debug( "(perform " ) + + cc.sunny( "all steps" ) + cc.debug( ")" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "check-registration1" ) + cc.debug( "..................." ) + + cc.notice( "Perform registration status check " ) + cc.sunny( "step 1" ) + + cc.notice( " - register " ) + cc.note( "S-Chain" ) + cc.notice( " on " ) + + cc.note( "Main-net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "check-registration2" ) + cc.debug( "..................." ) + + cc.notice( "Perform registration status check " ) + cc.sunny( "step 2" ) + + cc.notice( " - register " ) + cc.note( "S-Chain" ) + cc.notice( " in " ) + + cc.attention( "deposit box" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "check-registration3" ) + cc.debug( "..................." ) + + cc.notice( "Perform registration status check " ) + cc.sunny( "step 3" ) + + cc.notice( " - register " ) + cc.note( "Main-net" ) + cc.notice( "'s " ) + + cc.attention( "deposit box" ) + cc.notice( " on " ) + cc.note( "S-Chain" ) + + cc.notice( "." ) ); +} + +function printHelpAction( soi ) { + console.log( cc.sunny( "ACTION" ) + cc.info( " commands:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "show-config" ) + cc.debug( "..........................." ) + + cc.notice( "Show " ) + cc.note( "configuration values" ) + + cc.notice( " and exit." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "show-balance" ) + cc.debug( ".........................." ) + + cc.notice( "Show " ) + cc.note( "ETH" ) + + cc.notice( " and/or token balances on " ) + cc.note( "Main-net" ) + + cc.notice( " and/or " ) + cc.note( "S-Chain" ) + cc.notice( " and exit." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "m2s-payment" ) + cc.debug( "..........................." ) + + cc.notice( "Do one payment from " ) + cc.note( "Main-net" ) + + cc.notice( " user account to " ) + cc.note( "S-chain" ) + + cc.notice( " user account." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-payment" ) + cc.debug( "..........................." ) + + cc.notice( "Do one payment from " ) + cc.note( "S-chain" ) + + cc.notice( " user account to " ) + cc.note( "Main-net" ) + + cc.notice( " user account." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-receive" ) + cc.debug( "..........................." ) + + cc.notice( "Receive one payment from " ) + cc.note( "S-chain" ) + + cc.notice( " user account to " ) + cc.note( "Main-net" ) + + cc.notice( " user account" ) + + cc.debug( "(ETH only, receives all the ETH pending in transfer)" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-view" ) + cc.debug( ".............................." ) + + cc.notice( "View money amount user can receive as payment from " ) + + cc.note( "S-chain" ) + cc.notice( " user account to " ) + cc.note( "Main-net" ) + + cc.notice( " user account" ) + + cc.debug( "(ETH only, receives all the ETH pending in transfer)" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-payment" ) + cc.debug( "..........................." ) + + cc.notice( "Do one payment from " ) + cc.note( "S-chain" ) + + cc.notice( " user account to other " ) + cc.note( "S-chain" ) + + cc.notice( " user account." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-forward" ) + cc.debug( "..........................." ) + + cc.notice( "Indicates " ) + cc.note( "S<->S" ) + + cc.notice( " transfer direction is " ) + cc.attention( "forward" ) + + cc.notice( ". I.e. source " ) + cc.note( "S-chain" ) + + cc.notice( " is token minter and instantiator. " ) + + cc.debug( "This is default mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-reverse" ) + cc.debug( "..........................." ) + + cc.notice( "Indicates " ) + cc.note( "S<->S" ) + + cc.notice( " transfer direction is " ) + cc.attention( "reverse" ) + + cc.notice( ". I.e. destination " ) + cc.note( "S-chain" ) + + cc.notice( " is token minter and instantiator." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "m2s-transfer" ) + cc.debug( ".........................." ) + + cc.notice( "Do single " ) + cc.attention( "message transfer loop" ) + + cc.notice( " from " ) + cc.note( "Main-net" ) + cc.notice( " to " ) + + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-transfer" ) + cc.debug( ".........................." ) + + cc.notice( "Do single " ) + cc.attention( "message transfer loop" ) + + cc.notice( " from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + + cc.note( "Main-net" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-transfer" ) + cc.debug( ".........................." ) + + cc.notice( "Do single " ) + cc.attention( "message transfer loop" ) + + cc.notice( " from " ) + cc.note( "S-chain" ) + cc.notice( " to " ) + + cc.note( "S-chain" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "with-metadata" ) + cc.debug( "........................." ) + + cc.notice( "Makes " ) + cc.bright( "ERC721" ) + + cc.notice( " transfer using special version of " ) + + cc.bright( "Token Manager" ) + cc.notice( " to transfer token metadata." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "transfer" ) + cc.debug( ".............................." ) + + cc.notice( "Run single " ) + cc.note( "M<->S" ) + + cc.notice( " and, optionally, " ) + cc.note( "S->S" ) + + cc.notice( " transfer loop iteration" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "loop" ) + cc.debug( ".................................." ) + + cc.notice( "Run " ) + cc.note( "M<->S" ) + cc.notice( " and, optionally, " ) + + cc.note( "S->S" ) + cc.notice( " transfer loops in parallel threads." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "simple-loop" ) + cc.debug( "..........................." ) + + cc.notice( "Run " ) + cc.note( "M<->S" ) + cc.notice( " and, optionally, " ) + + cc.note( "S->S" ) + cc.notice( " transfer loops in main thread only." ) ); +} + +function printHelpActionAdditional( soi ) { + console.log( cc.sunny( "ADDITIONAL ACTION" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-wait-s-chain" ) + cc.debug( "......................." ) + + cc.notice( "Do not wait until " ) + cc.note( "S-Chain" ) + + cc.notice( " is started." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "max-wait-attempts" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( "..............." ) + cc.notice( "Max number of " ) + + cc.note( "S-Chain" ) + + cc.notice( " call attempts to do while it became alive and sane." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "skip-dry-run" ) + cc.debug( ".........................." ) + + cc.notice( "Skip " ) + cc.note( "dry run" ) + + cc.notice( " invocation before payed contract method calls." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-ignore-dry-run" ) + cc.debug( "....................." ) + + cc.notice( "Use error results of " ) + cc.note( "dry run" ) + + cc.notice( " contract method calls as actual errors and stop execute." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "m2s-transfer-block-size" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( "........." ) + cc.notice( "Number of transactions in one block " + + "to use in message transfer loop from " ) + cc.note( "Main-net" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) + + cc.debug( " Default is " ) + cc.sunny( "4" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-transfer-block-size" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( "........." ) + cc.notice( "Number of transactions in one block " + + "to use in message transfer loop from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.notice( "." ) + + cc.debug( " Default is " ) + cc.sunny( "4" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-transfer-block-size" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( "........." ) + cc.notice( "Number of transactions in one block " + + "to use in message transfer loop from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) + + cc.debug( " Default is " ) + cc.sunny( "4" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "transfer-block-size" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( "............." ) + cc.notice( "Number of transactions in one block " + + "to use in all message transfer loops." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "m2s-transfer-steps" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( ".............." ) + cc.notice( "Maximal number of blocks " + + "to transfer at a job run from " ) + cc.note( "Main-net" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) + + cc.debug( " Value " ) + cc.sunny( "0" ) + cc.debug( " is unlimited" ) + + cc.notice( "." ) + cc.debug( " Default is " ) + cc.sunny( "8" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-transfer-steps" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( ".............." ) + cc.notice( "Maximal number of blocks " + + "to transfer at a job run from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.notice( "." ) + + cc.debug( " Value " ) + cc.sunny( "0" ) + cc.debug( " is unlimited" ) + + cc.notice( "." ) + cc.debug( " Default is " ) + cc.sunny( "8" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-transfer-steps" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( ".............." ) + cc.notice( "Maximal number of blocks " + + "to transfer at a job run from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.notice( "." ) + + cc.debug( " Value " ) + cc.sunny( "0" ) + cc.debug( " is unlimited" ) + + cc.notice( "." ) + cc.debug( " Default is " ) + cc.sunny( "8" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "transfer-steps" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( ".................." ) + cc.notice( "Maximal number of blocks " + + "to transfer at a job run in all transfer loops." ) + cc.debug( " Value " ) + + cc.sunny( "0" ) + cc.debug( " is unlimited" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "m2s-max-transactions" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..........." ) + cc.notice( "Maximal number of transactions " + + "to do in message transfer loop from " ) + cc.note( "Main-net" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + + cc.sunny( "0" ) + cc.debug( " is unlimited)" ) + cc.notice( "." ) + + cc.debug( " Default is " ) + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-max-transactions" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..........." ) + cc.notice( "Maximal number of transactions " + + "to do in message transfer loop from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + + cc.sunny( "0" ) + cc.debug( " is unlimited)" ) + cc.notice( "." ) + + cc.debug( " Default is " ) + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-max-transactions" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..........." ) + cc.notice( "Maximal number of transactions " + + "to do in message transfer loop from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " is unlimited)" ) + cc.notice( "." ) + cc.debug( " Default is " ) + + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "max-transactions" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..............." ) + cc.notice( "Maximal number of transactions " + + "to do in all message transfer loops" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " is unlimited)" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "m2s-await-blocks" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..............." ) + cc.notice( "Maximal number of blocks to wait " + + "to appear in blockchain before transaction from " ) + cc.note( "Main-net" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " is no wait)" ) + cc.notice( "." ) + cc.debug( " Default is " ) + + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-await-blocks" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..............." ) + cc.notice( "Maximal number of blocks to wait " + + "to appear in blockchain before transaction from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " is no wait)" ) + cc.notice( "." ) + cc.debug( " Default is " ) + + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-await-blocks" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..............." ) + cc.notice( "Maximal number of blocks to wait " + + "to appear in blockchain before transaction from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " is no wait)" ) + cc.notice( "." ) + cc.debug( " Default is " ) + + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "await-blocks" ) + cc.sunny( "=" ) + cc.info( "number" ) + + cc.debug( "..................." ) + cc.notice( "Maximal number of blocks " + + "to wait to appear in blockchain before transaction between both " ) + + cc.note( "S-chain" ) + cc.notice( " and " ) + cc.note( "Main-net" ) + + cc.debug( "(" ) + cc.sunny( "0 " ) + cc.debug( "is no wait)" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "m2s-await-time" ) + cc.sunny( "=" ) + cc.info( "seconds" ) + + cc.debug( "................" ) + + cc.notice( "Minimal age of transaction message" ) + + cc.debug( "(in seconds)" ) + cc.notice( " before it will be transferred from " ) + + cc.note( "Main-net" ) + cc.notice( " to " ) + cc.note( "S-chain" ) + + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + + cc.notice( "." ) + cc.debug( " Default is " ) + cc.sunny( "0" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2m-await-time" ) + cc.sunny( "=" ) + cc.info( "seconds" ) + + cc.debug( "................" ) + + cc.notice( "Minimal age of transaction message" ) + cc.debug( "(in seconds)" ) + + cc.notice( " before it will be transferred from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "Main-net" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " is no wait)" ) + cc.notice( "." ) + cc.debug( " Default is " ) + + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "s2s-await-time" ) + cc.sunny( "=" ) + cc.info( "seconds" ) + + cc.debug( "................" ) + + cc.notice( "Minimal age of transaction message" ) + cc.debug( "(in seconds)" ) + + cc.notice( " before it will be transferred from " ) + cc.note( "S-chain" ) + + cc.notice( " to " ) + cc.note( "S-chain" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " is no wait)" ) + cc.notice( "." ) + cc.debug( " Default is " ) + + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "await-time" ) + cc.sunny( "=" ) + cc.info( "seconds" ) + + cc.debug( "...................." ) + + cc.notice( "Minimal age of transaction message" ) + cc.debug( "(in seconds)" ) + + cc.notice( " before it will be transferred between both " ) + + cc.note( "S-chain" ) + cc.notice( " and " ) + cc.note( "Main-net" ) + + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no wait)" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "period" ) + cc.debug( "................................" ) + + cc.notice( "Transfer " ) + cc.note( "loop period" ) + cc.debug( "(in seconds)" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "node-number" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( "....................." ) + cc.note( "S-Chain" ) + " " + + cc.bright( "node number" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( "-based)" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "nodes-count" ) + cc.sunny( "=" ) + cc.info( "value" ) + + cc.debug( "....................." ) + cc.note( "S-Chain" ) + " " + + cc.bright( "nodes count" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "time-framing" ) + cc.sunny( "=" ) + cc.note( "value" ) + + cc.debug( "...................." ) + cc.notice( "Specifies " ) + + cc.note( "period" ) + cc.debug( "(in seconds) " ) + + cc.note( "for time framing" ) + cc.debug( "(" ) + cc.sunny( "0" ) + + cc.debug( " to " ) + cc.error( "disable" ) + + cc.debug( " time framing)" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "time-gap" ) + cc.sunny( "=" ) + cc.note( "value" ) + + cc.debug( "........................" ) + cc.notice( "Specifies " ) + + cc.note( "gap" ) + cc.debug( "(in seconds) " ) + + cc.note( "before next time frame" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "auto-exit" ) + cc.sunny( "=" ) + cc.note( "seconds" ) + + cc.debug( "....................." ) + cc.notice( "Automatically exit " ) + + cc.bright( "IMA Agent" ) + cc.notice( " after specified number of seconds" ) + + cc.debug( "(" ) + cc.sunny( "0" ) + cc.debug( " is no automatic exit, " ) + + cc.sunny( "3600" ) + cc.debug( " is no default)" ) + cc.notice( "." ) ); +} + +function printHelpTokenTesting( soi ) { + console.log( cc.sunny( "TOKEN TESTING" ) + cc.info( " commands:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "mint-erc20" ) + cc.debug( "............................" ) + + cc.notice( "Mint " ) + cc.note( "ERC20" ) + cc.notice( " tokens." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "mint-erc721" ) + cc.debug( "..........................." ) + + cc.notice( "Mint " ) + cc.note( "ERC721" ) + cc.notice( " tokens." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "mint-erc1155" ) + cc.debug( ".........................." ) + + cc.notice( "Mint " ) + cc.note( "ERC1155" ) + cc.notice( " tokens." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "burn-erc20" ) + cc.debug( "............................" ) + + cc.notice( "Burn " ) + cc.note( "ERC20" ) + cc.notice( " tokens." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "burn-erc721" ) + cc.debug( "..........................." ) + + cc.notice( "Burn " ) + cc.note( "ERC721" ) + cc.notice( " tokens." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "burn-erc1155" ) + cc.debug( ".........................." ) + + cc.notice( "Burn " ) + cc.note( "ERC1155" ) + cc.notice( " tokens." ) ); + console.log( soi + cc.debug( "Please notice, token testing commands require " ) + + cc.attention( "--tm-url-t-chain" ) + cc.debug( ", " ) + + cc.attention( "cid-t-chain" ) + cc.debug( ", " ) + + cc.attention( "erc20-t-chain" ) + cc.debug( " or " ) + + cc.attention( "erc721-t-chain" ) + cc.debug( " or " ) + + cc.attention( "erc1155-t-chain" ) + + cc.debug( ", account information (like private key " ) + + cc.attention( "key-t-chain" ) + + cc.debug( ") command line arguments specified. Token amounts are specified via " ) + + cc.attention( "amount" ) + + cc.debug( " command line arguments specified. Token IDs are specified via " ) + + cc.attention( "tid" ) + cc.debug( " or " ) + cc.attention( "tids" ) + + cc.debug( " command line arguments." ) + ); +} + +function printHelpNetworkStateAnalysis( soi ) { + console.log( cc.sunny( "IMA WORK STATE ANALYSIS" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "pwa" ) + cc.debug( "..................................." ) + + cc.success( "Enable" ) + " " + cc.attention( "pending work analysis" ) + + cc.notice( " to avoid transaction conflicts." ) + " " + + cc.debug( "Default mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-pwa" ) + cc.debug( "................................" ) + + cc.error( "Disable" ) + " " + cc.attention( "pending work analysis" ) + + cc.notice( ". " ) + cc.warning( "Not recommended" ) + + cc.notice( " for slow and overloaded blockchains." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "pwa-timeout" ) + cc.sunny( "=" ) + cc.note( "seconds" ) + + cc.debug( "..................." ) + cc.notice( "Node state timeout during " ) + + cc.attention( "pending work analysis" ) + cc.notice( ". " ) + + cc.debug( "Default is " ) + cc.sunny( "60" ) + cc.debug( " seconds" ) + + cc.notice( "." ) ); +} + +function printHelpMessageSigning( soi ) { + console.log( cc.sunny( "MESSAGE SIGNING" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "sign-messages" ) + cc.debug( "........................." ) + + cc.notice( "Sign transferred messages." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "bls-glue" ) + cc.sunny( "=" ) + cc.note( "path" ) + + cc.debug( "........................." ) + cc.notice( "Specifies path to " ) + + cc.note( "bls_glue" ) + cc.notice( " application." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "hash-g1" ) + cc.sunny( "=" ) + cc.note( "path" ) + + cc.debug( ".........................." ) + cc.notice( "Specifies path to " ) + + cc.note( "hash_g1" ) + cc.notice( " application." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "bls-verify" ) + cc.sunny( "=" ) + cc.note( "path" ) + + cc.debug( "......................." ) + + cc.debug( "Optional parameter, specifies path to " ) + + cc.note( "verify_bls" ) + cc.debug( " application." ) ); +} + +function printHelpMonitoring( soi ) { + console.log( cc.sunny( "MONITORING" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "monitoring-port" ) + cc.sunny( "=" ) + cc.note( "number" ) + + cc.debug( "................" ) + cc.notice( "Run " ) + + cc.note( "monitoring web socket RPC server" ) + + cc.notice( " on specified port. " ) + cc.debug( "Specify " ) + + cc.sunny( "0" ) + cc.debug( " to " ) + cc.error( "disable" ) + + cc.notice( "." ) + cc.debug( " By default monitoring server is " ) + + cc.error( "disabled" ) + cc.notice( "." ) ); +} + +function printHelpGasReimbursement( soi ) { + console.log( cc.sunny( "GAS REIMBURSEMENT" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "reimbursement-chain" ) + cc.sunny( "=" ) + cc.note( "name" ) + + cc.debug( ".............." ) + cc.notice( "Specifies chain name." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "reimbursement-recharge" ) + cc.sunny( "=" ) + cc.note( "v" ) + + cc.warning( "u" ) + cc.debug( "............." ) + cc.success( "Recharge" ) + + cc.notice( " user wallet with specified value " ) + cc.attention( "v" ) + + cc.notice( ", unit name " ) + cc.attention( "u" ) + + cc.notice( " is well known Ethereum unit name like " ) + cc.attention( "ether" ) + + cc.notice( " or " ) + cc.attention( "wei" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "reimbursement-withdraw" ) + cc.sunny( "=" ) + cc.note( "v" ) + + cc.warning( "u" ) + cc.debug( "............." ) + cc.error( "Withdraw" ) + + cc.notice( " user wallet with specified value " ) + cc.attention( "v" ) + + cc.notice( ", unit name " ) + cc.attention( "u" ) + + cc.notice( " is well known Ethereum unit name like " ) + cc.attention( "ether" ) + + cc.notice( " or " ) + cc.attention( "wei" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "reimbursement-balance" ) + cc.debug( "................." ) + + cc.notice( "Show wallet balance." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "reimbursement-range" ) + cc.sunny( "=" ) + cc.note( "number" ) + + cc.debug( "............" ) + cc.notice( "Sets " ) + + cc.note( "minimal time interval" ) + cc.notice( " between transfers from " ) + + cc.note( "S-Chain" ) + cc.notice( " to " ) + cc.note( "Main Net" ) + + cc.notice( "." ) ); +} + +function printHelpPastEventsScan( soi ) { + console.log( cc.sunny( "PAST EVENTS SCAN" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "bs-step-size" ) + cc.sunny( "=" ) + cc.note( "number" ) + + cc.debug( "..................." ) + cc.notice( "Specifies " ) + + cc.note( "step block range size" ) + + cc.notice( " to search iterative past events step by step. " ) + + cc.sunny( "0" ) + cc.notice( " to " ) + cc.error( "disable" ) + + cc.notice( " iterative search." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "bs-max-all-range" ) + + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "..............." ) + + cc.notice( "Specifies " ) + cc.note( "max number of steps" ) + + cc.notice( " to allow to search as [0...latest] range. " ) + + cc.sunny( "0" ) + cc.notice( " to " ) + cc.error( "disable" ) + + cc.notice( " iterative search." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "bs-progressive-enable" ) + cc.debug( "................." ) + + cc.success( "Enables" ) + " " + cc.attention( "progressive block scan" ) + + cc.notice( " to search past events." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "bs-progressive-disable" ) + cc.debug( "................" ) + + cc.error( "Disables" ) + " " + cc.attention( "progressive block scan" ) + + cc.notice( " to search past events." ) ); +} + +function printHelpOracleBasedReimbursement( soi ) { + console.log( cc.sunny( "ORACLE BASED GAS REIMBURSEMENT" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "enable-oracle" ) + cc.debug( "........................." ) + + cc.success( "Enable" ) + cc.notice( " call to " ) + cc.note( "Oracle" ) + + cc.notice( " to compute " ) + cc.note( "gas price" ) + cc.notice( " for " ) + + cc.attention( "gas reimbursement" ) + cc.notice( ". " ) + + cc.debug( "Default mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "disable-oracle" ) + cc.debug( "........................" ) + + cc.error( "Disable" ) + cc.notice( " call to " ) + cc.note( "Oracle" ) + + cc.notice( " to compute " ) + cc.note( "gas price" ) + cc.notice( " for " ) + + cc.attention( "gas reimbursement" ) + cc.notice( "." ) ); +} + +function printHelpJsonRpcServer( soi ) { + console.log( cc.sunny( "IMA JSON RPC SERVER" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "json-rpc-port" ) + cc.sunny( "=" ) + cc.note( "number" ) + + cc.debug( ".................." ) + cc.notice( "Run " ) + + cc.note( "IMA JSON RPC server" ) + cc.notice( " on specified " ) + + cc.note( "port" ) + cc.notice( "." ) + cc.debug( " Specify " ) + + cc.sunny( "0" ) + cc.debug( " to " ) + cc.error( "disable" ) + cc.notice( "." ) + + cc.debug( " Default is " ) + cc.sunny( "0" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "cross-ima" ) + cc.debug( "............................." ) + + cc.success( "Enable" ) + cc.notice( " calls to " ) + + cc.note( "IMA JSON RPC servers" ) + cc.notice( " to compute " ) + + cc.note( "BLS signature parts" ) + + cc.notice( " and operation state inside time frames." ) + + cc.debug( "Use calls to " ) + cc.attention( "IMA Agent" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-cross-ima" ) + cc.debug( ".........................." ) + + cc.error( "Disable" ) + cc.notice( " calls to " ) + + cc.note( "IMA JSON RPC servers" ) + cc.notice( " to compute " ) + + cc.note( "BLS signature parts" ) + + cc.notice( " and operation state inside time frames. " ) + + cc.debug( "Use calls to " ) + cc.attention( "skaled" ) + cc.notice( "." ) + + cc.debug( " Default mode" ) + cc.notice( "." ) ); +} + +function printHelpTest( soi ) { + console.log( cc.sunny( "TEST" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "browse-s-chain" ) + cc.debug( "........................" ) + + cc.notice( "Download own " ) + cc.note( "S-Chain" ) + + cc.notice( " network information." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "browse-skale-network" ) + cc.debug( ".................." ) + + cc.notice( "Download entire " ) + cc.note( "SKALE network" ) + + cc.notice( " description." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "browse-connected-schains" ) + cc.debug( ".............." ) + + cc.notice( "Download " ) + cc.note( "S-Chains" ) + + cc.notice( " connected to " ) + cc.note( "S-Chain" ) + + cc.notice( " with name specified in " ) + cc.bright( "id-s-chain" ) + + cc.notice( " command line parameter." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "discover-cid" ) + cc.debug( ".........................." ) + + cc.notice( "Discover " ) + cc.attention( "chains ID(s)" ) + + cc.notice( " from provided " ) + cc.note( "URL(s)" ) + cc.notice( "." ) + + cc.debug( " This command is not executed automatically at startup" ) + + cc.notice( "." ) ); +} + +function printHelpOptimization( soi ) { + console.log( cc.sunny( "OPTIMIZATION" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "enable-multicall" ) + cc.debug( "......................" ) + + cc.success( "Enable" ) + cc.notice( " optimizations via multi-call." ) + + cc.debug( " Default mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "disable-multicall" ) + cc.debug( "....................." ) + + cc.error( "Disable" ) + cc.notice( " optimizations via multi-call." ) ); +} + +function printHelpLogging( soi ) { + console.log( cc.sunny( "LOGGING" ) + cc.info( " options:" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "expose" ) + cc.debug( "................................" ) + + cc.notice( "Expose " ) + cc.note( "low-level log details" ) + + cc.notice( " after " ) + cc.success( "successful operations" ) + + cc.notice( ". " ) + cc.debug( "By default details exposed only " ) + + cc.error( "on errors" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-expose" ) + cc.debug( "............................." ) + + cc.notice( "Expose " ) + cc.note( "low-level log details" ) + + cc.notice( " only after " ) + cc.error( "errors" ) + cc.notice( ". " ) + + cc.debug( "Default expose mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "verbose" ) + cc.sunny( "=" ) + cc.bright( "value" ) + + cc.debug( "........................." ) + + cc.notice( "Set " ) + cc.note( "level" ) + cc.notice( " of output details." ) ); + console.log( soi + cc.debug( "--" ) + cc.bright( "verbose-list" ) + + cc.debug( ".........................." ) + + cc.notice( "List available " ) + cc.note( "verbose levels" ) + + cc.notice( " and exit." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "log" ) + cc.sunny( "=" ) + cc.note( "path" ) + + cc.debug( ".............................." ) + + cc.notice( "Write program output to specified " ) + cc.note( "log file" ) + + cc.debug( "(multiple files can be specified)" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "log-size" ) + cc.sunny( "=" ) + cc.note( "value" ) + + cc.debug( "........................" ) + cc.notice( "Max size" ) + + cc.debug( "(in bytes)" ) + cc.notice( " of one log file" ) + + cc.debug( "(affects to log log rotation)" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "log-files" ) + cc.sunny( "=" ) + cc.note( "value" ) + + cc.debug( "......................." ) + + cc.notice( "Maximum number of log files for log rotation." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "gathered" ) + cc.debug( ".............................." ) + + cc.notice( "Print details of gathering data from command line arguments. " ) + + cc.debug( "Default mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-gathered" ) + cc.debug( "..........................." ) + + cc.notice( "Do not print details of gathering data " + + "from command line arguments." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "expose-security-info" ) + cc.debug( ".................." ) + + cc.notice( "Expose security-related values in log output." ) + " " + + cc.debug( "This mode is needed for debugging purposes only" ) + + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-expose-security-info" ) + cc.debug( "..............." ) + + cc.notice( "Do not expose security-related values in log output." ) + + " " + cc.debug( "Default mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "expose-pwa" ) + cc.debug( "............................" ) + + cc.notice( "Expose IMA agent pending work analysis information" ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "no-expose-pwa" ) + cc.debug( "........................." ) + + cc.notice( "Do not expose IMA agent pending work analysis information" ) + + cc.notice( "." ) + " " + cc.debug( "Default mode" ) + cc.notice( "." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "accumulated-log-in-transfer" ) + cc.debug( "..........." ) + + cc.notice( "Use accumulated log in message transfer loop." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "accumulated-log-in-bls-signer" ) + cc.debug( "........." ) + + cc.notice( "Use accumulated log in BLS signer." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "dynamic-log-in-transfer" ) + cc.debug( "..............." ) + + cc.notice( "Use realtime log in message transfer loop." ) ); + console.log( soi + cc.debug( "--" ) + + cc.bright( "dynamic-log-in-bls-signer" ) + cc.debug( "............." ) + + cc.notice( "Use realtime log in BLS signer." ) ); +} + +function parseHelp( imaState, joArg ) { // exits process on "--help" + if( joArg.name != "help" ) + return false; + printAbout(); + const soi = " "; // options indent + printHelpGeneral( soi ); + printHelpBlockchainNetwork( soi ); + printHelpBlockchainInterface( soi ); + printHelpErcInterfaces( soi ); + printHelpUserAccount1( soi ); + printHelpUserAccount2( soi ); + printHelpTransfers( soi ); + printHelpPaymentTransaction( soi ); + printHelpRegistration( soi ); + printHelpAction( soi ); + printHelpActionAdditional( soi ); + printHelpTokenTesting( soi ); + printHelpNetworkStateAnalysis( soi ); + printHelpMessageSigning( soi ); + printHelpMonitoring( soi ); + printHelpGasReimbursement( soi ); + printHelpPastEventsScan( soi ); + printHelpOracleBasedReimbursement( soi ); + printHelpJsonRpcServer( soi ); + printHelpTest( soi ); + printHelpOptimization( soi ); + printHelpLogging( soi ); + process.exit( 0 ); +} + +function parseVersion( imaState, joArg ) { // exits process on "--version" + if( joArg.name != "version" ) + return false; + printAbout(); + process.exit( 0 ); +} + +function parseBasicArgs( imaState, joArg ) { + if( joArg.name == "colors" ) { + cc.enable( true ); + return true; + } + if( joArg.name == "no-colors" ) { + cc.enable( false ); + return true; + } + if( joArg.name == "expose" ) { + log.exposeDetailsSet( true ); + return true; + } + if( joArg.name == "no-expose" ) { + log.exposeDetailsSet( false ); + return true; + } + if( joArg.name == "verbose" ) { + log.verboseSet( log.verboseParse( joArg.value ) ); + return true; + } + if( joArg.name == "verbose-list" ) { + log.verboseList(); + return true; + } + return false; +} + +function parseChainAccessArgs( imaState, joArg ) { + if( joArg.name == "url-main-net" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + imaState.chainProperties.mn.strURL = joArg.value; + return true; + } + if( joArg.name == "url-s-chain" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + imaState.chainProperties.sc.strURL = joArg.value; + return true; + } + if( joArg.name == "url-t-chain" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + imaState.chainProperties.tc.strURL = joArg.value; + return true; + } + if( joArg.name == "id-main-net" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.mn.strChainName = joArg.value; + return true; + } + if( joArg.name == "id-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.sc.strChainName = joArg.value; + return true; + } + if( joArg.name == "id-origin-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strChainNameOriginChain = joArg.value; + return true; + } + if( joArg.name == "id-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.tc.strChainName = joArg.value; + return true; + } + if( joArg.name == "cid-main-net" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.chainProperties.mn.chainId = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "cid-s-chain" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.chainProperties.sc.chainId = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "cid-t-chain" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.chainProperties.tc.chainId = owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +function parseTransactionManagerArgs( imaState, joArg ) { + if( joArg.name == "tm-url-main-net" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + const strURL = "" + joArg.value; + imaState.chainProperties.mn.joAccount.strTransactionManagerURL = strURL; + return true; + } + if( joArg.name == "tm-url-s-chain" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + const strURL = "" + joArg.value; + imaState.chainProperties.sc.joAccount.strTransactionManagerURL = strURL; + return true; + } + if( joArg.name == "tm-url-t-chain" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + const strURL = "" + joArg.value; + imaState.chainProperties.tc.joAccount.strTransactionManagerURL = strURL; + return true; + } + if( joArg.name == "tm-priority-main-net" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.chainProperties.mn.joAccount.nTmPriority = + owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "tm-priority-s-chain" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.chainProperties.sc.joAccount.nTmPriority = + owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "tm-priority-t-chain" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.chainProperties.tc.joAccount.nTmPriority = + owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +function parseSgxArgs( imaState, joArg ) { + if( joArg.name == "sgx-url-main-net" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + imaState.chainProperties.mn.joAccount.strSgxURL = joArg.value; + return true; + } + if( joArg.name == "sgx-url-s-chain" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + imaState.chainProperties.sc.joAccount.strSgxURL = joArg.value; + return true; + } + if( joArg.name == "sgx-url-t-chain" ) { + owaspUtils.verifyArgumentIsURL( joArg ); + imaState.chainProperties.tc.joAccount.strSgxURL = joArg.value; + return true; + } + if( joArg.name == "sgx-ecdsa-key-main-net" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.mn.joAccount.strSgxKeyName = joArg.value; + return true; + } + if( joArg.name == "sgx-ecdsa-key-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.sc.joAccount.strSgxKeyName = joArg.value; + return true; + } + if( joArg.name == "sgx-ecdsa-key-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.tc.joAccount.strSgxKeyName = joArg.value; + return true; + } + if( joArg.name == "sgx-bls-key-main-net" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.mn.joAccount.strBlsKeyName = joArg.value; + return true; + } + if( joArg.name == "sgx-bls-key-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.sc.joAccount.strBlsKeyName = joArg.value; + return true; + } + if( joArg.name == "sgx-bls-key-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.tc.joAccount.strBlsKeyName = joArg.value; + return true; + } + if( joArg.name == "sgx-ssl-key-main-net" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.mn.joAccount.strPathSslKey = + imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "sgx-ssl-key-s-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.sc.joAccount.strPathSslKey = + imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "sgx-ssl-key-t-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.tc.joAccount.strPathSslKey = + imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "sgx-ssl-cert-main-net" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.mn.joAccount.strPathSslCert = + imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "sgx-ssl-cert-s-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.sc.joAccount.strPathSslCert = + imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "sgx-ssl-cert-t-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.tc.joAccount.strPathSslCert = + imaUtils.normalizePath( joArg.value ); + return true; + } + return false; +} + +function parseCredentialsArgs( imaState, joArg ) { + if( joArg.name == "address-main-net" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.mn.joAccount.address_ = joArg.value; + return true; + } + if( joArg.name == "address-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.sc.joAccount.address_ = joArg.value; + return true; + } + if( joArg.name == "address-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.tc.joAccount.address_ = joArg.value; + return true; + } + if( joArg.name == "receiver" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.receiver = joArg.value; + return true; + } + if( joArg.name == "key-main-net" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.mn.joAccount.privateKey = joArg.value; + return true; + } + if( joArg.name == "key-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.sc.joAccount.privateKey = joArg.value; + return true; + } + if( joArg.name == "key-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.chainProperties.tc.joAccount.privateKey = joArg.value; + return true; + } + return false; +} + +function parseAbiArgs( imaState, joArg ) { + if( joArg.name == "abi-skale-manager" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.strPathAbiJsonSkaleManager = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "abi-main-net" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.mn.strPathAbiJson = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "abi-s-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.sc.strPathAbiJson = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "abi-t-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.tc.strPathAbiJson = imaUtils.normalizePath( joArg.value ); + return true; + } + return false; +} + +function parseErcArgs( imaState, joArg ) { + if( joArg.name == "erc20-main-net" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.mn.strPathJsonErc20 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "erc20-s-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.sc.strPathJsonErc20 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "addr-erc20-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strAddrErc20Explicit = joArg.value; + return true; + } + if( joArg.name == "erc20-t-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.tc.strPathJsonErc20 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "addr-erc20-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strAddrErc20ExplicitTarget = joArg.value; + return true; + } + + if( joArg.name == "erc721-main-net" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.mn.strPathJsonErc721 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "erc721-s-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.sc.strPathJsonErc721 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "addr-erc721-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strAddrErc721Explicit = joArg.value; + return true; + } + if( joArg.name == "erc721-t-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.tc.strPathJsonErc721 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "addr-erc721-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strAddrErc721ExplicitTarget = joArg.value; + return true; + } + + if( joArg.name == "erc1155-main-net" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.mn.strPathJsonErc1155 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "erc1155-s-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.sc.strPathJsonErc1155 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "addr-erc1155-s-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strAddrErc1155Explicit = joArg.value; + return true; + } + if( joArg.name == "erc1155-t-chain" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.chainProperties.tc.strPathJsonErc1155 = imaUtils.normalizePath( joArg.value ); + return true; + } + if( joArg.name == "addr-erc1155-t-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strAddrErc1155ExplicitTarget = joArg.value; + return true; + } + if( joArg.name == "with-metadata" ) { + imaState.isWithMetadata721 = true; + return true; + } + return false; +} + +function parseTransactionArgs( imaState, joArg ) { + if( joArg.name == "sleep-between-tx" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaHelperAPIs.setSleepBetweenTransactionsOnSChainMilliseconds( joArg.value ); + return true; + } + if( joArg.name == "wait-next-block" ) { + imaHelperAPIs.setWaitForNextBlockOnSChain( true ); + return true; + } + if( joArg.name == "gas-price-multiplier-mn" ) { + let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasPriceMultiplier < 0.0 ) + gasPriceMultiplier = 0.0; + imaState.chainProperties.mn.transactionCustomizer.gasPriceMultiplier = + gasPriceMultiplier; + return true; + } + if( joArg.name == "gas-price-multiplier-sc" ) { + let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasPriceMultiplier < 0.0 ) + gasPriceMultiplier = 0.0; + imaState.chainProperties.sc.transactionCustomizer.gasPriceMultiplier = + gasPriceMultiplier; + return true; + } + if( joArg.name == "gas-price-multiplier-tc" ) { + let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasPriceMultiplier < 0.0 ) + gasPriceMultiplier = 0.0; + imaState.chainProperties.tc.transactionCustomizer.gasPriceMultiplier = + gasPriceMultiplier; + return true; + } + if( joArg.name == "gas-price-multiplier" ) { + let gasPriceMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasPriceMultiplier < 0.0 ) + gasPriceMultiplier = 0.0; + imaState.chainProperties.mn.transactionCustomizer.gasPriceMultiplier = + imaState.chainProperties.sc.transactionCustomizer.gasPriceMultiplier = + imaState.chainProperties.tc.transactionCustomizer.gasPriceMultiplier = + gasPriceMultiplier; + return true; + } + + if( joArg.name == "gas-multiplier-mn" ) { + let gasMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasMultiplier < 0.0 ) + gasMultiplier = 0.0; + imaState.chainProperties.mn.transactionCustomizer.gasMultiplier = + gasMultiplier; + return true; + } + if( joArg.name == "gas-multiplier-sc" ) { + let gasMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasMultiplier < 0.0 ) + gasMultiplier = 0.0; + imaState.chainProperties.sc.transactionCustomizer.gasMultiplier = + gasMultiplier; + return true; + } + if( joArg.name == "gas-multiplier-tc" ) { + let gasMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasMultiplier < 0.0 ) + gasMultiplier = 0.0; + imaState.chainProperties.tc.transactionCustomizer.gasMultiplier = + gasMultiplier; + return true; + } + if( joArg.name == "gas-multiplier" ) { + let gasMultiplier = owaspUtils.toFloat( joArg.value ); + if( gasMultiplier < 0.0 ) + gasMultiplier = 0.0; + imaState.chainProperties.mn.transactionCustomizer.gasMultiplier = + imaState.chainProperties.sc.transactionCustomizer.gasMultiplier = + imaState.chainProperties.tc.transactionCustomizer.gasMultiplier = + gasMultiplier; + return true; + } + if( joArg.name == "skip-dry-run" ) { + imaTx.dryRunEnable( false ); + return true; + } + if( joArg.name == "no-skip-dry-run" ) { + imaTx.dryRunEnable( true ); + return true; + } + if( joArg.name == "ignore-dry-run" ) { + imaTx.dryRunIgnore( true ); + return true; + } + if( joArg.name == "dry-run" || joArg.name == "no-ignore-dry-run" ) { + imaTx.dryRunIgnore( false ); + return true; + } + return false; +} + +function parsePaymentAmountArgs( imaState, joArg ) { + if( joArg.name == "value" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = owaspUtils.parseMoneySpecToWei( "" + joArg.value, true ); + return true; + } + if( joArg.name == "wei" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = + owaspUtils.parseMoneySpecToWei( "" + joArg.value + "wei", true ); + return true; + } + if( joArg.name == "babbage" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = + owaspUtils.parseMoneySpecToWei( "" + joArg.value + "babbage", true ); + return true; + } + if( joArg.name == "lovelace" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = + owaspUtils.parseMoneySpecToWei( "" + joArg.value + "lovelace", true ); + return true; + } + if( joArg.name == "shannon" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = + owaspUtils.parseMoneySpecToWei( "" + joArg.value + "shannon", true ); + return true; + } + if( joArg.name == "szabo" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = + owaspUtils.parseMoneySpecToWei( "" + joArg.value + "szabo", true ); + return true; + } + if( joArg.name == "finney" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = + owaspUtils.parseMoneySpecToWei( "" + joArg.value + "finney", true ); + return true; + } + if( joArg.name == "ether" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfWei = + owaspUtils.parseMoneySpecToWei( "" + joArg.value + "ether", true ); + return true; + } + if( joArg.name == "amount" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nAmountOfToken = joArg.value; + return true; + } + if( joArg.name == "tid" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.idToken = joArg.value; + imaState.haveOneTokenIdentifier = true; + return true; + } + if( joArg.name == "amounts" ) { + imaState.arrAmountsOfTokens = owaspUtils.verifyArgumentIsArrayOfIntegers( joArg ); + return true; + } + if( joArg.name == "tids" ) { + imaState.idTokens = owaspUtils.verifyArgumentIsArrayOfIntegers( joArg ); + imaState.haveArrayOfTokenIdentifiers = true; + return true; + } + return false; +} + +function parseTransferArgs( imaState, joArg ) { + if( joArg.name == "s2s-forward" ) { + imaHelperAPIs.setForwardS2S(); + return true; + } + if( joArg.name == "s2s-reverse" ) { + imaHelperAPIs.setReverseS2S(); + return true; + } + if( joArg.name == "s2s-enable" ) { + imaState.optsS2S.isEnabled = true; + return true; + } + if( joArg.name == "s2s-disable" ) { + imaState.optsS2S.isEnabled = false; + return true; + } + if( joArg.name == "no-wait-s-chain" ) { + imaState.bNoWaitSChainStarted = true; + return true; + } + if( joArg.name == "max-wait-attempts" ) { + imaState.nMaxWaitSChainAttempts = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "m2s-transfer-block-size" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferBlockSizeM2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2m-transfer-block-size" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferBlockSizeS2M = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2s-transfer-block-size" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferBlockSizeS2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "transfer-block-size" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferBlockSizeM2S = + imaState.nTransferBlockSizeS2M = + imaState.nTransferBlockSizeS2S = + owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "m2s-transfer-steps" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferStepsM2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2m-transfer-steps" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferStepsS2M = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2s-transfer-steps" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferStepsS2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "transfer-steps" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTransferStepsM2S = + imaState.nTransferStepsS2M = + imaState.nTransferStepsS2S = + owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "m2s-max-transactions" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nMaxTransactionsM2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2m-max-transactions" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nMaxTransactionsS2M = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2s-max-transactions" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nMaxTransactionsS2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "max-transactions" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nMaxTransactionsM2S = + imaState.nMaxTransactionsS2M = + imaState.nMaxTransactionsS2S = + owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "m2s-await-blocks" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAwaitDepthM2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2m-await-blocks" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAwaitDepthS2M = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2s-await-blocks" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAwaitDepthS2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "await-blocks" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAwaitDepthM2S = + imaState.nBlockAwaitDepthS2M = + imaState.nBlockAwaitDepthS2S = + owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "m2s-await-time" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAgeM2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2m-await-time" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAgeS2M = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "s2s-await-time" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAgeS2S = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "await-time" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nBlockAgeM2S = + imaState.nBlockAgeS2M = + imaState.nBlockAgeS2S = + owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "period" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nLoopPeriodSeconds = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "node-number" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nNodeNumber = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "nodes-count" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nNodesCount = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "time-framing" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTimeFrameSeconds = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "time-gap" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nNextFrameGap = owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +function parseMulticallArgs( imaState, joArg ) { + if( joArg.name == "enable-multicall" ) { + imaState.isEnabledMultiCall = true; + return true; + } + if( joArg.name == "disable-multicall" ) { + imaState.isEnabledMultiCall = false; + return true; + } + return false; +} + +function parsePendingWorkAnalysisArgs( imaState, joArg ) { + if( joArg.name == "pwa" ) { + imaState.isPWA = true; + return true; + } + if( joArg.name == "no-pwa" ) { + imaState.isPWA = false; + return true; + } + if( joArg.name == "pwa-timeout" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nTimeoutSecondsPWA = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "expose-pwa" ) { + imaState.isPrintPWA = true; + return true; + } + if( joArg.name == "no-expose-pwa" ) { + imaState.isPrintPWA = false; + return true; + } + return false; +} + +function parseLoggingArgs( imaState, joArg ) { + if( joArg.name == "gathered" ) { + imaState.isPrintGathered = true; + return true; + } + if( joArg.name == "no-gathered" ) { + imaState.isPrintGathered = false; + return true; + } + if( joArg.name == "expose-security-info" ) { + imaState.isPrintSecurityValues = true; + return true; + } + if( joArg.name == "no-expose-security-info" ) { + imaState.isPrintSecurityValues = false; + return true; + } + if( joArg.name == "log-size" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nLogMaxSizeBeforeRotation = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "log-files" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nLogMaxFilesCount = owaspUtils.toInteger( joArg.value ); + return true; + } + if( joArg.name == "accumulated-log-in-transfer" ) { + imaState.isDynamicLogInDoTransfer = false; + return true; + } + if( joArg.name == "accumulated-log-in-bls-signer" ) { + imaState.isDynamicLogInBlsSigner = false; + return true; + } + if( joArg.name == "dynamic-log-in-transfer" ) { + imaState.isDynamicLogInDoTransfer = true; + return true; + } + if( joArg.name == "dynamic-log-in-bls-signer" ) { + imaState.isDynamicLogInBlsSigner = true; + return true; + } + if( joArg.name == "log" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strLogFilePath = "" + joArg.value; + return true; + } + return false; +} + +function parseBlsArgs( imaState, joArg ) { + if( joArg.name == "sign-messages" ) { + imaState.bSignMessages = true; + return true; + } + if( joArg.name == "bls-glue" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.strPathBlsGlue = "" + joArg.value; + return true; + } + if( joArg.name == "hash-g1" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.strPathHashG1 = "" + joArg.value; + return true; + } + if( joArg.name == "bls-verify" ) { + owaspUtils.verifyArgumentIsPathToExistingFile( joArg ); + imaState.strPathBlsVerify = "" + joArg.value; + return true; + } + return false; +} + +function parseMonitoringArgs( imaState, joArg ) { + if( joArg.name == "monitoring-port" ) { + owaspUtils.verifyArgumentIsIntegerIpPortNumber( joArg, true ); + imaState.nMonitoringPort = owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +function parseReimbursementArgs( imaState, joArg ) { + if( joArg.name == "reimbursement-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strReimbursementChain = joArg.value.trim(); + return true; + } + if( joArg.name == "reimbursement-recharge" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nReimbursementRecharge = + owaspUtils.parseMoneySpecToWei( "" + joArg.value, true ); + return true; + } + if( joArg.name == "reimbursement-withdraw" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nReimbursementWithdraw = + owaspUtils.parseMoneySpecToWei( "" + joArg.value, true ); + return true; + } + if( joArg.name == "reimbursement-balance" ) { + imaState.isShowReimbursementBalance = true; + return true; + } + if( joArg.name == "reimbursement-estimate" ) { + imaState.nReimbursementEstimate = true; + return true; + } + if( joArg.name == "reimbursement-range" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.nReimbursementRange = owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +function parseOracleArgs( imaState, joArg ) { + if( joArg.name == "enable-oracle" ) { + imaOracleOperations.setEnabledOracle( true ); + return true; + } + if( joArg.name == "disable-oracle" ) { + imaOracleOperations.setEnabledOracle( false ); + return true; + } + return false; +} + +function parseNetworkDiscoveryArgs( imaState, joArg ) { + if( joArg.name == "net-rediscover" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.optsS2S.secondsToReDiscoverSkaleNetwork = + owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +function parseBlockScannerArgs( imaState, joArg ) { + if( joArg.name == "bs-step-size" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaHelperAPIs.setBlocksCountInInIterativeStepOfEventsScan( + owaspUtils.toInteger( joArg.value ) ); + return true; + } + if( joArg.name == "bs-max-all-range" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaHelperAPIs.setMaxIterationsInAllRangeEventsScan( owaspUtils.toInteger( joArg.value ) ); + return true; + } + if( joArg.name == "bs-progressive-enable" ) { + imaTransferErrorHandling.setEnabledProgressiveEventsScan( true ); + return true; + } + if( joArg.name == "bs-progressive-disable" ) { + imaTransferErrorHandling.setEnabledProgressiveEventsScan( false ); + return true; + } + return false; +} + +function parseJsonRpcServerArgs( imaState, joArg ) { + if( joArg.name == "json-rpc-port" ) { + owaspUtils.verifyArgumentIsIntegerIpPortNumber( joArg, true ); + imaState.nJsonRpcPort = owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +function parseCrossImaCommunicationArgs( imaState, joArg ) { + if( joArg.name == "cross-ima" ) { + imaState.isCrossImaBlsMode = true; + return true; + } + if( joArg.name == "no-cross-ima" ) { + imaState.isCrossImaBlsMode = false; + return true; + } + return false; +} + +function parseShowConfigArgs( imaState, joArg ) { + if( joArg.name == "show-config" ) { + imaState.bShowConfigMode = true; + return true; + } + return false; +} + +function parseOtherArgs( imaState, joArg ) { + if( joArg.name == "auto-exit" ) { + owaspUtils.verifyArgumentIsInteger( joArg ); + imaState.nAutoExitAfterSeconds = owaspUtils.toInteger( joArg.value ); + return true; + } + return false; +} + +export function parse( joExternalHandlers, argv ) { + const imaState = state.get(); + const cntArgs = argv || process.argv.length; + for( let idxArg = 2; idxArg < cntArgs; ++idxArg ) { + const joArg = parseCommandLineArgument( process.argv[idxArg] ); + parseHelp( imaState, joArg ); // exits process on "--help" + parseVersion( imaState, joArg ); // exits process on "--version" + if( parseBasicArgs( imaState, joArg ) ) + continue; + if( parseChainAccessArgs( imaState, joArg ) ) + continue; + if( parseTransactionManagerArgs( imaState, joArg ) ) + continue; + if( parseSgxArgs( imaState, joArg ) ) + continue; + if( parseCredentialsArgs( imaState, joArg ) ) + continue; + if( parseAbiArgs( imaState, joArg ) ) + continue; + if( parseErcArgs( imaState, joArg ) ) + continue; + if( parseTransactionArgs( imaState, joArg ) ) + continue; + if( parsePaymentAmountArgs( imaState, joArg ) ) + continue; + if( parseTransferArgs( imaState, joArg ) ) + continue; + if( parseMulticallArgs( imaState, joArg ) ) + continue; + if( parsePendingWorkAnalysisArgs( imaState, joArg ) ) + continue; + if( parseLoggingArgs( imaState, joArg ) ) + continue; + if( parseBlsArgs( imaState, joArg ) ) + continue; + if( parseMonitoringArgs( imaState, joArg ) ) + continue; if( parseBlockScannerArgs( imaState, joArg ) ) + continue; + if( parseReimbursementArgs( imaState, joArg ) ) + continue; + if( parseOracleArgs( imaState, joArg ) ) + continue; + if( parseNetworkDiscoveryArgs( imaState, joArg ) ) + continue; + if( parseBlockScannerArgs( imaState, joArg ) ) + continue; + if( parseJsonRpcServerArgs( imaState, joArg ) ) + continue; + if( parseCrossImaCommunicationArgs( imaState, joArg ) ) + continue; + if( parseShowConfigArgs( imaState, joArg ) ) + continue; + if( parseOtherArgs( imaState, joArg ) ) + continue; + if( joArg.name == "register" || + joArg.name == "register1" || + joArg.name == "check-registration" || + joArg.name == "check-registration1" || + joArg.name == "check-registration2" || + joArg.name == "check-registration3" || + joArg.name == "mint-erc20" || + joArg.name == "mint-erc721" || + joArg.name == "mint-erc1155" || + joArg.name == "burn-erc20" || + joArg.name == "burn-erc721" || + joArg.name == "burn-erc1155" || + joArg.name == "show-balance" || + joArg.name == "m2s-payment" || + joArg.name == "s2m-payment" || + joArg.name == "s2m-receive" || + joArg.name == "s2m-view" || + joArg.name == "s2s-payment" | + joArg.name == "m2s-transfer" || + joArg.name == "s2m-transfer" || + joArg.name == "s2s-transfer" || + joArg.name == "transfer" || + joArg.name == "loop" || + joArg.name == "simple-loop" || + joArg.name == "browse-s-chain" || + joArg.name == "browse-skale-network" || + joArg.name == "browse-connected-schains" || + joArg.name == "discover-cid" + ) { + joExternalHandlers[joArg.name](); + continue; + } + console.log( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " unknown command line argument " ) + cc.info( joArg.name ) ); + return 666; + } + return 0; +} + +async function asyncCheckUrlAtStartup( u, name ) { + const details = log.createMemoryStream(); + const nTimeoutMilliseconds = 10 * 1000; + try { + details.write( + cc.debug( "Will check URL " ) + cc.u( u ) + cc.debug( " connectivity for " ) + + cc.info( name ) + cc.debug( " at start-up..." ) + + "\n" ); + const isLog = false; + const isOnLine = await rpcCall.checkUrl( u, nTimeoutMilliseconds, isLog ); + if( isOnLine ) { + details.write( + cc.success( "Done, start-up checking URL " ) + cc.u( u ) + + cc.success( " connectivity for " ) + cc.info( name ) + + cc.success( ", URL is on-line." ) + + "\n" ); + } else { + details.write( + cc.error( "Done, start-up checking URL " ) + cc.u( u ) + + cc.error( " connectivity for " ) + cc.info( name ) + + cc.error( ", URL is off-line." ) + + "\n" ); + } + return isOnLine; + } catch ( err ) { + details.write( + cc.fatal( "ERROR:" ) + cc.error( " Failed to check URL " ) + + cc.u( u ) + cc.error( " connectivity for " ) + cc.info( name ) + + cc.error( " at start-up, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n" ); + } + return false; +} + +function commonInitPrintSysInfo() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + if( isPrintGathered ) { + log.write( cc.debug( "This process " ) + cc.sunny( "PID" ) + + cc.debug( " is " ) + cc.bright( process.pid ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "PPID" ) + + cc.debug( " is " ) + cc.bright( process.ppid ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "EGID" ) + + cc.debug( " is " ) + cc.bright( process.getegid() ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "EUID" ) + + cc.debug( " is " ) + cc.bright( process.geteuid() ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "GID" ) + + cc.debug( " is " ) + cc.bright( process.getgid() ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "UID" ) + + cc.debug( " is " ) + cc.bright( process.getuid() ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "groups" ) + + cc.debug( " are " ) + cc.j( process.getgroups() ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "CWD" ) + + cc.debug( " is " ) + cc.bright( process.cwd() ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "platform" ) + + cc.debug( " is " ) + cc.bright( process.platform ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "release" ) + + cc.debug( " is " ) + cc.j( process.release ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "report" ) + + cc.debug( " is " ) + cc.j( process.report ) + "\n" ); + log.write( cc.debug( "This process " ) + cc.sunny( "config" ) + + cc.debug( " is " ) + cc.j( process.config ) + "\n" ); + log.write( cc.sunny( "Node JS" ) + " " + cc.bright( "detailed version information" ) + + cc.debug( " is " ) + cc.j( process.versions ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "type" ) + + cc.debug( " is " ) + cc.bright( os.type() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "platform" ) + + cc.debug( " is " ) + cc.bright( os.platform() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "release" ) + + cc.debug( " is " ) + cc.bright( os.release() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "architecture" ) + + cc.debug( " is " ) + cc.bright( os.arch() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "endianness" ) + + cc.debug( " is " ) + cc.bright( os.endianness() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "host name" ) + + cc.debug( " is " ) + cc.bright( os.hostname() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "CPUs" ) + + cc.debug( " are " ) + cc.j( os.cpus() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "network interfaces" ) + + cc.debug( " are " ) + cc.j( os.networkInterfaces() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "home dir" ) + + cc.debug( " is " ) + cc.bright( os.homedir() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "tmp dir" ) + + cc.debug( " is " ) + cc.bright( os.tmpdir() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "uptime" ) + + cc.debug( " is " ) + cc.bright( os.uptime() ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "user" ) + + cc.debug( " is " ) + cc.j( os.userInfo() ) + "\n" ); + const joMemory = { total: os.totalmem(), free: os.freemem() }; + joMemory.freePercent = ( joMemory.free / joMemory.total ) * 100.0; + log.write( cc.sunny( "OS" ) + " " + cc.bright( "memory" ) + + cc.debug( " is " ) + cc.j( joMemory ) + "\n" ); + log.write( cc.sunny( "OS" ) + " " + cc.bright( "average load" ) + + cc.debug( " is " ) + cc.j( os.loadavg() ) + "\n" ); + } +} + +function commonInitCheckAbiPaths() { + const imaState = state.get(); + if( imaState.strPathAbiJsonSkaleManager && + ( typeof imaState.strPathAbiJsonSkaleManager == "string" ) && + imaState.strPathAbiJsonSkaleManager.length > 0 + ) { + imaState.joAbiSkaleManager = + imaUtils.jsonFileLoad( imaState.strPathAbiJsonSkaleManager, null ); + imaState.bHaveSkaleManagerABI = true; + } else { + imaState.bHaveSkaleManagerABI = false; + log.write( + cc.warning( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Skale Manager" ) + + cc.warning( " ABI file path is provided in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + + "\n" ); + } + + if( imaState.chainProperties.mn.strPathAbiJson && + typeof imaState.chainProperties.mn.strPathAbiJson == "string" && + imaState.chainProperties.mn.strPathAbiJson.length > 0 ) { + imaState.chainProperties.mn.joAbiIMA = + imaUtils.jsonFileLoad( imaState.chainProperties.mn.strPathAbiJson, null ); + imaState.chainProperties.mn.bHaveAbiIMA = true; + } else { + imaState.chainProperties.mn.bHaveAbiIMA = false; + log.write( + cc.warning( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Main-net" ) + + cc.warning( " IMA ABI file path is provided in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + + "\n" ); + } + + if( imaState.chainProperties.sc.strPathAbiJson && + typeof imaState.chainProperties.sc.strPathAbiJson == "string" && + imaState.chainProperties.sc.strPathAbiJson.length > 0 + ) { + imaState.chainProperties.sc.joAbiIMA = + imaUtils.jsonFileLoad( imaState.chainProperties.sc.strPathAbiJson, null ); + imaState.chainProperties.sc.bHaveAbiIMA = true; + } else { + imaState.chainProperties.sc.bHaveAbiIMA = false; + log.write( + cc.warning( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S-Chain" ) + + cc.warning( " IMA ABI file path is provided in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + + "\n" ); + } + + if( imaState.chainProperties.tc.strPathAbiJson && + typeof imaState.chainProperties.tc.strPathAbiJson == "string" && + imaState.chainProperties.tc.strPathAbiJson.length > 0 + ) { + imaState.chainProperties.tc.joAbiIMA = + imaUtils.jsonFileLoad( imaState.chainProperties.tc.strPathAbiJson, null ); + imaState.chainProperties.tc.bHaveAbiIMA = true; + } else { + imaState.chainProperties.tc.bHaveAbiIMA = false; + log.write( + cc.warning( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S<->S Target S-Chain" ) + + cc.warning( " IMA ABI file path is provided in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + + "\n" ); + } +} + +function commonInitCheckContractPresences() { + const imaState = state.get(); + if( imaState.bHaveSkaleManagerABI ) { + imaUtils.checkKeysExistInABI( "skale-manager", + imaState.strPathAbiJsonSkaleManager, + imaState.joAbiSkaleManager, [ + // partial list of Skale Manager's contracts specified here: + "constants_holder_abi", + "constants_holder_address", + "nodes_abi", + "nodes_address", + "key_storage_abi", + "key_storage_address", + "schains_abi", + "schains_address", + "schains_internal_abi", + "schains_internal_address", + "skale_d_k_g_abi", + "skale_d_k_g_address", + "skale_manager_abi", + "skale_manager_address", + "skale_token_abi", + "skale_token_address", + "validator_service_abi", + "validator_service_address", + "wallets_abi", + "wallets_address" + ] ); + } else if( imaState.optsS2S.isEnabled ) { + log.write( cc.warning( "WARNING:" ) + + cc.warning( " Missing " ) + cc.note( "Skale Manager" ) + + cc.warning( " ABI path for " ) + cc.note( "S-Chain" ) + cc.warning( " to " ) + + cc.note( "S-Chain" ) + cc.warning( " transfers" ) + + "\n" ); + } + + if( imaState.chainProperties.mn.bHaveAbiIMA ) { + imaUtils.checkKeysExistInABI( "main-net", + imaState.chainProperties.mn.strPathAbiJson, + imaState.chainProperties.mn.joAbiIMA, [ + "deposit_box_eth_abi", + "deposit_box_eth_address", + "message_proxy_mainnet_abi", + "message_proxy_mainnet_address", + "linker_abi", + "linker_address", + "deposit_box_erc20_abi", + "deposit_box_erc20_address", + "deposit_box_erc721_abi", + "deposit_box_erc721_address", + "deposit_box_erc1155_abi", + "deposit_box_erc1155_address", + "deposit_box_erc721_with_metadata_abi", + "deposit_box_erc721_with_metadata_address", + "community_pool_abi", + "community_pool_address" + ] ); + } + if( imaState.chainProperties.sc.bHaveAbiIMA ) { + imaUtils.checkKeysExistInABI( "S-Chain", + imaState.chainProperties.sc.strPathAbiJson, + imaState.chainProperties.sc.joAbiIMA, [ + "token_manager_eth_abi", + "token_manager_eth_address", + "token_manager_erc20_abi", + "token_manager_erc20_address", + "token_manager_erc721_abi", + "token_manager_erc721_address", + "token_manager_erc1155_abi", + "token_manager_erc1155_address", + "token_manager_erc721_with_metadata_abi", + "token_manager_erc721_with_metadata_address", + "message_proxy_chain_abi", + "message_proxy_chain_address", + "token_manager_linker_abi", + "token_manager_linker_address", + "community_locker_abi", + "community_locker_address" + ] ); + } + if( imaState.chainProperties.tc.bHaveAbiIMA ) { + imaUtils.checkKeysExistInABI( "S<->S Target S-Chain", + imaState.chainProperties.tc.strPathAbiJson, + imaState.chainProperties.tc.joAbiIMA, [ + "token_manager_eth_abi", + "token_manager_eth_address", + "token_manager_erc20_abi", + "token_manager_erc20_address", + "token_manager_erc721_abi", + "token_manager_erc721_address", + "token_manager_erc1155_abi", + "token_manager_erc1155_address", + "token_manager_erc721_with_metadata_abi", + "token_manager_erc721_with_metadata_address", + "message_proxy_chain_abi", + "message_proxy_chain_address", + "token_manager_linker_abi", + "token_manager_linker_address", + "community_locker_abi", + "community_locker_address" + ] ); + } +} + +function commonInitPrintFoundContracts() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + // deposit_box_eth_address --> deposit_box_eth_abi + // deposit_box_erc20_address --> deposit_box_erc20_abi + // deposit_box_erc721_address --> deposit_box_erc721_abi + // deposit_box_erc1155_address --> deposit_box_erc1155_abi + // deposit_box_erc721_with_metadata_address --> deposit_box_erc721_with_metadata_abi + // linker_address --> linker_abi + // token_manager_eth_address --> token_manager_eth_abi + // token_manager_erc20_address --> token_manager_erc20_abi + // token_manager_erc721_address --> token_manager_erc721_abi + // token_manager_erc1155_address --> token_manager_erc1155_abi + // token_manager_erc721_with_metadata_address --> token_manager_erc721_with_metadata_abi + // token_manager_linker_address --> token_manager_linker_abi + // message_proxy_mainnet_address --> message_proxy_mainnet_abi + // message_proxy_chain_address --> message_proxy_chain_abi + + const oct = function( joContract ) { // optional contract address + if( joContract && "options" in joContract && "address" in joContract.options ) + return cc.bright( joContract.address ); + return cc.error( "contract is not available" ); + }; + + if( isPrintGathered ) { + log.write( cc.bright( "IMA contracts(Main Net):" ) + "\n" ); + log.write( cc.sunny( "DepositBoxEth" ) + cc.debug( "...................address is....." ) + + oct( imaState.joDepositBoxETH ) + "\n" ); + log.write( cc.sunny( "DepositBoxERC20" ) + cc.debug( ".................address is....." ) + + oct( imaState.joDepositBoxERC20 ) + "\n" ); + log.write( cc.sunny( "DepositBoxERC721" ) + cc.debug( "................address is....." ) + + oct( imaState.joDepositBoxERC721 ) + "\n" ); + log.write( cc.sunny( "DepositBoxERC1155" ) + cc.debug( "...............address is....." ) + + oct( imaState.joDepositBoxERC1155 ) + "\n" ); + log.write( cc.sunny( "DepositBoxERC721WithMetadata" ) + cc.debug( "....address is....." ) + + oct( imaState.joDepositBoxERC721WithMetadata ) + "\n" ); + log.write( cc.sunny( "CommunityPool" ) + cc.debug( "...................address is....." ) + + oct( imaState.joCommunityPool ) + "\n" ); + log.write( cc.sunny( "MessageProxy" ) + cc.debug( "....................address is....." ) + + oct( imaState.joMessageProxyMainNet ) + "\n" ); + log.write( cc.sunny( "Linker" ) + cc.debug( "..........................address is....." ) + + oct( imaState.joLinker ) + "\n" ); + log.write( cc.bright( "IMA contracts(S-Chain):" ) + "\n" ); + log.write( cc.sunny( "TokenManagerEth" ) + cc.debug( ".................address is....." ) + + oct( imaState.joTokenManagerETH ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC20" ) + cc.debug( "...............address is....." ) + + oct( imaState.joTokenManagerERC20 ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC721" ) + cc.debug( "..............address is....." ) + + oct( imaState.joTokenManagerERC721 ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC1155" ) + cc.debug( ".............address is....." ) + + oct( imaState.joTokenManagerERC1155 ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC721WithMetadata" ) + cc.debug( "..address is....." ) + + oct( imaState.joTokenManagerERC721WithMetadata ) + "\n" ); + log.write( cc.sunny( "CommunityLocker" ) + cc.debug( ".................address is....." ) + + oct( imaState.joCommunityLocker ) + "\n" ); + log.write( cc.sunny( "MessageProxy" ) + cc.debug( "....................address is....." ) + + oct( imaState.joMessageProxySChain ) + "\n" ); + log.write( cc.sunny( "TokenManagerLinker" ) + cc.debug( "..............address is....." ) + + oct( imaState.joTokenManagerLinker ) + "\n" ); + log.write( cc.sunny( "ERC20" ) + cc.debug( " ..........................address is....." ) + + oct( imaState.joEthErc20 ) + "\n" ); + log.write( cc.bright( "IMA contracts(Target S-Chain):" ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC20" ) + cc.debug( "...............address is....." ) + + oct( imaState.joTokenManagerERC20Target ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC721" ) + cc.debug( "..............address is....." ) + + oct( imaState.joTokenManagerERC721Target ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC1155" ) + cc.debug( ".............address is....." ) + + oct( imaState.joTokenManagerERC1155Target ) + "\n" ); + log.write( cc.sunny( "TokenManagerERC721WithMetadata" ) + cc.debug( "..address is....." ) + + oct( imaState.joTokenManagerERC721WithMetadataTarget ) + "\n" ); + log.write( cc.sunny( "CommunityLocker" ) + cc.debug( ".................address is....." ) + + oct( imaState.joCommunityLockerTarget ) + "\n" ); + log.write( cc.sunny( "MessageProxy" ) + cc.debug( "....................address is....." ) + + oct( imaState.joMessageProxySChainTarget ) + "\n" ); + log.write( cc.sunny( "TokenManagerLinker" ) + cc.debug( "..............address is....." ) + + oct( imaState.joTokenManagerLinkerTarget ) + "\n" ); + log.write( cc.sunny( "ERC20" ) + cc.debug( " ..........................address is....." ) + + oct( imaState.joEthErc20Target ) + "\n" ); + + log.write( cc.bright( "Skale Manager contracts:" ) + "\n" ); + log.write( cc.sunny( "ConstantsHolder" ) + cc.debug( ".................address is....." ) + + oct( imaState.joConstantsHolder ) + "\n" ); + log.write( cc.sunny( "Nodes" ) + cc.debug( "...........................address is....." ) + + oct( imaState.joNodes ) + "\n" ); + log.write( cc.sunny( "KeyStorage" ) + cc.debug( "......................address is....." ) + + oct( imaState.joKeyStorage ) + "\n" ); + log.write( cc.sunny( "Schains" ) + cc.debug( ".........................address is....." ) + + oct( imaState.joSChains ) + "\n" ); + log.write( cc.sunny( "SchainsInternal" ) + cc.debug( ".................address is....." ) + + oct( imaState.joSChainsInternal ) + "\n" ); + log.write( cc.sunny( "SkaleDKG" ) + cc.debug( "........................address is....." ) + + oct( imaState.joSkaleDKG ) + "\n" ); + log.write( cc.sunny( "SkaleManager" ) + cc.debug( "....................address is....." ) + + oct( imaState.joSkaleManager ) + "\n" ); + log.write( cc.sunny( "SkaleToken" ) + cc.debug( "......................address is....." ) + + oct( imaState.joSkaleToken ) + "\n" ); + log.write( cc.sunny( "ValidatorService" ) + cc.debug( "................address is....." ) + + oct( imaState.joValidatorService ) + "\n" ); + log.write( cc.sunny( "Wallets" ) + cc.debug( ".........................address is....." ) + + oct( imaState.joWallets ) + "\n" ); + } +} + +function commonInitCheckErc20() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + let n1 = 0; + let n2 = 0; + if( imaState.chainProperties.mn.strPathJsonErc20.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( cc.info( "Loading Main-net ERC20 ABI from " ) + + cc.info( imaState.chainProperties.mn.strPathJsonErc20 ) + "\n" ); + } + imaState.chainProperties.mn.joErc20 = + imaUtils.jsonFileLoad( imaState.chainProperties.mn.strPathJsonErc20, null ); + n1 = Object.keys( imaState.chainProperties.mn.joErc20 ).length; + if( imaState.chainProperties.sc.strPathJsonErc20.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( cc.info( "Loading S-Chain ERC20 ABI from " ) + + cc.info( imaState.chainProperties.sc.strPathJsonErc20 ) + + "\n" ); + } + imaState.chainProperties.sc.joErc20 = + imaUtils.jsonFileLoad( imaState.chainProperties.sc.strPathJsonErc20, null ); + n2 = Object.keys( imaState.chainProperties.sc.joErc20 ).length; + } + if( n1 > 0 ) { + imaState.chainProperties.tc.strCoinNameErc20 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.mn.joErc20 ); + if( n2 > 0 ) { + imaState.chainProperties.sc.strCoinNameErc20 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.sc.joErc20 ); + } + n1 = imaState.chainProperties.tc.strCoinNameErc20.length; + if( n2 > 0 ) + n2 = imaState.chainProperties.sc.strCoinNameErc20.length; + if( n1 > 0 ) { + if( isPrintGathered && + log.verboseGet() >= log.verboseReversed().information && + ( !imaState.bShowConfigMode ) + ) { + if( isPrintGathered ) { + log.write( cc.info( "Loaded Main-net ERC20 ABI " ) + + cc.attention( imaState.chainProperties.tc.strCoinNameErc20 ) + + "\n" ); + } + if( isPrintGathered && n2 > 0 ) { + log.write( cc.info( "Loaded S-Chain ERC20 ABI " ) + + cc.attention( imaState.chainProperties.sc.strCoinNameErc20 ) + + "\n" ); + } + } + } else { + if( n1 === 0 ) { + log.write( + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "Main-net ERC20 token name is not discovered (malformed JSON)" ) + + "\n" ); + } + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc20.length > 0 ) { + log.write( + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC20 token name is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc20 = null; + imaState.chainProperties.sc.joErc20 = null; + imaState.chainProperties.tc.strCoinNameErc20 = ""; + imaState.chainProperties.sc.strCoinNameErc20 = ""; + process.exit( 126 ); + } + } else { + if( n1 === 0 ) { + log.write( + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "Main-net ERC20 JSON is invalid" ) + + "\n" ); + } + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc20.length > 0 ) { + log.write( + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC20 JSON is invalid" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc20 = null; + imaState.chainProperties.sc.joErc20 = null; + imaState.chainProperties.tc.strCoinNameErc20 = ""; + imaState.chainProperties.sc.strCoinNameErc20 = ""; + process.exit( 126 ); + } + } else { + if( imaState.chainProperties.sc.strPathJsonErc20.length > 0 ) { + n1 = 0; + n2 = 0; + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( + cc.info( "Loading S-Chain ERC20 ABI from " ) + + cc.info( imaState.chainProperties.sc.strPathJsonErc20 ) + + "\n" ); + } + imaState.chainProperties.sc.joErc20 = + imaUtils.jsonFileLoad( imaState.chainProperties.sc.strPathJsonErc20, null ); + n2 = Object.keys( imaState.chainProperties.sc.joErc20 ).length; + if( n2 > 0 ) { + imaState.chainProperties.sc.strCoinNameErc20 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.sc.joErc20 ); + n2 = imaState.chainProperties.sc.strCoinNameErc20.length; + if( n2 > 0 ) { + if( isPrintGathered ) { + log.write( + cc.info( "Loaded S-Chain ERC20 ABI " ) + + cc.attention( imaState.chainProperties.sc.strCoinNameErc20 ) + + "\n" ); + } + } else { + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc20.length > 0 ) { + log.write( + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC20 token name is " + + "not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc20 = null; + imaState.chainProperties.sc.joErc20 = null; + imaState.chainProperties.tc.strCoinNameErc20 = ""; + imaState.chainProperties.sc.strCoinNameErc20 = ""; + process.exit( 126 ); + } + } + } + } + if( n1 !== 0 && n2 === 0 ) { + if( imaState.strAddrErc20Explicit.length === 0 ) { + log.write( + cc.error( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Both S-Chain ERC20 JSON and explicit " + + "ERC20 address are not specified" ) + + "\n" ); + } else { + if( isPrintGathered ) { + log.write( + cc.attention( "IMPORTANT NOTICE:" ) + " " + + cc.note( "S-Chain ERC20 ABI will be auto-generated" ) + + "\n" ); + } + imaState.chainProperties.sc.strCoinNameErc20 = + "" + imaState.chainProperties.tc.strCoinNameErc20; // assume same + imaState.chainProperties.sc.joErc20 = + JSON.parse( JSON.stringify( imaState.chainProperties.mn.joErc20 ) ); // clone + imaState.chainProperties.sc.joErc20[ + imaState.chainProperties.sc.strCoinNameErc20 + "_address"] = + "" + imaState.strAddrErc20Explicit; // set explicit address + } + } + + if( imaState.chainProperties.tc.strPathJsonErc20.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( + cc.info( "Loading S<->S Target S-Chain ERC20 ABI from " ) + + cc.info( imaState.chainProperties.tc.strPathJsonErc20 ) + + "\n" ); + } + imaState.chainProperties.tc.joErc20 = + imaUtils.jsonFileLoad( imaState.chainProperties.tc.strPathJsonErc20, null ); + n2 = Object.keys( imaState.chainProperties.tc.joErc20 ).length; + if( n2 > 0 ) { + imaState.chainProperties.tc.strCoinNameErc20 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.tc.joErc20 ); + n2 = imaState.chainProperties.tc.strCoinNameErc20.length; + if( n2 > 0 ) { + if( isPrintGathered ) { + log.write( + cc.info( "Loaded S<->S Target S-Chain ERC20 ABI " ) + + cc.attention( imaState.chainProperties.tc.strCoinNameErc20 ) + + "\n" ); + } + } else { + if( n2 === 0 && imaState.chainProperties.tc.strPathJsonErc20.length > 0 ) { + log.write( + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S<->S Target S-Chain " + + "ERC20 token name is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.tc.joErc20 = null; + imaState.chainProperties.tc.strCoinNameErc20 = ""; + process.exit( 126 ); + } + } + } + if( isPrintGathered && + imaState.strAddrErc20ExplicitTarget.length === 0 && + imaState.chainProperties.tc.strCoinNameErc20.length === 0 && + imaState.chainProperties.sc.strCoinNameErc20.length > 0 + ) { + log.write( + cc.error( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Both S<->S Target S-Chain ERC20 JSON and " + + "explicit ERC20 address are not specified" ) + + "\n" ); + } +} + +function commonInitCheckErc721() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + let n1 = 0; + let n2 = 0; + if( imaState.chainProperties.mn.strPathJsonErc721.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( cc.info( "Loading Main-net ERC721 ABI from " ) + + cc.info( imaState.chainProperties.mn.strPathJsonErc721 ) + + "\n" ); + } + imaState.chainProperties.mn.joErc721 = + imaUtils.jsonFileLoad( imaState.chainProperties.mn.strPathJsonErc721, null ); + n1 = Object.keys( imaState.chainProperties.mn.joErc721 ).length; + if( imaState.chainProperties.sc.strPathJsonErc721.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( + cc.info( "Loading S-Chain ERC721 ABI from " ) + + cc.info( imaState.chainProperties.sc.strPathJsonErc721 ) + + "\n" ); + } + imaState.chainProperties.sc.joErc721 = + imaUtils.jsonFileLoad( imaState.chainProperties.sc.strPathJsonErc721, null ); + n2 = Object.keys( imaState.chainProperties.sc.joErc721 ).length; + } + if( n1 > 0 ) { + imaState.chainProperties.mn.strCoinNameErc721 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.mn.joErc721 ); + if( n2 > 0 ) { + imaState.chainProperties.sc.strCoinNameErc721 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.sc.joErc721 ); + } + n1 = imaState.chainProperties.mn.strCoinNameErc721.length; + if( n2 > 0 ) + n2 = imaState.chainProperties.sc.strCoinNameErc721.length; + if( n1 > 0 ) { + if( log.verboseGet() >= log.verboseReversed().information && + ( !imaState.bShowConfigMode ) ) { + if( isPrintGathered ) { + log.write( cc.info( "Loaded Main-net ERC721 ABI " ) + + cc.attention( imaState.chainProperties.mn.strCoinNameErc721 ) + + "\n" ); + } + if( n2 > 0 && isPrintGathered ) { + log.write( cc.info( "Loaded S-Chain ERC721 ABI " ) + + cc.attention( imaState.chainProperties.sc.strCoinNameErc721 ) + + "\n" ); + } + } + } else { + if( n1 === 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "Main-net ERC721 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc721.length > 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC721 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc721 = null; + imaState.chainProperties.sc.joErc721 = null; + imaState.chainProperties.mn.strCoinNameErc721 = ""; + imaState.chainProperties.sc.strCoinNameErc721 = ""; + process.exit( 126 ); + } + } else { + if( n1 === 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "Main-net ERC721 JSON is invalid" ) + + "\n" ); + } + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc721.length > 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC721 JSON is invalid" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc721 = null; + imaState.chainProperties.sc.joErc721 = null; + imaState.chainProperties.mn.strCoinNameErc721 = ""; + imaState.chainProperties.sc.strCoinNameErc721 = ""; + process.exit( 126 ); + } + } else { + if( imaState.chainProperties.sc.strPathJsonErc721.length > 0 ) { + n1 = 0; + n2 = 0; + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( + cc.info( "Loading S-Chain ERC721 ABI from " ) + + cc.info( imaState.chainProperties.sc.strPathJsonErc721 ) + + "\n" ); + } + imaState.chainProperties.sc.joErc721 = + imaUtils.jsonFileLoad( imaState.chainProperties.sc.strPathJsonErc721, null ); + n2 = Object.keys( imaState.chainProperties.sc.joErc721 ).length; + + if( n2 > 0 ) { + imaState.chainProperties.sc.strCoinNameErc721 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.sc.joErc721 ); + n2 = imaState.chainProperties.sc.strCoinNameErc721.length; + if( n2 > 0 ) { + if( isPrintGathered ) { + log.write( + cc.info( "Loaded S-Chain ERC721 ABI " ) + + cc.attention( imaState.chainProperties.sc.strCoinNameErc721 ) + + "\n" ); + } else { + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc721.length > 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC721 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc721 = null; + imaState.chainProperties.sc.joErc721 = null; + imaState.chainProperties.mn.strCoinNameErc721 = ""; + imaState.chainProperties.sc.strCoinNameErc721 = ""; + process.exit( 126 ); + } + } + } + } + } + if( n1 !== 0 && n2 === 0 ) { + if( imaState.strAddrErc721Explicit.length === 0 ) { + if( isPrintGathered ) { + log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Both S-Chain ERC721 JSON and " + + "explicit ERC721 address are not specified" ) + + "\n" ); + } + } else { + if( isPrintGathered ) { + log.write( cc.attention( "IMPORTANT NOTICE:" ) + " " + + cc.note( "S-Chain ERC721 ABI will be auto-generated" ) + + "\n" ); + } + imaState.chainProperties.sc.strCoinNameErc721 = + "" + imaState.chainProperties.mn.strCoinNameErc721; // assume same + imaState.chainProperties.sc.joErc721 = + JSON.parse( JSON.stringify( imaState.chainProperties.mn.joErc721 ) ); // clone + imaState.chainProperties.sc.joErc721[ + imaState.chainProperties.sc.strCoinNameErc721 + "_address"] = + "" + imaState.strAddrErc721Explicit; // set explicit address + } + } + + if( imaState.chainProperties.tc.strPathJsonErc721.length > 0 && + isPrintGathered + ) { + if( log.verboseGet() > log.verboseReversed().information ) { + log.write( cc.info( "Loading S<->S Target S-Chain ERC721 ABI from " ) + + cc.info( imaState.chainProperties.tc.strPathJsonErc721 ) + + "\n" ); + } + imaState.chainProperties.tc.joErc721 = + imaUtils.jsonFileLoad( imaState.chainProperties.tc.strPathJsonErc721, null ); + n2 = Object.keys( imaState.chainProperties.tc.joErc721 ).length; + if( n2 > 0 ) { + imaState.chainProperties.tc.strCoinNameErc721 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.tc.joErc721 ); + n2 = imaState.chainProperties.tc.strCoinNameErc721.length; + if( n2 > 0 && isPrintGathered ) { + log.write( cc.info( "Loaded S<->S Target S-Chain ERC721 ABI " ) + + cc.attention( imaState.chainProperties.tc.strCoinNameErc721 ) + + "\n" ); + } else { + if( n2 === 0 && + imaState.chainProperties.tc.strPathJsonErc721.length > 0 && + isPrintGathered + ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S<->S Target S-Chain ERC721 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.tc.joErc721 = null; + imaState.chainProperties.tc.strCoinNameErc721 = ""; + process.exit( 126 ); + } + } + } + if( isPrintGathered && + imaState.strAddrErc721ExplicitTarget.length === 0 && + imaState.chainProperties.tc.strCoinNameErc721.length === 0 && + imaState.chainProperties.sc.strCoinNameErc721.length > 0 + ) { + log.write( cc.error( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Both S<->S Target S-Chain ERC721 JSON and " + + "explicit ERC721 address are not specified" ) + + "\n" ); + } +} + +function commonInitCheckErc1155() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + let n1 = 0; + let n2 = 0; + if( imaState.chainProperties.mn.strPathJsonErc1155.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( cc.info( "Loading Main-net ERC1155 ABI from " ) + + cc.info( imaState.chainProperties.mn.strPathJsonErc1155 ) + + "\n" ); + } + imaState.chainProperties.mn.joErc1155 = + imaUtils.jsonFileLoad( imaState.chainProperties.mn.strPathJsonErc1155, null ); + n1 = Object.keys( imaState.chainProperties.mn.joErc1155 ).length; + if( imaState.chainProperties.sc.strPathJsonErc1155.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( cc.info( "Loading S-Chain ERC1155 ABI from " ) + + cc.info( imaState.chainProperties.sc.strPathJsonErc1155 ) + + "\n" ); + } + imaState.chainProperties.sc.joErc1155 = + imaUtils.jsonFileLoad( imaState.chainProperties.sc.strPathJsonErc1155, null ); + n2 = Object.keys( imaState.chainProperties.sc.joErc1155 ).length; + } + if( n1 > 0 ) { + imaState.chainProperties.mn.strCoinNameErc1155 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.mn.joErc1155 ); + if( n2 > 0 ) { + imaState.chainProperties.sc.strCoinNameErc1155 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.sc.joErc1155 ); + } + n1 = imaState.chainProperties.mn.strCoinNameErc1155.length; + if( n2 > 0 ) + n2 = imaState.chainProperties.sc.strCoinNameErc1155.length; + if( n1 > 0 ) { + if( log.verboseGet() >= log.verboseReversed().information && + ( !imaState.bShowConfigMode ) + ) { + if( isPrintGathered ) { + log.write( cc.info( "Loaded Main-net ERC1155 ABI " ) + + cc.attention( imaState.chainProperties.mn.strCoinNameErc1155 ) + + "\n" ); + } + if( n2 > 0 && isPrintGathered ) { + log.write( cc.info( "Loaded S-Chain ERC1155 ABI " ) + + cc.attention( imaState.chainProperties.sc.strCoinNameErc1155 ) + + "\n" ); + } + } + } else { + if( n1 === 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "Main-net ERC1155 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc1155.length > 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC1155 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc1155 = null; + imaState.chainProperties.sc.joErc1155 = null; + imaState.chainProperties.mn.strCoinNameErc1155 = ""; + imaState.chainProperties.sc.strCoinNameErc1155 = ""; + process.exit( 126 ); + } + } else { + if( n1 === 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "Main-net ERC1155 JSON is invalid" ) + + "\n" ); + } + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc1155.length > 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC1155 JSON is invalid" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc1155 = null; + imaState.chainProperties.sc.joErc1155 = null; + imaState.chainProperties.mn.strCoinNameErc1155 = ""; + imaState.chainProperties.sc.strCoinNameErc1155 = ""; + process.exit( 126 ); + } + } else { + if( imaState.chainProperties.sc.strPathJsonErc1155.length > 0 ) { + n1 = 0; + n2 = 0; + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( cc.info( "Loading S-Chain ERC1155 ABI from " ) + + cc.info( imaState.chainProperties.sc.strPathJsonErc1155 ) + + "\n" ); + } + imaState.chainProperties.sc.joErc1155 = + imaUtils.jsonFileLoad( imaState.chainProperties.sc.strPathJsonErc1155, null ); + n2 = Object.keys( imaState.chainProperties.sc.joErc1155 ).length; + + if( n2 > 0 ) { + imaState.chainProperties.sc.strCoinNameErc1155 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.sc.joErc1155 ); + n2 = imaState.chainProperties.sc.strCoinNameErc1155.length; + if( n2 > 0 ) { + if( isPrintGathered ) { + log.write( cc.info( "Loaded S-Chain ERC1155 ABI " ) + + cc.attention( imaState.chainProperties.sc.strCoinNameErc1155 ) + + "\n" ); + } + } else { + if( n2 === 0 && imaState.chainProperties.sc.strPathJsonErc1155.length > 0 ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S-Chain ERC1155 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.mn.joErc1155 = null; + imaState.chainProperties.sc.joErc1155 = null; + imaState.chainProperties.mn.strCoinNameErc1155 = ""; + imaState.chainProperties.sc.strCoinNameErc1155 = ""; + process.exit( 126 ); + } + } + } + } + if( n1 !== 0 && n2 === 0 ) { + if( imaState.strAddrErc1155Explicit.length === 0 ) { + if( isPrintGathered ) { + log.write( + cc.error( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Both S-Chain ERC1155 JSON and " + + "explicit ERC1155 address are not specified" ) + + "\n" ); + } + } else { + if( isPrintGathered ) { + log.write( + cc.attention( "IMPORTANT NOTICE:" ) + " " + + cc.note( "S-Chain ERC1155 ABI will be auto-generated" ) + + "\n" ); + } + imaState.chainProperties.sc.strCoinNameErc1155 = + "" + imaState.chainProperties.mn.strCoinNameErc1155; // assume same + imaState.chainProperties.sc.joErc1155 = + JSON.parse( JSON.stringify( imaState.chainProperties.mn.joErc1155 ) ); // clone + imaState.chainProperties.sc.joErc1155[ + imaState.chainProperties.sc.strCoinNameErc1155 + "_address"] = + "" + imaState.strAddrErc1155Explicit; // set explicit address + } + } + + if( imaState.chainProperties.tc.strPathJsonErc1155.length > 0 ) { + if( isPrintGathered && log.verboseGet() > log.verboseReversed().information ) { + log.write( + cc.info( "Loading S<->S Target S-Chain ERC1155 ABI from " ) + + cc.info( imaState.chainProperties.tc.strPathJsonErc1155 ) + + "\n" ); + } + imaState.chainProperties.tc.joErc1155 = + imaUtils.jsonFileLoad( imaState.chainProperties.tc.strPathJsonErc1155, null ); + n2 = Object.keys( imaState.chainProperties.tc.joErc1155 ).length; + if( n2 > 0 ) { + imaState.chainProperties.tc.strCoinNameErc1155 = + imaUtils.discoverCoinNameInJSON( imaState.chainProperties.tc.joErc1155 ); + n2 = imaState.chainProperties.tc.strCoinNameErc1155.length; + if( n2 > 0 ) { + if( isPrintGathered ) { + log.write( + cc.info( "Loaded S<->S Target S-Chain ERC1155 ABI " ) + + cc.attention( imaState.chainProperties.tc.strCoinNameErc1155 ) + + "\n" ); + } + } else { + if( n2 === 0 && + imaState.chainProperties.tc.strPathJsonErc1155.length > 0 && + isPrintGathered + ) { + log.write( + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( "S<->S Target S-Chain ERC1155 token name " + + "is not discovered (malformed JSON)" ) + + "\n" ); + } + imaState.chainProperties.tc.joErc1155 = null; + imaState.chainProperties.tc.strCoinNameErc1155 = ""; + process.exit( 126 ); + } + } + } + if( isPrintGathered && + imaState.strAddrErc1155ExplicitTarget.length === 0 && + imaState.chainProperties.tc.strCoinNameErc1155.length === 0 && + imaState.chainProperties.sc.strCoinNameErc1155.length > 0 + ) { + log.write( + cc.error( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Both S<->S Target S-Chain ERC1155 JSON and " + + "explicit ERC1155 address are not specified" ) + + "\n" ); + } +} + +function commonInitCheckGeneralArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + const isPrintSecurityValues = imaState.isPrintSecurityValues ? true : false; + if( isPrintGathered ) { + printAbout( true ); + log.write( + cc.attention( "IMA AGENT" ) + cc.normal( " is using " ) + + cc.bright( "Ethers JS" ) + cc.normal( " version " ) + + cc.sunny( + owaspUtils.ethersMod.ethers.version.toString().replace( "ethers/", "" ) + ) + + "\n" ); + } + ensureHaveValue( + "App path", + path.join( __dirname, "main.mjs" ), false, isPrintGathered, null, ( x ) => { + return cc.normal( x ); + } ); + ensureHaveValue( + "Verbose level", + log.verboseLevelAsTextForLog( log.verboseGet() ), + false, isPrintGathered, null, ( x ) => { + return cc.sunny( x ); + } ); + ensureHaveValue( + "Multi-call optimizations", + imaState.isEnabledMultiCall, false, isPrintGathered, null, ( x ) => { + return cc.yn( x ); + } ); + ensureHaveValue( + "Main-net URL", + imaState.chainProperties.mn.strURL, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.u( x ); + } ); + ensureHaveValue( + "S-chain URL", + imaState.chainProperties.sc.strURL, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.u( x ); + } ); + ensureHaveValue( + "S<->S Target S-chain URL", + imaState.chainProperties.tc.strURL, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.u( x ); + } ); + ensureHaveValue( + "Main-net Ethereum network name", + imaState.chainProperties.mn.strChainName, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S-Chain Ethereum network name", + imaState.chainProperties.sc.strChainName, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S<->S Target S-Chain Ethereum network name", + imaState.chainProperties.tc.strChainName, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "Main-net Ethereum chain ID", + imaState.chainProperties.mn.chainId, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S-Chain Ethereum chain ID", + imaState.chainProperties.sc.chainId, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S<->S Target S-Chain Ethereum chain ID", + imaState.chainProperties.tc.chainId, false, + isPrintGathered && isPrintSecurityValues, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "Skale Manager ABI JSON file path", + imaState.strPathAbiJsonSkaleManager, false, isPrintGathered, null, ( x ) => { + return cc.warning( x ); + } ); + ensureHaveValue( + "Main-net ABI JSON file path", + imaState.chainProperties.mn.strPathAbiJson, false, isPrintGathered, null, ( x ) => { + return cc.warning( x ); + } ); + ensureHaveValue( + "S-Chain ABI JSON file path", + imaState.chainProperties.sc.strPathAbiJson, false, isPrintGathered, null, ( x ) => { + return cc.warning( x ); + } ); + ensureHaveValue( + "S<->S Target S-Chain ABI JSON file path", + imaState.chainProperties.tc.strPathAbiJson, false, isPrintGathered, null, ( x ) => { + return cc.warning( x ); + } ); + + try { + ensureHaveValue( "Main-net user account address", + imaState.chainProperties.mn.joAccount.address(), false, + isPrintGathered && isPrintSecurityValues ); + } catch ( err ) {} + try { + ensureHaveValue( "S-chain user account address", + imaState.chainProperties.sc.joAccount.address(), false, + isPrintGathered && isPrintSecurityValues ); + } catch ( err ) {} + try { + ensureHaveValue( + "S<->S Target S-chain user account address", + imaState.chainProperties.tc.joAccount.address(), + false, isPrintGathered ); + } catch ( err ) {} +} + +function commonInitCheckCredentialsArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + const isPrintSecurityValues = imaState.isPrintSecurityValues ? true : false; + try { + ensureHaveCredentials( + "Main Net", + imaState.chainProperties.mn.joAccount, false, + isPrintGathered && isPrintSecurityValues ); + } catch ( err ) {} + try { + ensureHaveCredentials( + "S-Chain", + imaState.chainProperties.sc.joAccount, false, + isPrintGathered && isPrintSecurityValues ); + } catch ( err ) {} + try { + commonInitCheckTransferAmountArgs(); + ensureHaveCredentials( + "S<->S Target S-Chain", + imaState.chainProperties.tc.joAccount, false, + isPrintGathered && isPrintSecurityValues ); + } catch ( err ) {} + if( isPrintGathered && isPrintSecurityValues ) { + if( imaState.chainProperties.mn.joAccount.strBlsKeyName ) { + ensureHaveValue( + "BLS/Main Net key name", + imaState.chainProperties.mn.joAccount.strBlsKeyName, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + } + if( imaState.chainProperties.sc.joAccount.strBlsKeyName ) { + ensureHaveValue( + "BLS/S-Chain key name", + imaState.chainProperties.sc.joAccount.strBlsKeyName, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + } + if( imaState.chainProperties.tc.joAccount.strBlsKeyName ) { + ensureHaveValue( + "BLS/Target S-Chain key name", + imaState.chainProperties.tc.joAccount.strBlsKeyName, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + } + } +} + +function commonInitCheckTransferAmountArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + ensureHaveValue( + "Amount of wei to transfer", imaState.nAmountOfWei, + false, isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); +} + +function commonInitTransferringArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + ensureHaveValue( + "M->S transfer block size", imaState.nTransferBlockSizeM2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S->M transfer block size", imaState.nTransferBlockSizeS2M, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + if( imaState.bHaveSkaleManagerABI ) { + ensureHaveValue( + "S->S transfer block size", imaState.nTransferBlockSizeS2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + } + ensureHaveValue( + "M->S transfer job steps", imaState.nTransferStepsM2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S->M transfer job steps", imaState.nTransferStepsS2M, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + if( imaState.bHaveSkaleManagerABI ) { + ensureHaveValue( + "S->S transfer job steps", imaState.nTransferStepsS2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + } + ensureHaveValue( + "M->S transactions limit", imaState.nMaxTransactionsM2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S->M transactions limit", imaState.nMaxTransactionsS2M, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + if( imaState.bHaveSkaleManagerABI ) { + ensureHaveValue( + "S->S transactions limit", imaState.nMaxTransactionsS2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + } + ensureHaveValue( + "M->S await blocks", imaState.nBlockAwaitDepthM2S, false, + isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S->M await blocks", imaState.nBlockAwaitDepthS2M, false, + isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + if( imaState.bHaveSkaleManagerABI ) { + ensureHaveValue( + "S->S await blocks", imaState.nBlockAwaitDepthS2S, false, + isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + } + ensureHaveValue( + "M->S minimal block age", imaState.nBlockAgeM2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + ensureHaveValue( + "S->M minimal block age", imaState.nBlockAgeS2M, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + if( imaState.bHaveSkaleManagerABI ) { + ensureHaveValue( + "S->S minimal block age", imaState.nBlockAgeS2S, + false, isPrintGathered, null, ( x ) => { + return cc.note( x ); + } ); + } + ensureHaveValue( + "Transfer loop period(seconds)", imaState.nLoopPeriodSeconds, + false, isPrintGathered, null, ( x ) => { + return cc.success( x ); + } ); + if( imaState.nTimeFrameSeconds > 0 ) { + ensureHaveValue( + "Time framing(seconds)", imaState.nTimeFrameSeconds, + false, isPrintGathered ); + ensureHaveValue( + "Next frame gap(seconds)", imaState.nNextFrameGap, + false, isPrintGathered ); + } else { + ensureHaveValue( + "Time framing", cc.error( "disabled" ), + false, isPrintGathered + ); + } +} + +function commonInitCheckAccessArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + ensureHaveValue( + "S-Chain node number(zero based)", + imaState.nNodeNumber, false, isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + ensureHaveValue( + "S-Chain nodes count", + imaState.nNodesCount, false, isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); +} + +function commonInitErcTokensArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + if( imaState.chainProperties.tc.strCoinNameErc20.length > 0 ) { + ensureHaveValue( + "Loaded Main-net ERC20 ABI ", + imaState.chainProperties.tc.strCoinNameErc20, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + ensureHaveValue( + "Loaded S-Chain ERC20 ABI ", + imaState.chainProperties.sc.strCoinNameErc20, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + ensureHaveValue( + "Amount of tokens to transfer", + imaState.nAmountOfToken, + false, isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + if( isPrintGathered ) { + log.write( + cc.info( "ERC20 explicit S-Chain address is " ) + + cc.attention( imaState.strAddrErc20Explicit ) + + "\n" ); + } + } + if( imaState.chainProperties.tc.strCoinNameErc20.length > 0 ) { + ensureHaveValue( + "Loaded S<->S Target S-Chain ERC20 ABI ", + imaState.chainProperties.tc.strCoinNameErc20, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + } + if( imaState.chainProperties.mn.strCoinNameErc721.length > 0 ) { + ensureHaveValue( + "Loaded Main-net ERC721 ABI ", + imaState.chainProperties.mn.strCoinNameErc721, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + ensureHaveValue( + "Loaded S-Chain ERC721 ABI ", + imaState.chainProperties.sc.strCoinNameErc721, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + ensureHaveValue( + "ERC721 token id ", + imaState.idToken, false, + isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + if( isPrintGathered ) { + log.write( + cc.info( "ERC721 explicit S-Chain address is " ) + + cc.attention( imaState.strAddrErc721Explicit ) + + "\n" ); + } + } + if( imaState.chainProperties.tc.strCoinNameErc721.length > 0 ) { + ensureHaveValue( + "Loaded S<->S Target S-Chain ERC721 ABI ", + imaState.chainProperties.tc.strCoinNameErc721, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + } + if( imaState.chainProperties.mn.strCoinNameErc1155.length > 0 ) { + ensureHaveValue( "Loaded Main-net ERC1155 ABI ", + imaState.chainProperties.mn.strCoinNameErc1155, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + ensureHaveValue( "Loaded S-Chain ERC1155 ABI ", + imaState.chainProperties.sc.strCoinNameErc1155, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + try { + ensureHaveValue( "ERC1155 token id ", + imaState.idToken, false, isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + ensureHaveValue( "ERC1155 token amount ", + imaState.nAmountOfToken, false, isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + } catch ( e1 ) { + try { + ensureHaveValue( + "ERC1155 batch of token ids ", + imaState.idTokens, false, + isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + ensureHaveValue( + "ERC1155 batch of token amounts ", + imaState.arrAmountsOfTokens, false, + isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + } catch ( e2 ) { + log.write( cc.warning( "Please check your params in ERC1155 transfer \n" ) ); + log.write( cc.warning( "Error 1" ) + cc.sunny( e1 ) + "\n" ); + log.write( cc.warning( "Error 2" ) + cc.sunny( e2 ) + "\n" ); + process.exit( 126 ); + } + } + if( isPrintGathered ) { + log.write( + cc.info( "ERC1155 explicit S-Chain address is " ) + + cc.attention( imaState.strAddrErc1155Explicit ) + + "\n" ); + } + } + if( imaState.chainProperties.tc.strCoinNameErc1155.length > 0 ) { + ensureHaveValue( + "Loaded S<->S Target S-Chain ERC1155 ABI ", + imaState.chainProperties.tc.strCoinNameErc1155, + false, isPrintGathered, null, ( x ) => { + return cc.attention( x ); + } ); + } +} + +function commonInitGasMultipliersAndTransactionArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + if( isPrintGathered ) { + log.write( + cc.info( "Main Net Gas Price Multiplier is" ) + + cc.debug( "....................." ) + + ( imaState.chainProperties.mn.transactionCustomizer.gasPriceMultiplier + ? cc.info( + imaState.chainProperties.mn.transactionCustomizer + .gasPriceMultiplier.toString() ) + : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "S-Chain Gas Price Multiplier is" ) + + cc.debug( "......................" ) + + ( imaState.chainProperties.sc.transactionCustomizer.gasPriceMultiplier + ? cc.info( + imaState.chainProperties.sc.transactionCustomizer + .gasPriceMultiplier.toString() ) + : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "Target S-Chain Gas Price Multiplier is" ) + + cc.debug( "..............." ) + + ( imaState.chainProperties.tc.transactionCustomizer.gasPriceMultiplier + ? cc.info( imaState.chainProperties.tc.transactionCustomizer + .gasPriceMultiplier.toString() ) + : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "Main Net Gas Value Multiplier is" ) + + cc.debug( "....................." ) + + ( imaState.chainProperties.mn.transactionCustomizer.gasMultiplier + ? cc.info( + imaState.chainProperties.mn + .transactionCustomizer.gasMultiplier.toString() ) + : cc.notice( "default" ) ) + + "\n" ); + log.write( + cc.info( "S-Chain Gas Value Multiplier is" ) + + cc.debug( "......................" ) + + ( imaState.chainProperties.sc.transactionCustomizer.gasMultiplier + ? cc.info( + imaState.chainProperties.sc + .transactionCustomizer.gasMultiplier.toString() ) + : cc.notice( "default" ) ) + + "\n" ); + log.write( + cc.info( "Target S-Chain Gas Value Multiplier is" ) + + cc.debug( "..............." ) + + ( imaState.chainProperties.tc.transactionCustomizer.gasMultiplier + ? cc.info( + imaState.chainProperties.tc + .transactionCustomizer.gasMultiplier.toString() ) + : cc.notice( "default" ) ) + + "\n" ); + log.write( + cc.info( "Pending work analysis(PWA) is" ) + + cc.debug( "........................" ) + + ( imaState.isPWA ? cc.success( "enabled" ) : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "Expose PWA details to log is" ) + + cc.debug( "........................." ) + + ( imaState.isPrintPWA ? cc.success( "enabled" ) : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "Oracle based gas reimbursement is" ) + + cc.debug( "...................." ) + + ( imaOracleOperations.getEnabledOracle() + ? cc.success( "enabled" ) : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "S-Chain to S-Chain transferring is" ) + + cc.debug( "..................." ) + + ( imaState.optsS2S.isEnabled + ? cc.success( "enabled" ) + : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "SKALE network re-discovery interval is" ) + + cc.debug( "..............." ) + + ( imaState.optsS2S.secondsToReDiscoverSkaleNetwork + ? cc.info( imaState.optsS2S.secondsToReDiscoverSkaleNetwork.toString() ) + : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "S<->S transfer mode is" ) + + cc.debug( "..............................." ) + + imaHelperAPIs.getS2STransferModeDescriptionColorized() + + "\n" ); + log.write( + cc.info( "IMA JSON RPC server port is" ) + + cc.debug( "...,,,,,,,,,,,............" ) + + ( ( imaState.nJsonRpcPort > 0 ) + ? cc.info( imaState.nJsonRpcPort ) + : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "Cross-IMA mode is" ) + + cc.debug( "...................................." ) + + ( imaState.isCrossImaBlsMode + ? cc.success( "enabled" ) + : cc.error( "disabled" ) ) + + "\n" ); + log.write( + cc.info( "Dry-run is enabled" ) + + cc.debug( "..................................." ) + + cc.yn( imaTx.dryRunIsEnabled() ) + + "\n" ); + log.write( + cc.info( "Dry-run execution result is ignored" ) + + cc.debug( ".................." ) + + cc.yn( imaTx.dryRunIsIgnored() ) + + "\n" ); + } +} + +function commonInitLoggingArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + if( imaState.strLogFilePath.length > 0 ) { + ensureHaveValue( + "Log file path", + imaState.strLogFilePath, false, + isPrintGathered, null, ( x ) => { + return cc.info( x ); + } ); + ensureHaveValue( + "Max size of log file path", + imaState.nLogMaxSizeBeforeRotation, false, + isPrintGathered, null, ( x ) => { + return ( x <= 0 ) ? cc.warning( "unlimited" ) : cc.note( x ); + } ); + ensureHaveValue( + "Max rotated count of log files", + imaState.nLogMaxFilesCount, + false, isPrintGathered, null, ( x ) => { + return ( x <= 1 ) ? cc.warning( "not set" ) : cc.note( x ); + } ); + } +} + +function commonInitAutomaticExitArgs() { + const imaState = state.get(); + const isPrintGathered = imaState.isPrintGathered ? true : false; + const isPrintSecurityValues = imaState.isPrintSecurityValues ? true : false; + ensureHaveValue( + "Automatic exit(seconds)", + imaState.nAutoExitAfterSeconds, false, + isPrintGathered && isPrintSecurityValues ); +} + +export function commonInit() { + const imaState = state.get(); + commonInitPrintSysInfo(); + commonInitCheckAbiPaths(); + commonInitCheckContractPresences(); + commonInitPrintFoundContracts(); + commonInitCheckErc20(); + commonInitCheckErc721(); + commonInitCheckErc1155(); + if( log.verboseGet() > log.verboseReversed().information || imaState.bShowConfigMode ) { + commonInitCheckGeneralArgs(); + commonInitCheckCredentialsArgs(); + commonInitCheckTransferAmountArgs(); + commonInitTransferringArgs(); + commonInitCheckAccessArgs(); + commonInitErcTokensArgs(); + commonInitGasMultipliersAndTransactionArgs(); + commonInitLoggingArgs(); + commonInitAutomaticExitArgs(); + } +} // commonInit + +export function imaInitEthersProviders() { + const imaState = state.get(); + if( imaState.chainProperties.mn.strURL && + typeof imaState.chainProperties.mn.strURL == "string" && + imaState.chainProperties.mn.strURL.length > 0 + ) { + const u = imaState.chainProperties.mn.strURL; + asyncCheckUrlAtStartup( u, "Main-net" ); + imaState.chainProperties.mn.ethersProvider = owaspUtils.getEthersProviderFromURL( u ); + } else { + log.write( + cc.warning( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Main-net" ) + + cc.warning( " URL specified in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + + "\n" + ); + } + + if( imaState.chainProperties.sc.strURL && + typeof imaState.chainProperties.sc.strURL == "string" && + imaState.chainProperties.sc.strURL.length > 0 + ) { + const u = imaState.chainProperties.sc.strURL; + asyncCheckUrlAtStartup( u, "S-Chain" ); + imaState.chainProperties.sc.ethersProvider = owaspUtils.getEthersProviderFromURL( u ); + } else { + log.write( + cc.warning( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S-Chain" ) + + cc.warning( " URL specified in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + + "\n" + ); + } + + if( imaState.chainProperties.tc.strURL && + typeof imaState.chainProperties.tc.strURL == "string" && + imaState.chainProperties.tc.strURL.length > 0 + ) { + const u = imaState.chainProperties.tc.strURL; + asyncCheckUrlAtStartup( u, "S<->S Target S-Chain" ); + imaState.chainProperties.tc.ethersProvider = owaspUtils.getEthersProviderFromURL( u ); + } else { + log.write( + cc.warning( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S<->S Target S-Chain" ) + + cc.warning( " URL specified in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + + "\n" + ); + } + +} // imaInitEthersProviders + +function initContractsIMA() { + const imaState = state.get(); + if( imaState.chainProperties.mn.bHaveAbiIMA ) { + const cp = imaState.chainProperties.mn; + const ep = cp.ethersProvider; + const joABI = cp.joAbiIMA; + imaState.joDepositBoxETH = + new owaspUtils.ethersMod.ethers.Contract( + joABI.deposit_box_eth_address, + joABI.deposit_box_eth_abi, + ep + ); // only main net + imaState.joDepositBoxERC20 = + new owaspUtils.ethersMod.ethers.Contract( + joABI.deposit_box_erc20_address, + joABI.deposit_box_erc20_abi, + ep + ); // only main net + imaState.joDepositBoxERC721 = + new owaspUtils.ethersMod.ethers.Contract( + joABI.deposit_box_erc721_address, + joABI.deposit_box_erc721_abi, + ep + ); // only main net + imaState.joDepositBoxERC1155 = + new owaspUtils.ethersMod.ethers.Contract( + joABI.deposit_box_erc1155_address, + joABI.deposit_box_erc1155_abi, + ep ) + ; // only main net + imaState.joDepositBoxERC721WithMetadata = + new owaspUtils.ethersMod.ethers.Contract( + joABI.deposit_box_erc721_with_metadata_address, + joABI.deposit_box_erc721_with_metadata_abi, + ep + ); // only main net + imaState.joCommunityPool = + new owaspUtils.ethersMod.ethers.Contract( + joABI.community_pool_address, + joABI.community_pool_abi, + ep + ); // only main net + imaState.joLinker = + new owaspUtils.ethersMod.ethers.Contract( + joABI.linker_address, joABI.linker_abi, ep ); // only main net + imaState.joMessageProxyMainNet = + new owaspUtils.ethersMod.ethers.Contract( + joABI.message_proxy_mainnet_address, joABI.message_proxy_mainnet_abi, ep ); + } + if( imaState.chainProperties.sc.bHaveAbiIMA ) { + const cp = imaState.chainProperties.sc; + const ep = cp.ethersProvider; + const joABI = cp.joAbiIMA; + imaState.joTokenManagerETH = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_eth_address, + joABI.token_manager_eth_abi, + ep ); // only s-chain + imaState.joTokenManagerERC20 = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc20_address, + joABI.token_manager_erc20_abi, + ep ); // only s-chain + imaState.joTokenManagerERC721 = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc721_address, + joABI.token_manager_erc721_abi, + ep ); // only s-chain + imaState.joTokenManagerERC1155 = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc1155_address, + joABI.token_manager_erc1155_abi, + ep ); // only s-chain + imaState.joTokenManagerERC721WithMetadata = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc721_with_metadata_address, + joABI.token_manager_erc721_with_metadata_abi, + ep ); // only s-chain + imaState.joCommunityLocker = + new owaspUtils.ethersMod.ethers.Contract( + joABI.community_locker_address, + joABI.community_locker_abi, + ep ); // only s-chain + imaState.joMessageProxySChain = + new owaspUtils.ethersMod.ethers.Contract( + joABI.message_proxy_chain_address, + joABI.message_proxy_chain_abi, + ep ); + imaState.joTokenManagerLinker = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_linker_address, + joABI.token_manager_linker_abi, + ep ); + imaState.joEthErc20 = + new owaspUtils.ethersMod.ethers.Contract( + joABI.eth_erc20_address, + joABI.eth_erc20_abi, + ep ); // only s-chain + } + if( imaState.chainProperties.tc.bHaveAbiIMA ) { + const cp = imaState.chainProperties.tc; + const ep = cp.ethersProvider; + const joABI = cp.joAbiIMA; + imaState.joTokenManagerETHTarget = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_eth_address, + joABI.token_manager_eth_abi, + ep ); // only s-chain + imaState.joTokenManagerERC20Target = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc20_address, + joABI.token_manager_erc20_abi, + ep ); // only s-chain + imaState.joTokenManagerERC721Target = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc721_address, + joABI.token_manager_erc721_abi, + ep ); // only s-chain + imaState.joTokenManagerERC1155Target = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc1155_address, + joABI.token_manager_erc1155_abi, + ep ); // only s-chain + imaState.joTokenManagerERC721WithMetadataTarget = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_erc721_with_metadata_address, + joABI.token_manager_erc721_with_metadata_abi, + ep ); // only s-chain + imaState.joCommunityLockerTarget = + new owaspUtils.ethersMod.ethers.Contract( + joABI.community_locker_address, + joABI.community_locker_abi, + ep ); // only s-chain + imaState.joMessageProxySChainTarget = + new owaspUtils.ethersMod.ethers.Contract( + joABI.message_proxy_chain_address, + joABI.message_proxy_chain_abi, + ep ); + imaState.joTokenManagerLinkerTarget = + new owaspUtils.ethersMod.ethers.Contract( + joABI.token_manager_linker_address, + joABI.token_manager_linker_abi, + ep ); + imaState.joEthErc20Target = + new owaspUtils.ethersMod.ethers.Contract( + joABI.eth_erc20_address, + joABI.eth_erc20_abi, + ep ); // only s-chain + } +} + +function initContractsSkaleManager() { + const imaState = state.get(); + if( imaState.bHaveSkaleManagerABI ) { + const cp = imaState.chainProperties.mn; + const ep = cp.ethersProvider; + const joABI = imaState.joAbiSkaleManager; + imaState.joConstantsHolder = + new owaspUtils.ethersMod.ethers.Contract( + joABI.constants_holder_address, + joABI.constants_holder_abi, + ep ); + imaState.joNodes = + new owaspUtils.ethersMod.ethers.Contract( + joABI.nodes_address, + joABI.nodes_abi, + ep ); + imaState.joKeyStorage = + new owaspUtils.ethersMod.ethers.Contract( + joABI.key_storage_address, + joABI.key_storage_abi, + ep ); + imaState.joSChains = + new owaspUtils.ethersMod.ethers.Contract( + joABI.schains_address, + joABI.schains_abi, + ep ); + imaState.joSChainsInternal = + new owaspUtils.ethersMod.ethers.Contract( + joABI.schains_internal_address, + joABI.schains_internal_abi, + ep ); + imaState.joSkaleDKG = + new owaspUtils.ethersMod.ethers.Contract( + joABI.skale_d_k_g_address, + joABI.skale_d_k_g_abi, + ep ); + imaState.joSkaleManager = + new owaspUtils.ethersMod.ethers.Contract( + joABI.skale_manager_address, + joABI.skale_manager_abi, + ep ); + imaState.joSkaleToken = + new owaspUtils.ethersMod.ethers.Contract( + joABI.skale_token_address, + joABI.skale_token_abi, + ep ); + imaState.joValidatorService = + new owaspUtils.ethersMod.ethers.Contract( + joABI.validator_service_address, + joABI.validator_service_abi, + ep ); + imaState.joWallets = + new owaspUtils.ethersMod.ethers.Contract( + joABI.wallets_address, + joABI.wallets_abi, + ep ); + } +} + +export function initContracts() { + imaInitEthersProviders(); + initContractsIMA(); + initContractsSkaleManager(); +} diff --git a/agent/clpTools.mjs b/agent/clpTools.mjs new file mode 100644 index 000000000..3f2dd7bb3 --- /dev/null +++ b/agent/clpTools.mjs @@ -0,0 +1,1883 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file clpTools.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as imaCLI from "./cli.mjs"; +import * as rpcCall from "./rpcCall.mjs"; +import * as state from "./state.mjs"; +import * as IMA from "../npms/skale-ima/index.mjs"; +import * as imaHelperAPIs from "../npms/skale-ima/imaHelperAPIs.mjs"; +import * as imaGasUsage from "../npms/skale-ima/imaGasUsageOperations.mjs"; +import * as imaReimbursement from "../npms/skale-ima/imaReimbursementOperations.mjs"; +import * as imaReg from "../npms/skale-ima/imaRegistrationOperations.mjs"; +import * as imaEth from "../npms/skale-ima/imaEthOperations.mjs"; +import * as imaToken from "../npms/skale-ima/imaTokenOperations.mjs"; +import * as skaleObserver from "../npms/skale-observer/observer.mjs"; +import * as discoveryTools from "./discoveryTools.mjs"; +import * as loop from "./loop.mjs"; +import * as imaUtils from "./utils.mjs"; +import * as imaBLS from "./bls.mjs"; + +export async function registerAll( isPrintSummaryRegistrationCosts ) { + if( !await registerStep1( false ) ) + return false; + if( isPrintSummaryRegistrationCosts ) + printSummaryRegistrationCosts(); + return true; +} + +export async function checkRegistrationAll() { + const b1 = await checkRegistrationStep1(); + return b1; +} + +const gInfoRegistrationCost = { + mn: [], + sc: [] +}; + +export async function registerStep1( isPrintSummaryRegistrationCosts ) { + const imaState = state.get(); + imaCLI.initContracts(); + const strLogPrefix = cc.info( "Reg 1:" ) + " "; + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( strLogPrefix + cc.debug( "Will check chain registration now..." ) + "\n" ); + let bSuccess = await imaReg.checkIsRegisteredSChainInDepositBoxes( // step 1 + imaState.chainProperties.mn.ethersProvider, + imaState.joLinker, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.strChainName + ); + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + cc.debug( "Chain is " ) + + ( bSuccess ? cc.success( "already registered" ) : cc.warning( "not registered yet" ) ) + + "\n" ); + } + if( bSuccess ) + return true; + const jarrReceipts = + await imaReg.registerSChainInDepositBoxes( // step 1 + imaState.chainProperties.mn.ethersProvider, + imaState.joLinker, + imaState.chainProperties.mn.joAccount, + imaState.joTokenManagerETH, // only s-chain + imaState.joTokenManagerERC20, // only s-chain + imaState.joTokenManagerERC721, // only s-chain + imaState.joTokenManagerERC1155, // only s-chain + imaState.joTokenManagerERC721WithMetadata, // only s-chain + imaState.joCommunityLocker, // only s-chain + imaState.joTokenManagerLinker, // only s-chain + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.transactionCustomizer //, + ); + bSuccess = ( jarrReceipts != null && jarrReceipts.length > 0 ) ? true : false; + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + cc.debug( "Chain was " ) + + ( bSuccess ? cc.success( "registered successfully" ) : cc.error( "not registered" ) ) + + "\n" ); + } + if( bSuccess ) { + gInfoRegistrationCost.mn = + gInfoRegistrationCost.mn.concat( gInfoRegistrationCost.mn, jarrReceipts ); + } + if( isPrintSummaryRegistrationCosts ) + clpTools.printSummaryRegistrationCosts(); + if( !bSuccess ) { + const nRetCode = 163; + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( strLogPrefix + cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( " failed to register S-Chain in deposit box, will return code " ) + + cc.warning( nRetCode ) + "\n" ); + } + process.exit( nRetCode ); + } + return true; +} + +export async function checkRegistrationStep1() { + const imaState = state.get(); + imaCLI.initContracts(); + const bRetVal = await imaReg.checkIsRegisteredSChainInDepositBoxes( // step 1 + imaState.chainProperties.mn.ethersProvider, + imaState.joLinker, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.strChainName + ); + return bRetVal; +} + +export function printSummaryRegistrationCosts( details ) { + imaGasUsage.printGasUsageReportFromArray( + "Main Net REGISTRATION", gInfoRegistrationCost.mn, details ); + imaGasUsage.printGasUsageReportFromArray( + "S-Chain REGISTRATION", gInfoRegistrationCost.sc, details ); +} + +export function commandLineTaskRegister() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Full registration(all steps)", + "fn": async function() { + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // registerAll + return await registerAll( true ); + } + } ); +} + +export function commandLineTaskRegister1() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Registration step 1, register S-Chain in deposit box", + "fn": async function() { + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // registerStep1 + return await registerStep1( true ); + } + } ); +} + +export function commandLineTaskCheckRegistration() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Full registration status check(all steps)", + "fn": async function() { + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // checkRegistrationAll + const b = await checkRegistrationAll(); + // nExitCode is: 0 - OKay - registered; non-zero - not registered or error + const nExitCode = b ? 0 : 150; + log.write( cc.notice( "Exiting with code " ) + cc.info( nExitCode ) + "\n" ); + process.exit( nExitCode ); + } + } ); +} + +export function commandLineTaskCheckRegistration1() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Registration status check step 1, register S-Chain in deposit box", + "fn": async function() { + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // checkRegistrationStep1 + const b = await checkRegistrationStep1(); + // nExitCode is: 0 - OKay - registered; non-zero - not registered or error + const nExitCode = b ? 0 : 152; + log.write( cc.notice( "Exiting with code " ) + cc.info( nExitCode ) + "\n" ); + process.exit( nExitCode ); + } + } ); +} + +export function commandLineTaskMintErc20() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "mint ERC20", + "fn": async function() { + let bMintIsOK = false; + if( imaState.chainProperties.tc.strCoinNameErc20.length > 0 ) { + try { + const strAddressMintTo = // same as caller/transaction signer + imaState.chainProperties.tc.joAccount.address(); + bMintIsOK = + await imaToken.mintErc20( + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.strChainName, + imaState.chainProperties.tc.joAccount, + strAddressMintTo, + imaState.nAmountOfToken, + imaState.chainProperties.tc.joErc20[imaState.chainProperties + .tc.strCoinNameErc20 + "_address"], + imaState.chainProperties.tc.joErc20[imaState.chainProperties + .tc.strCoinNameErc20 + "_abi"], + imaState.chainProperties.tc.transactionCustomizer + ) ? true : false; + } catch ( err ) { + bMintIsOK = false; + } + } + return bMintIsOK; + } + } ); +} + +export function commandLineTaskMintErc721() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "mint ERC721", + "fn": async function() { + let bMintIsOK = false; + if( imaState.chainProperties.tc.strCoinNameErc721.length > 0 ) { + try { + const strAddressMintTo = // same as caller/transaction signer + imaState.chainProperties.tc.joAccount.address(); + const idTokens = imaState.haveArrayOfTokenIdentifiers ? imaState.idTokens : []; + if( imaState.haveOneTokenIdentifier ) + idTokens.push( imaState.idToken ); + if( idTokens.length > 0 ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + bMintIsOK = + await imaToken.mintErc721( + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.strChainName, + imaState.chainProperties.tc.joAccount, + strAddressMintTo, + idToken, + imaState.chainProperties.tc.joErc721[imaState + .chainProperties.tc.strCoinNameErc721 + "_address"], + imaState.chainProperties.tc.joErc721[imaState + .chainProperties.tc.strCoinNameErc721 + "_abi"], + imaState.chainProperties.tc.transactionCustomizer + ) ? true : false; + } + } + } catch ( err ) { + bMintIsOK = false; + } + } + return bMintIsOK; + } + } ); +} + +export function commandLineTaskMintErc1155() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "mint ERC1155", + "fn": async function() { + let bMintIsOK = false; + if( imaState.chainProperties.tc.strCoinNameErc1155.length > 0 ) { + try { + const strAddressMintTo = // same as caller/transaction signer + imaState.chainProperties.tc.joAccount.address(); + const idTokens = imaState.haveArrayOfTokenIdentifiers ? imaState.idTokens : []; + if( imaState.haveOneTokenIdentifier ) + idTokens.push( imaState.idToken ); + if( idTokens.length > 0 ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + bMintIsOK = + await imaToken.mintErc1155( + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.strChainName, + imaState.chainProperties.tc.joAccount, + strAddressMintTo, + idToken, + imaState.nAmountOfToken, + imaState.chainProperties.tc + .joErc1155[imaState.chainProperties.tc + .strCoinNameErc1155 + "_address"], + imaState.chainProperties.tc + .joErc1155[imaState.chainProperties.tc + .strCoinNameErc1155 + "_abi"], + imaState.chainProperties.tc.transactionCustomizer + ) ? true : false; + } + } + } catch ( err ) { + bMintIsOK = false; + } + } + return bMintIsOK; + } + } ); +} + +export function commandLineTaskBurnErc20() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "burn ERC20", + "fn": async function() { + let bBurnIsOK = false; + if( imaState.chainProperties.tc.strCoinNameErc20.length > 0 ) { + try { + const strAddressBurnFrom = // same as caller/transaction signer + imaState.chainProperties.tc.joAccount.address(); + bBurnIsOK = + await imaToken.burnErc20( + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.strChainName, + imaState.chainProperties.tc.joAccount, + strAddressBurnFrom, + imaState.nAmountOfToken, + imaState.chainProperties.tc + .joErc20[imaState.chainProperties + .tc.strCoinNameErc20 + "_address"], + imaState.chainProperties.tc + .joErc20[imaState.chainProperties + .tc.strCoinNameErc20 + "_abi"], + imaState.chainProperties.tc.transactionCustomizer + ) ? true : false; + } catch ( err ) { + bBurnIsOK = false; + } + } + return bBurnIsOK; + } + } ); +} + +export function commandLineTaskBurnErc721() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "burn ERC721", + "fn": async function() { + let bBurnIsOK = false; + if( imaState.chainProperties.tc.strCoinNameErc721.length > 0 ) { + try { + const idTokens = imaState.haveArrayOfTokenIdentifiers ? imaState.idTokens : []; + if( imaState.haveOneTokenIdentifier ) + idTokens.push( imaState.idToken ); + if( idTokens.length > 0 ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + bBurnIsOK = + await imaToken.burnErc721( + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.strChainName, + imaState.chainProperties.tc.joAccount, + idToken, + imaState.chainProperties.tc + .joErc721[imaState.chainProperties + .tc.strCoinNameErc721 + "_address"], + imaState.chainProperties.tc + .oErc721[imaState.chainProperties + .tc.strCoinNameErc721 + "_abi"], + imaState.chainProperties.tc.transactionCustomizer + ) ? true : false; + } + } + } catch ( err ) { + bBurnIsOK = false; + } + } + return bBurnIsOK; + } + } ); +} + +export function commandLineTaskBurnErc1155() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "burn ERC1155", + "fn": async function() { + let bBurnIsOK = false; + if( imaState.chainProperties.tc.strCoinNameErc1155.length > 0 ) { + try { + const strAddressBurnFrom = // same as caller/transaction signer + imaState.chainProperties.tc.joAccount.address(); + const idTokens = imaState.haveArrayOfTokenIdentifiers ? imaState.idTokens : []; + if( imaState.haveOneTokenIdentifier ) + idTokens.push( imaState.idToken ); + if( idTokens.length > 0 ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + bBurnIsOK = + await imaToken.burnErc1155( + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.strChainName, + imaState.chainProperties.tc.joAccount, + strAddressBurnFrom, + idToken, + imaState.nAmountOfToken, + imaState.chainProperties.tc + .joErc1155[imaState.chainProperties + .tc.strCoinNameErc1155 + "_address"], + imaState.chainProperties.tc + .joErc1155[imaState.chainProperties + .tc.strCoinNameErc1155 + "_abi"], + imaState.chainProperties.tc.transactionCustomizer + ) ? true : false; + } + } + } catch ( err ) { + bBurnIsOK = false; + } + } + return bBurnIsOK; + } + } ); +} + +export async function commandLineTaskShowBalanceEth( + arrBalancesMN, arrBalancesSC, arrBalancesTC +) { + const imaState = state.get(); + let assetAddress = null; + if( imaState.chainProperties.mn.ethersProvider ) { + arrBalancesMN.push( { + "assetName": "RealETH", + "balance": await imaEth.getBalanceEth( true, // isMainNet + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.mn.chainId, imaState.chainProperties.mn.joAccount ) + } ); + arrBalancesMN.push( { + "assetName": "CanReceiveETH", + "balance": await imaEth.viewEthPaymentFromSchainOnMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.mn.joAccount, imaState.joDepositBoxETH ) + } ); + } + try { + assetAddress = imaState.joEthErc20.address; + } catch ( err ) { + assetAddress = null; + } + if( imaState.chainProperties.sc.ethersProvider ) { + arrBalancesSC.push( { + "assetName": "S-Chain Real ETH as ERC20", + "assetAddress": assetAddress, + "balance": await imaEth.getBalanceEth( false, // isMainNet + imaState.chainProperties.sc.ethersProvider, imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, imaState.joEthErc20 ) + } ); + arrBalancesSC.push( { + "assetName": "S-Chain ETH Fuel", + "balance": await imaEth.getBalanceEth( true, // isMainNet=true here, but we call S-Chain + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.sc.chainId, imaState.chainProperties.sc.joAccount ) + } ); + } + if( imaState.chainProperties.tc.ethersProvider ) { + arrBalancesSC.push( { + "assetName": "Target S-Chain Real ETH as ERC20", + "assetAddress": assetAddress, + "balance": await imaEth.getBalanceEth( false, // isMainNet + imaState.chainProperties.tc.ethersProvider, imaState.chainProperties.sc.chainId, + imaState.chainProperties.tc.joAccount, imaState.joEthErc20 ) + } ); + arrBalancesTC.push( { + "assetName": "Target S-Chain ETH Fuel", + "balance": await imaEth.getBalanceEth( true, // isMainNet=true here, but we call S-Chain + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, imaState.chainProperties.tc.joAccount ) + } ); + } +} + +export async function commandLineTaskShowBalanceErc20( + arrBalancesMN, arrBalancesSC, arrBalancesTC +) { + const imaState = state.get(); + let assetAddress = null; + if( imaState.chainProperties.mn.ethersProvider && + imaState.chainProperties.mn.strCoinNameErc20.length > 0 + ) { + try { + assetAddress = imaState.chainProperties.mn.joErc20[ + imaState.chainProperties.mn.strCoinNameErc20 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesMN.push( { + "assetName": "ERC20", + "assetAddress": assetAddress, + "balance": await imaToken.getBalanceErc20( true, // isMainNet + imaState.chainProperties.mn.ethersProvider, imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.mn.strCoinNameErc20, + imaState.chainProperties.mn.joErc20 ) + } ); + } + if( imaState.chainProperties.sc.ethersProvider && + imaState.chainProperties.sc.strCoinNameErc20.length > 0 + ) { + try { + assetAddress = imaState.chainProperties.sc.joErc20[ + imaState.chainProperties.sc.strCoinNameErc20 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesSC.push( { + "assetName": "ERC20", + "assetAddress": assetAddress, + "balance": await imaToken.getBalanceErc20( false, // isMainNet + imaState.chainProperties.sc.ethersProvider, imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.sc.strCoinNameErc20, + imaState.chainProperties.sc.joErc20 ) + } ); + } + if( imaState.chainProperties.tc.ethersProvider && + imaState.chainProperties.tc.strCoinNameErc20.length > 0 + ) { + try { + assetAddress = imaState.chainProperties.tc.joErc20[ + imaState.chainProperties.tc.strCoinNameErc20 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesTC.push( { + "assetName": "ERC20", + "assetAddress": assetAddress, + "balance": await imaToken.getBalanceErc20( true, // isMainNet + imaState.chainProperties.tc.ethersProvider, imaState.chainProperties.mn.chainId, + imaState.chainProperties.tc.joAccount, + imaState.chainProperties.tc.strCoinNameErc20, + imaState.chainProperties.tc.joErc20 ) + } ); + } +} + +export async function commandLineTaskShowBalanceErc721( + arrBalancesMN, arrBalancesSC, arrBalancesTC, idTokens +) { + const imaState = state.get(); + let assetAddress = null; + if( imaState.chainProperties.mn.ethersProvider && + imaState.chainProperties.mn.strCoinNameErc721.length > 0 + ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + try { + assetAddress = imaState.chainProperties.mn.joErc721[ + imaState.chainProperties.mn.strCoinNameErc721 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesMN.push( { + "assetName": "ERC721", + "assetAddress": assetAddress, + "idToken": idToken, + "owner": await imaToken.getOwnerOfErc721( true, // isMainNet + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.mn.strCoinNameErc721, + imaState.chainProperties.mn.joErc721, idToken ) + } ); + } + } + if( imaState.chainProperties.sc.ethersProvider && + imaState.chainProperties.sc.strCoinNameErc721.length > 0 + ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + try { + assetAddress = imaState.chainProperties.sc.joErc721[ + imaState.chainProperties.sc.strCoinNameErc721 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesSC.push( { + "assetName": "ERC721", + "assetAddress": assetAddress, + "idToken": idToken, + "owner": await imaToken.getOwnerOfErc721( false, // isMainNet + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.sc.strCoinNameErc721, + imaState.chainProperties.sc.joErc721, idToken ) + } ); + } + } + if( imaState.chainProperties.tc.ethersProvider && + imaState.chainProperties.tc.strCoinNameErc721.length > 0 + ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + try { + assetAddress = imaState.chainProperties.tc.joErc721[ + imaState.chainProperties.tc.strCoinNameErc721 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesTC.push( { + "assetName": "ERC721", + "assetAddress": assetAddress, + "idToken": idToken, + "owner": await imaToken.getOwnerOfErc721( false, // isMainNet + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.joAccount, + imaState.chainProperties.tc.strCoinNameErc721, + imaState.chainProperties.tc.joErc721, idToken ) + } ); + } + } +} + +export async function commandLineTaskShowBalanceErc1155( + arrBalancesMN, arrBalancesSC, arrBalancesTC, idTokens +) { + const imaState = state.get(); + let assetAddress = null; + if( imaState.chainProperties.mn.ethersProvider && + imaState.chainProperties.mn.strCoinNameErc1155.length > 0 + ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + try { + assetAddress = imaState.chainProperties.mn.joErc1155[ + imaState.chainProperties.mn.strCoinNameErc1155 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesMN.push( { + "assetName": "ERC1155", + "assetAddress": assetAddress, + "idToken": idToken, + "balance": await imaToken.getBalanceErc1155( true, // isMainNet + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.mn.strCoinNameErc1155, + imaState.chainProperties.mn.joErc1155, idToken ) + } ); + } + } + if( imaState.chainProperties.sc.ethersProvider && + imaState.chainProperties.sc.strCoinNameErc1155.length > 0 + ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + try { + assetAddress = imaState.chainProperties.sc.joErc1155[ + imaState.chainProperties.sc.strCoinNameErc1155 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesSC.push( { + "assetName": "ERC1155", + "assetAddress": assetAddress, + "idToken": idToken, + "balance": await imaToken.getBalanceErc1155( false, // isMainNet + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.sc.strCoinNameErc1155, + imaState.chainProperties.sc.joErc1155, idToken ) + } ); + } + } + if( imaState.chainProperties.tc.ethersProvider && + imaState.chainProperties.tc.strCoinNameErc1155.length > 0 + ) { + for( let i = 0; i < idTokens.length; ++ i ) { + const idToken = idTokens[i]; + try { + assetAddress = imaState.chainProperties.tc.joErc1155[ + imaState.chainProperties.tc.strCoinNameErc1155 + "_address"]; + } catch ( err ) { assetAddress = null; } + arrBalancesTC.push( { + "assetName": "ERC1155", + "assetAddress": assetAddress, + "idToken": idToken, + "balance": await imaToken.getBalanceErc1155( false, // isMainNet + imaState.chainProperties.tc.ethersProvider, + imaState.chainProperties.tc.chainId, + imaState.chainProperties.tc.joAccount, + imaState.chainProperties.tc.strCoinNameErc1155, + imaState.chainProperties.tc.joErc1155, idToken ) + } ); + } + } +} + +export function commandLineTaskShowBalance() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "show balance", + "fn": async function() { + const arrBalancesMN = [], arrBalancesSC = [], arrBalancesTC = []; + await commandLineTaskShowBalanceEth( + arrBalancesMN, arrBalancesSC, arrBalancesTC ); + await commandLineTaskShowBalanceErc20( + arrBalancesMN, arrBalancesSC, arrBalancesTC ); + const idTokens = imaState.haveArrayOfTokenIdentifiers ? imaState.idTokens : []; + if( imaState.haveOneTokenIdentifier ) + idTokens.push( imaState.idToken ); + if( idTokens.length > 0 ) { + await commandLineTaskShowBalanceErc721( + arrBalancesMN, arrBalancesSC, arrBalancesTC, idTokens ); + await commandLineTaskShowBalanceErc1155( + arrBalancesMN, arrBalancesSC, arrBalancesTC, idTokens ); + } + if( arrBalancesMN.length > 0 || arrBalancesSC.length > 0 || arrBalancesTC.length > 0 ) { + if( arrBalancesMN.length > 0 ) { + const strAddress = imaState.chainProperties.mn.joAccount.address(); + log.write( cc.sunny( "Main Net" ) + " " + + cc.bright( arrBalancesMN.length > 1 ? "balances" : "balance" ) + + cc.bright( " of " ) + cc.notice( strAddress ) + cc.bright( ":" ) + "\n" ); + for( let i = 0; i < arrBalancesMN.length; ++ i ) { + const bi = arrBalancesMN[i]; + log.write( " " + discoveryTools.formatBalanceInfo( bi, strAddress ) + + "\n" ); + } + } + if( arrBalancesSC.length > 0 ) { + const strAddress = imaState.chainProperties.sc.joAccount.address(); + log.write( cc.sunny( "S-Chain" ) + " " + + cc.bright( arrBalancesMN.length > 1 ? "balances" : "balance" ) + + cc.bright( " of " ) + cc.notice( strAddress ) + cc.bright( ":" ) + "\n" ); + for( let i = 0; i < arrBalancesSC.length; ++ i ) { + const bi = arrBalancesSC[i]; + log.write( " " + discoveryTools.formatBalanceInfo( bi, strAddress ) + + "\n" ); + } + } + if( arrBalancesTC.length > 0 ) { + const strAddress = imaState.chainProperties.mn.joAccount.address(); + log.write( cc.sunny( "Target S-Chain" ) + " " + + cc.bright( arrBalancesTC.length > 1 ? "balances" : "balance" ) + + cc.bright( " of " ) + cc.notice( strAddress ) + cc.bright( ":" ) + "\n" ); + for( let i = 0; i < arrBalancesTC.length; ++ i ) { + const bi = arrBalancesTC[i]; + log.write( " " + discoveryTools.formatBalanceInfo( bi, strAddress ) + + "\n" ); + } + } + } else + log.write( cc.warning( "No balances to scan." ) ); + return true; + } + } ); +} + +export function commandLineTaskPaymentM2S() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "one M->S single payment", + "fn": async function() { + if( imaState.chainProperties.mn.strCoinNameErc721.length > 0 ) { + // ERC721 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one M->S single ERC721 payment: " ) + + cc.sunny( imaState.idToken ) + "\n" ); + } + return await imaToken.doErc721PaymentFromMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.joAccount, + imaState.isWithMetadata721 + ? imaState.joDepositBoxERC721WithMetadata + : imaState.joDepositBoxERC721, // only main net + imaState.joMessageProxyMainNet, // for checking logs + imaState.chainProperties.sc.strChainName, + imaState.idToken, // which ERC721 token id to send + imaState.nAmountOfWei, // how much to send + imaState.isWithMetadata721 + ? imaState.joTokenManagerERC721WithMetadata + : imaState.joTokenManagerERC721, // only s-chain + imaState.chainProperties.mn.strCoinNameErc721, + imaState.chainProperties.mn.joErc721, + imaState.chainProperties.sc.strCoinNameErc721, + imaState.chainProperties.sc.joErc721, + imaState.chainProperties.mn.transactionCustomizer + ); + } + if( imaState.chainProperties.tc.strCoinNameErc20.length > 0 ) { + // ERC20 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one M->S single ERC20 payment: " ) + + cc.sunny( imaState.nAmountOfToken ) + "\n" ); + } + return await imaToken.doErc20PaymentFromMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.joAccount, + imaState.joDepositBoxERC20, // only main net + imaState.joMessageProxyMainNet, // for checking logs + imaState.chainProperties.sc.strChainName, + imaState.nAmountOfToken, // how much ERC20 tokens to send + imaState.nAmountOfWei, // how much to send + imaState.joTokenManagerERC20, // only s-chain + imaState.chainProperties.tc.strCoinNameErc20, + imaState.chainProperties.mn.joErc20, + imaState.chainProperties.sc.strCoinNameErc20, + imaState.chainProperties.sc.joErc20, + imaState.chainProperties.mn.transactionCustomizer + ); + } + if( + imaState.chainProperties.mn.strCoinNameErc1155.length > 0 && + imaState.idToken && + imaState.idToken !== null && + imaState.idToken !== undefined && + imaState.nAmountOfToken && + imaState.nAmountOfToken !== null && + imaState.nAmountOfToken !== undefined && + ( ( !imaState.idTokens ) || + imaState.idTokens === null || + imaState.idTokens === undefined ) && + ( ( !imaState.arrAmountsOfTokens ) || + imaState.arrAmountsOfTokens === null || + imaState.arrAmountsOfTokens === undefined ) + ) { + // ERC1155 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one M->S single ERC1155 payment: " ) + + cc.sunny( imaState.idToken ) + " " + + cc.sunny( imaState.nAmountOfToken ) + "\n" ); + } + return await imaToken.doErc1155PaymentFromMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.joAccount, + imaState.joDepositBoxERC1155, // only main net + imaState.joMessageProxyMainNet, // for checking logs + imaState.chainProperties.sc.strChainName, + imaState.idToken, // which ERC1155 token id to send + imaState.nAmountOfToken, // which ERC1155 token amount to send + imaState.nAmountOfWei, // how much to send + imaState.joTokenManagerERC1155, // only s-chain + imaState.chainProperties.mn.strCoinNameErc1155, + imaState.chainProperties.mn.joErc1155, + imaState.chainProperties.sc.strCoinNameErc1155, + imaState.chainProperties.sc.joErc1155, + imaState.chainProperties.mn.transactionCustomizer + ); + } + if( + imaState.chainProperties.mn.strCoinNameErc1155.length > 0 && + imaState.idTokens && + imaState.idTokens !== null && + imaState.idTokens !== undefined && + imaState.arrAmountsOfTokens && + imaState.arrAmountsOfTokens !== null && + imaState.arrAmountsOfTokens !== undefined && + ( !imaState.idToken || + imaState.idToken === null || + imaState.idToken === undefined ) && + ( !imaState.nAmountOfToken || + imaState.nAmountOfToken === null || + imaState.nAmountOfToken === undefined ) + ) { + // ERC1155 Batch payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one M->S single ERC1155 Batch payment: " ) + + cc.sunny( imaState.idTokens ) + " " + + cc.sunny( imaState.arrAmountsOfTokens ) + "\n" ); + } + return await imaToken.doErc1155BatchPaymentFromMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.joAccount, + imaState.joDepositBoxERC1155, // only main net + imaState.joMessageProxyMainNet, // for checking logs + imaState.chainProperties.sc.strChainName, + imaState.idTokens, // which ERC1155 token id to send + imaState.arrAmountsOfTokens, // which ERC1155 token amount to send + imaState.nAmountOfWei, // how much to send + imaState.joTokenManagerERC1155, // only s-chain + imaState.chainProperties.mn.strCoinNameErc1155, + imaState.chainProperties.mn.joErc1155, + imaState.chainProperties.sc.strCoinNameErc1155, + imaState.chainProperties.sc.joErc1155, + imaState.chainProperties.mn.transactionCustomizer + ); + } + // ETH payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one M->S single ETH payment: " ) + + cc.sunny( imaState.nAmountOfWei ) + "\n" ); + } + return await imaEth.doEthPaymentFromMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.joAccount, + imaState.joDepositBoxETH, // only main net + imaState.joMessageProxyMainNet, // for checking logs + imaState.chainProperties.sc.strChainName, + imaState.nAmountOfWei, // how much WEI money to send + imaState.chainProperties.mn.transactionCustomizer + ); + } + } ); +} + +export function commandLineTaskPaymentS2M() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "one S->M single payment", + "fn": async function() { + if( imaState.chainProperties.sc.strCoinNameErc721.length > 0 ) { + // ERC721 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->M single ERC721 payment: " ) + + cc.sunny( imaState.idToken ) + "\n" ); + } + return await imaToken.doErc721PaymentFromSChain( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.joAccount, + imaState.isWithMetadata721 + ? imaState.joTokenManagerERC721WithMetadata + : imaState.joTokenManagerERC721, // only s-chain + imaState.joMessageProxySChain, // for checking logs + imaState.isWithMetadata721 + ? imaState.joDepositBoxERC721WithMetadata + : imaState.joDepositBoxERC721, // only main net + imaState.idToken, // which ERC721 token id to send + imaState.nAmountOfWei, // how much to send + imaState.chainProperties.mn.strCoinNameErc721, + imaState.chainProperties.mn.joErc721, + imaState.chainProperties.sc.strCoinNameErc721, + imaState.chainProperties.sc.joErc721, + imaState.chainProperties.sc.transactionCustomizer + ); + } + if( imaState.chainProperties.sc.strCoinNameErc20.length > 0 ) { + // ERC20 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->M single ERC20 payment: " ) + + cc.sunny( imaState.nAmountOfToken ) + "\n" ); + } + return await imaToken.doErc20PaymentFromSChain( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.joAccount, + imaState.joTokenManagerERC20, // only s-chain + imaState.joMessageProxySChain, // for checking logs + imaState.joDepositBoxERC20, // only main net + imaState.nAmountOfToken, // how ERC20 tokens money to send + imaState.nAmountOfWei, // how much to send + imaState.chainProperties.tc.strCoinNameErc20, + imaState.chainProperties.mn.joErc20, + imaState.chainProperties.sc.strCoinNameErc20, + imaState.chainProperties.sc.joErc20, + imaState.chainProperties.sc.transactionCustomizer + ); + } + if( + imaState.chainProperties.sc.strCoinNameErc1155.length > 0 && + imaState.idToken && + imaState.idToken !== null && + imaState.idToken !== undefined && + imaState.nAmountOfToken && + imaState.nAmountOfToken !== null && + imaState.nAmountOfToken !== undefined && + ( ( !imaState.idTokens ) || + imaState.idTokens === null || + imaState.idTokens === undefined ) && + ( ( !imaState.arrAmountsOfTokens ) || + imaState.arrAmountsOfTokens === null || + imaState.arrAmountsOfTokens === undefined ) + ) { + // ERC1155 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->M single ERC1155 payment: " ) + + cc.sunny( imaState.idToken ) + " " + + cc.sunny( imaState.nAmountOfToken ) + "\n" ); + } + return await imaToken.doErc1155PaymentFromSChain( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.joAccount, + imaState.joTokenManagerERC1155, // only s-chain + imaState.joMessageProxySChain, // for checking logs + imaState.joDepositBoxERC1155, // only main net + imaState.idToken, // which ERC1155 token id to send + imaState.nAmountOfToken, // which ERC1155 token amount to send + imaState.nAmountOfWei, // how much to send + imaState.chainProperties.mn.strCoinNameErc1155, + imaState.chainProperties.mn.joErc1155, + imaState.chainProperties.sc.strCoinNameErc1155, + imaState.chainProperties.sc.joErc1155, + imaState.chainProperties.sc.transactionCustomizer + ); + } + if( + imaState.chainProperties.sc.strCoinNameErc1155.length > 0 && + imaState.idTokens && + imaState.idTokens !== null && + imaState.idTokens !== undefined && + imaState.arrAmountsOfTokens && + imaState.arrAmountsOfTokens !== null && + imaState.arrAmountsOfTokens !== undefined && + ( !imaState.idToken || + imaState.idToken === null || + imaState.idToken === undefined ) && + ( !imaState.nAmountOfToken || + imaState.nAmountOfToken === null || + imaState.nAmountOfToken === undefined ) + ) { + // ERC1155 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->M single ERC1155 payment: " ) + + cc.sunny( imaState.idTokens ) + " " + + cc.sunny( imaState.arrAmountsOfTokens ) + "\n" ); + } + return await imaToken.doErc1155BatchPaymentFromSChain( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.joAccount, + imaState.joTokenManagerERC1155, // only s-chain + imaState.joMessageProxySChain, // for checking logs + imaState.joDepositBoxERC1155, // only main net + imaState.idTokens, // which ERC1155 token id to send + imaState.arrAmountsOfTokens, // which ERC1155 token amount to send + imaState.nAmountOfWei, // how much to send + imaState.chainProperties.mn.strCoinNameErc1155, + imaState.chainProperties.mn.joErc1155, + imaState.chainProperties.sc.strCoinNameErc1155, + imaState.chainProperties.sc.joErc1155, + imaState.chainProperties.sc.transactionCustomizer + ); + } + // ETH payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->M single ETH payment: " ) + + cc.sunny( imaState.nAmountOfWei ) + "\n" ); + } + return await imaEth.doEthPaymentFromSChain( + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.joAccount, + imaState.joTokenManagerETH, // only s-chain + imaState.joMessageProxySChain, // for checking logs + imaState.nAmountOfWei, // how much WEI money to send + imaState.chainProperties.sc.transactionCustomizer + ); + } + } ); +} + +export function commandLineTaskPaymentS2S() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "one S->S single payment", + "fn": async function() { + const isForward = imaHelperAPIs.isForwardS2S(); + const sc = imaState.chainProperties.sc, tc = imaState.chainProperties.tc; + const ethersProviderSrc = isForward ? sc.ethersProvider : tc.ethersProvider; + const chainIdSrc = isForward ? sc.chainId : tc.chainId; + const joAccountSrc = isForward ? sc.joAccount : tc.joAccount; + const joTokenManagerERC20Src = isForward + ? imaState.joTokenManagerERC20 : imaState.joTokenManagerERC20Target; + const joTokenManagerERC721Src = isForward + ? ( imaState.isWithMetadata721 + ? imaState.joTokenManagerERC721WithMetadata + : imaState.joTokenManagerERC721 ) + : ( imaState.isWithMetadata721 + ? imaState.joTokenManagerERC721WithMetadataTarget + : imaState.joTokenManagerERC721Target ) + ; + const joTokenManagerERC1155Src = isForward + ? imaState.joTokenManagerERC1155 : imaState.joTokenManagerERC1155Target; + const strChainNameDst = isForward ? tc.strChainName : sc.strChainName; + const strCoinNameErc20Src = isForward ? sc.strCoinNameErc20 : tc.strCoinNameErc20; + const strCoinNameErc721Src = isForward ? sc.strCoinNameErc721 : tc.strCoinNameErc721; + const strCoinNameErc1155Src = + isForward ? sc.strCoinNameErc1155 : tc.strCoinNameErc1155; + const joSrcErc20 = isForward ? sc.joErc20 : tc.joErc20; + const joSrcErc721 = isForward ? sc.joErc721 : tc.joErc721; + const joSrcErc1155 = isForward ? sc.joErc1155 : tc.joErc1155; + let strAddrErc20Explicit = imaState.strAddrErc20Explicit; + let strAddrErc20ExplicitTarget = imaState.strAddrErc20ExplicitTarget; + let strAddrErc721Explicit = imaState.strAddrErc721Explicit; + let strAddrErc721ExplicitTarget = imaState.strAddrErc721ExplicitTarget; + let strAddrErc1155Explicit = imaState.strAddrErc1155Explicit; + let strAddrErc1155ExplicitTarget = imaState.strAddrErc1155ExplicitTarget; + if( ( ! strAddrErc20Explicit ) && sc.joErc20 && sc.strCoinNameErc20 ) + strAddrErc20Explicit = sc.joErc20[sc.strCoinNameErc20 + "_address"]; + if( ( ! strAddrErc20ExplicitTarget ) && tc.joErc20 && tc.strCoinNameErc20 ) + strAddrErc20ExplicitTarget = tc.joErc20[tc.strCoinNameErc20 + "_address"]; + if( ( ! strAddrErc721Explicit ) && sc.joErc721 && sc.strCoinNameErc721 ) + strAddrErc721Explicit = sc.joErc721[sc.strCoinNameErc721 + "_address"]; + if( ( ! strAddrErc721ExplicitTarget ) && tc.joErc721 && tc.strCoinNameErc721 ) + strAddrErc721ExplicitTarget = tc.joErc721[tc.strCoinNameErc721 + "_address"]; + if( ( ! strAddrErc1155Explicit ) && sc.joErc1155 && sc.strCoinNameErc1155 ) + strAddrErc1155Explicit = sc.joErc1155[sc.strCoinNameErc1155 + "_address"]; + if( ( ! strAddrErc1155ExplicitTarget ) && tc.joErc1155 && tc.strCoinNameErc1155 ) + strAddrErc1155ExplicitTarget = tc.joErc1155[tc.strCoinNameErc1155 + "_address"]; + const strAddrErc20Dst = isForward + ? strAddrErc20ExplicitTarget : strAddrErc20Explicit; + const strAddrErc721Dst = isForward + ? strAddrErc721ExplicitTarget : strAddrErc721Explicit; + const strAddrErc1155Dst = isForward + ? strAddrErc1155ExplicitTarget : strAddrErc1155Explicit; + const tx_customizer = isForward ? sc.transactionCustomizer : tc.transactionCustomizer; + if( strCoinNameErc721Src.length > 0 ) { + // ERC721 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->S single ERC721 payment: " ) + + cc.sunny( imaState.idToken ) + "\n" ); + } + return await imaToken.doErc721PaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC721Src, + imaState.idToken, // which ERC721 token id to send + imaState.nAmountOfWei, // how much to send + strCoinNameErc721Src, + joSrcErc721, + strAddrErc721Dst, // only reverse payment needs it + tx_customizer + ); + } + if( strCoinNameErc20Src.length > 0 ) { + // ERC20 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->S single ERC20 payment: " ) + + cc.sunny( imaState.nAmountOfToken ) + "\n" ); + } + return await imaToken.doErc20PaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC20Src, + imaState.nAmountOfToken, // how much ERC20 tokens to send + imaState.nAmountOfWei, // how much to send + strCoinNameErc20Src, + joSrcErc20, + strAddrErc20Dst, // only reverse payment needs it + tx_customizer + ); + } + if( + strCoinNameErc1155Src.length > 0 && + imaState.idToken && + imaState.idToken !== null && + imaState.idToken !== undefined && + imaState.nAmountOfToken && + imaState.nAmountOfToken !== null && + imaState.nAmountOfToken !== undefined && + ( ( !imaState.idTokens ) || + imaState.idTokens === null || + imaState.idTokens === undefined ) && + ( ( !imaState.arrAmountsOfTokens ) || + imaState.arrAmountsOfTokens === null || + imaState.arrAmountsOfTokens === undefined ) + ) { + // ERC1155 payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->S single ERC1155 payment: " ) + + cc.sunny( imaState.idToken ) + " " + + cc.sunny( imaState.nAmountOfToken ) + "\n" ); + } + return await imaToken.doErc1155PaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC1155Src, + imaState.idToken, // which ERC1155 token id to send + imaState.nAmountOfToken, // how much ERC1155 tokens to send + imaState.nAmountOfWei, // how much to send + strCoinNameErc1155Src, + joSrcErc1155, + strAddrErc1155Dst, // only reverse payment needs it + tx_customizer + ); + } + if( + strCoinNameErc1155Src.length > 0 && + imaState.idTokens && + imaState.idTokens !== null && + imaState.idTokens !== undefined && + imaState.arrAmountsOfTokens && + imaState.arrAmountsOfTokens !== null && + imaState.arrAmountsOfTokens !== undefined && + ( !imaState.idToken || + imaState.idToken === null || + imaState.idToken === undefined ) && + ( !imaState.nAmountOfToken || + imaState.nAmountOfToken === null || + imaState.nAmountOfToken === undefined ) + ) { + // ERC1155 Batch payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->S single ERC1155 Batch payment: " ) + + cc.sunny( imaState.idTokens ) + " " + + cc.sunny( imaState.arrAmountsOfTokens ) + "\n" ); + } + return await imaToken.doErc1155BatchPaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC1155Src, + imaState.idTokens, // which ERC1155 token id to send + imaState.arrAmountsOfTokens, // which ERC1155 token amount to send + imaState.nAmountOfWei, // how much to send + strCoinNameErc1155Src, + joSrcErc1155, + strAddrErc1155Dst, + tx_customizer + ); + } + // ETH payment + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "one S->S single ETH payment: " ) + + cc.sunny( imaState.nAmountOfWei ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().fatal ) { + lop.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " S->S ETH payment(s) are neither supported nor allowed" ) + "\n" ); + } + process.exit( 154 ); + } + } ); +} + +export function commandLineTaskReceiveS2M() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "receive one S->M single ETH payment", + "fn": async function() { + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( cc.info( "receive one S->M single ETH payment: " ) + "\n" ); + return await imaEth.receiveEthPaymentFromSchainOnMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.joAccount, + imaState.joDepositBoxETH, + imaState.chainProperties.mn.transactionCustomizer + ); + } + } ); +} + +export function commandLineTaskViewS2M() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "view one S->M single ETH payment", + "fn": async function() { + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( cc.info( "view one S->M single ETH payment: " ) + "\n" ); + const xWei = await imaEth.viewEthPaymentFromSchainOnMainNet( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.mn.joAccount, + imaState.joDepositBoxETH + ); + if( xWei === null || xWei === undefined ) + return false; + const xEth = + owaspUtils.ethersMod.ethers.utils.formatEther( owaspUtils.toBN( xWei ) ); + log.write( cc.success( "Main-net user can receive: " ) + cc.attention( xWei ) + + cc.success( " wei = " ) + cc.attention( xEth ) + cc.success( " eth" ) + "\n" ); + return true; + } + } ); +} + +export function commandLineTaskTransferM2S() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "single M->S transfer loop", + "fn": async function() { + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // main-net --> s-chain transfer + const joRuntimeOpts = { + isInsideWorker: false, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }; + return await IMA.doTransfer( // main-net --> s-chain + "M2S", + joRuntimeOpts, + imaState.chainProperties.mn.ethersProvider, + imaState.joMessageProxyMainNet, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.ethersProvider, + imaState.joMessageProxySChain, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + null, + imaState.joTokenManagerETH, // for logs validation on s-chain + imaState.nTransferBlockSizeM2S, + imaState.nTransferStepsM2S, + imaState.nMaxTransactionsM2S, + imaState.nBlockAwaitDepthM2S, + imaState.nBlockAgeM2S, + imaBLS.doSignMessagesM2S, + null, + imaState.chainProperties.sc.transactionCustomizer + ); + } + } ); +} + +export function commandLineTaskTransferS2M() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "single S->M transfer loop", + "fn": async function() { + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // s-chain --> main-net transfer + const joRuntimeOpts = { + isInsideWorker: false, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }; + return await IMA.doTransfer( // s-chain --> main-net + "S2M", + joRuntimeOpts, + imaState.chainProperties.sc.ethersProvider, + imaState.joMessageProxySChain, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.ethersProvider, + imaState.joMessageProxyMainNet, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.mn.chainId, + imaState.joDepositBoxETH, // for logs validation on mainnet + null, + imaState.nTransferBlockSizeS2M, + imaState.nTransferStepsS2M, + imaState.nMaxTransactionsS2M, + imaState.nBlockAwaitDepthS2M, + imaState.nBlockAgeS2M, + imaBLS.doSignMessagesS2M, + null, + imaState.chainProperties.mn.transactionCustomizer + ); + } + } ); +} + +export function commandLineTaskTransferS2S() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "single S->S transfer loop", + "fn": async function() { + if( ! imaState.optsS2S.isEnabled ) + return; + discoveryTools.initialSkaleNetworkScanForS2S(); + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // s-chain --> main-net transfer + const joRuntimeOpts = { + isInsideWorker: false, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }; + return await IMA.doAllS2S( // s-chain --> s-chain + joRuntimeOpts, + imaState, + skaleObserver, + imaState.chainProperties.sc.ethersProvider, + imaState.joMessageProxySChain, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.sc.chainId, + imaState.joTokenManagerETH, // for logs validation on s-chain + imaState.nTransferBlockSizeM2S, + imaState.nTransferStepsS2S, + imaState.nMaxTransactionsM2S, + imaState.nBlockAwaitDepthM2S, + imaState.nBlockAgeM2S, + imaBLS.doSignMessagesM2S, + imaState.chainProperties.sc.transactionCustomizer + ); + } + } ); +} + +export function commandLineTaskTransfer() { + const imaState = state.get(); + discoveryTools.initialSkaleNetworkScanForS2S(); + imaState.arrActions.push( { + "name": "Single M<->S transfer loop iteration", + "fn": async function() { + discoveryTools.initialSkaleNetworkScanForS2S(); + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); + const joRuntimeOpts = { + isInsideWorker: false, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }; + const optsLoop = { + joRuntimeOpts: joRuntimeOpts, + isDelayFirstRun: false, + enableStepOracle: true, + enableStepM2S: true, + enableStepS2M: true, + enableStepS2S: true + }; + return await singleTransferLoop( optsLoop ); + } + } ); +} + +export function commandLineTaskLoop() { + const imaState = state.get(); + discoveryTools.initialSkaleNetworkScanForS2S(); + imaState.arrActions.push( { + "name": "M<->S and S->S transfer loop, startup in parallel mode", + "fn": async function() { + state.setPreventExitAfterLastAction( true ); + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // M<->S transfer loop + let isPrintSummaryRegistrationCosts = false; + if( !await checkRegistrationStep1() ) { + if( !await registerStep1( false ) ) + return false; + isPrintSummaryRegistrationCosts = true; + } + if( isPrintSummaryRegistrationCosts ) + printSummaryRegistrationCosts(); + const opts = { + imaState: imaState, + "details": log + }; + return await loop.runParallelLoops( + opts + ); + } + } ); +} + +export function commandLineTaskLoopSimple() { + const imaState = state.get(); + discoveryTools.initialSkaleNetworkScanForS2S(); + imaState.arrActions.push( { + "name": "M<->S and S->S transfer loop, simple mode", + "fn": async function() { + state.setPreventExitAfterLastAction( true ); + if( ! imaState.bNoWaitSChainStarted ) + await discoveryTools.waitUntilSChainStarted(); // M<->S transfer loop + let isPrintSummaryRegistrationCosts = false; + if( !await checkRegistrationStep1() ) { + if( !await registerStep1( false ) ) + return false; + isPrintSummaryRegistrationCosts = true; + } + if( isPrintSummaryRegistrationCosts ) + printSummaryRegistrationCosts(); + const joRuntimeOpts = { + isInsideWorker: false, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }; + const optsLoop = { + joRuntimeOpts: joRuntimeOpts, + isDelayFirstRun: false, + enableStepOracle: true, + enableStepM2S: true, + enableStepS2M: true, + enableStepS2S: true + }; + return await loop.runTransferLoop( optsLoop ); + } + } ); +} + +export function commandLineTaskBrowseSChain() { + const imaState = state.get(); + imaState.bIsNeededCommonInit = false; + imaState.arrActions.push( { + "name": "Browse S-Chain network", + "fn": async function() { + const strLogPrefix = cc.info( "S-Chain Browse:" ) + " "; + if( imaState.chainProperties.sc.strURL.length === 0 ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " missing S-Chain URL, please specify " ) + + cc.info( "url-s-chain" ) + "\n" ); + } + process.exit( 155 ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + + cc.normal( "Downloading S-Chain network information " ) + + cc.normal( "..." ) + "\n" ); + } + const rpcCallOpts = null; + await rpcCall.create( + imaState.chainProperties.sc.strURL, + rpcCallOpts, + async function( joCall, err ) { + if( err ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain failed" ) + "\n" ); + } + if( joCall ) + await joCall.disconnect(); + process.exit( 156 ); + } + const joDataIn = { + "method": "skale_nodesRpcInfo", + "params": { } + }; + if( discoveryTools.isSendImaAgentIndex() ) + joDataIn.params.fromImaAgentIndex = imaState.nNodeNumber; + await joCall.call( joDataIn, async function( joIn, joOut, err ) { + if( err ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain failed, error: " ) + + cc.warning( strError ) + "\n" ); + } + await joCall.disconnect(); + process.exit( 157 ); + } + log.write( strLogPrefix + cc.normal( "S-Chain network information: " ) + + cc.j( joOut.result ) + "\n" ); + let nCountReceivedImaDescriptions = 0; + const jarrNodes = joOut.result.network; + for( let i = 0; i < jarrNodes.length; ++ i ) { + const joNode = jarrNodes[i]; + if( ! joNode ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + log.write( strLogPrefix + cc.error( "Discovery node " ) + + cc.info( i ) + + cc.error( " is completely unknown and will be skipped" ) + + "\n" ); + } + continue; + } + const strNodeURL = imaUtils.composeSChainNodeUrl( joNode ); + const rpcCallOpts = null; + await rpcCall.create( + strNodeURL, + rpcCallOpts, + async function( joCall, err ) { + if( err ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain failed" ) + + "\n" ); + } + await joCall.disconnect(); + process.exit( 158 ); + } + const joDataIn = { + "method": "skale_imaInfo", + "params": { } + }; + if( discoveryTools.isSendImaAgentIndex() ) + joDataIn.params.fromImaAgentIndex = imaState.nNodeNumber; + await joCall.call( joDataIn, async function( + joIn, joOut, err ) { + ++ nCountReceivedImaDescriptions; + if( err ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + const strError = + owaspUtils.extractErrorMessage( err ); + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain failed, " + + "error: " ) + cc.warning( strError ) + "\n" ); + } + process.exit( 159 ); + } + log.write( strLogPrefix + + cc.normal( "Node " ) + cc.info( joNode.nodeID ) + + cc.normal( " IMA information: " ) + + cc.j( joOut.result ) + "\n" ); + await joCall.disconnect(); + } ); + } ); + } + const iv = setInterval( function() { + if( nCountReceivedImaDescriptions == jarrNodes.length ) { + clearInterval( iv ); + process.exit( 0 ); + } + }, 100 ); + await joCall.disconnect(); + } ); + } ); + return true; + } + } ); +} + +export function commandLineTaskBrowseSkaleNetwork() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Browse S-Chain network", + "fn": async function() { + const strLogPrefix = cc.info( "SKALE NETWORK Browse:" ) + " "; + if( imaState.strPathAbiJsonSkaleManager.length === 0 ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " missing Skale Manager ABI, please specify " ) + + cc.info( "abi-skale-manager" ) + "\n" ); + } + process.exit( 160 ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + + cc.debug( "Downloading SKALE network information..." ) + "\n" ); + } + const opts = { + imaState: imaState, + "details": log, + "bStopNeeded": false + }; + const addressFrom = imaState.chainProperties.mn.joAccount.address(); + const arrSChains = await skaleObserver.loadSChains( addressFrom, opts ); + const cnt = arrSChains.length; + log.write( strLogPrefix + cc.normal( "Got " ) + cc.info( cnt ) + + cc.normal( " S-Chains(s) in SKALE NETWORK information: " ) + + cc.j( arrSChains ) + "\n" ); + return true; + } + } ); +} + +export function commandLineTaskBrowseConnectedSChains() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Browse connected S-Chains", + "fn": async function() { + const strLogPrefix = cc.info( "Browse connected S-Chains:" ) + " "; + if( imaState.strPathAbiJsonSkaleManager.length === 0 ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " missing Skale Manager ABI, please specify " ) + + cc.info( "abi-skale-manager" ) + "\n" ); + } + process.exit( 161 ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + + cc.debug( "Downloading SKALE network information..." ) + "\n" ); + } + const opts = { + imaState: imaState, + "details": log, + "bStopNeeded": false + }; + const addressFrom = imaState.chainProperties.mn.joAccount.address(); + const arrSChainsCached = await skaleObserver.loadSChainsConnectedOnly( + imaState.chainProperties.sc.strChainName, + addressFrom, + opts + ); + const cnt = arrSChainsCached.length; + log.write( strLogPrefix + cc.normal( "Got " ) + cc.info( cnt ) + + cc.normal( " connected S-Chain(s): " ) + cc.j( arrSChainsCached ) + "\n" ); + return true; + } + } ); +} + +export function commandLineTaskDiscoverChainId() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Discover chains ID(s)", + "fn": async function() { + const strLogPrefix = cc.info( "Discover chains ID(s):" ) + " "; + const arrURLsToDiscover = []; + if( imaState.chainProperties.mn.strURL && + typeof( imaState.chainProperties.mn.strURL ) == "string" && + imaState.chainProperties.mn.strURL.length > 0 + ) { + arrURLsToDiscover.push( { + "name": "Main Net", + "strURL": "" + imaState.chainProperties.mn.strURL, + "fnSave": function( chainId ) { + imaState.chainProperties.mn.chainId = chainId; + } + } ); + } + if( imaState.chainProperties.sc.strURL && + typeof( imaState.chainProperties.sc.strURL ) == "string" && + imaState.chainProperties.sc.strURL.length > 0 + ) { + arrURLsToDiscover.push( { + "name": "S-Chain", + "strURL": "" + "" + imaState.chainProperties.sc.strURL, + "fnSave": function( chainId ) { + imaState.chainProperties.sc.chainId = chainId; + } + } ); + } + if( imaState.chainProperties.tc.strURL && + typeof( imaState.chainProperties.tc.strURL ) == "string" && + imaState.chainProperties.tc.strURL.length > 0 + ) { + arrURLsToDiscover.push( { + "name": "S<->S Target S-Chain", + "strURL": "" + "" + imaState.chainProperties.tc.strURL, + "fnSave": function( chainId ) { + imaState.chainProperties.tc.chainId = chainId; + } + } ); + } + if( arrURLsToDiscover.length === 0 ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " no URLs provided to discover chain IDs, please specify " ) + + cc.warning( "--url-main-net" ) + cc.error( " and/or " ) + + cc.warning( "--url-s-chain" ) + cc.error( " and/or " ) + + cc.warning( "--url-t-chain" ) + cc.error( "." ) + "\n" ); + } + process.exit( 162 ); + } + for( let i = 0; i < arrURLsToDiscover.length; ++ i ) { + const joDiscoverEntry = arrURLsToDiscover[i]; + const chainId = await + skaleObserver.discoverChainId( joDiscoverEntry.strURL ); + if( chainId === null ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( strLogPrefix + cc.error( "Failed to detect " ) + + cc.note( joDiscoverEntry.name ) + " " + cc.attention( "chain ID" ) + + "\n" ); + } + } else { + const cid16 = + owaspUtils.ensureStartsWith0x( + owaspUtils.toBN( chainId ).toHexString() ); + const cid10 = "" + owaspUtils.toBN( chainId ).toString(); + log.write( strLogPrefix + cc.normal( "Got " ) + + cc.note( joDiscoverEntry.name ) + " " + cc.attention( "chain ID" ) + + cc.normal( "=" ) + cc.note( cid16 ) + cc.normal( "=" ) + cc.note( cid10 ) + + cc.normal( " from URL " ) + cc.u( joDiscoverEntry.strURL ) + "\n" ); + joDiscoverEntry.fnSave( chainId ); + } + } + return true; + } + } ); +} + +export function commandLineTaskReimbursementShowBalance() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Gas Reimbursement - Show Balance", + "fn": async function() { + await imaReimbursement.reimbursementShowBalance( + imaState.chainProperties.mn.ethersProvider, + imaState.joCommunityPool, + imaState.chainProperties.mn.joAccount.address(), + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.transactionCustomizer, + imaState.strReimbursementChain, + true + ); + return true; + } + } ); +} + +export function commandLineTaskReimbursementEstimateAmount() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Gas Reimbursement - Estimate Amount", + "fn": async function() { + await imaReimbursement.reimbursementEstimateAmount( + imaState.chainProperties.mn.ethersProvider, + imaState.joCommunityPool, + imaState.chainProperties.mn.joAccount.address(), + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.transactionCustomizer, + imaState.strReimbursementChain, + true + ); + return true; + } + } ); +} + +export function commandLineTaskReimbursementRecharge() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Gas Reimbursement - Recharge User Wallet", + "fn": async function() { + await imaReimbursement.reimbursementWalletRecharge( + imaState.chainProperties.mn.ethersProvider, + imaState.joCommunityPool, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.transactionCustomizer, + imaState.strReimbursementChain, + imaState.nReimbursementRecharge + ); + return true; + } + } ); +} + +export function commandLineTaskReimbursementWithdraw() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Gas Reimbursement - Withdraw User Wallet", + "fn": async function() { + await imaReimbursement.reimbursementWalletWithdraw( + imaState.chainProperties.mn.ethersProvider, + imaState.joCommunityPool, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.mn.transactionCustomizer, + imaState.strReimbursementChain, + imaState.nReimbursementWithdraw + ); + return true; + } + } ); +} + +export function commandLineTaskReimbursementSetRange() { + const imaState = state.get(); + imaState.arrActions.push( { + "name": "Gas Reimbursement - Set Minimal time interval from S2M and S2S transfers", + "fn": async function() { + await imaReimbursement.reimbursementSetRange( + imaState.chainProperties.sc.ethersProvider, + imaState.joCommunityLocker, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.sc.transactionCustomizer, + imaState.strChainNameOriginChain, + imaState.nReimbursementRange + ); + return true; + } + } ); +} diff --git a/agent/discoveryTools.mjs b/agent/discoveryTools.mjs new file mode 100644 index 000000000..04935f9a2 --- /dev/null +++ b/agent/discoveryTools.mjs @@ -0,0 +1,650 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file discoveryTools.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as rpcCall from "./rpcCall.mjs"; +import * as imaHelperAPIs from "../npms/skale-ima/imaHelperAPIs.mjs"; +import * as skaleObserver from "../npms/skale-observer/observer.mjs"; +import * as state from "./state.mjs"; +import * as imaUtils from "./utils.mjs"; + +export function initialSkaleNetworkScanForS2S() { + const imaState = state.get(); + if( ! imaState.optsS2S.isEnabled ) + return; + imaState.arrActions.push( { + "name": "SKALE network scan for S2S", + "fn": async function() { + const strLogPrefix = cc.info( "SKALE network scan for S2S:" ) + " "; + if( imaState.strPathAbiJsonSkaleManager.length === 0 ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " missing Skale Manager ABI, please specify " ) + + cc.info( "abi-skale-manager" ) + "\n" ); + } + process.exit( 153 ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + + cc.debug( "Downloading SKALE network information..." ) + "\n" ); + } + const opts = { + imaState: imaState, + "details": log, + "bStopNeeded": false, + "secondsToReDiscoverSkaleNetwork": + imaState.optsS2S.secondsToReDiscoverSkaleNetwork, + "chain": imaState.chainProperties.sc, + "bParallelMode": true + }; + const addressFrom = imaState.chainProperties.mn.joAccount.address(); + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + + cc.debug( "Will start periodic S-Chains caching..." ) + "\n" ); + } + await skaleObserver.periodicCachingStart( + imaState.chainProperties.sc.strChainName, + addressFrom, + opts + ); + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + + cc.success( "Done, did started periodic S-Chains caching." ) + "\n" ); + } + return true; + } + } ); +}; + +export function formatBalanceInfo( bi, strAddress ) { + let s = ""; + s += cc.attention( bi.assetName ); + if( "assetAddress" in bi && + typeof bi.assetAddress == "string" && bi.assetAddress.length > 0 ) + s += cc.normal( "/" ) + cc.notice( bi.assetAddress ); + if( "idToken" in bi ) + s += cc.normal( " token ID " ) + cc.notice( bi.idToken ); + s += cc.normal( ( bi.assetName == "ERC721" ) + ? " owner is " : " balance is " ); + s += ( bi.assetName == "ERC721" ) + ? cc.bright( bi.owner ) : cc.sunny( bi.balance ); + if( bi.assetName == "ERC721" ) { + const isSame = + ( bi.owner.trim().toLowerCase() == strAddress.trim().toLowerCase() ); + s += " " + ( isSame + ? cc.success( "same (as account " ) + cc.attention( strAddress ) + + cc.success( " specified in the command line arguments)" ) + : cc.error( "different (than account " ) + cc.attention( strAddress ) + + cc.error( " specified in the command line arguments)" ) ); + } + return s; +} + +function getSChainNodesCount( joSChainNetworkInfo ) { + try { + if( ! joSChainNetworkInfo ) + return 0; + const jarrNodes = joSChainNetworkInfo.network; + const cntNodes = jarrNodes.length; + return cntNodes; + } catch ( err ) { + return 0; + } +} + +function getSChainDiscoveredNodesCount( joSChainNetworkInfo ) { + try { + if( ! joSChainNetworkInfo ) + return 0; + if( ! ( "network" in joSChainNetworkInfo && joSChainNetworkInfo.network ) ) + return 0; + const jarrNodes = joSChainNetworkInfo.network; + const cntNodes = jarrNodes.length; + if( cntNodes <= 0 ) + return 0; + let cntDiscovered = 0; + for( let i = 0; i < cntNodes; ++ i ) { + try { + const joNode = joSChainNetworkInfo.network[i]; + if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && + "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" + ) + ++ cntDiscovered; + } catch ( err ) { + return 0; + } + } + return cntDiscovered; + } catch ( err ) { + return 0; + } +} + +export async function waitUntilSChainStarted() { + const imaState = state.get(); + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( cc.debug( "Checking " ) + cc.info( "S-Chain" ) + + cc.debug( " is accessible and sane..." ) + "\n" ); + } + if( ( !imaState.chainProperties.sc.strURL ) || + imaState.chainProperties.sc.strURL.length === 0 + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Skipped, " ) + cc.info( "S-Chain" ) + + cc.warning( " URL was not provided." ) + "\n" ); + } + return; + } + let bSuccess = false; + let idxWaitAttempt = 0; + for( ; !bSuccess; ) { + try { + const joSChainNetworkInfo = await discoverSChainNetwork( + function( err, joSChainNetworkInfo ) { + if( ! err ) + bSuccess = true; + }, true, null, -1 ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " S-Chain network discovery failed: " ) + + cc.warning( strError ) + "\n" ); + } + } ); + if( ! joSChainNetworkInfo ) + bSuccess = false; + } catch ( err ) { + bSuccess = false; + } + if( !bSuccess ) + ++ idxWaitAttempt; + if( idxWaitAttempt >= imaState.nMaxWaitSChainAttempts ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Incomplete, " ) + cc.info( "S-Chain" ) + + cc.warning( " sanity check failed after " ) + cc.info( idxWaitAttempt ) + + cc.warning( " attempts." ) + "\n" ); + } + return; + } + await imaHelperAPIs.sleep( 1000 ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.success( "Done, " ) + cc.info( "S-Chain" ) + + cc.success( " is accessible and sane." ) + "\n" ); + } +} + +export function isSendImaAgentIndex() { + return true; +} + +let gTimerSChainDiscovery = null; +let gFlagIsInSChainDiscovery = false; + +export async function continueSChainDiscoveryInBackgroundIfNeeded( isSilent ) { + const imaState = state.get(); + const cntNodes = getSChainNodesCount( imaState.joSChainNetworkInfo ); + const cntDiscovered = getSChainDiscoveredNodesCount( imaState.joSChainNetworkInfo ); + if( cntDiscovered >= cntNodes ) { + if( gTimerSChainDiscovery != null ) { + clearInterval( gTimerSChainDiscovery ); + gTimerSChainDiscovery = null; + } + return; + } + if( gTimerSChainDiscovery != null ) + return; + if( imaState.joSChainDiscovery.repeatIntervalMilliseconds <= 0 ) + return; // no S-Chain re-discovery (for debugging only) + const fnAsyncHandler = async function() { + if( gFlagIsInSChainDiscovery ) + return; + if( gFlagIsInSChainDiscovery ) { + isInsideAsyncHandler = false; + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( cc.warning( "Notice: long S-Chain discovery is in progress" ) + "\n" ); + return; + } + gFlagIsInSChainDiscovery = true; + try { + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.info( "Will re-discover " ) + cc.notice( cntNodes ) + + cc.info( "-node S-Chain network, " ) + cc.notice( cntDiscovered ) + + cc.info( " node(s) already discovered..." ) + "\n" ); + } + await discoverSChainNetwork( function( err, joSChainNetworkInfo ) { + if( ! err ) { + const cntDiscoveredNew = + getSChainDiscoveredNodesCount( joSChainNetworkInfo ); + if( log.verboseGet() >= log.verboseReversed().information ) { + const strDiscoveryStatus = + cc.info( cntDiscoveredNew ) + cc.success( " nodes known" ); + let strMessage = + cc.success( "S-Chain network was re-discovered, " ) + + cc.info( cntDiscoveredNew ) + + cc.success( " of " ) + cc.info( cntNodes ) + + cc.success( " node(s) (" ) + strDiscoveryStatus + cc.success( ")" ); + const cntStillUnknown = cntNodes - cntDiscoveredNew; + if( cntStillUnknown > 0 ) { + strMessage += cc.success( ", " ) + + cc.info( cntStillUnknown ) + + cc.success( " of " ) + cc.info( cntNodes ) + + cc.success( " still unknown (" ); + try { + const jarrNodes = joSChainNetworkInfo.network; + let cntBad = 0; + for( let i = 0; i < jarrNodes.length; ++i ) { + const joNode = jarrNodes[i]; + try { + if( ! ( joNode && "imaInfo" in joNode && + typeof joNode.imaInfo === "object" && + "t" in joNode.imaInfo && + typeof joNode.imaInfo.t === "number" ) + ) { + if( cntBad > 0 ) + strMessage += cc.success( ", " ); + const strNodeURL = + imaUtils.composeSChainNodeUrl( joNode ); + const strNodeDescColorized = + cc.notice( "#" ) + cc.info( i ) + + cc.attention( "(" ) + cc.u( strNodeURL ) + + cc.attention( ")" ); + strMessage += strNodeDescColorized; + ++ cntBad; + } + } catch ( err ) { } + } + } catch ( err ) { } + strMessage += cc.success( ")" ); + } + if( ! isSilent ) { + strMessage += + cc.success( ", complete re-discovered S-Chain network info: " ) + + cc.j( joSChainNetworkInfo ); + } + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( strMessage + "\n" ); + } + imaState.joSChainNetworkInfo = joSChainNetworkInfo; + } + continueSChainDiscoveryInBackgroundIfNeeded( isSilent ); + }, isSilent, imaState.joSChainNetworkInfo, cntNodes ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " S-Chain network re-discovery failed: " ) + + cc.warning( strError ) + "\n" ); + } + } ); + } catch ( err ) { } + gFlagIsInSChainDiscovery = false; + }; + gTimerSChainDiscovery = setInterval( function() { + if( gFlagIsInSChainDiscovery ) + return; + fnAsyncHandler(); + }, imaState.joSChainDiscovery.repeatIntervalMilliseconds ); +} + +async function discoverSChainWalkNodes( optsDiscover ) { + optsDiscover.cntFailed = 0; + for( let i = 0; i < optsDiscover.cntNodes; ++ i ) { + const nCurrentNodeIdx = 0 + i; + const joNode = optsDiscover.jarrNodes[nCurrentNodeIdx]; + const strNodeURL = imaUtils.composeSChainNodeUrl( joNode ); + const strNodeDescColorized = + cc.notice( "#" ) + cc.info( nCurrentNodeIdx ) + + cc.attention( "(" ) + cc.u( strNodeURL ) + cc.attention( ")" ); + try { + if( optsDiscover.joPrevSChainNetworkInfo && + "network" in optsDiscover.joPrevSChainNetworkInfo && + optsDiscover.joPrevSChainNetworkInfo.network ) { + const joPrevNode = + optsDiscover.joPrevSChainNetworkInfo.network[nCurrentNodeIdx]; + if( joPrevNode && "imaInfo" in joPrevNode && + typeof joPrevNode.imaInfo === "object" && + "t" in joPrevNode.imaInfo && + typeof joPrevNode.imaInfo.t === "number" + ) { + joNode.imaInfo = JSON.parse( JSON.stringify( joPrevNode.imaInfo ) ); + if( log.verboseGet() >= log.verboseReversed().information ) { + if( ( !optsDiscover.isSilent ) ) { + log.write( optsDiscover.strLogPrefix + + cc.info( "OK, in case of " ) + strNodeDescColorized + + cc.info( " node " ) + cc.info( joNode.nodeID ) + + cc.info( " will use previous discovery result." ) + "\n" ); + } + } + continue; // skip this node discovery, enrich rest of nodes + } + } + } catch ( err ) { } + const rpcCallOpts = null; + try { + await rpcCall.create( strNodeURL, rpcCallOpts, + async function( joCall, err ) { + if( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain node " ) + + strNodeDescColorized + cc.error( " failed" ) + "\n" ); + } + } + ++ optsDiscover.cntFailed; + if( joCall ) + await joCall.disconnect(); + return; + } + const joDataIn = { + "method": "skale_imaInfo", + "params": { } + }; + if( isSendImaAgentIndex() ) + joDataIn.params.fromImaAgentIndex = optsDiscover.imaState.nNodeNumber; + joCall.call( joDataIn, function( joIn, joOut, err ) { + ++ optsDiscover.nCountReceivedImaDescriptions; + if( err ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain node " ) + + strNodeDescColorized + cc.error( " failed, error: " ) + + cc.warning( strError ) + "\n" ); + } + } + ++ optsDiscover.cntFailed; + return; + } + joNode.imaInfo = joOut.result; + if( log.verboseGet() >= log.verboseReversed().information ) { + if( !optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + cc.success( "OK, got " ) + + strNodeDescColorized + cc.success( " node " ) + + cc.info( joNode.nodeID ) + cc.success( " IMA information(" ) + + cc.info( optsDiscover.nCountReceivedImaDescriptions ) + + cc.success( " of " ) + + cc.info( optsDiscover.cntNodes ) + cc.success( ")." ) + "\n" ); + } + } + } ); + } ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( optsDiscover.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + + cc.error( " was not created: " ) + cc.warning( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + ++ optsDiscover.cntFailed; + } + } +} + +async function discoverSChainWait( optsDiscover ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + if( !optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + + cc.debug( "Waiting for response from at least " ) + + cc.info( optsDiscover.nCountToWait ) + + cc.debug( " node(s)..." ) + "\n" ); + } + } + let nWaitAttempt = 0; + const nWaitStepMilliseconds = 1000; + let cntWaitAttempts = Math.floor( + optsDiscover.imaState.joSChainDiscovery.repeatIntervalMilliseconds / + nWaitStepMilliseconds ) - 3; + if( cntWaitAttempts < 1 ) + cntWaitAttempts = 1; + const iv = setInterval( function() { + optsDiscover.nCountAvailable = + optsDiscover.cntNodes - optsDiscover.cntFailed; + if( log.verboseGet() >= log.verboseReversed().debug ) { + if( ! optsDiscover.isSilent ) { + log.write( cc.debug( "Waiting attempt " ) + cc.info( nWaitAttempt ) + + cc.debug( " of " ) + cc.info( cntWaitAttempts ) + + cc.debug( " for S-Chain nodes, total " ) + + cc.info( optsDiscover.cntNodes ) + cc.debug( ", available " ) + + cc.info( optsDiscover.nCountAvailable ) + cc.debug( ", expected at least " ) + + cc.info( optsDiscover.nCountToWait ) + "\n" ); + } + } + if( log.verboseGet() >= log.verboseReversed().information ) { + if( !optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + + cc.debug( "Have S-Chain description response about " ) + + cc.info( optsDiscover.nCountReceivedImaDescriptions ) + + cc.debug( " node(s)." ) + "\n" ); + } + } + if( optsDiscover.nCountReceivedImaDescriptions >= + optsDiscover.nCountToWait ) { + clearInterval( iv ); + optsDiscover.fnAfter( null, optsDiscover.joSChainNetworkInfo ); + return; + } + ++ nWaitAttempt; + if( nWaitAttempt >= cntWaitAttempts ) { + clearInterval( iv ); + const strErrorDescription = + "S-Chain network discovery wait timeout, " + + "network will be re-discovered"; + if( log.verboseGet() >= log.verboseReversed().warning ) { + if( ! optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + cc.warning( "WARNING:" ) + " " + + cc.warning( strErrorDescription ) + "\n" ); + } + } + if( getSChainDiscoveredNodesCount( + optsDiscover.joSChainNetworkInfo ) > 0 ) + optsDiscover.fnAfter( null, optsDiscover.joSChainNetworkInfo ); + else + optsDiscover.fnAfter( new Error( strErrorDescription ), null ); + return; + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + if( ! optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + cc.debug( " Waiting attempt " ) + + cc.info( nWaitAttempt ) + cc.debug( " of " ) + cc.info( cntWaitAttempts ) + + cc.debug( " for " ) + cc.notice( optsDiscover.nCountToWait - + optsDiscover.nCountReceivedImaDescriptions ) + + cc.debug( " node answer(s)" ) + "\n" ); + } + } + }, nWaitStepMilliseconds ); + await joCall.disconnect(); +} + +export async function discoverSChainNetwork( + fnAfter, isSilent, joPrevSChainNetworkInfo, nCountToWait +) { + const optsDiscover = { + fnAfter: fnAfter, + isSilent: isSilent || false, + joPrevSChainNetworkInfo: joPrevSChainNetworkInfo || null, + nCountToWait: nCountToWait, + imaState: state.get(), + strLogPrefix: cc.info( "S-Chain network discovery:" ) + " ", + joSChainNetworkInfo: null, + jarrNodes: [], + cntNodes: 0, + cntFailed: 0, + nCountReceivedImaDescriptions: 0, + nCountAvailable: 0 + }; + if( optsDiscover.nCountToWait == null || + optsDiscover.nCountToWait == undefined || + optsDiscover.nCountToWait < 0 ) + optsDiscover.nCountToWait = 0; + optsDiscover.fnAfter = optsDiscover.fnAfter || function() {}; + const rpcCallOpts = null; + try { + await rpcCall.create( optsDiscover.imaState.chainProperties.sc.strURL, rpcCallOpts, + async function( joCall, err ) { + if( err ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to (own) S-Chain " ) + + cc.u( optsDiscover.imaState.chainProperties.sc.strURL ) + + cc.error( " failed: " ) + cc.warning( strError ) + "\n" ); + } + } + optsDiscover.fnAfter( err, null ); + if( joCall ) + await joCall.disconnect(); + return; + } + const joDataIn = { + "method": "skale_nodesRpcInfo", + "params": { } + }; + if( isSendImaAgentIndex() ) + joDataIn.params.fromImaAgentIndex = optsDiscover.imaState.nNodeNumber; + await joCall.call( joDataIn, async function( joIn, joOut, err ) { + if( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( optsDiscover.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to (own) S-Chain " ) + + cc.u( optsDiscover.imaState.chainProperties.sc.strURL ) + + cc.error( " failed, error: " ) + cc.warning( strError ) + + "\n" ); + } + } + optsDiscover.fnAfter( err, null ); + await joCall.disconnect(); + return; + } + if( ( !optsDiscover.isSilent ) && + log.verboseGet() >= log.verboseReversed().trace ) { + log.write( optsDiscover.strLogPrefix + + cc.debug( "OK, got (own) S-Chain network information: " ) + + cc.j( joOut.result ) + "\n" ); + } else if( + ( !optsDiscover.isSilent ) && + log.verboseGet() >= log.verboseReversed().information ) { + log.write( optsDiscover.strLogPrefix + cc.success( "OK, got S-Chain " ) + + cc.u( optsDiscover.imaState.chainProperties.sc.strURL ) + + cc.success( " network information." ) + "\n" ); + } + optsDiscover.nCountReceivedImaDescriptions = 0; + optsDiscover.joSChainNetworkInfo = joOut.result; + if( ! optsDiscover.joSChainNetworkInfo ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + const err2 = new Error( "Got wrong response, " + + "network information description was not detected" ); + log.write( optsDiscover.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Network was not detected via call to " ) + + cc.u( optsDiscover.imaState.chainProperties.sc.strURL ) + + cc.error( ": " ) + cc.warning( err2 ) + "\n" ); + } + } + optsDiscover.fnAfter( err2, null ); + await joCall.disconnect(); + return; + } + optsDiscover.jarrNodes = optsDiscover.joSChainNetworkInfo.network; + optsDiscover.cntNodes = optsDiscover.jarrNodes.length; + if( optsDiscover.nCountToWait <= 0 ) { + optsDiscover.nCountToWait = 0 + optsDiscover.cntNodes; + if( optsDiscover.nCountToWait > 2 ) { + optsDiscover.nCountToWait = + Math.ceil( optsDiscover.nCountToWait * 2 / 3 ); + } + } else if( optsDiscover.nCountToWait > optsDiscover.cntNodes ) + optsDiscover.nCountToWait = optsDiscover.cntNodes; + if( log.verboseGet() >= log.verboseReversed().information ) { + if( ! optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + + cc.debug( "Will gather details of " ) + + cc.info( optsDiscover.nCountToWait ) + cc.debug( " of " ) + + cc.info( optsDiscover.cntNodes ) + cc.debug( " node(s)..." ) + + "\n" ); + } + } + await discoverSChainWalkNodes( optsDiscover ); + optsDiscover.nCountAvailable = optsDiscover.cntNodes - optsDiscover.cntFailed; + if( log.verboseGet() >= log.verboseReversed().information ) { + if( ! optsDiscover.isSilent ) { + log.write( cc.debug( "Waiting for S-Chain nodes, total " ) + + cc.warning( optsDiscover.cntNodes ) + cc.debug( ", available " ) + + cc.warning( optsDiscover.nCountAvailable ) + + cc.debug( ", expected at least " ) + + cc.warning( optsDiscover.nCountToWait ) + "\n" ); + } + } + if( optsDiscover.nCountAvailable < optsDiscover.nCountToWait ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + log.write( optsDiscover.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Not enough nodes available on S-Chain, total " ) + + cc.warning( optsDiscover.cntNodes ) + + cc.error( ", available " ) + + cc.warning( optsDiscover.nCountAvailable ) + + cc.error( ", expected at least " ) + + cc.warning( optsDiscover.nCountToWait ) + "\n" ); + } + } + const err = new Error( + "Not enough nodes available on S-Chain, total " + + optsDiscover.cntNodes + ", available " + optsDiscover.nCountAvailable + + ", expected at least " + optsDiscover.nCountToWait ); + optsDiscover.fnAfter( err, null ); + return; + } + await discoverSChainWait( optsDiscover ); + } ); + } ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( ! optsDiscover.isSilent ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( optsDiscover.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " JSON RPC call to S-Chain was not created: " ) + + cc.warning( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + } + optsDiscover.joSChainNetworkInfo = null; + optsDiscover.fnAfter( err, null ); + } + return optsDiscover.joSChainNetworkInfo; +} diff --git a/agent/loop.mjs b/agent/loop.mjs new file mode 100644 index 000000000..63920e5e0 --- /dev/null +++ b/agent/loop.mjs @@ -0,0 +1,757 @@ + +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file loop.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as networkLayer from "../npms/skale-cool-socket/socket.mjs"; +import * as url from "url"; +import { Worker } from "worker_threads"; +import * as path from "path"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as IMA from "../npms/skale-ima/index.mjs"; +import * as imaHelperAPIs from "../npms/skale-ima/imaHelperAPIs.mjs"; +import * as imaTransferErrorHandling from "../npms/skale-ima/imaTransferErrorHandling.mjs"; +import * as imaOracleOperations from "../npms/skale-ima/imaOracleOperations.mjs"; +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as imaBLS from "./bls.mjs"; +import * as skaleObserver from "../npms/skale-observer/observer.mjs"; +import * as pwa from "./pwa.mjs"; +import * as state from "./state.mjs"; + +const __dirname = path.dirname( url.fileURLToPath( import.meta.url ) ); + +// Run transfer loop + +export function checkTimeFraming( d, strDirection, joRuntimeOpts ) { + try { + const imaState = state.get(); + if( imaState.nTimeFrameSeconds <= 0 || imaState.nNodesCount <= 1 ) + return true; // time framing is disabled + + if( d == null || d == undefined ) + d = new Date(); // now + + const nFrameShift = 0; + + // Unix UTC timestamp, see: + // https://stackoverflow.com/questions/9756120/how-do-i-get-a-utc-timestamp-in-javascript + const nUtcUnixTimeStamp = Math.floor( ( d ).getTime() / 1000 ); + + const nSecondsRangeForAllSChains = imaState.nTimeFrameSeconds * imaState.nNodesCount; + const nMod = Math.floor( nUtcUnixTimeStamp % nSecondsRangeForAllSChains ); + let nActiveNodeFrameIndex = Math.floor( nMod / imaState.nTimeFrameSeconds ); + if( nFrameShift > 0 ) { + nActiveNodeFrameIndex += nFrameShift; + nActiveNodeFrameIndex %= imaState.nNodesCount; // for safety only + } + let bSkip = ( nActiveNodeFrameIndex != imaState.nNodeNumber ) ? true : false; + let bInsideGap = false; + + const nRangeStart = + nUtcUnixTimeStamp - + Math.floor( nUtcUnixTimeStamp % nSecondsRangeForAllSChains ); + const nFrameStart = nRangeStart + imaState.nNodeNumber * imaState.nTimeFrameSeconds; + const nGapStart = nFrameStart + imaState.nTimeFrameSeconds - imaState.nNextFrameGap; + if( !bSkip ) { + if( nUtcUnixTimeStamp >= nGapStart ) { + bSkip = true; + bInsideGap = true; + } + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( "\n" + + cc.info( "Unix UTC time stamp" ) + cc.debug( "........" ) + + cc.attention( nUtcUnixTimeStamp ) + "\n" + + cc.info( "All Chains Range" ) + cc.debug( "..........." ) + + cc.notice( nSecondsRangeForAllSChains ) + "\n" + + cc.info( "S-Chain Range Mod" ) + cc.debug( ".........." ) + + cc.notice( nMod ) + "\n" + + cc.info( "Active Node Frame Index" ) + cc.debug( "...." ) + + cc.notice( nActiveNodeFrameIndex ) + "\n" + + cc.info( "Testing Frame Index" ) + cc.debug( "........" ) + + cc.notice( imaState.nNodeNumber ) + "\n" + + cc.info( "Transfer Direction" ) + cc.debug( "........." ) + + cc.sunny( strDirection || "NA" ) + "\n" + + ( ( nFrameShift > 0 ) + ? ( cc.info( "Frame Shift" ) + cc.debug( "................" ) + + cc.note( nFrameShift ) + "\n" + + cc.info( "S2S known chain index" ) + cc.debug( "......" ) + + cc.note( joRuntimeOpts.idxChainKnownForS2S ) + "\n" + + cc.info( "S2S known chains count" ) + cc.debug( "....." ) + + cc.note( joRuntimeOpts.cntChainsKnownForS2S ) + + "\n" + + ( ( "joExtraSignOpts" in joRuntimeOpts && + typeof joRuntimeOpts.joExtraSignOpts == "object" ) + ? cc.info( "S-Chain source" ) + cc.debug( "............." ) + + cc.info( joRuntimeOpts.joExtraSignOpts.chainNameSrc ) + + cc.debug( "/" ) + + cc.attention( joRuntimeOpts.joExtraSignOpts.chainIdSrc ) + + "\n" + + cc.info( "S-Chain destination" ) + cc.debug( "........" ) + + cc.info( joRuntimeOpts.joExtraSignOpts.chainNameDst ) + + cc.debug( "/" ) + + cc.attention( joRuntimeOpts.joExtraSignOpts.chainIdDst ) + + "\n" + : "" ) + ) + : "" ) + + cc.info( "Is skip" ) + cc.debug( "...................." ) + + cc.yn( bSkip ) + "\n" + + cc.info( "Is inside gap" ) + cc.debug( ".............." ) + + cc.yn( bInsideGap ) + "\n" + + cc.info( "Range Start" ) + cc.debug( "................" ) + + cc.notice( nRangeStart ) + "\n" + + cc.info( "Frame Start" ) + cc.debug( "................" ) + + cc.notice( nFrameStart ) + "\n" + + cc.info( "Gap Start" ) + cc.debug( ".................." ) + + cc.notice( nGapStart ) + "\n" + ); + } + if( bSkip ) + return false; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Exception in time framing check: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return true; +}; + +async function singleTransferLoopPartOracle( optsLoop, strLogPrefix ) { + const imaState = state.get(); + let b0 = true; + if( optsLoop.enableStepOracle && imaOracleOperations.getEnabledOracle() ) { + if( log.verboseGet() >= log.verboseReversed().notice ) + log.write( strLogPrefix + cc.debug( "Will invoke Oracle gas price setup..." ) + "\n" ); + try { + if( ! await pwa.checkOnLoopStart( imaState, "oracle" ) ) { + imaState.loopState.oracle.wasInProgress = false; + if( log.verboseGet() >= log.verboseReversed().notice ) { + log.write( strLogPrefix + + cc.warning( "Skipped(oracle) due to cancel mode reported from PWA" ) + + "\n" ); + } + } else { + if( checkTimeFraming( null, "oracle", optsLoop.joRuntimeOpts ) ) { + imaState.loopState.oracle.isInProgress = true; + await pwa.notifyOnLoopStart( imaState, "oracle" ); + b0 = imaOracleOperations.doOracleGasPriceSetup( + imaState.chainProperties.mn.ethersProvider, + imaState.chainProperties.sc.ethersProvider, + imaState.chainProperties.sc.transactionCustomizer, + imaState.joCommunityLocker, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + imaBLS.doSignU256 + ); + imaState.loopState.oracle.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "oracle" ); + } else { + if( log.verboseGet() >= log.verboseReversed().notice ) { + log.write( strLogPrefix + + cc.warning( "Skipped(oracle) due to time framing check" ) + + "\n" ); + } + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( strLogPrefix + cc.error( "Oracle operation exception: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + imaState.loopState.oracle.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "oracle" ); + throw err; + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + cc.debug( "Oracle gas price setup done: " ) + cc.tf( b0 ) + + "\n" ); + } + } + return b0; +} + +async function singleTransferLoopPartM2S( optsLoop, strLogPrefix ) { + const imaState = state.get(); + let b1 = true; + if( optsLoop.enableStepM2S ) { + if( log.verboseGet() >= log.verboseReversed().notice ) + log.write( strLogPrefix + cc.debug( "Will invoke M2S transfer..." ) + "\n" ); + try { + if( ! await pwa.checkOnLoopStart( imaState, "m2s" ) ) { + imaState.loopState.m2s.wasInProgress = false; + if( log.verboseGet() >= log.verboseReversed().notice ) { + log.write( strLogPrefix + + cc.warning( "Skipped(m2s) due to cancel mode reported from PWA" ) + "\n" ); + } + } else { + if( checkTimeFraming( null, "m2s", optsLoop.joRuntimeOpts ) ) { + imaState.loopState.m2s.isInProgress = true; + await pwa.notifyOnLoopStart( imaState, "m2s" ); + b1 = await IMA.doTransfer( // main-net --> s-chain + "M2S", + optsLoop.joRuntimeOpts, + + imaState.chainProperties.mn.ethersProvider, + imaState.joMessageProxyMainNet, + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.ethersProvider, + imaState.joMessageProxySChain, + + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.mn.chainId, + imaState.chainProperties.sc.chainId, + null, + imaState.joTokenManagerETH, // for logs validation on s-chain + imaState.nTransferBlockSizeM2S, + imaState.nTransferStepsM2S, + imaState.nMaxTransactionsM2S, + imaState.nBlockAwaitDepthM2S, + imaState.nBlockAgeM2S, + imaBLS.doSignMessagesM2S, + null, + imaState.chainProperties.sc.transactionCustomizer + ); + imaState.loopState.m2s.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "m2s" ); + } else { + if( log.verboseGet() >= log.verboseReversed().notice ) { + log.write( strLogPrefix + + cc.warning( "Skipped(m2s) due to time framing check" ) + "\n" ); + } + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( strLogPrefix + cc.error( "M2S transfer exception: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + imaState.loopState.m2s.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "m2s" ); + throw err; + } + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( strLogPrefix + cc.debug( "M2S transfer done: " ) + cc.tf( b1 ) + "\n" ); + } else { + if( log.verboseGet() >= log.verboseReversed().debug ) + log.write( strLogPrefix + cc.debug( "Skipped M2S transfer." ) + "\n" ); + } + return b1; +} + +async function singleTransferLoopPartS2M( optsLoop, strLogPrefix ) { + const imaState = state.get(); + let b2 = true; + if( optsLoop.enableStepS2M ) { + if( log.verboseGet() >= log.verboseReversed().notice ) + log.write( strLogPrefix + cc.debug( "Will invoke S2M transfer..." ) + "\n" ); + try { + if( ! await pwa.checkOnLoopStart( imaState, "s2m" ) ) { + imaState.loopState.s2m.wasInProgress = false; + if( log.verboseGet() >= log.verboseReversed().notice ) { + log.write( strLogPrefix + + cc.warning( "Skipped(s2m) due to cancel mode reported from PWA" ) + "\n" ); + } + } else { + if( checkTimeFraming( null, "s2m", optsLoop.joRuntimeOpts ) ) { + imaState.loopState.s2m.isInProgress = true; + await pwa.notifyOnLoopStart( imaState, "s2m" ); + b2 = await IMA.doTransfer( // s-chain --> main-net + "S2M", + optsLoop.joRuntimeOpts, + + imaState.chainProperties.sc.ethersProvider, + imaState.joMessageProxySChain, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.mn.ethersProvider, + imaState.joMessageProxyMainNet, + + imaState.chainProperties.mn.joAccount, + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.mn.strChainName, + imaState.chainProperties.sc.chainId, + imaState.chainProperties.mn.chainId, + imaState.joDepositBoxETH, // for logs validation on mainnet + null, + imaState.nTransferBlockSizeS2M, + imaState.nTransferStepsS2M, + imaState.nMaxTransactionsS2M, + imaState.nBlockAwaitDepthS2M, + imaState.nBlockAgeS2M, + imaBLS.doSignMessagesS2M, + null, + imaState.chainProperties.mn.transactionCustomizer + ); + imaState.loopState.s2m.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "s2m" ); + } else { + if( log.verboseGet() >= log.verboseReversed().notice ) { + log.write( strLogPrefix + + cc.warning( "Skipped(s2m) due to time framing check" ) + "\n" ); + } + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( strLogPrefix + cc.error( "S2M transfer exception: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + imaState.loopState.s2m.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "s2m" ); + throw err; + } + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( strLogPrefix + cc.debug( "S2M transfer done: " ) + cc.tf( b2 ) + "\n" ); + } else { + if( log.verboseGet() >= log.verboseReversed().debug ) + log.write( strLogPrefix + cc.debug( "Skipped S2M transfer." ) + "\n" ); + } + return b2; +} + +async function singleTransferLoopPartS2S( optsLoop, strLogPrefix ) { + const imaState = state.get(); + let b3 = true; + if( optsLoop.enableStepS2S && imaState.optsS2S.isEnabled ) { + if( log.verboseGet() >= log.verboseReversed().notice ) + log.write( strLogPrefix + cc.debug( "Will invoke all S2S transfers..." ) + "\n" ); + try { + b3 = await IMA.doAllS2S( // s-chain --> s-chain + optsLoop.joRuntimeOpts, + imaState, + skaleObserver, + imaState.chainProperties.sc.ethersProvider, + imaState.joMessageProxySChain, + imaState.chainProperties.sc.joAccount, + imaState.chainProperties.sc.strChainName, + imaState.chainProperties.sc.chainId, + imaState.joTokenManagerETH, // for logs validation on s-chain + imaState.nTransferBlockSizeS2S, + imaState.nTransferStepsS2S, + imaState.nMaxTransactionsS2S, + imaState.nBlockAwaitDepthMSS, + imaState.nBlockAgeS2S, + imaBLS.doSignMessagesS2S, + imaState.chainProperties.sc.transactionCustomizer + ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( strLogPrefix + cc.error( "S2S transfer exception: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + throw err; + } + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( strLogPrefix + cc.debug( "All S2S transfers done: " ) + cc.tf( b3 ) + "\n" ); + + } else { + if( log.verboseGet() >= log.verboseReversed().debug ) + log.write( strLogPrefix + cc.debug( "Skipped S2S transfer." ) + "\n" ); + } + return b3; +} + +export async function singleTransferLoop( optsLoop ) { + const imaState = state.get(); + const strLogPrefix = cc.attention( "Single Loop:" ) + " "; + try { + if( log.verboseGet() >= log.verboseReversed().debug ) + log.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + if( ( optsLoop.enableStepOracle && imaState.loopState.oracle.isInProgress ) || + ( optsLoop.enableStepM2S && imaState.loopState.m2s.isInProgress ) || + ( optsLoop.enableStepS2M && imaState.loopState.s2m.isInProgress ) || + ( optsLoop.enableStepS2S && imaState.loopState.s2s.isInProgress ) + ) { + imaState.loopState.oracle.wasInProgress = false; + imaState.loopState.m2s.wasInProgress = false; + imaState.loopState.s2m.wasInProgress = false; + imaState.loopState.s2s.wasInProgress = false; + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( strLogPrefix + cc.warning( "Skipped due to other single " + + "transfer loop is in progress right now" ) + "\n" ); + } + return true; + } + const b0 = await singleTransferLoopPartOracle( optsLoop, strLogPrefix ); + const b1 = await singleTransferLoopPartM2S( optsLoop, strLogPrefix ); + const b2 = await singleTransferLoopPartS2M( optsLoop, strLogPrefix ); + const b3 = await singleTransferLoopPartS2S( optsLoop, strLogPrefix ); + const bResult = b0 && b1 && b2 && b3; + if( log.verboseGet() >= log.verboseReversed().notice ) + log.write( strLogPrefix + cc.debug( "Completed: " ) + cc.tf( bResult ) + "\n" ); + return bResult; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( strLogPrefix + cc.fatal( "Exception in single transfer loop: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + imaState.loopState.oracle.isInProgress = false; + imaState.loopState.m2s.isInProgress = false; + imaState.loopState.s2m.isInProgress = false; + imaState.loopState.s2s.isInProgress = false; + return false; +} +export async function singleTransferLoopWithRepeat( optsLoop ) { + const imaState = state.get(); + await singleTransferLoop( optsLoop ); + setTimeout( async function() { + await singleTransferLoopWithRepeat( optsLoop ); + }, imaState.nLoopPeriodSeconds * 1000 ); +}; +export async function runTransferLoop( optsLoop ) { + const imaState = state.get(); + const isDelayFirstRun = owaspUtils.toBoolean( optsLoop.isDelayFirstRun ); + if( isDelayFirstRun ) { + setTimeout( async function() { + await singleTransferLoopWithRepeat( optsLoop ); + }, imaState.nLoopPeriodSeconds * 1000 ); + } else + await singleTransferLoopWithRepeat( optsLoop ); + return true; +} + +// Parallel thread based loop + +const sleepImpl = ( milliseconds ) => { + return new Promise( resolve => setTimeout( resolve, milliseconds ) ); +}; + +const gArrWorkers = []; +const gArrClients = []; + +export function notifyCacheChangedSNB( arrSChainsCached ) { + const cntWorkers = gArrWorkers.length; + for( let idxWorker = 0; idxWorker < cntWorkers; ++ idxWorker ) { + const jo = { + "method": "schainsCached", + "message": { + "arrSChainsCached": arrSChainsCached + } + }; + gArrClients[idxWorker].send( jo ); + } +} + +skaleObserver.events.on( "chainsCacheChanged", function( eventData ) { + notifyCacheChangedSNB( eventData.detail.arrSChainsCached ); +} ); + +function constructChainProperties( opts ) { + return { + "mn": { + "joAccount": { + "privateKey": + opts.imaState.chainProperties.mn.joAccount.privateKey, + "address_": + opts.imaState.chainProperties.mn.joAccount.address_, + "strTransactionManagerURL": + opts.imaState.chainProperties.mn + .joAccount.strTransactionManagerURL, + "nTmPriority": + opts.imaState.chainProperties.mn.joAccount.nTmPriority, + "strSgxURL": + opts.imaState.chainProperties.mn.joAccount.strSgxURL, + "strSgxKeyName": + opts.imaState.chainProperties.mn.joAccount.strSgxKeyName, + "strPathSslKey": + opts.imaState.chainProperties.mn.joAccount.strPathSslKey, + "strPathSslCert": + opts.imaState.chainProperties.mn.joAccount.strPathSslCert, + "strBlsKeyName": + opts.imaState.chainProperties.mn.joAccount.strBlsKeyName + }, + "ethersProvider": null, + "strURL": opts.imaState.chainProperties.mn.strURL, + "strChainName": opts.imaState.chainProperties.mn.strChainName, + "chainId": opts.imaState.chainProperties.mn.chainId, + "joAbiIMA": opts.imaState.chainProperties.mn.joAbiIMA, + "bHaveAbiIMA": opts.imaState.chainProperties.mn.bHaveAbiIMA + }, + "sc": { + "joAccount": { + "privateKey": + opts.imaState.chainProperties.sc.joAccount.privateKey, + "address_": + opts.imaState.chainProperties.sc.joAccount.address_, + "strTransactionManagerURL": + opts.imaState.chainProperties.sc + .joAccount.strTransactionManagerURL, + "nTmPriority": + opts.imaState.chainProperties.sc.joAccount.nTmPriority, + "strSgxURL": + opts.imaState.chainProperties.sc.joAccount.strSgxURL, + "strSgxKeyName": + opts.imaState.chainProperties.sc.joAccount.strSgxKeyName, + "strPathSslKey": + opts.imaState.chainProperties.sc.joAccount.strPathSslKey, + "strPathSslCert": + opts.imaState.chainProperties.mn.joAccount.strPathSslCert, + "strBlsKeyName": + opts.imaState.chainProperties.mn.joAccount.strBlsKeyName + }, + "ethersProvider": null, + "strURL": opts.imaState.chainProperties.sc.strURL, + "strChainName": opts.imaState.chainProperties.sc.strChainName, + "chainId": opts.imaState.chainProperties.sc.chainId, + "joAbiIMA": opts.imaState.chainProperties.sc.joAbiIMA, + "bHaveAbiIMA": opts.imaState.chainProperties.sc.bHaveAbiIMA + }, + "tc": { + "joAccount": { + "privateKey": + opts.imaState.chainProperties.tc.joAccount.privateKey, + "address_": + opts.imaState.chainProperties.tc.joAccount.address_, + "strTransactionManagerURL": + opts.imaState.chainProperties.tc + .joAccount.strTransactionManagerURL, + "nTmPriority": + opts.imaState.chainProperties.tc.joAccount.nTmPriority, + "strSgxURL": + opts.imaState.chainProperties.tc.joAccount.strSgxURL, + "strSgxKeyName": + opts.imaState.chainProperties.tc.joAccount.strSgxKeyName, + "strPathSslKey": + opts.imaState.chainProperties.tc.joAccount.strPathSslKey, + "strPathSslCert": + opts.imaState.chainProperties.tc.joAccount.strPathSslCert, + "strBlsKeyName": + opts.imaState.chainProperties.tc.joAccount.strBlsKeyName + }, + "ethersProvider": null, + "strURL": opts.imaState.chainProperties.tc.strURL, + "strChainName": opts.imaState.chainProperties.tc.strChainName, + "chainId": opts.imaState.chainProperties.tc.chainId, + "joAbiIMA": opts.imaState.chainProperties.tc.joAbiIMA, + "bHaveAbiIMA": opts.imaState.chainProperties.tc.bHaveAbiIMA + } + }; +} + +export async function ensureHaveWorkers( opts ) { + if( gArrWorkers.length > 0 ) + return gArrWorkers; + const cntWorkers = 2; + for( let idxWorker = 0; idxWorker < cntWorkers; ++ idxWorker ) { + const workerData = { + url: "ima_loop_server" + idxWorker, + cc: { isEnabled: cc.isEnabled() } + }; + gArrWorkers.push( + new Worker( + path.join( __dirname, "loopWorker.mjs" ), + { "type": "module", "workerData": workerData } + ) + ); + gArrWorkers[idxWorker].on( "message", jo => { + if( networkLayer.outOfWorkerAPIs.onMessage( gArrWorkers[idxWorker], jo ) ) + return; + } ); + gArrClients.push( + new networkLayer.OutOfWorkerSocketClientPipe( + workerData.url, gArrWorkers[idxWorker] ) + ); + gArrClients[idxWorker].on( "message", async function( eventData ) { + const joMessage = eventData.message; + switch ( joMessage.method ) { + case "log": + log.write( cc.attention( "LOOP WORKER" ) + + " " + cc.notice( workerData.url ) + " " + joMessage.message + "\n" + ); + break; + case "saveTransferError": + imaTransferErrorHandling.saveTransferError( + joMessage.message.category, + joMessage.message.textLog, + joMessage.message.ts + ); + break; + case "saveTransferSuccess": + imaTransferErrorHandling.saveTransferSuccess( joMessage.message.category ); + break; + } // switch ( joMessage.method ) + } ); + await sleepImpl( 3 * 1000 ); + const optsLoop = { + joRuntimeOpts: { + isInsideWorker: true, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }, + isDelayFirstRun: false, + enableStepOracle: ( idxWorker == 0 ) ? true : false, + enableStepM2S: ( idxWorker == 0 ) ? true : false, + enableStepS2M: ( idxWorker == 1 ) ? true : false, + enableStepS2S: ( idxWorker == 0 ) ? true : false + }; + const jo = { + "method": "init", + "message": { + "opts": { + "imaState": { + "optsLoop": optsLoop, + "verbose_": log.verboseGet(), + "expose_details_": log.exposeDetailsGet(), + "arrSChainsCached": skaleObserver.getLastCachedSChains(), + "loopState": state.gDefaultValueForLoopState, + "isPrintGathered": opts.imaState.isPrintGathered, + "isPrintSecurityValues": opts.imaState.isPrintSecurityValues, + "isPrintPWA": opts.imaState.isPrintPWA, + "isDynamicLogInDoTransfer": opts.imaState.isDynamicLogInDoTransfer, + "isDynamicLogInBlsSigner": opts.imaState.isDynamicLogInBlsSigner, + "bIsNeededCommonInit": false, + "bSignMessages": opts.imaState.bSignMessages, + "joSChainNetworkInfo": opts.imaState.joSChainNetworkInfo, + "strPathBlsGlue": opts.imaState.strPathBlsGlue, + "strPathHashG1": opts.imaState.strPathHashG1, + "strPathBlsVerify": opts.imaState.strPathBlsVerify, + "isEnabledMultiCall": opts.imaState.isEnabledMultiCall, + + "bNoWaitSChainStarted": opts.imaState.bNoWaitSChainStarted, + "nMaxWaitSChainAttempts": opts.imaState.nMaxWaitSChainAttempts, + + "nTransferBlockSizeM2S": opts.imaState.nTransferBlockSizeM2S, + "nTransferBlockSizeS2M": opts.imaState.nTransferBlockSizeS2M, + "nTransferBlockSizeS2S": opts.imaState.nTransferBlockSizeS2S, + "nTransferStepsM2S": opts.imaState.nTransferStepsM2S, + "nTransferStepsS2M": opts.imaState.nTransferStepsS2M, + "nTransferStepsS2S": opts.imaState.nTransferStepsS2S, + "nMaxTransactionsM2S": opts.imaState.nMaxTransactionsM2S, + "nMaxTransactionsS2M": opts.imaState.nMaxTransactionsS2M, + "nMaxTransactionsS2S": opts.imaState.nMaxTransactionsS2S, + + "nBlockAwaitDepthM2S": opts.imaState.nBlockAwaitDepthM2S, + "nBlockAwaitDepthS2M": opts.imaState.nBlockAwaitDepthS2M, + "nBlockAwaitDepthS2S": opts.imaState.nBlockAwaitDepthS2S, + "nBlockAgeM2S": opts.imaState.nBlockAgeM2S, + "nBlockAgeS2M": opts.imaState.nBlockAgeS2M, + "nBlockAgeS2S": opts.imaState.nBlockAgeS2S, + + "nLoopPeriodSeconds": opts.imaState.nLoopPeriodSeconds, + + "nNodeNumber": opts.imaState.nNodeNumber, + "nNodesCount": opts.imaState.nNodesCount, + "nTimeFrameSeconds": opts.imaState.nTimeFrameSeconds, + "nNextFrameGap": opts.imaState.nNextFrameGap, + + "joCommunityPool": null, + "joDepositBoxETH": null, + "joDepositBoxERC20": null, + "joDepositBoxERC721": null, + "joDepositBoxERC1155": null, + "joDepositBoxERC721WithMetadata": null, + "joLinker": null, + + "isWithMetadata721": false, + + "joTokenManagerETH": null, + "joTokenManagerERC20": null, + "joTokenManagerERC20Target": null, + "joTokenManagerERC721": null, + "joTokenManagerERC721Target": null, + "joTokenManagerERC1155": null, + "joTokenManagerERC1155Target": null, + "joTokenManagerERC721WithMetadata": null, + "joTokenManagerERC721WithMetadataTarget": null, + "joCommunityLocker": null, + "joCommunityLockerTarget": null, + "joMessageProxyMainNet": null, + "joMessageProxySChain": null, + "joMessageProxySChainTarget": null, + "joTokenManagerLinker": null, + "joTokenManagerLinkerTarget": null, + "joEthErc20": null, + "joEthErc20Target": null, + + "chainProperties": constructChainProperties( opts ), + "joAbiSkaleManager": opts.imaState.joAbiSkaleManager, + "bHaveSkaleManagerABI": opts.imaState.bHaveSkaleManagerABI, + + "strChainNameOriginChain": opts.imaState.strChainNameOriginChain, + + "isPWA": opts.imaState.isPWA, + "nTimeoutSecondsPWA": opts.imaState.nTimeoutSecondsPWA, + + "strReimbursementChain": opts.imaState.strReimbursementChain, + "isShowReimbursementBalance": opts.imaState.isShowReimbursementBalance, + "nReimbursementRecharge": opts.imaState.nReimbursementRecharge, + "nReimbursementWithdraw": opts.imaState.nReimbursementWithdraw, + "nReimbursementRange": opts.imaState.nReimbursementRange, + + "joSChainDiscovery": { + "isSilentReDiscovery": + opts.imaState.joSChainDiscovery.isSilentReDiscovery, + "repeatIntervalMilliseconds": + opts.imaState.joSChainDiscovery.repeatIntervalMilliseconds + }, + + "optsS2S": { // S-Chain to S-Chain transfer options + "isEnabled": true, + "secondsToReDiscoverSkaleNetwork": 1 * 60 * 60 + }, + + "nJsonRpcPort": opts.imaState.nJsonRpcPort, + "isCrossImaBlsMode": opts.imaState.isCrossImaBlsMode + } + }, + "cc": { + "isEnabled": cc.isEnabled() + } + } + }; + gArrClients[idxWorker].send( jo ); + } +} + +export async function runParallelLoops( opts ) { + if( log.verboseGet() >= log.verboseReversed().notice ) + log.write( cc.debug( "Will start parallel IMA transfer loops..." ) + "\n" ); + await ensureHaveWorkers( opts ); + if( log.verboseGet() >= log.verboseReversed().notice ) + log.write( cc.success( "Done, did parallel IMA transfer loops." ) + "\n" ); + return true; +} + +export async function spreadArrivedStateOfPendingWorkAnalysis( joMessage ) { + if( ! ( joMessage && typeof joMessage == "object" && + "method" in joMessage && joMessage.method == "skale_imaNotifyLoopWork" ) + ) + return; + const cntWorkers = gArrWorkers.length; + for( let idxWorker = 0; idxWorker < cntWorkers; ++ idxWorker ) + gArrClients[idxWorker].send( joMessage ); + +} diff --git a/agent/loopWorker.mjs b/agent/loopWorker.mjs new file mode 100644 index 000000000..f8458424f --- /dev/null +++ b/agent/loopWorker.mjs @@ -0,0 +1,216 @@ + +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file loopWorker.mjs + * @copyright SKALE Labs 2019-Present + */ + +import { parentPort, workerData } from "worker_threads"; +import * as networkLayer from "../npms/skale-cool-socket/socket.mjs"; +import { SocketServer } from "../npms/skale-cool-socket/socketServer.mjs"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as loop from "./loop.mjs"; +import * as imaTx from "../npms/skale-ima/imaTx.mjs"; +import * as imaTransferErrorHandling from "../npms/skale-ima/imaTransferErrorHandling.mjs"; +import * as skaleObserver from "../npms/skale-observer/observer.mjs"; +import * as imaCLI from "./cli.mjs"; +import * as state from "./state.mjs"; +import * as pwa from "./pwa.mjs"; +import * as log from "../npms/skale-log/log.mjs"; + +let imaState = state.get(); + +parentPort.on( "message", jo => { + if( networkLayer.inWorkerAPIs.onMessage( jo ) ) + return; +} ); + +function doSendMessage( type, endpoint, workerUUID, data ) { + const jo = networkLayer.socketReceivedDataReverseMarshall( data ); + const joSend = { + "workerMessageType": + ( type && typeof type == "string" && type.length > 0 ) + ? type + : "inWorkerMessage", + "workerEndPoint": endpoint, + "workerUUID": workerUUID, + "data": jo + }; + parentPort.postMessage( networkLayer.socketSentDataMarshall( joSend ) ); +} + +class ObserverServer extends SocketServer { + constructor( acceptor ) { + super( acceptor ); + const self = this; + cc.enable( workerData.cc.isEnabled ); + self.opts = null; + self.intervalPeriodicSchainsCaching = null; + self.bIsPeriodicCachingStepInProgress = false; + self.mapApiHandlers.init = function( joMessage, joAnswer, eventData, socket ) { + self.log = function() { + const args = Array.prototype.slice.call( arguments ); + const jo = { + "method": "log", + "error": null, + "message": args.join( " " ) + }; + const isFlush = true; + socket.send( jo, isFlush ); + }; + self.opts = JSON.parse( JSON.stringify( joMessage.message.opts ) ); + self.opts.details = { + write: self.log + }; + cc.enable( joMessage.message.cc.isEnabled ); + log.verboseSet( self.opts.imaState.verbose_ ); + log.exposeDetailsSet( self.opts.imaState.expose_details_ ); + imaTransferErrorHandling.saveTransferEvents.on( "error", function( eventData ) { + const jo = { + "method": "saveTransferError", + "message": eventData.detail + }; + const isFlush = true; + socket.send( jo, isFlush ); + } ); + imaTransferErrorHandling.saveTransferEvents.on( "success", function( eventData ) { + const jo = { + "method": "saveTransferSuccess", + "message": eventData.detail + }; + const isFlush = true; + socket.send( jo, isFlush ); + } ); + skaleObserver.setLastCachedSChains( self.opts.imaState.arrSChainsCached ); + joAnswer.message = { + "method": "" + joMessage.method, + "error": null + }; + self.opts.imaState.chainProperties.mn.joAccount.address = owaspUtils.fnAddressImpl_; + self.opts.imaState.chainProperties.sc.joAccount.address = owaspUtils.fnAddressImpl_; + if( self.opts.imaState.chainProperties.mn.strURL && + typeof self.opts.imaState.chainProperties.mn.strURL == "string" && + self.opts.imaState.chainProperties.mn.strURL.length > 0 + ) { + const u = self.opts.imaState.chainProperties.mn.strURL; + self.opts.imaState.chainProperties.mn.ethersProvider = + owaspUtils.getEthersProviderFromURL( u ); + } else { + if( log.verboseGet() >= log.verboseReversed().warning ) { + self.log( cc.warning( "WARNING:" ) + cc.warning( " No " ) + + cc.note( "Main-net" ) + + cc.warning( " URL specified in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + "\n" ); + } + } + + if( self.opts.imaState.chainProperties.sc.strURL && + typeof self.opts.imaState.chainProperties.sc.strURL == "string" && + self.opts.imaState.chainProperties.sc.strURL.length > 0 + ) { + const u = self.opts.imaState.chainProperties.sc.strURL; + self.opts.imaState.chainProperties.sc.ethersProvider = + owaspUtils.getEthersProviderFromURL( u ); + } else { + if( log.verboseGet() >= log.verboseReversed().warning ) { + self.log( cc.warning( "WARNING:" ) + cc.warning( " No " ) + + cc.note( "Main-net" ) + + cc.warning( " URL specified in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + "\n" ); + } + } + + self.opts.imaState.optsLoop.joRuntimeOpts.isInsideWorker = true; + imaState = self.opts.imaState; + imaState.chainProperties.mn.ethersProvider = null; + imaState.chainProperties.sc.ethersProvider = null; + imaState.chainProperties.tc.ethersProvider = null; + imaState.chainProperties.mn.transactionCustomizer = + imaTx.getTransactionCustomizerForMainNet(); + imaState.chainProperties.sc.transactionCustomizer = + imaTx.getTransactionCustomizerForSChain(); + imaState.chainProperties.tc.transactionCustomizer = + imaTx.getTransactionCustomizerForSChainTarget(); + state.set( imaState ); + imaCLI.initContracts(); + if( log.verboseGet() >= log.verboseReversed().information ) { + self.log( cc.debug( "IMA loop worker" ) + " " + cc.notice( workerData.url ) + + cc.debug( " will do the following work:" ) + "\n" + " " + + cc.info( "Oracle" ) + cc.debug( " operations....." ) + + cc.yn( self.opts.imaState.optsLoop.enableStepOracle ) + "\n" + + " " + cc.info( "M2S" ) + cc.debug( " transfers........." ) + + cc.yn( self.opts.imaState.optsLoop.enableStepM2S ) + "\n" + + " " + cc.info( "S2M" ) + cc.debug( " transfers........." ) + + cc.yn( self.opts.imaState.optsLoop.enableStepS2M ) + "\n" + + " " + cc.info( "S2S" ) + cc.debug( " transfers........." ) + + cc.yn( self.opts.imaState.optsLoop.enableStepS2S ) + "\n" ); + } + /* await */ + loop.runTransferLoop( self.opts.imaState.optsLoop ); + if( log.verboseGet() >= log.verboseReversed().information ) { + self.log( cc.debug( "Full init compete for in-worker IMA loop" ) + + " " + cc.notice( workerData.url ) + "\n" ); + } + return joAnswer; + }; + self.mapApiHandlers.schainsCached = function( joMessage, joAnswer, eventData, socket ) { + skaleObserver.setLastCachedSChains( joMessage.message.arrSChainsCached ); + }; + // eslint-disable-next-line dot-notation + self.mapApiHandlers["skale_imaNotifyLoopWork"] = + function( joMessage, joAnswer, eventData, socket ) { + pwa.handleLoopStateArrived( // NOTICE: no await here, executed async + imaState, + owaspUtils.toInteger( joMessage.params.nNodeNumber ), + joMessage.params.strLoopWorkType, + joMessage.params.nIndexS2S, + joMessage.params.isStart ? true : false, + owaspUtils.toInteger( joMessage.params.ts ), + joMessage.params.signature + ); + }; + if( log.verboseGet() >= log.verboseReversed().information ) { + self.log( cc.debug( "Initialized in-worker IMA loop " ) + + cc.info( workerData.url ) + cc.debug( " server" ) + "\n" ); + } + } + dispose() { + const self = this; + self.isDisposing = true; + if( self.intervalPeriodicSchainsCaching ) { + clearInterval( self.intervalPeriodicSchainsCaching ); + self.intervalPeriodicSchainsCaching = null; + } + super.dispose(); + } +}; + +const acceptor = new networkLayer.InWorkerSocketServerAcceptor( workerData.url, doSendMessage ); +const server = new ObserverServer( acceptor ); +server.on( "dispose", function() { + const self = server; + if( log.verboseGet() >= log.verboseReversed().debug ) { + self.log( cc.debug( "Disposed in-worker IMA loop" ) + + " " + cc.notice( workerData.url ) + "\n" ); + } +} ); diff --git a/agent/main.js b/agent/main.js deleted file mode 100644 index 58f1c25a7..000000000 --- a/agent/main.js +++ /dev/null @@ -1,2624 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file main.js - * @copyright SKALE Labs 2019-Present - */ - -process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; // allow self-signed wss and https - -// const fs = require( "fs" ); -// const path = require( "path" ); -// const url = require( "url" ); -// const os = require( "os" ); -const ws = require( "ws" ); // https://www.npmjs.com/package/ws -global.IMA = require( "../npms/skale-ima" ); -global.w3mod = IMA.w3mod; -global.ethereumjs_tx = IMA.ethereumjs_tx; -global.ethereumjs_wallet = IMA.ethereumjs_wallet; -global.ethereumjs_util = IMA.ethereumjs_util; -global.compose_tx_instance = IMA.compose_tx_instance; -global.owaspUtils = IMA.owaspUtils; -global.imaUtils = require( "./utils.js" ); -IMA.expose_details_set( false ); -IMA.verbose_set( IMA.verbose_parse( "info" ) ); -global.log = global.imaUtils.log; -global.cc = global.imaUtils.cc; -global.imaCLI = require( "./cli.js" ); -global.imaBLS = require( "./bls.js" ); -global.rpcCall = require( "./rpc-call.js" ); -global.skale_observer = require( "../npms/skale-observer/observer.js" ); -global.rpcCall.init(); -global.imaOracle = require( "./oracle.js" ); -global.imaOracle.init(); - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -global.imaState = { - "strLogFilePath": "", - "nLogMaxSizeBeforeRotation": -1, - "nLogMaxFilesCount": -1, - "isPrintGathered": true, - "isPrintSecurityValues": false, - - "bIsNeededCommonInit": true, - "bSignMessages": false, // use BLS message signing, turned on with --sign-messages - "joSChainNetworkInfo": null, // scanned S-Chain network description - "strPathBlsGlue": "", // path to bls_glue app, must have if --sign-messages specified - "strPathHashG1": "", // path to hash_g1 app, must have if --sign-messages specified - "strPathBlsVerify": "", // path to verify_bls app, optional, if specified then we will verify gathered BLS signature - - "joAbiPublishResult_skale_manager": { }, - "joAbiPublishResult_main_net": { }, - "joAbiPublishResult_s_chain": { }, - "joAbiPublishResult_t_chain": { }, - "bHaveSkaleManagerABI": false, - "bHaveImaAbiMainNet": false, - "bHaveImaAbiSchain": false, - "bHaveImaAbiSchainTarget": false, - - "joErc20_main_net": null, - "joErc20_s_chain": null, - "joErc20_t_chain": null, - "strAddrErc20_explicit": "", - "strAddrErc20_explicit_target": "", // S<->S target - "strCoinNameErc20_main_net": "", // in-JSON coin name - "strCoinNameErc20_s_chain": "", // in-JSON coin name - "strCoinNameErc20_t_chain": "", // in-JSON coin name - - "joErc721_main_net": null, - "joErc721_s_chain": null, - "joErc721_t_chain": null, - "strAddrErc721_explicit": "", - "strAddrErc721_explicit_target": "", // S<->S target - "strCoinNameErc721_main_net": "", // in-JSON coin name - "strCoinNameErc721_s_chain": "", // in-JSON coin name - "strCoinNameErc721_t_chain": "", // in-JSON coin name - - "joErc1155_main_net": null, - "joErc1155_s_chain": null, - "joErc1155_t_chain": null, - "strAddrErc1155_explicit": "", - "strAddrErc1155_explicit_target": "", // S<->S target - "strCoinNameErc1155_main_net": "", // in-JSON coin name - "strCoinNameErc1155_s_chain": "", // in-JSON coin name - "strCoinNameErc1155_t_chain": "", // in-JSON coin name - - "strPathAbiJson_skale_manager": "", // imaUtils.normalizePath( "../proxy/data/skaleManager.json" ), - "strPathAbiJson_main_net": null, // imaUtils.normalizePath( "../proxy/data/proxyMainnet.json" ), - "strPathAbiJson_s_chain": null, // imaUtils.normalizePath( "../proxy/data/proxySchain.json" ), - "strPathAbiJson_t_chain": null, // imaUtils.normalizePath( "../proxy/data/proxySchainTarget.json" ), - - "bShowConfigMode": false, // true - just show configuration values and exit - - "bNoWaitSChainStarted": false, - "nMaxWaitSChainAttempts": 0 + Number.MAX_SAFE_INTEGER, // 20 - "isPreventExitAfterLastAction": false, - - "strURL_main_net": owaspUtils.toStringURL( process.env.URL_W3_ETHEREUM ), // example: "http://127.0.0.1:8545" - "strURL_s_chain": owaspUtils.toStringURL( process.env.URL_W3_S_CHAIN ), // example: "http://127.0.0.1:2231" - "strURL_t_chain": owaspUtils.toStringURL( process.env.URL_W3_S_CHAIN_TARGET ), // example: "http://127.0.0.1:2231" - - "strChainName_main_net": ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), - "strChainName_s_chain": ( process.env.CHAIN_NAME_SCHAIN || "id-S-chain" ).toString().trim(), - "strChainName_origin_chain": ( process.env.CHAIN_NAME_SCHAIN_ORIGIN || "Mainnet" ).toString().trim(), - "strChainName_t_chain": ( process.env.CHAIN_NAME_SCHAIN_TARGET || "id-T-chain" ).toString().trim(), - "cid_main_net": owaspUtils.toInteger( process.env.CID_ETHEREUM ) || -4, - "cid_s_chain": owaspUtils.toInteger( process.env.CID_SCHAIN ) || -4, - "cid_t_chain": owaspUtils.toInteger( process.env.CID_SCHAIN_TARGET ) || -4, - - "strPathJsonErc20_main_net": "", - "strPathJsonErc20_s_chain": "", - "strPathJsonErc20_t_chain": "", - "strPathJsonErc721_main_net": "", - "strPathJsonErc721_s_chain": "", - "strPathJsonErc721_t_chain": "", - "strPathJsonErc1155_main_net": "", - "strPathJsonErc1155_s_chain": "", - "strPathJsonErc1155_t_chain": "", - - "nAmountOfWei": 0, - "nAmountOfToken": 0, - "arrAmountsOfTokens": null, - "idToken": 0, - - "nTransferBlockSizeM2S": 4, // 10 - "nTransferBlockSizeS2M": 4, // 10 - "nTransferBlockSizeS2S": 4, // 10 - "nMaxTransactionsM2S": 0, - "nMaxTransactionsS2M": 0, - "nMaxTransactionsS2S": 0, - - "nBlockAwaitDepthM2S": 0, - "nBlockAwaitDepthS2M": 0, - "nBlockAwaitDepthS2S": 0, - "nBlockAgeM2S": 0, - "nBlockAgeS2M": 0, - "nBlockAgeS2S": 0, - - "nLoopPeriodSeconds": 10, - - "nNodeNumber": 0, // S-Chain node number(zero based) - "nNodesCount": 1, - "nTimeFrameSeconds": 0, // 0-disable, 60-recommended - "nNextFrameGap": 10, - - "nAutoExitAfterSeconds": 3600, // 0-disable - - "w3_main_net": null, - "w3_s_chain": null, - "w3_t_chain": null, - - "jo_community_pool": null, // only main net - "jo_deposit_box_eth": null, // only main net - "jo_deposit_box_erc20": null, // only main net - "jo_deposit_box_erc721": null, // only main net - "jo_deposit_box_erc1155": null, // only main net - "jo_deposit_box_erc721_with_metadata": null, // only main net - "jo_linker": null, // only main net - - "isWithMetadata721": false, - - "jo_token_manager_eth": null, // only s-chain - // "jo_token_manager_eth_target": null, // only s-chain target - "jo_token_manager_erc20": null, // only s-chain - "jo_token_manager_erc20_target": null, // only s-chain - "jo_token_manager_erc721": null, // only s-chain target - "jo_token_manager_erc721_target": null, // only s-chain target - "jo_token_manager_erc1155": null, // only s-chain - "jo_token_manager_erc1155_target": null, // only s-chain target - "jo_token_manager_erc721_with_metadata": null, // only s-chain target - "jo_token_manager_erc721_with_metadata_target": null, // only s-chain target - "jo_community_locker": null, // only s-chain - "jo_community_locker_target": null, // only s-chain target - "jo_message_proxy_main_net": null, - "jo_message_proxy_s_chain": null, - "jo_message_proxy_s_chain_target": null, // only s-chain target - "jo_token_manager_linker": null, - "jo_token_manager_linker_target": null, // only s-chain target - "eth_erc20": null, // only s-chain - // "eth_erc721": null, // only s-chain - // "eth_erc1155": null, // only s-chain - "eth_erc20_target": null, // only s-chain target - // "eth_erc721_target": null, // only s-chain target - // "eth_erc1155_target": null, // only s-chain target - - // - // example: - // - // "joAccount_main_net": { "name": "g3", "privateKey": "", "address": IMA.owaspUtils.fn_address_impl_ }, - // "joAccount_s_chain ": { "name": "Bob", "privateKey": "", "address": IMA.owaspUtils.fn_address_impl_ }, - // "joAccount_t_chain ": { "name": "Alice", "privateKey": "", "address": IMA.owaspUtils.fn_address_impl_ }, - // - // - // example of empty values to fill from command line arguments: - // - // "joAccount_main_net": { "privateKey": "", "address": IMA.owaspUtils.fn_address_impl_ }, - // "joAccount_s_chain": { "privateKey": "", "address": IMA.owaspUtils.fn_address_impl_ }, - // "joAccount_t_chain": { "privateKey": "", "address": IMA.owaspUtils.fn_address_impl_ }, - // - "joAccount_main_net": { - "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_ETHEREUM ), - "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_ETHEREUM ), - "tm_priority": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_PRIORITY_ETHEREUM ) || 5, - "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_ETHEREUM ), - "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_ETHEREUM ), - "strPathSslKey": ( process.env.SGX_SSL_KEY_FILE_ETHEREUM || "" ).toString().trim(), - "strPathSslCert": ( process.env.SGX_SSL_CERT_FILE_ETHEREUM || "" ).toString().trim() - }, - "joAccount_s_chain": { - "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN ), - "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_S_CHAIN ), - "tm_priority": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_PRIORITY_S_CHAIN ) || 5, - "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN ), - "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN ), - "strPathSslKey": ( process.env.SGX_SSL_KEY_FILE_S_CHAIN || "" ).toString().trim(), - "strPathSslCert": ( process.env.SGX_SSL_CERT_FILE_S_CHAIN || "" ).toString().trim() - }, - "joAccount_t_chain": { - "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN_TARGET ), - "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_S_CHAIN_TARGET ), - "tm_priority": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_PRIORITY_S_CHAIN_TARGET ) || 5, - "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN_TARGET ), - "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN_TARGET ), - "strPathSslKey": ( process.env.SGX_SSL_KEY_FILE_S_CHAIN_TARGET || "" ).toString().trim(), - "strPathSslCert": ( process.env.SGX_SSL_CERT_FILE_S_CHAIN_TARGET || "" ).toString().trim() - }, - - // - "tc_main_net": IMA.tc_main_net, - "tc_s_chain": IMA.tc_s_chain, - "tc_t_chain": IMA.tc_t_chain, - // - - "doEnableDryRun": function( isEnable ) { return IMA.dry_run_enable( isEnable ); }, - "doIgnoreDryRun": function( isIgnore ) { return IMA.dry_run_ignore( isIgnore ); }, - - "optsPendingTxAnalysis": { - "isEnabled": false, // disable bv default - "nTimeoutSecondsBeforeSecondAttempt": 3, // 0 - disable 2nd attempt - "isIgnore": false, // ignore PTX result - "isIgnore2": true // ignore secondary PTX result - }, - - "nMonitoringPort": 0, // 0 - default, means monitoring server is disabled - - "strReimbursementChain": "", - "isShowReimbursementBalance": false, - "nReimbursementRecharge": 0, - "nReimbursementWithdraw": 0, - "nReimbursementRange": -1, // < 0 - do not change anything - - "joSChainDiscovery": { - "isSilentReDiscovery": true, - "repeatIntervalMilliseconds": 10 * 1000 // zero to disable (for debugging only) - }, - - "s2s_opts": { // S-Chain to S-Chain transfer options - "isEnabled": true, // is S-Chain to S-Chain transfers enabled - "secondsToReDiscoverSkaleNetwork": 1 * 60 * 60 // seconts to re-discover SKALE network, 0 to disable - }, - - "arrActions": [] // array of actions to run -}; - -const tmp_address_MN_from_env = owaspUtils.toEthPrivateKey( process.env.ACCOUNT_FOR_ETHEREUM ); -const tmp_address_SC_from_env = owaspUtils.toEthPrivateKey( process.env.ACCOUNT_FOR_SCHAIN ); -const tmp_address_TC_from_env = owaspUtils.toEthPrivateKey( process.env.ACCOUNT_FOR_SCHAIN_TARGET ); -if( tmp_address_MN_from_env && typeof tmp_address_MN_from_env == "string" && tmp_address_MN_from_env.length > 0 ) - imaState.joAccount_main_net.address_ = "" + tmp_address_MN_from_env; -if( tmp_address_SC_from_env && typeof tmp_address_SC_from_env == "string" && tmp_address_SC_from_env.length > 0 ) - imaState.joAccount_s_chain.address_ = "" + tmp_address_SC_from_env; -if( tmp_address_TC_from_env && typeof tmp_address_TC_from_env == "string" && tmp_address_TC_from_env.length > 0 ) - imaState.joAccount_t_chain.address_ = "" + tmp_address_TC_from_env; - -imaBLS.init(); - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const fnInitActionSkaleNetworkScanForS2S = function() { - if( ! imaState.s2s_opts.isEnabled ) - return; - imaState.arrActions.push( { - "name": "SKALE network scan for S2S", - "fn": async function() { - const strLogPrefix = cc.info( "SKALE network scan for S2S:" ) + " "; - if( imaState.strPathAbiJson_skale_manager.length === 0 ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " missing Skale Manager ABI, please specify " ) + cc.info( "abi-skale-manager" ) ); - process.exit( 153 ); - } - log.write( strLogPrefix + cc.debug( "Downloading SKALE network information..." ) + "\n" ); // just print value - const opts = { - imaState: imaState, - "details": log, - "bStopNeeded": false, - "secondsToReDiscoverSkaleNetwork": imaState.s2s_opts.secondsToReDiscoverSkaleNetwork - }; - const addressFrom = imaState.joAccount_main_net.address( imaState.w3_main_net ); - // const strError = await skale_observer.cache_schains( - // imaState.strChainName_s_chain, // strChainNameConnectedTo - // imaState.w3_main_net, - // imaState.w3_s_chain, - // addressFrom, - // opts - // ); - // if( strError ) { - // log.write( strLogPrefix + cc.error( "Failed to get " ) + cc.info( "SKALE NETWORK" ) + cc.error( " information: " ) + cc.warning( strError ) + "\n" ); - // return true; - // } - // const arr_schains = skale_observer.get_last_cached_schains(); - // log.write( strLogPrefix + cc.normal( "Got " ) + cc.info( "SKALE NETWORK" ) + cc.normal( " information: " ) + cc.j( arr_schains ) + "\n" ); - log.write( strLogPrefix + cc.debug( "Will start periodic S-Chains caching..." ) + "\n" ); - await skale_observer.periodic_caching_start( - imaState.strChainName_s_chain, // strChainNameConnectedTo - imaState.w3_main_net, - imaState.w3_s_chain, - addressFrom, - opts - ); - log.write( strLogPrefix + cc.success( "Done, did started periodic S-Chains caching." ) + "\n" ); - return true; - } - } ); -}; - -imaCLI.init(); -imaCLI.parse( { - "register": function() { - imaState.arrActions.push( { - "name": "Full registration(all steps)", - "fn": async function() { - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // register_all - return await register_all( true ); - } - } ); - }, - "register1": function() { - imaState.arrActions.push( { - "name": "Registration step 1, register S-Chain in deposit box", - "fn": async function() { - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // register_step1 - return await register_step1( true ); - } - } ); - }, - "check-registration": function() { - imaState.arrActions.push( { - "name": "Full registration status check(all steps)", - "fn": async function() { - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // check_registration_all - const b = await check_registration_all(); - const nExitCode = b ? 0 : 150; // 0 - OKay - registered; non-zero - not registered or error - log.write( cc.notice( "Exiting with code " ) + cc.info( nExitCode ) + "\n" ); - process.exit( nExitCode ); - } - } ); - }, - "check-registration1": function() { - imaState.arrActions.push( { - "name": "Registration status check step 1, register S-Chain in deposit box", - "fn": async function() { - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // check_registration_step1 - const b = await check_registration_step1(); - const nExitCode = b ? 0 : 152; // 0 - OKay - registered; non-zero - not registered or error - log.write( cc.notice( "Exiting with code " ) + cc.info( nExitCode ) + "\n" ); - process.exit( nExitCode ); - } - } ); - }, - "mint-erc20": function() { - imaState.arrActions.push( { - "name": "mint ERC20", - "fn": async function() { - let bMintIsOK = false; - if( imaState.strCoinNameErc20_t_chain.length > 0 ) { - try { - const strAddressMintTo = imaState.joAccount_t_chain.address( imaState.w3_t_chain ); // same as caller/transaction signer - bMintIsOK = await IMA.mintERC20( - imaState.w3_t_chain, - imaState.cid_t_chain, - imaState.strChainName_t_chain, - imaState.joAccount_t_chain, - strAddressMintTo, - imaState.nAmountOfToken, - imaState.joErc20_t_chain[imaState.strCoinNameErc20_t_chain + "_address"], - imaState.joErc20_t_chain[imaState.strCoinNameErc20_t_chain + "_abi"], - imaState.tc_t_chain - ) ? true : false; - } catch ( err ) { - bMintIsOK = false; - } - } - return bMintIsOK; - } - } ); - }, - "mint-erc721": function() { - imaState.arrActions.push( { - "name": "mint ERC721", - "fn": async function() { - let bMintIsOK = false; - if( imaState.strCoinNameErc721_t_chain.length > 0 ) { - try { - const strAddressMintTo = imaState.joAccount_t_chain.address( imaState.w3_t_chain ); // same as caller/transaction signer - const idTokens = imaState.have_idTokens ? imaState.idTokens : []; - if( imaState.have_idToken ) - idTokens.push( imaState.idToken ); - if( idTokens.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - bMintIsOK = await IMA.mintERC721( - imaState.w3_t_chain, - imaState.cid_t_chain, - imaState.strChainName_t_chain, - imaState.joAccount_t_chain, - strAddressMintTo, - idToken, - imaState.joErc721_t_chain[imaState.strCoinNameErc721_t_chain + "_address"], - imaState.joErc721_t_chain[imaState.strCoinNameErc721_t_chain + "_abi"], - imaState.tc_t_chain - ) ? true : false; - } - } - - } catch ( err ) { - bMintIsOK = false; - } - } - return bMintIsOK; - } - } ); - }, - "mint-erc1155": function() { - imaState.arrActions.push( { - "name": "mint ERC1155", - "fn": async function() { - let bMintIsOK = false; - if( imaState.strCoinNameErc1155_t_chain.length > 0 ) { - try { - const strAddressMintTo = imaState.joAccount_t_chain.address( imaState.w3_t_chain ); // same as caller/transaction signer - const idTokens = imaState.have_idTokens ? imaState.idTokens : []; - if( imaState.have_idToken ) - idTokens.push( imaState.idToken ); - if( idTokens.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - bMintIsOK = await IMA.mintERC1155( - imaState.w3_t_chain, - imaState.cid_t_chain, - imaState.strChainName_t_chain, - imaState.joAccount_t_chain, - strAddressMintTo, - idToken, - imaState.nAmountOfToken, - imaState.joErc1155_t_chain[imaState.strCoinNameErc1155_t_chain + "_address"], - imaState.joErc1155_t_chain[imaState.strCoinNameErc1155_t_chain + "_abi"], - imaState.tc_t_chain - ) ? true : false; - } - } - - } catch ( err ) { - bMintIsOK = false; - } - } - return bMintIsOK; - } - } ); - }, - "burn-erc20": function() { - imaState.arrActions.push( { - "name": "burn ERC20", - "fn": async function() { - let bBurnIsOK = false; - if( imaState.strCoinNameErc20_t_chain.length > 0 ) { - try { - const strAddressBurnFrom = imaState.joAccount_t_chain.address( imaState.w3_t_chain ); // same as caller/transaction signer - bBurnIsOK = await IMA.burnERC20( - imaState.w3_t_chain, - imaState.cid_t_chain, - imaState.strChainName_t_chain, - imaState.joAccount_t_chain, - strAddressBurnFrom, - imaState.nAmountOfToken, - imaState.joErc20_t_chain[imaState.strCoinNameErc20_t_chain + "_address"], - imaState.joErc20_t_chain[imaState.strCoinNameErc20_t_chain + "_abi"], - imaState.tc_t_chain - ) ? true : false; - } catch ( err ) { - bBurnIsOK = false; - } - } - return bBurnIsOK; - } - } ); - }, - "burn-erc721": function() { - imaState.arrActions.push( { - "name": "burn ERC721", - "fn": async function() { - let bBurnIsOK = false; - if( imaState.strCoinNameErc721_t_chain.length > 0 ) { - try { - // const strAddressBurnFrom = imaState.joAccount_t_chain.address( imaState.w3_t_chain ); // same as caller/transaction signer - const idTokens = imaState.have_idTokens ? imaState.idTokens : []; - if( imaState.have_idToken ) - idTokens.push( imaState.idToken ); - if( idTokens.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - bBurnIsOK = await IMA.burnERC721( - imaState.w3_t_chain, - imaState.cid_t_chain, - imaState.strChainName_t_chain, - imaState.joAccount_t_chain, - // strAddressBurnFrom, - idToken, - imaState.joErc721_t_chain[imaState.strCoinNameErc721_t_chain + "_address"], - imaState.joErc721_t_chain[imaState.strCoinNameErc721_t_chain + "_abi"], - imaState.tc_t_chain - ) ? true : false; - } - } - - } catch ( err ) { - bBurnIsOK = false; - } - } - return bBurnIsOK; - } - } ); - }, - "burn-erc1155": function() { - imaState.arrActions.push( { - "name": "burn ERC1155", - "fn": async function() { - let bBurnIsOK = false; - if( imaState.strCoinNameErc1155_t_chain.length > 0 ) { - try { - const strAddressBurnFrom = imaState.joAccount_t_chain.address( imaState.w3_t_chain ); // same as caller/transaction signer - const idTokens = imaState.have_idTokens ? imaState.idTokens : []; - if( imaState.have_idToken ) - idTokens.push( imaState.idToken ); - if( idTokens.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - bBurnIsOK = await IMA.burnERC1155( - imaState.w3_t_chain, - imaState.cid_t_chain, - imaState.strChainName_t_chain, - imaState.joAccount_t_chain, - strAddressBurnFrom, - idToken, - imaState.nAmountOfToken, - imaState.joErc1155_t_chain[imaState.strCoinNameErc1155_t_chain + "_address"], - imaState.joErc1155_t_chain[imaState.strCoinNameErc1155_t_chain + "_abi"], - imaState.tc_t_chain - ) ? true : false; - } - } - - } catch ( err ) { - bBurnIsOK = false; - } - } - return bBurnIsOK; - } - } ); - }, - "show-balance": function() { - imaState.arrActions.push( { - "name": "show balance", - "fn": async function() { - let assetAddress = null; - const arrBalancesMN = [], arrBalancesSC = []; - arrBalancesMN.push( { - assetName: "RealETH", - balance: await IMA.balanceETH( - true, // isMainNet - imaState.w3_main_net, - imaState.cid_main_net, - imaState.joAccount_main_net - ) - } ); - arrBalancesMN.push( { - assetName: "CanReceiveETH", - balance: await IMA.view_eth_payment_from_s_chain_on_main_net( - imaState.w3_main_net, - imaState.joAccount_main_net, - imaState.jo_deposit_box_eth - ) - } ); - try { assetAddress = imaState.eth_erc20.options.address; } catch ( err ) { assetAddress = null; } - arrBalancesSC.push( { - assetName: "RealETH", - assetAddress: assetAddress, - balance: await IMA.balanceETH( - false, // isMainNet - imaState.w3_s_chain, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.eth_erc20 - ) - } ); - arrBalancesSC.push( { - assetName: "FakeETH", - balance: await IMA.balanceETH( - true, // isMainNet here is true, but we do call S-Chain - imaState.w3_s_chain, - imaState.cid_s_chain, - imaState.joAccount_s_chain - ) - } ); - if( imaState.strCoinNameErc20_main_net.length > 0 ) { - try { assetAddress = imaState.joErc20_main_net[imaState.strCoinNameErc20_main_net + "_address"]; } catch ( err ) { assetAddress = null; } - arrBalancesMN.push( { - assetName: "ERC20", - assetAddress: assetAddress, - balance: await IMA.balanceERC20( - true, // isMainNet - imaState.w3_main_net, - imaState.cid_main_net, - imaState.joAccount_main_net, - imaState.strCoinNameErc20_main_net, - imaState.joErc20_main_net - ) - } ); - } - if( imaState.strCoinNameErc20_s_chain.length > 0 ) { - try { assetAddress = imaState.joErc20_s_chain[imaState.strCoinNameErc20_s_chain + "_address"]; } catch ( err ) { assetAddress = null; } - arrBalancesSC.push( { - assetName: "ERC20", - assetAddress: assetAddress, - balance: await IMA.balanceERC20( - false, // isMainNet - imaState.w3_s_chain, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.strCoinNameErc20_s_chain, - imaState.joErc20_s_chain - ) - } ); - } - const idTokens = imaState.have_idTokens ? imaState.idTokens : []; - if( imaState.have_idToken ) - idTokens.push( imaState.idToken ); - if( idTokens.length > 0 ) { - if( imaState.strCoinNameErc721_main_net.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - try { assetAddress = imaState.joErc721_main_net[imaState.strCoinNameErc721_main_net + "_address"]; } catch ( err ) { assetAddress = null; } - arrBalancesMN.push( { - assetName: "ERC721", - assetAddress: assetAddress, - idToken: idToken, - owner: await IMA.ownerOfERC721( - true, // isMainNet - imaState.w3_main_net, - imaState.cid_main_net, - imaState.joAccount_main_net, - imaState.strCoinNameErc721_main_net, - imaState.joErc721_main_net, - idToken - ) - } ); - } - } - if( imaState.strCoinNameErc721_s_chain.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - try { assetAddress = imaState.joErc721_s_chain[imaState.strCoinNameErc721_s_chain + "_address"]; } catch ( err ) { assetAddress = null; } - arrBalancesSC.push( { - assetName: "ERC721", - assetAddress: assetAddress, - idToken: idToken, - owner: await IMA.ownerOfERC721( - false, // isMainNet - imaState.w3_s_chain, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.strCoinNameErc721_s_chain, - imaState.joErc721_s_chain, - idToken - ) - } ); - } - } - if( imaState.strCoinNameErc1155_main_net.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - try { assetAddress = imaState.joErc1155_main_net[imaState.strCoinNameErc1155_main_net + "_address"]; } catch ( err ) { assetAddress = null; } - arrBalancesMN.push( { - assetName: "ERC1155", - assetAddress: assetAddress, - idToken: idToken, - balance: await IMA.balanceERC1155( - true, // isMainNet - imaState.w3_main_net, - imaState.cid_main_net, - imaState.joAccount_main_net, - imaState.strCoinNameErc1155_main_net, - imaState.joErc1155_main_net, - idToken - ) - } ); - } - } - if( imaState.strCoinNameErc1155_s_chain.length > 0 ) { - for( let i = 0; i < idTokens.length; ++ i ) { - const idToken = idTokens[i]; - try { assetAddress = imaState.joErc1155_s_chain[imaState.strCoinNameErc1155_s_chain + "_address"]; } catch ( err ) { assetAddress = null; } - arrBalancesSC.push( { - assetName: "ERC1155", - assetAddress: assetAddress, - idToken: idToken, - balance: await IMA.balanceERC1155( - false, // isMainNet - imaState.w3_s_chain, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.strCoinNameErc1155_s_chain, - imaState.joErc1155_s_chain, - idToken - ) - } ); - } - } - } // if( idTokens.length > 0 ) - const format_balance_info = function( bi, strAddress ) { - let s = ""; - s += cc.attention( bi.assetName ); - if( "assetAddress" in bi && typeof bi.assetAddress == "string" && bi.assetAddress.length > 0 ) - s += cc.normal( "/" ) + cc.notice( bi.assetAddress ); - if( "idToken" in bi ) - s += cc.normal( " token ID " ) + cc.notice( bi.idToken ); - s += cc.normal( ( bi.assetName == "ERC721" ) ? " owner is " : " balance is " ); - s += ( bi.assetName == "ERC721" ) ? cc.bright( bi.owner ) : cc.sunny( bi.balance ); - if( bi.assetName == "ERC721" ) { - const isSame = ( bi.owner.trim().toLowerCase() == strAddress.trim().toLowerCase() ); - s += " " + ( isSame - ? cc.success( "same (as account " ) + cc.attention( strAddress ) + cc.success( " specified in the command line arguments)" ) - : cc.error( "different (than account " ) + cc.attention( strAddress ) + cc.error( " specified in the command line arguments)" ) ); - } - return s; - }; - if( arrBalancesMN.length > 0 || arrBalancesSC.length > 0 ) { - if( arrBalancesMN.length > 0 ) { - const strAddress = imaState.joAccount_main_net.address( imaState.w3_main_net ); - log.write( cc.sunny( "Main Net" ) + " " + - cc.bright( arrBalancesMN.length > 1 ? "balances" : "balance" ) + - cc.bright( " of " ) + cc.notice( strAddress ) + - cc.bright( ":" ) + "\n" ); - for( let i = 0; i < arrBalancesMN.length; ++ i ) { - const bi = arrBalancesMN[i]; - log.write( " " + format_balance_info( bi, strAddress ) + "\n" ); - } - } - if( arrBalancesSC.length > 0 ) { - const strAddress = imaState.joAccount_s_chain.address( imaState.w3_s_chain ); - log.write( cc.sunny( "S-Chain" ) + " " + - cc.bright( arrBalancesMN.length > 1 ? "balances" : "balance" ) + - cc.bright( " of " ) + cc.notice( strAddress ) + - cc.bright( ":" ) + "\n" ); - for( let i = 0; i < arrBalancesSC.length; ++ i ) { - const bi = arrBalancesSC[i]; - log.write( " " + format_balance_info( bi, strAddress ) + "\n" ); - } - } - } else - log.write( cc.warning( "No balances to scan." ) ); - return true; - } - } ); - }, - "m2s-payment": function() { - imaState.arrActions.push( { - "name": "one M->S single payment", - "fn": async function() { - if( imaState.strCoinNameErc721_main_net.length > 0 - // && imaState.strCoinNameErc721_s_chain.length > 0 - ) { - // ERC721 payment - log.write( cc.info( "one M->S single ERC721 payment: " ) + cc.sunny( imaState.idToken ) + "\n" ); // just print value - return await IMA.do_erc721_payment_from_main_net( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_main_net, - imaState.joAccount_s_chain, - imaState.isWithMetadata721 ? imaState.jo_deposit_box_erc721_with_metadata : imaState.jo_deposit_box_erc721, // only main net - imaState.jo_message_proxy_main_net, // for checking logs - imaState.strChainName_s_chain, - imaState.idToken, // which ERC721 token id to send - imaState.nAmountOfWei, // how much to send - imaState.isWithMetadata721 ? imaState.jo_token_manager_erc721_with_metadata : imaState.jo_token_manager_erc721, // only s-chain - imaState.strCoinNameErc721_main_net, - imaState.joErc721_main_net, - imaState.strCoinNameErc721_s_chain, - imaState.joErc721_s_chain, - imaState.tc_main_net - ); - } - if( imaState.strCoinNameErc20_main_net.length > 0 - // && imaState.strCoinNameErc20_s_chain.length > 0 - ) { - // ERC20 payment - log.write( cc.info( "one M->S single ERC20 payment: " ) + cc.sunny( imaState.nAmountOfToken ) + "\n" ); // just print value - return await IMA.do_erc20_payment_from_main_net( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_main_net, - imaState.joAccount_s_chain, - imaState.jo_deposit_box_erc20, // only main net - imaState.jo_message_proxy_main_net, // for checking logs - imaState.strChainName_s_chain, - imaState.nAmountOfToken, // how much ERC20 tokens to send - imaState.nAmountOfWei, // how much to send - imaState.jo_token_manager_erc20, // only s-chain - imaState.strCoinNameErc20_main_net, - imaState.joErc20_main_net, - imaState.strCoinNameErc20_s_chain, - imaState.joErc20_s_chain, - imaState.tc_main_net - ); - } - if( - imaState.strCoinNameErc1155_main_net.length > 0 && - imaState.idToken && imaState.idToken !== null && imaState.idToken !== undefined && - imaState.nAmountOfToken && imaState.nAmountOfToken !== null && imaState.nAmountOfToken !== undefined && - ( ( !imaState.idTokens ) || imaState.idTokens === null || imaState.idTokens === undefined ) && - ( ( !imaState.arrAmountsOfTokens ) || imaState.arrAmountsOfTokens === null || imaState.arrAmountsOfTokens === undefined ) - ) { - // ERC1155 payment - log.write( cc.info( "one M->S single ERC1155 payment: " ) + cc.sunny( imaState.idToken ) + " " + cc.sunny( imaState.nAmountOfToken ) + "\n" ); // just print value - return await IMA.do_erc1155_payment_from_main_net( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_main_net, - imaState.joAccount_s_chain, - imaState.jo_deposit_box_erc1155, // only main net - imaState.jo_message_proxy_main_net, // for checking logs - imaState.strChainName_s_chain, - imaState.idToken, // which ERC1155 token id to send - imaState.nAmountOfToken, // which ERC1155 token amount to send - imaState.nAmountOfWei, // how much to send - imaState.jo_token_manager_erc1155, // only s-chain - imaState.strCoinNameErc1155_main_net, - imaState.joErc1155_main_net, - imaState.strCoinNameErc1155_s_chain, - imaState.joErc1155_s_chain, - imaState.tc_main_net - ); - } - if( - imaState.strCoinNameErc1155_main_net.length > 0 && - imaState.idTokens && imaState.idTokens !== null && imaState.idTokens !== undefined && - imaState.arrAmountsOfTokens && imaState.arrAmountsOfTokens !== null && imaState.arrAmountsOfTokens !== undefined && - ( !imaState.idToken || imaState.idToken === null || imaState.idToken === undefined ) && - ( !imaState.nAmountOfToken || imaState.nAmountOfToken === null || imaState.nAmountOfToken === undefined ) - ) { - // ERC1155 Batch payment - log.write( cc.info( "one M->S single ERC1155 Batch payment: " ) + cc.sunny( imaState.idTokens ) + " " + cc.sunny( imaState.arrAmountsOfTokens ) + "\n" ); // just print value - return await IMA.do_erc1155_batch_payment_from_main_net( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_main_net, - imaState.joAccount_s_chain, - imaState.jo_deposit_box_erc1155, // only main net - imaState.jo_message_proxy_main_net, // for checking logs - imaState.strChainName_s_chain, - imaState.idTokens, // which ERC1155 token id to send - imaState.arrAmountsOfTokens, // which ERC1155 token amount to send - imaState.nAmountOfWei, // how much to send - imaState.jo_token_manager_erc1155, // only s-chain - imaState.strCoinNameErc1155_main_net, - imaState.joErc1155_main_net, - imaState.strCoinNameErc1155_s_chain, - imaState.joErc1155_s_chain, - imaState.tc_main_net - ); - } - // ETH payment - log.write( cc.info( "one M->S single ETH payment: " ) + cc.sunny( imaState.nAmountOfWei ) + "\n" ); // just print value - return await IMA.do_eth_payment_from_main_net( - imaState.w3_main_net, - imaState.cid_main_net, - imaState.joAccount_main_net, - imaState.joAccount_s_chain, - imaState.jo_deposit_box_eth, // only main net - imaState.jo_message_proxy_main_net, // for checking logs - imaState.strChainName_s_chain, - imaState.nAmountOfWei, // how much WEI money to send - imaState.tc_main_net - ); - } - } ); - }, - "s2m-payment": function() { - imaState.arrActions.push( { - "name": "one S->M single payment", - "fn": async function() { - if( imaState.strCoinNameErc721_s_chain.length > 0 ) { - // ERC721 payment - log.write( cc.info( "one S->M single ERC721 payment: " ) + cc.sunny( imaState.idToken ) + "\n" ); // just print value - return await IMA.do_erc721_payment_from_s_chain( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.joAccount_main_net, - imaState.isWithMetadata721 ? imaState.jo_token_manager_erc721_with_metadata : imaState.jo_token_manager_erc721, // only s-chain - imaState.jo_message_proxy_s_chain, // for checking logs - imaState.isWithMetadata721 ? imaState.jo_deposit_box_erc721_with_metadata : imaState.jo_deposit_box_erc721, // only main net - imaState.idToken, // which ERC721 token id to send - imaState.nAmountOfWei, // how much to send - imaState.strCoinNameErc721_main_net, - imaState.joErc721_main_net, - imaState.strCoinNameErc721_s_chain, - imaState.joErc721_s_chain, - imaState.tc_s_chain - ); - } - if( imaState.strCoinNameErc20_s_chain.length > 0 ) { - // ERC20 payment - log.write( cc.info( "one S->M single ERC20 payment: " ) + cc.sunny( imaState.nAmountOfToken ) + "\n" ); // just print value - return await IMA.do_erc20_payment_from_s_chain( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.joAccount_main_net, - imaState.jo_token_manager_erc20, // only s-chain - imaState.jo_message_proxy_s_chain, // for checking logs - imaState.jo_deposit_box_erc20, // only main net - imaState.nAmountOfToken, // how ERC20 tokens money to send - imaState.nAmountOfWei, // how much to send - imaState.strCoinNameErc20_main_net, - imaState.joErc20_main_net, - imaState.strCoinNameErc20_s_chain, - imaState.joErc20_s_chain, - imaState.tc_s_chain - ); - } - if( - imaState.strCoinNameErc1155_s_chain.length > 0 && - imaState.idToken && imaState.idToken !== null && imaState.idToken !== undefined && - imaState.nAmountOfToken && imaState.nAmountOfToken !== null && imaState.nAmountOfToken !== undefined && - ( ( !imaState.idTokens ) || imaState.idTokens === null || imaState.idTokens === undefined ) && - ( ( !imaState.arrAmountsOfTokens ) || imaState.arrAmountsOfTokens === null || imaState.arrAmountsOfTokens === undefined ) - ) { - // ERC1155 payment - log.write( cc.info( "one S->M single ERC1155 payment: " ) + cc.sunny( imaState.idToken ) + " " + cc.sunny( imaState.nAmountOfToken ) + "\n" ); // just print value - return await IMA.do_erc1155_payment_from_s_chain( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.joAccount_main_net, - imaState.jo_token_manager_erc1155, // only s-chain - imaState.jo_message_proxy_s_chain, // for checking logs - imaState.jo_deposit_box_erc1155, // only main net - imaState.idToken, // which ERC1155 token id to send - imaState.nAmountOfToken, // which ERC1155 token amount to send - imaState.nAmountOfWei, // how much to send - imaState.strCoinNameErc1155_main_net, - imaState.joErc1155_main_net, - imaState.strCoinNameErc1155_s_chain, - imaState.joErc1155_s_chain, - imaState.tc_s_chain - ); - } - if( - imaState.strCoinNameErc1155_s_chain.length > 0 && - imaState.idTokens && imaState.idTokens !== null && imaState.idTokens !== undefined && - imaState.arrAmountsOfTokens && imaState.arrAmountsOfTokens !== null && imaState.arrAmountsOfTokens !== undefined && - ( !imaState.idToken || imaState.idToken === null || imaState.idToken === undefined ) && - ( !imaState.nAmountOfToken || imaState.nAmountOfToken === null || imaState.nAmountOfToken === undefined ) - ) { - // ERC1155 payment - log.write( cc.info( "one S->M single ERC1155 payment: " ) + cc.sunny( imaState.idTokens ) + " " + cc.sunny( imaState.arrAmountsOfTokens ) + "\n" ); // just print value - return await IMA.do_erc1155_batch_payment_from_s_chain( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.joAccount_main_net, - imaState.jo_token_manager_erc1155, // only s-chain - imaState.jo_message_proxy_s_chain, // for checking logs - imaState.jo_deposit_box_erc1155, // only main net - imaState.idTokens, // which ERC1155 token id to send - imaState.arrAmountsOfTokens, // which ERC1155 token amount to send - imaState.nAmountOfWei, // how much to send - imaState.strCoinNameErc1155_main_net, - imaState.joErc1155_main_net, - imaState.strCoinNameErc1155_s_chain, - imaState.joErc1155_s_chain, - imaState.tc_s_chain - ); - } - // ETH payment - log.write( cc.info( "one S->M single ETH payment: " ) + cc.sunny( imaState.nAmountOfWei ) + "\n" ); // just print value - return await IMA.do_eth_payment_from_s_chain( - imaState.w3_s_chain, - imaState.cid_s_chain, - imaState.joAccount_s_chain, - imaState.joAccount_main_net, - imaState.jo_token_manager_eth, // only s-chain - imaState.jo_message_proxy_s_chain, // for checking logs - imaState.nAmountOfWei, // how much WEI money to send - imaState.tc_s_chain - ); - } - } ); - }, - "s2s-payment": function() { - imaState.arrActions.push( { - "name": "one S->S single payment", - "fn": async function() { - const isForward = IMA.isForwardS2S(); - const w3_src = isForward ? imaState.w3_s_chain : imaState.w3_t_chain; - // const w3_dst = isForward ? imaState.w3_t_chain : imaState.w3_s_chain; - const cid_src = isForward ? imaState.cid_s_chain : imaState.cid_t_chain; - // const cid_dst = isForward ? imaState.cid_t_chain : imaState.cid_s_chain; - const joAccountSrc = isForward ? imaState.joAccount_s_chain : imaState.joAccount_t_chain; - // const joAccountDst = isForward ? imaState.joAccount_t_chain : imaState.joAccount_s_chain; - // const jo_message_proxy_src = isForward ? imaState.jo_message_proxy_s_chain : imaState.jo_message_proxy_t_chain; - // const jo_message_proxy_dst = isForward ? imaState.jo_message_proxy_t_chain : imaState.jo_message_proxy_s_chain; - const jo_token_manager_erc20_src = isForward ? imaState.jo_token_manager_erc20 : imaState.jo_token_manager_erc20_target; - // const jo_token_manager_erc20_dst = isForward ? imaState.jo_token_manager_erc20_target : imaState.jo_token_manager_erc20 - const jo_token_manager_erc721_src = isForward - ? ( imaState.isWithMetadata721 ? imaState.jo_token_manager_erc721_with_metadata : imaState.jo_token_manager_erc721 ) - : ( imaState.isWithMetadata721 ? imaState.jo_token_manager_erc721_with_metadata_target : imaState.jo_token_manager_erc721_target ) - ; - // const jo_token_manager_erc721_dst = isForward - // ? ( imaState.isWithMetadata721 ? imaState.jo_token_manager_erc721_with_metadata_target : imaState.jo_token_manager_erc721_target ) - // : ( imaState.isWithMetadata721 ? imaState.jo_token_manager_erc721_with_metadata : imaState.jo_token_manager_erc721 ) - // ; - const jo_token_manager_erc1155_src = isForward ? imaState.jo_token_manager_erc1155 : imaState.jo_token_manager_erc1155_target; - // const jo_token_manager_erc1155_dst = isForward ? imaState.jo_token_manager_erc1155_target : imaState.jo_token_manager_erc1155 - // const strChainName_src = isForward ? imaState.strChainName_s_chain : imaState.strChainName_t_chain; - const strChainName_dst = isForward ? imaState.strChainName_t_chain : imaState.strChainName_s_chain; - const strCoinNameErc20_src = isForward ? imaState.strCoinNameErc20_s_chain : imaState.strCoinNameErc20_t_chain; - // const strCoinNameErc20_dst = isForward ? imaState.strCoinNameErc20_t_chain : imaState.strCoinNameErc20_s_chain; - const strCoinNameErc721_src = isForward ? imaState.strCoinNameErc721_s_chain : imaState.strCoinNameErc721_t_chain; - // const strCoinNameErc721_dst = isForward ? imaState.strCoinNameErc721_t_chain : imaState.strCoinNameErc721_s_chain; - const strCoinNameErc1155_src = isForward ? imaState.strCoinNameErc1155_s_chain : imaState.strCoinNameErc1155_t_chain; - // const strCoinNameErc1155_dst = isForward ? imaState.strCoinNameErc1155_t_chain : imaState.strCoinNameErc1155_s_chain; - const joErc20_src = isForward ? imaState.joErc20_s_chain : imaState.joErc20_t_chain; - const joErc721_src = isForward ? imaState.joErc721_s_chain : imaState.joErc721_t_chain; - const joErc1155_src = isForward ? imaState.joErc1155_s_chain : imaState.joErc1155_t_chain; - let strAddrErc20_explicit = imaState.strAddrErc20_explicit; - let strAddrErc20_explicit_target = imaState.strAddrErc20_explicit_target; - let strAddrErc721_explicit = imaState.strAddrErc721_explicit; - let strAddrErc721_explicit_target = imaState.strAddrErc721_explicit_target; - let strAddrErc1155_explicit = imaState.strAddrErc1155_explicit; - let strAddrErc1155_explicit_target = imaState.strAddrErc1155_explicit_target; - if( ( ! strAddrErc20_explicit ) && imaState.joErc20_s_chain && imaState.strCoinNameErc20_s_chain ) - strAddrErc20_explicit = imaState.joErc20_s_chain[imaState.strCoinNameErc20_s_chain + "_address"]; - if( ( ! strAddrErc20_explicit_target ) && imaState.joErc20_t_chain && imaState.strCoinNameErc20_t_chain ) - strAddrErc20_explicit_target = imaState.joErc20_t_chain[imaState.strCoinNameErc20_t_chain + "_address"]; - if( ( ! strAddrErc721_explicit ) && imaState.joErc721_s_chain && imaState.strCoinNameErc721_s_chain ) - strAddrErc721_explicit = imaState.joErc721_s_chain[imaState.strCoinNameErc721_s_chain + "_address"]; - if( ( ! strAddrErc721_explicit_target ) && imaState.joErc721_t_chain && imaState.strCoinNameErc721_t_chain ) - strAddrErc721_explicit_target = imaState.joErc721_t_chain[imaState.strCoinNameErc721_t_chain + "_address"]; - if( ( ! strAddrErc1155_explicit ) && imaState.joErc1155_s_chain && imaState.strCoinNameErc1155_s_chain ) - strAddrErc1155_explicit = imaState.joErc1155_s_chain[imaState.strCoinNameErc1155_s_chain + "_address"]; - if( ( ! strAddrErc1155_explicit_target ) && imaState.joErc1155_t_chain && imaState.strCoinNameErc1155_t_chain ) - strAddrErc1155_explicit_target = imaState.joErc1155_t_chain[imaState.strCoinNameErc1155_t_chain + "_address"]; - // const strAddrErc20_src = isForward ? strAddrErc20_explicit : strAddrErc20_explicit_target; - const strAddrErc20_dst = isForward ? strAddrErc20_explicit_target : strAddrErc20_explicit; - // const strAddrErc721_src = isForward ? strAddrErc721_explicit : strAddrErc721_explicit_target; - const strAddrErc721_dst = isForward ? strAddrErc721_explicit_target : strAddrErc721_explicit; - // const strAddrErc1155_src = isForward ? strAddrErc1155_explicit : strAddrErc1155_explicit_target; - const strAddrErc1155_dst = isForward ? strAddrErc1155_explicit_target : strAddrErc1155_explicit; - const tc = isForward ? imaState.tc_s_chain : imaState.tc_t_chain; - if( strCoinNameErc721_src.length > 0 ) { - // ERC721 payment - log.write( cc.info( "one S->S single ERC721 payment: " ) + cc.sunny( imaState.idToken ) + "\n" ); // just print value - return await IMA.do_erc721_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc721_src, - imaState.idToken, // which ERC721 token id to send - imaState.nAmountOfWei, // how much to send - strCoinNameErc721_src, - joErc721_src, - strAddrErc721_dst, // only reverse payment needs it - tc - ); - } - if( strCoinNameErc20_src.length > 0 ) { - // ERC20 payment - log.write( cc.info( "one S->S single ERC20 payment: " ) + cc.sunny( imaState.nAmountOfToken ) + "\n" ); // just print value - return await IMA.do_erc20_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc20_src, - imaState.nAmountOfToken, // how much ERC20 tokens to send - imaState.nAmountOfWei, // how much to send - strCoinNameErc20_src, - joErc20_src, - strAddrErc20_dst, // only reverse payment needs it - tc - ); - } - if( - strCoinNameErc1155_src.length > 0 && - imaState.idToken && imaState.idToken !== null && imaState.idToken !== undefined && - imaState.nAmountOfToken && imaState.nAmountOfToken !== null && imaState.nAmountOfToken !== undefined && - ( ( !imaState.idTokens ) || imaState.idTokens === null || imaState.idTokens === undefined ) && - ( ( !imaState.arrAmountsOfTokens ) || imaState.arrAmountsOfTokens === null || imaState.arrAmountsOfTokens === undefined ) - ) { - // ERC1155 payment - log.write( cc.info( "one S->S single ERC1155 payment: " ) + cc.sunny( imaState.idToken ) + " " + cc.sunny( imaState.nAmountOfToken ) + "\n" ); // just print value - return await IMA.do_erc1155_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc1155_src, - imaState.idToken, // which ERC1155 token id to send - imaState.nAmountOfToken, // how much ERC1155 tokens to send - imaState.nAmountOfWei, // how much to send - strCoinNameErc1155_src, - joErc1155_src, - strAddrErc1155_dst, // only reverse payment needs it - tc - ); - } - if( - strCoinNameErc1155_src.length > 0 && - imaState.idTokens && imaState.idTokens !== null && imaState.idTokens !== undefined && - imaState.arrAmountsOfTokens && imaState.arrAmountsOfTokens !== null && imaState.arrAmountsOfTokens !== undefined && - ( !imaState.idToken || imaState.idToken === null || imaState.idToken === undefined ) && - ( !imaState.nAmountOfToken || imaState.nAmountOfToken === null || imaState.nAmountOfToken === undefined ) - ) { - // ERC1155 Batch payment - log.write( cc.info( "one S->S single ERC1155 Batch payment: " ) + cc.sunny( imaState.idTokens ) + " " + cc.sunny( imaState.arrAmountsOfTokens ) + "\n" ); // just print value - return await IMA.do_erc1155_batch_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc1155_src, - imaState.idTokens, // which ERC1155 token id to send - imaState.arrAmountsOfTokens, // which ERC1155 token amount to send - imaState.nAmountOfWei, // how much to send - strCoinNameErc1155_src, - joErc1155_src, - strAddrErc1155_dst, - tc - ); - } - // ETH payment - log.write( cc.info( "one S->S single ETH payment: " ) + cc.sunny( imaState.nAmountOfWei ) + "\n" ); // just print value - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " S->S ETH payment(s) are neither supported nor allowed" ) ); - process.exit( 154 ); - } - } ); - }, - "s2m-receive": function() { - imaState.arrActions.push( { - "name": "receive one S->M single ETH payment", - "fn": async function() { - log.write( cc.info( "receive one S->M single ETH payment: " ) + "\n" ); // just print value - return await IMA.receive_eth_payment_from_s_chain_on_main_net( - imaState.w3_main_net, - imaState.cid_main_net, - imaState.joAccount_main_net, - imaState.jo_deposit_box_eth, - imaState.tc_main_net - ); - } - } ); - }, - "s2m-view": function() { - imaState.arrActions.push( { - "name": "view one S->M single ETH payment", - "fn": async function() { - log.write( cc.info( "view one S->M single ETH payment: " ) + "\n" ); // just print value - const xWei = await IMA.view_eth_payment_from_s_chain_on_main_net( - imaState.w3_main_net, - imaState.joAccount_main_net, - imaState.jo_deposit_box_eth - ); - if( xWei === null || xWei === undefined ) - return false; - - const xEth = imaState.w3_main_net.utils.fromWei( xWei, "ether" ); - log.write( cc.success( "Main-net user can receive: " ) + cc.attention( xWei ) + cc.success( " wei = " ) + cc.attention( xEth ) + cc.success( " eth" ) + "\n" ); - return true; - } - } ); - }, - "m2s-transfer": function() { - imaState.arrActions.push( { - "name": "single M->S transfer loop", - "fn": async function() { - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // main-net --> s-chain transfer - return await IMA.do_transfer( // main-net --> s-chain - "M2S", - // - imaState.w3_main_net, - imaState.jo_message_proxy_main_net, - imaState.joAccount_main_net, - imaState.w3_s_chain, - imaState.jo_message_proxy_s_chain, - // - imaState.joAccount_s_chain, - imaState.strChainName_main_net, - imaState.strChainName_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - null, // imaState.jo_deposit_box, // for logs validation on mainnet - imaState.jo_token_manager_eth, // for logs validation on s-chain - imaState.nTransferBlockSizeM2S, - imaState.nMaxTransactionsM2S, - imaState.nBlockAwaitDepthM2S, - imaState.nBlockAgeM2S, - imaBLS.do_sign_messages_m2s, // fn_sign_messages - null, // joExtraSignOpts - imaState.tc_s_chain, - imaState.optsPendingTxAnalysis - ); - } - } ); - }, - "s2m-transfer": function() { - imaState.arrActions.push( { - "name": "single S->M transfer loop", - "fn": async function() { - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // s-chain --> main-net transfer - return await IMA.do_transfer( // s-chain --> main-net - "S2M", - // - imaState.w3_s_chain, - imaState.jo_message_proxy_s_chain, - imaState.joAccount_s_chain, - imaState.w3_main_net, - imaState.jo_message_proxy_main_net, - // - imaState.joAccount_main_net, - imaState.strChainName_s_chain, - imaState.strChainName_main_net, - imaState.cid_s_chain, - imaState.cid_main_net, - imaState.jo_deposit_box_eth, // for logs validation on mainnet - null, // imaState.jo_token_manager - for logs validation on s-chain - imaState.nTransferBlockSizeS2M, - imaState.nMaxTransactionsS2M, - imaState.nBlockAwaitDepthS2M, - imaState.nBlockAgeS2M, - imaBLS.do_sign_messages_s2m, // fn_sign_messages - null, // joExtraSignOpts - imaState.tc_main_net, - imaState.optsPendingTxAnalysis - ); - } - } ); - }, - "s2s-transfer": function() { - imaState.arrActions.push( { - "name": "single S->S transfer loop", - "fn": async function() { - if( ! imaState.s2s_opts.isEnabled ) - return; - fnInitActionSkaleNetworkScanForS2S(); - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // s-chain --> main-net transfer - return await IMA.do_s2s_all( // s-chain --> s-chain - imaState, - skale_observer, - imaState.w3_s_chain, - imaState.jo_message_proxy_s_chain, - // - imaState.joAccount_s_chain, - imaState.strChainName_s_chain, - imaState.cid_s_chain, - imaState.jo_token_manager_eth, // for logs validation on s-chain - imaState.nTransferBlockSizeM2S, - imaState.nMaxTransactionsM2S, - imaState.nBlockAwaitDepthM2S, - imaState.nBlockAgeM2S, - imaBLS.do_sign_messages_m2s, // fn_sign_messages - imaState.tc_s_chain, - imaState.optsPendingTxAnalysis - ); - } - } ); - }, - "transfer": function() { - fnInitActionSkaleNetworkScanForS2S(); - imaState.arrActions.push( { - "name": "Single M<->S transfer loop iteration", - "fn": async function() { - fnInitActionSkaleNetworkScanForS2S(); - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // single_transfer_loop - return await single_transfer_loop(); - } - } ); - }, - "loop": function() { - fnInitActionSkaleNetworkScanForS2S(); - imaState.arrActions.push( { - "name": "M<->S and S->S transfer loop", - "fn": async function() { - IMA.isPreventExitAfterLastAction = true; - if( ! imaState.bNoWaitSChainStarted ) - await wait_until_s_chain_started(); // M<->S transfer loop - let isPrintSummaryRegistrationCosts = false; - if( !await check_registration_step1() ) { - if( !await register_step1( false ) ) - return false; - isPrintSummaryRegistrationCosts = true; - } - if( isPrintSummaryRegistrationCosts ) - print_summary_registration_costs(); - return await run_transfer_loop( false ); - } - } ); - }, - "browse-s-chain": function() { - imaState.bIsNeededCommonInit = false; - imaState.arrActions.push( { - "name": "Brows S-Chain network", - "fn": async function() { - const strLogPrefix = cc.info( "S-Chain Browse:" ) + " "; - if( imaState.strURL_s_chain.length === 0 ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " missing S-Chain URL, please specify " ) + cc.info( "url-s-chain" ) ); - process.exit( 155 ); - } - log.write( strLogPrefix + cc.normal( "Downloading S-Chain network information " ) + cc.normal( "..." ) + "\n" ); // just print value - // - const rpcCallOpts = null; - await rpcCall.create( imaState.strURL_s_chain, rpcCallOpts, async function( joCall, err ) { - if( err ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed" ) ); - process.exit( 156 ); - } - await joCall.call( { - "method": "skale_nodesRpcInfo", - "params": { - "fromImaAgentIndex": imaState.nNodeNumber - } - }, async function( joIn, joOut, err ) { - if( err ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed, error: " ) + cc.warning( err ) ); - process.exit( 157 ); - } - log.write( strLogPrefix + cc.normal( "S-Chain network information: " ) + cc.j( joOut.result ) + "\n" ); - let nCountReceivedImaDescriptions = 0; - const jarrNodes = joOut.result.network; - for( let i = 0; i < jarrNodes.length; ++ i ) { - const joNode = jarrNodes[i]; - if( ! joNode ) { - log.write( - strLogPrefix + cc.error( "Discovery node " ) + cc.info( i ) + - cc.error( " is completely unknown and will be skipped" ) + "\n" ); - continue; - } - const strNodeURL = imaUtils.compose_schain_node_url( joNode ); - const rpcCallOpts = null; - await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed" ) ); - process.exit( 158 ); - } - await joCall.call( { - "method": "skale_imaInfo", - "params": { - "fromImaAgentIndex": imaState.nNodeNumber - } - }, async function( joIn, joOut, err ) { - ++ nCountReceivedImaDescriptions; - if( err ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " JSON RPC call to S-Chain failed, error: " ) + cc.warning( err ) ); - process.exit( 159 ); - } - log.write( strLogPrefix + cc.normal( "Node " ) + cc.info( joNode.nodeID ) + cc.normal( " IMA information: " ) + cc.j( joOut.result ) + "\n" ); - //process.exit( 0 ); - } ); - } ); - } - //process.exit( 0 ); - const iv = setInterval( function() { - if( nCountReceivedImaDescriptions == jarrNodes.length ) { - clearInterval( iv ); - process.exit( 0 ); - } - }, 100 ); - } ); - } ); - return true; - } - } ); - }, - "browse-skale-network": function() { - // imaState.bIsNeededCommonInit = false; - imaState.arrActions.push( { - "name": "Browse S-Chain network", - "fn": async function() { - const strLogPrefix = cc.info( "SKALE NETWORK Browse:" ) + " "; - if( imaState.strPathAbiJson_skale_manager.length === 0 ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " missing Skale Manager ABI, please specify " ) + cc.info( "abi-skale-manager" ) ); - process.exit( 160 ); - } - log.write( strLogPrefix + cc.debug( "Downloading SKALE network information..." ) + "\n" ); // just print value - const opts = { - imaState: imaState, - "details": log, - "bStopNeeded": false - }; - const addressFrom = imaState.joAccount_main_net.address( imaState.w3_main_net ); - const arr_schains = await skale_observer.load_schains( imaState.w3_main_net, addressFrom, opts ); - const cnt = arr_schains.length; - log.write( strLogPrefix + cc.normal( "Got " ) + cc.info( cnt ) + cc.normal( " S-Chains(s) in SKALE NETWORK information: " ) + cc.j( arr_schains ) + "\n" ); - return true; - } - } ); - }, - "browse-connected-schains": function() { - // imaState.bIsNeededCommonInit = false; - imaState.arrActions.push( { - "name": "Browse connected S-Chains", - "fn": async function() { - const strLogPrefix = cc.info( "Browse connected S-Chains:" ) + " "; - if( imaState.strPathAbiJson_skale_manager.length === 0 ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " missing Skale Manager ABI, please specify " ) + cc.info( "abi-skale-manager" ) ); - process.exit( 161 ); - } - log.write( strLogPrefix + cc.debug( "Downloading SKALE network information..." ) + "\n" ); // just print value - - const opts = { - imaState: imaState, - "details": log, - "bStopNeeded": false - }; - const addressFrom = imaState.joAccount_main_net.address( imaState.w3_main_net ); - - const arr_schains_cached = await skale_observer.load_schains_connected_only( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.strChainName_s_chain, // strChainNameConnectedTo - addressFrom, - opts - ); - - const cnt = arr_schains_cached.length; - log.write( strLogPrefix + cc.normal( "Got " ) + cc.info( cnt ) + cc.normal( " onnected S-Chain(s): " ) + cc.j( arr_schains_cached ) + "\n" ); - return true; - } - } ); - }, - "discover-cid": function() { - // imaState.bIsNeededCommonInit = false; - imaState.arrActions.push( { - "name": "Discover chains ID(s)", - "fn": async function() { - const strLogPrefix = cc.info( "Discover chains ID(s):" ) + " "; - const arr_urls_to_discover = []; - if( imaState.strURL_main_net && typeof( imaState.strURL_main_net ) == "string" && imaState.strURL_main_net.length > 0 ) { - arr_urls_to_discover.push( { - "name": "Main Net", - "strURL": "" + imaState.strURL_main_net, - "fnSave": function( chainID ) { imaState.cid_main_net = chainID; } - } ); - } - if( imaState.strURL_s_chain && typeof( imaState.strURL_s_chain ) == "string" && imaState.strURL_s_chain.length > 0 ) { - arr_urls_to_discover.push( { - "name": "S-Chain", - "strURL": "" + "" + imaState.strURL_s_chain, - "fnSave": function( chainID ) { imaState.cid_s_chain = chainID; } - } ); - } - if( imaState.strURL_t_chain && typeof( imaState.strURL_t_chain ) == "string" && imaState.strURL_t_chain.length > 0 ) { - arr_urls_to_discover.push( { - "name": "S<->S Target S-Chain", - "strURL": "" + "" + imaState.strURL_t_chain, - "fnSave": function( chainID ) { imaState.cid_t_chain = chainID; } - } ); - } - if( arr_urls_to_discover.length === 0 ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " no URLs privided to discover chain IDs, please specify " ) + - cc.warning( "--url-main-net" ) + cc.error( " and/or " ) + - cc.warning( "--url-s-chain" ) + cc.error( " and/or " ) + - cc.warning( "--url-t-chain" ) + cc.error( "." ) + - "\n" ); - process.exit( 162 ); - } - for( let i = 0; i < arr_urls_to_discover.length; ++ i ) { - const joDiscoverEntry = arr_urls_to_discover[i]; - const chainID = await skale_observer.discover_chain_id( joDiscoverEntry.strURL ); - if( chainID === null ) { - log.write( strLogPrefix + - cc.error( "Failed to detect " ) + cc.note( joDiscoverEntry.name ) + " " + - cc.attention( "chain ID" ) + - "\n" ); - } else { - const cid16 = "0x" + w3mod.utils.toBN( chainID ).toString( 16 ); - const cid10 = "" + w3mod.utils.toBN( chainID ).toString( 10 ); - log.write( strLogPrefix + - cc.normal( "Got " ) + cc.note( joDiscoverEntry.name ) + " " + - cc.attention( "chain ID" ) + cc.normal( "=" ) + cc.note( cid16 ) + cc.normal( "=" ) + - cc.note( cid10 ) + cc.normal( " from URL " ) + cc.u( joDiscoverEntry.strURL ) + - "\n" ); - joDiscoverEntry.fnSave( chainID ); - } - } - return true; - } - } ); - } -} ); - -// "strReimbursementChain": "", -let haveReimbursementCommands = false; -if( imaState.isShowReimbursementBalance ) { - haveReimbursementCommands = true; - imaState.arrActions.push( { - "name": "Gas Reimbursement - Show Balance", - "fn": async function() { - await IMA.reimbursement_show_balance( - imaState.w3_main_net, - imaState.jo_community_pool, - imaState.joAccount_main_net.address( imaState.w3_main_net ), - imaState.strChainName_main_net, - imaState.cid_main_net, - imaState.tc_main_net, - imaState.strReimbursementChain, - true - ); - return true; - } - } ); -} -if( imaState.nReimbursementEstimate ) { - haveReimbursementCommands = true; - imaState.arrActions.push( { - "name": "Gas Reimbursement - Estimate Amount", - "fn": async function() { - await IMA.reimbursement_estimate_amount( - imaState.w3_main_net, - imaState.jo_community_pool, - imaState.joAccount_main_net.address( imaState.w3_main_net ), - imaState.strChainName_main_net, - imaState.cid_main_net, - imaState.tc_main_net, - imaState.strReimbursementChain, - true - ); - return true; - } - } ); -} -if( imaState.nReimbursementRecharge ) { - haveReimbursementCommands = true; - imaState.arrActions.push( { - "name": "Gas Reimbursement - Recharge User Wallet", - "fn": async function() { - await IMA.reimbursement_wallet_recharge( - imaState.w3_main_net, - imaState.jo_community_pool, - imaState.joAccount_main_net, - imaState.strChainName_main_net, - imaState.cid_main_net, - imaState.tc_main_net, - imaState.strReimbursementChain, - imaState.nReimbursementRecharge - ); - return true; - } - } ); -} -if( imaState.nReimbursementWithdraw ) { - haveReimbursementCommands = true; - imaState.arrActions.push( { - "name": "Gas Reimbursement - Withdraw User Wallet", - "fn": async function() { - await IMA.reimbursement_wallet_withdraw( - imaState.w3_main_net, - imaState.jo_community_pool, - imaState.joAccount_main_net, - imaState.strChainName_main_net, - imaState.cid_main_net, - imaState.tc_main_net, - imaState.strReimbursementChain, - imaState.nReimbursementWithdraw - ); - return true; - } - } ); -} -if( haveReimbursementCommands ) { - if( imaState.strReimbursementChain == "" ) { - console.log( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " missing value for " ) + cc.warning( "reimbursement-chain" ) + cc.error( " parameter, must be non-empty chain name" ) + "\n" ); - process.exit( 163 ); - } -} -if( imaState.nReimbursementRange >= 0 ) { - imaState.arrActions.push( { - "name": "Gas Reimbursement - Set Minimal time interval from S2M and S2S transfers", - "fn": async function() { - await IMA.reimbursement_set_range( - imaState.w3_s_chain, - imaState.jo_community_locker, - imaState.joAccount_s_chain, - imaState.strChainName_s_chain, - imaState.cid_s_chain, - imaState.tc_s_chain, - imaState.strChainName_origin_chain, - imaState.nReimbursementRange - ); - return true; - } - } ); -} - -if( imaState.nAutoExitAfterSeconds > 0 ) { - log.write( cc.debug( "Automatic exit after " ) + cc.info( imaState.nAutoExitAfterSeconds ) + cc.debug( " second(s) is requested." ) + "\n" ); - const iv = setInterval( function() { - log.write( cc.debug( "Performing automatic exit after " ) + cc.info( imaState.nAutoExitAfterSeconds ) + cc.debug( " second(s)..." ) + "\n" ); - clearInterval( iv ); - process.exit( 0 ); - }, imaState.nAutoExitAfterSeconds * 1000 ); -} else - log.write( cc.debug( "Automatic exit was not requested, skipping it." ) + "\n" ); - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -if( imaState.strLogFilePath.length > 0 ) { - log.write( cc.debug( "Will print message to file " ) + cc.info( imaState.strLogFilePath ) + "\n" ); - log.add( imaState.strLogFilePath, imaState.nLogMaxSizeBeforeRotation, imaState.nLogMaxFilesCount ); -} - -if( imaState.bIsNeededCommonInit ) - imaCLI.ima_common_init(); - -if( imaState.bShowConfigMode ) { - // just show configuration values and exit - process.exit( 0 ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function get_s_chain_nodes_count( joSChainNetworkInfo ) { - try { - if( ! joSChainNetworkInfo ) - return 0; - const jarrNodes = joSChainNetworkInfo.network; - const cntNodes = jarrNodes.length; - return cntNodes; - } catch ( err ) { - return 0; - } -} - -function get_s_chain_discovered_nodes_count( joSChainNetworkInfo ) { - try { - if( ! joSChainNetworkInfo ) - return 0; - if( ! ( "network" in joSChainNetworkInfo && joSChainNetworkInfo.network ) ) - return 0; - const jarrNodes = joSChainNetworkInfo.network; - const cntNodes = jarrNodes.length; - if( cntNodes <= 0 ) - return 0; - let cntDiscovered = 0; - for( let i = 0; i < cntNodes; ++ i ) { - try { - const joNode = joSChainNetworkInfo.network[i]; - if( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && - "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" - ) - ++ cntDiscovered; - } catch ( err ) { - return 0; - } - } - return cntDiscovered; - } catch ( err ) { - return 0; - } -} - -let g_timer_s_chain_discovery = null; -let g_b_in_s_chain_discovery = false; - -async function continue_schain_discovery_in_background_if_needed( isSilent ) { - const cntNodes = get_s_chain_nodes_count( imaState.joSChainNetworkInfo ); - const cntDiscovered = get_s_chain_discovered_nodes_count( imaState.joSChainNetworkInfo ); - if( cntDiscovered >= cntNodes ) { - if( g_timer_s_chain_discovery != null ) { - clearInterval( g_timer_s_chain_discovery ); - g_timer_s_chain_discovery = null; - } - return; - } - if( g_timer_s_chain_discovery != null ) - return; - if( imaState.joSChainDiscovery.repeatIntervalMilliseconds <= 0 ) - return; // no S-Chain re-discovery (for debugging only) - const fn_async_handler = async function() { - if( g_b_in_s_chain_discovery ) - return; - if( g_b_in_s_chain_discovery ) { - isInsideAsyncHandler = false; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( cc.warning( "Notice: long S-Chain discovery is in progress" ) + "\n" ); - return; - } - g_b_in_s_chain_discovery = true; - try { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) { - log.write( - cc.info( "Will re-discover " ) + cc.notice( cntNodes ) + cc.info( "-node S-Chain network, " ) + - cc.notice( cntDiscovered ) + cc.info( " node(s) already discovered..." ) + "\n" ); - } - await discover_s_chain_network( function( err, joSChainNetworkInfo ) { - if( ! err ) { - const cntDiscoveredNew = get_s_chain_discovered_nodes_count( joSChainNetworkInfo ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) { - const strDiscoveryStatus = cc.info( cntDiscoveredNew ) + cc.success( " nodes known" ); - let strMessage = - cc.success( "S-Chain network was re-discovered, " ) + cc.info( cntDiscoveredNew ) + - cc.success( " of " ) + cc.info( cntNodes ) + - cc.success( " node(s) (" ) + strDiscoveryStatus + cc.success( ")" ); - const cntStillUnknown = cntNodes - cntDiscoveredNew; - if( cntStillUnknown > 0 ) { - strMessage += cc.success( ", " ) + - cc.info( cntStillUnknown ) + cc.success( " of " ) + cc.info( cntNodes ) + - cc.success( " still unknown (" ); - try { - const jarrNodes = joSChainNetworkInfo.network; - let cntBad = 0; - for( let i = 0; i < jarrNodes.length; ++i ) { - const joNode = jarrNodes[i]; - try { - if( ! ( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" && - "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" ) ) { - if( cntBad > 0 ) - strMessage += cc.success( ", " ); - const strNodeURL = imaUtils.compose_schain_node_url( joNode ); - const strNodeDescColorized = - cc.notice( "#" ) + cc.info( i ) + - cc.attention( "(" ) + cc.u( strNodeURL ) + cc.attention( ")" ); - strMessage += strNodeDescColorized; - ++ cntBad; - } - } catch ( err ) { } - } - } catch ( err ) { } - strMessage += cc.success( ")" ); - } - if( ! isSilent ) { - strMessage += - cc.success( ", complete re-discovered S-Chain network info: " ) + - cc.j( joSChainNetworkInfo ); - } - log.write( strMessage + "\n" ); - } - imaState.joSChainNetworkInfo = joSChainNetworkInfo; - } - continue_schain_discovery_in_background_if_needed( isSilent ); - }, isSilent, imaState.joSChainNetworkInfo, cntNodes ).catch( ( err ) => { - log.write( - cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " S-Chain network re-discovery failed: " ) + - cc.warning( err ) + "\n" - ); - } ); - } catch ( err ) { } - g_b_in_s_chain_discovery = false; - }; - g_timer_s_chain_discovery = setInterval( function() { - if( g_b_in_s_chain_discovery ) - return; - fn_async_handler(); - }, imaState.joSChainDiscovery.repeatIntervalMilliseconds ); -} - -async function discover_s_chain_network( fnAfter, isSilent, joPrevSChainNetworkInfo, nCountToWait ) { - isSilent = isSilent || false; - joPrevSChainNetworkInfo = joPrevSChainNetworkInfo || null; - if( nCountToWait == null || nCountToWait == undefined || nCountToWait < 0 ) - nCountToWait = 0; - const strLogPrefix = cc.info( "S-Chain network discovery:" ) + " "; - fnAfter = fnAfter || function() {}; - let joSChainNetworkInfo = null; - const rpcCallOpts = null; - try { - await rpcCall.create( imaState.strURL_s_chain, rpcCallOpts, async function( joCall, err ) { - if( err ) { - if( ! isSilent ) { - log.write( - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to (own) S-Chain " ) + cc.u( imaState.strURL_s_chain ) + cc.error( " failed: " ) + - cc.warning( err ) + "\n" - ); - } - fnAfter( err, null ); - return; - } - await joCall.call( { - "method": "skale_nodesRpcInfo", - "params": { - "fromImaAgentIndex": imaState.nNodeNumber - } - }, async function( joIn, joOut, err ) { - if( err ) { - if( ! isSilent ) { - log.write( - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to (own) S-Chain " ) + cc.u( imaState.strURL_s_chain ) + cc.error( " failed, error: " ) + - cc.warning( err ) + "\n" - ); - } - fnAfter( err, null ); - return; - } - if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.trace ) - log.write( strLogPrefix + cc.debug( "OK, got (own) S-Chain network information: " ) + cc.j( joOut.result ) + "\n" ); - else if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.success( "OK, got S-Chain " ) + cc.u( imaState.strURL_s_chain ) + cc.success( " network information." ) + "\n" ); - // - let nCountReceivedImaDescriptions = 0; - joSChainNetworkInfo = joOut.result; - if( ! joSChainNetworkInfo ) { - const err2 = new Error( "Got wrong response, network information description was not detected" ); - if( ! isSilent ) { - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " Network was not detected via call to " ) + cc.u( imaState.strURL_s_chain ) + cc.error( ": " ) + - cc.warning( err2 ) + "\n" - ); - } - fnAfter( err2, null ); - return; - } - const jarrNodes = joSChainNetworkInfo.network; - const cntNodes = jarrNodes.length; - if( nCountToWait <= 0 ) { - nCountToWait = 0 + cntNodes; - if( nCountToWait > 2 ) - nCountToWait = Math.ceil( nCountToWait * 2 / 3 ); - } else if( nCountToWait > cntNodes ) - nCountToWait = cntNodes; - if( ! isSilent ) { - log.write( strLogPrefix + cc.debug( "Will gather details of " ) + cc.info( nCountToWait ) + - cc.debug( " of " ) + cc.info( cntNodes ) + cc.debug( " node(s)..." ) + "\n" - ); - } - let cntFailed = 0; - for( let i = 0; i < cntNodes; ++ i ) { - const nCurrentNodeIdx = 0 + i; - const joNode = jarrNodes[nCurrentNodeIdx]; - const strNodeURL = imaUtils.compose_schain_node_url( joNode ); - const strNodeDescColorized = - cc.notice( "#" ) + cc.info( nCurrentNodeIdx ) + - cc.attention( "(" ) + cc.u( strNodeURL ) + cc.attention( ")" ); - try { - if( joPrevSChainNetworkInfo && "network" in joPrevSChainNetworkInfo && joPrevSChainNetworkInfo.network ) { - const joPrevNode = joPrevSChainNetworkInfo.network[nCurrentNodeIdx]; - if( joPrevNode && "imaInfo" in joPrevNode && typeof joPrevNode.imaInfo === "object" && - "t" in joPrevNode.imaInfo && typeof joPrevNode.imaInfo.t === "number" - ) { - joNode.imaInfo = JSON.parse( JSON.stringify( joPrevNode.imaInfo ) ); - if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.information ) { - log.write( - strLogPrefix + cc.info( "OK, in case of " ) + strNodeDescColorized + - cc.info( " node " ) + cc.info( joNode.nodeID ) + - cc.info( " will use previous discovery result." ) + "\n" - ); - } - continue; // skip this node discovery, enrich rest of nodes - } - } - } catch ( err ) { - } - const rpcCallOpts = null; - try { - await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - if( ! isSilent ) { - log.write( - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + cc.error( " failed" ) + - "\n" - ); - } - // fnAfter( err, null ); - ++ cntFailed; - return; - } - joCall.call( { - "method": "skale_imaInfo", - "params": { - "fromImaAgentIndex": imaState.nNodeNumber - } - }, function( joIn, joOut, err ) { - ++ nCountReceivedImaDescriptions; - if( err ) { - if( ! isSilent ) { - log.write( - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + cc.error( " failed, error: " ) + - cc.warning( err ) + "\n" - ); - } - // fnAfter( err, null ); - ++ cntFailed; - return; - } - //if( (!isSilent) && IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - // log.write( strLogPrefix + cc.normal( "Node ") + cc.info(joNode.nodeID) + cc.normal(" IMA information: " ) + cc.j( joOut.result ) + "\n" ); - joNode.imaInfo = joOut.result; - //joNode.joCall = joCall; - if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.information ) { - log.write( - strLogPrefix + cc.success( "OK, got " ) + strNodeDescColorized + - cc.success( " node " ) + cc.info( joNode.nodeID ) + - cc.success( " IMA information(" ) + cc.info( nCountReceivedImaDescriptions ) + cc.success( " of " ) + - cc.info( cntNodes ) + cc.success( ")." ) + "\n" - ); - } - } ); - } ); - } catch ( err ) { - if( ! isSilent ) { - log.write( - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain node " ) + strNodeDescColorized + cc.error( " was not created: " ) + - cc.warning( err ) + "\n" - ); - } - // fnAfter( err, null ); - ++ cntFailed; - // return; - } - } - let nCountAvailable = cntNodes - cntFailed; - if( ! isSilent ) { - log.write( - cc.debug( "Waiting for S-Chain nodes, total " ) + cc.warning( cntNodes ) + - cc.debug( ", available " ) + cc.warning( nCountAvailable ) + - cc.debug( ", expected at least " ) + cc.warning( nCountToWait ) + - "\n" - ); - } - if( nCountAvailable < nCountToWait ) { - if( ! isSilent ) { - log.write( - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " Not enough nodes available on S-Chain, total " ) + cc.warning( cntNodes ) + - cc.error( ", available " ) + cc.warning( nCountAvailable ) + - cc.error( ", expected at least " ) + cc.warning( nCountToWait ) + - "\n" - ); - } - const err = new Error( - "Not enough nodes available on S-Chain, total " + cntNodes + - ", available " + nCountAvailable + ", expected at least " + nCountToWait - ); - fnAfter( err, null ); - return; - } - if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.information ) { - log.write( - strLogPrefix + cc.debug( "Waiting for response from at least " ) + cc.info( nCountToWait ) + - cc.debug( " node(s)..." ) + "\n" - ); - } - let nWaitAttempt = 0; - const nWaitStepMilliseconds = 1000; - let cntWaitAttempts = Math.floor( imaState.joSChainDiscovery.repeatIntervalMilliseconds / nWaitStepMilliseconds ) - 3; - if( cntWaitAttempts < 1 ) - cntWaitAttempts = 1; - const iv = setInterval( function() { - nCountAvailable = cntNodes - cntFailed; - if( ! isSilent ) { - log.write( - cc.debug( "Waiting attempt " ) + - cc.info( nWaitAttempt ) + cc.debug( " of " ) + cc.info( cntWaitAttempts ) + - cc.debug( " for S-Chain nodes, total " ) + cc.info( cntNodes ) + - cc.debug( ", available " ) + cc.info( nCountAvailable ) + - cc.debug( ", expected at least " ) + cc.info( nCountToWait ) + - "\n" - ); - } - if( ( !isSilent ) && IMA.verbose_get() >= IMA.RV_VERBOSE.information ) { - log.write( - strLogPrefix + cc.debug( "Have S-Chain description response about " ) + - cc.info( nCountReceivedImaDescriptions ) + cc.debug( " node(s)." ) + "\n" - ); - } - if( nCountReceivedImaDescriptions >= nCountToWait ) { - clearInterval( iv ); - fnAfter( null, joSChainNetworkInfo ); - return; - } - ++ nWaitAttempt; - if( nWaitAttempt >= cntWaitAttempts ) { - clearInterval( iv ); - const strErrorDescription = "S-Chain network discovery wait timeout, network will be re-discovered"; - if( ! isSilent ) - log.write( strLogPrefix + cc.error( "WARNING:" ) + " " + cc.warning( strErrorDescription ) + "\n" ); - if( get_s_chain_discovered_nodes_count( joSChainNetworkInfo ) > 0 ) - fnAfter( null, joSChainNetworkInfo ); - else - fnAfter( new Error( strErrorDescription ), null ); - return; - } - if( ! isSilent ) { - log.write( - strLogPrefix + cc.debug( " Waiting attempt " ) + - cc.info( nWaitAttempt ) + cc.debug( " of " ) + cc.info( cntWaitAttempts ) + - cc.debug( " for " ) + cc.notice( nCountToWait - nCountReceivedImaDescriptions ) + - cc.debug( " node answer(s)" ) + - "\n" - ); - } - }, nWaitStepMilliseconds ); - } ); - } ); - } catch ( err ) { - if( ! isSilent ) { - log.write( - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " JSON RPC call to S-Chain was not created: " ) + - cc.warning( err ) + "\n" - ); - } - joSChainNetworkInfo = null; - fnAfter( err, null ); - } - return joSChainNetworkInfo; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -let g_ws_server_monitoring = null; - -if( imaState.nMonitoringPort > 0 ) { - const strLogPrefix = cc.attention( "Monitoring" ) + " " + cc.sunny( ">>" ) + " "; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.trace ) - log.write( strLogPrefix + cc.normal( "Will start monitoring WS server on port " ) + cc.info( imaState.nMonitoringPort ) + "\n" ); - g_ws_server_monitoring = new ws.Server( { port: 0 + imaState.nMonitoringPort } ); - g_ws_server_monitoring.on( "connection", function( ws_peer, req ) { - const ip = req.socket.remoteAddress; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.trace ) - log.write( strLogPrefix + cc.normal( "New connection from " ) + cc.info( ip ) + "\n" ); - ws_peer.on( "message", function( message ) { - const joAnswer = { - method: null, - id: null, - error: null - }; - try { - const joMessage = JSON.parse( message ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.trace ) - log.write( strLogPrefix + cc.normal( "Message from " ) + cc.info( ip ) + cc.normal( ": " ) + cc.j( joMessage ) + "\n" ); - if( ! ( "method" in joMessage ) ) - throw new Error( "\"method\" field was not specified" ); - joAnswer.method = joMessage.method; - if( ! ( "id" in joMessage ) ) - throw new Error( "\"id\" field was not specified" ); - joAnswer.id = joMessage.id; - switch ( joMessage.method ) { - case "echo": - case "ping": - // call: { "id": 1, "method": "echo" } - // answer: { "id": 1, "method": "echo", "error": null } - // call: { "id": 1, "method": "ping" } - // answer: { "id": 1, "method": "ping", "error": null } - break; - case "get_schain_network_info": - // call: { "id": 1, "method": "get_schain_network_info" } - // answer: { "id": 1, "method": "get_schain_network_info", "error": null, "schain_network_info": ... } - joAnswer.schain_network_info = imaState.joSChainNetworkInfo; - break; - case "get_runtime_params": - // call: { "id": 1, "method": "get_runtime_params" } - // answer: { "id": 1, "method": "get_runtime_params", "error": null, "runtime_params": ... } - { - joAnswer.runtime_params = {}; - const arr_runtime_param_names = [ - "bNoWaitSChainStarted", - "nMaxWaitSChainAttempts", - "isPreventExitAfterLastAction", - - "strURL_main_net", - "strURL_s_chain", - //"strURL_t_chain", - - "strChainName_main_net", - "strChainName_s_chain", - //"strChainName_t_chain", - "cid_main_net", - "cid_s_chain", - //"cid_t_chain", - - "nTransferBlockSizeM2S", - "nTransferBlockSizeS2M", - "nTransferBlockSizeS2S", - "nMaxTransactionsM2S", - "nMaxTransactionsS2M", - "nMaxTransactionsS2S", - - "nBlockAwaitDepthM2S", - "nBlockAwaitDepthS2M", - "nBlockAwaitDepthS2S", - "nBlockAgeM2S", - "nBlockAgeS2M", - "nBlockAgeS2S", - - "nLoopPeriodSeconds", - - "nNodeNumber", - "nNodesCount", - "nTimeFrameSeconds", - "nNextFrameGap", - - "optsPendingTxAnalysis", - - "nMonitoringPort" - ]; - for( const param_name of arr_runtime_param_names ) { - if( param_name in imaState ) - joAnswer.runtime_params[param_name] = imaState[param_name]; - - } - } break; - case "get_last_transfer_errors": - // call: { "id": 1, "method": "get_last_transfer_errors" } - // answer: { "id": 1, "method": "get_last_transfer_errors", "isIncludeTextLog": true, "error": null, "last_transfer_errors": [ { ts: ..., textLog: ... }, ... ] } - joAnswer.last_transfer_errors = IMA.get_last_transfer_errors( ( ( "isIncludeTextLog" in joMessage ) && joMessage.isIncludeTextLog ) ? true : false ); - joAnswer.last_error_categories = IMA.get_last_error_categories(); - break; - default: - throw new Error( "Unknown method name \"" + joMessage.method + "\" was specified" ); - } // switch( joMessage.method ) - } catch ( err ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.error ) { - log.write( strLogPrefix + - cc.error( "Bad message from " ) + cc.info( ip ) + cc.error( ": " ) + cc.warning( message ) + - cc.error( ", error is: " ) + cc.warning( err ) + "\n" - ); - } - } - try { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.trace ) - log.write( strLogPrefix + cc.normal( "Answer to " ) + cc.info( ip ) + cc.normal( ": " ) + cc.j( joAnswer ) + "\n" ); - ws_peer.send( JSON.stringify( joAnswer ) ); - } catch ( err ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.error ) { - log.write( strLogPrefix + - cc.error( "Failed to sent answer to " ) + cc.info( ip ) + - cc.error( ", error is: " ) + cc.warning( err ) + "\n" - ); - } - } - } ); - // ws_peer.send( "something" ); - } ); -} // if( imaState.nMonitoringPort > 0 ) - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function do_the_job() { - const strLogPrefix = cc.info( "Job 1:" ) + " "; - let idxAction = 0; - const cntActions = imaState.arrActions.length; - let cntFalse = 0; - let cntTrue = 0; - for( idxAction = 0; idxAction < cntActions; ++idxAction ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( IMA.longSeparator ) + "\n" ); - - const joAction = imaState.arrActions[idxAction]; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.debug ) - log.write( strLogPrefix + cc.notice( "Will execute action:" ) + " " + cc.info( joAction.name ) + cc.debug( " (" ) + cc.info( idxAction + 1 ) + cc.debug( " of " ) + cc.info( cntActions ) + cc.debug( ")" ) + "\n" ); - - try { - if( await joAction.fn() ) { - ++cntTrue; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.success( "Succeeded action:" ) + " " + cc.info( joAction.name ) + "\n" ); - } else { - ++cntFalse; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.error ) - log.write( strLogPrefix + cc.warning( "Failed action:" ) + " " + cc.info( joAction.name ) + "\n" ); - } - } catch ( e ) { - ++cntFalse; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR: Exception occurred while executing action:" ) + " " + cc.info( joAction.name ) + cc.error( ", error description: " ) + cc.warning( e ) + "\n" ); - } - } // for( idxAction = 0; idxAction < cntActions; ++ idxAction ) - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) { - log.write( strLogPrefix + cc.debug( IMA.longSeparator ) + "\n" ); - log.write( strLogPrefix + cc.info( "FINISH:" ) + "\n" ); - log.write( strLogPrefix + cc.info( cntActions ) + cc.notice( " task(s) executed" ) + "\n" ); - log.write( strLogPrefix + cc.info( cntTrue ) + cc.success( " task(s) succeeded" ) + "\n" ); - log.write( strLogPrefix + cc.info( cntFalse ) + cc.error( " task(s) failed" ) + "\n" ); - log.write( strLogPrefix + cc.debug( IMA.longSeparator ) + "\n" ); - } - process.exitCode = ( cntFalse > 0 ) ? cntFalse : 0; - if( ! IMA.isPreventExitAfterLastAction ) - process.exit( process.exitCode ); -} - -if( imaState.bSignMessages ) { - if( imaState.strPathBlsGlue.length == 0 ) { - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( " please specify --bls-glue parameter." ) + "\n" ); - process.exit( 164 ); - } - if( imaState.strPathHashG1.length == 0 ) { - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( " please specify --hash-g1 parameter." ) + "\n" ); - process.exit( 165 ); - } - if( ! imaState.bNoWaitSChainStarted ) { - const isSilent = imaState.joSChainDiscovery.isSilentReDiscovery; - wait_until_s_chain_started().then( function() { // uses call to discover_s_chain_network() - discover_s_chain_network( function( err, joSChainNetworkInfo ) { - if( err ) - process.exit( 166 ); // error information is printed by discover_s_chain_network() - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( cc.success( "S-Chain network was discovered: " ) + cc.j( joSChainNetworkInfo ) + "\n" ); - imaState.joSChainNetworkInfo = joSChainNetworkInfo; - continue_schain_discovery_in_background_if_needed( isSilent ); - do_the_job(); - return 0; // FINISH - }, isSilent, imaState.joSChainNetworkInfo, -1 ).catch( ( err ) => { - log.write( - cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " S-Chain network discovery failed: " ) + - cc.warning( err ) + "\n" - ); - } ); - } ); - } -} else - do_the_job(); - // process.exit( 0 ); // FINISH (skip exit here to avoid early termination while tasks ase still running) - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const g_registrationCostInfo = { - mn: [], - sc: [] -}; - -async function register_step1( isPrintSummaryRegistrationCosts ) { - const strLogPrefix = cc.info( "Reg 1:" ) + " "; - let jarrReceipts = "true"; - const bRetVal = await IMA.check_is_registered_s_chain_in_deposit_boxes( // step 1 - imaState.w3_main_net, - imaState.jo_linker, - imaState.joAccount_main_net, - imaState.strChainName_s_chain - ); - if( !bRetVal ) { - jarrReceipts = await IMA.register_s_chain_in_deposit_boxes( // step 1 - imaState.w3_main_net, - // imaState.jo_deposit_box_eth, // only main net - // imaState.jo_deposit_box_erc20, // only main net - // imaState.isWithMetadata721 ? imaState.jo_deposit_box_erc721_with_metadata : imaState.jo_deposit_box_erc721, // only main net - imaState.jo_linker, - imaState.joAccount_main_net, - imaState.jo_token_manager_eth, // only s-chain - imaState.jo_token_manager_erc20, // only s-chain - imaState.jo_token_manager_erc721, // only s-chain - imaState.jo_token_manager_erc1155, // only s-chain - imaState.jo_token_manager_erc721_with_metadata, // only s-chain - imaState.jo_community_locker, // only s-chain - imaState.jo_token_manager_linker, // only s-chain - imaState.strChainName_s_chain, - imaState.cid_main_net, - imaState.tc_main_net //, - // cntWaitAttempts, - // nSleepMilliseconds - ); - } - const bSuccess = ( jarrReceipts != null && jarrReceipts.length > 0 ) ? true : false; - if( bSuccess && ( !bRetVal ) ) - g_registrationCostInfo.mn = g_registrationCostInfo.mn.concat( g_registrationCostInfo.mn, jarrReceipts ); - if( isPrintSummaryRegistrationCosts ) - print_summary_registration_costs(); - if( !bSuccess ) { - const nRetCode = 163; - log.write( strLogPrefix + cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( " failed to register S-Chain in deposit box, will return code " ) + cc.warning( nRetCode ) + "\n" ); - process.exit( nRetCode ); - } - return true; -} -async function register_all( isPrintSummaryRegistrationCosts ) { - if( !await register_step1( false ) ) - return false; - if( isPrintSummaryRegistrationCosts ) - print_summary_registration_costs(); - return true; -} - -async function check_registration_all() { - const b1 = await check_registration_step1(); - return b1; -} -async function check_registration_step1() { - const bRetVal = await IMA.check_is_registered_s_chain_in_deposit_boxes( // step 1 - imaState.w3_main_net, - imaState.jo_linker, - imaState.joAccount_main_net, - imaState.strChainName_s_chain - ); - return bRetVal; -} - -function print_summary_registration_costs() { - IMA.print_gas_usage_report_from_array( "Main Net REGISTRATION", g_registrationCostInfo.mn ); - IMA.print_gas_usage_report_from_array( "S-Chain REGISTRATION", g_registrationCostInfo.sc ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Run transfer loop -// - -global.check_time_framing = function( d ) { - try { - if( imaState.nTimeFrameSeconds <= 0 || imaState.nNodesCount <= 1 ) - return true; // time framing is disabled - - if( d == null || d == undefined ) - d = new Date(); // now - - // const nUtcUnixTimeStamp = Math.floor( d.valueOf() / 1000 ); // Unix UTC timestamp, see https://stackoverflow.com/questions/9756120/how-do-i-get-a-utc-timestamp-in-javascript - const nUtcUnixTimeStamp = Math.floor( ( d ).getTime() / 1000 ); // https://stackoverflow.com/questions/9756120/how-do-i-get-a-utc-timestamp-in-javascript - - const nSecondsRangeForAllSChains = imaState.nTimeFrameSeconds * imaState.nNodesCount; - const nMod = Math.floor( nUtcUnixTimeStamp % nSecondsRangeForAllSChains ); - const nActiveNodeFrameIndex = Math.floor( nMod / imaState.nTimeFrameSeconds ); - let bSkip = ( nActiveNodeFrameIndex != imaState.nNodeNumber ) ? true : false; - let bInsideGap = false; - // - const nRangeStart = nUtcUnixTimeStamp - Math.floor( nUtcUnixTimeStamp % nSecondsRangeForAllSChains ); - const nFrameStart = nRangeStart + imaState.nNodeNumber * imaState.nTimeFrameSeconds; - const nGapStart = nFrameStart + imaState.nTimeFrameSeconds - imaState.nNextFrameGap; - if( !bSkip ) { - if( nUtcUnixTimeStamp >= nGapStart ) { - bSkip = true; - bInsideGap = true; - } - } - // if( IMA.verbose_get() >= IMA.RV_VERBOSE.trace ) { - log.write( - "\n" + - cc.info( "Unix UTC time stamp" ) + cc.debug( "........" ) + cc.notice( nUtcUnixTimeStamp ) + "\n" + - cc.info( "All Chains Range" ) + cc.debug( "..........." ) + cc.notice( nSecondsRangeForAllSChains ) + "\n" + - cc.info( "S-Chain Range Mod" ) + cc.debug( ".........." ) + cc.notice( nMod ) + "\n" + - cc.info( "Active Node Frame Index" ) + cc.debug( "...." ) + cc.notice( nActiveNodeFrameIndex ) + "\n" + - cc.info( "Testing Frame Index" ) + cc.debug( "........" ) + cc.notice( imaState.nNodeNumber ) + "\n" + - cc.info( "Is skip" ) + cc.debug( "...................." ) + cc.yn( bSkip ) + "\n" + - cc.info( "Is inside gap" ) + cc.debug( ".............." ) + cc.yn( bInsideGap ) + "\n" + - cc.info( "Range Start" ) + cc.debug( "................" ) + cc.notice( nRangeStart ) + "\n" + - cc.info( "Frame Start" ) + cc.debug( "................" ) + cc.notice( nFrameStart ) + "\n" + - cc.info( "Gap Start" ) + cc.debug( ".................." ) + cc.notice( nGapStart ) + "\n" - ); - // } - if( bSkip ) - return false; - } catch ( e ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.fatal ) - log.write( cc.fatal( "Exception in check_time_framing():" ) + cc.error( e ) + "\n" ); - } - return true; -}; - -let g_is_single_transfer_loop = false; - -async function single_transfer_loop() { - const strLogPrefix = cc.attention( "Single Loop:" ) + " "; - try { - if( g_is_single_transfer_loop ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.debug ) - log.write( strLogPrefix + cc.warning( "Skipped due to other single transfer loop is in progress rignt now" ) + "\n" ); - return true; - } - g_is_single_transfer_loop = true; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.debug ) - log.write( strLogPrefix + cc.debug( IMA.longSeparator ) + "\n" ); - - if( ! global.check_time_framing() ) { - g_is_single_transfer_loop = false; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.debug ) - log.write( strLogPrefix + cc.warning( "Skipped due to time framing" ) + "\n" ); - IMA.save_transfer_success_all(); - return true; - } - - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Will invoke Oracle gas price setup..." ) + "\n" ); - let b0 = true; - if( IMA.getEnabledOracle() ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Will invoke Oracle gas price setup..." ) + "\n" ); - b0 = IMA.do_oracle_gas_price_setup( - imaState.w3_main_net, - imaState.w3_s_chain, - imaState.tc_s_chain, - imaState.jo_community_locker, - imaState.joAccount_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - imaBLS.do_sign_u256, // fn_sign - imaState.optsPendingTxAnalysis - ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Oracle gas price setup done: " ) + cc.tf( b0 ) + "\n" ); - } - - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Will invoke M2S transfer..." ) + "\n" ); - const b1 = await IMA.do_transfer( // main-net --> s-chain - "M2S", - // - imaState.w3_main_net, - imaState.jo_message_proxy_main_net, - imaState.joAccount_main_net, - imaState.w3_s_chain, - imaState.jo_message_proxy_s_chain, - // - imaState.joAccount_s_chain, - imaState.strChainName_main_net, - imaState.strChainName_s_chain, - imaState.cid_main_net, - imaState.cid_s_chain, - null, // imaState.jo_deposit_box - for logs validation on mainnet - imaState.jo_token_manager_eth, // for logs validation on s-chain - imaState.nTransferBlockSizeM2S, - imaState.nMaxTransactionsM2S, - imaState.nBlockAwaitDepthM2S, - imaState.nBlockAgeM2S, - imaBLS.do_sign_messages_m2s, // fn_sign_messages - null, // joExtraSignOpts - imaState.tc_s_chain, - imaState.optsPendingTxAnalysis - ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "M2S transfer done: " ) + cc.tf( b1 ) + "\n" ); - - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Will invoke S2M transfer..." ) + "\n" ); - const b2 = await IMA.do_transfer( // s-chain --> main-net - "S2M", - // - imaState.w3_s_chain, - imaState.jo_message_proxy_s_chain, - imaState.joAccount_s_chain, - imaState.w3_main_net, - imaState.jo_message_proxy_main_net, - // - imaState.joAccount_main_net, - imaState.strChainName_s_chain, - imaState.strChainName_main_net, - imaState.cid_s_chain, - imaState.cid_main_net, - imaState.jo_deposit_box_eth, // for logs validation on mainnet - null, // imaState.jo_token_manager, // for logs validation on s-chain - imaState.nTransferBlockSizeS2M, - imaState.nMaxTransactionsS2M, - imaState.nBlockAwaitDepthS2M, - imaState.nBlockAgeS2M, - imaBLS.do_sign_messages_s2m, // fn_sign_messages - null, // joExtraSignOpts - imaState.tc_main_net, - imaState.optsPendingTxAnalysis - ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "S2M transfer done: " ) + cc.tf( b2 ) + "\n" ); - - let b3 = true; - if( imaState.s2s_opts.isEnabled ) { - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Will invoke all S2S transfers..." ) + "\n" ); - b3 = await IMA.do_s2s_all( // s-chain --> s-chain - imaState, - skale_observer, - imaState.w3_s_chain, - imaState.jo_message_proxy_s_chain, - // - imaState.joAccount_s_chain, - imaState.strChainName_s_chain, - imaState.cid_s_chain, - imaState.jo_token_manager_eth, // for logs validation on s-chain - imaState.nTransferBlockSizeM2S, - imaState.nMaxTransactionsM2S, - imaState.nBlockAwaitDepthM2S, - imaState.nBlockAgeM2S, - imaBLS.do_sign_messages_s2s, // fn_sign_messages - imaState.tc_s_chain, - imaState.optsPendingTxAnalysis - ); - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "All S2S transfers done: " ) + cc.tf( b3 ) + "\n" ); - } - - g_is_single_transfer_loop = false; - const bResult = b0 && b1 && b2 && b3; - if( IMA.verbose_get() >= IMA.RV_VERBOSE.information ) - log.write( strLogPrefix + cc.debug( "Completed: " ) + cc.tf( bResult ) + "\n" ); - return bResult; - } catch ( err ) { - log.write( strLogPrefix + cc.fatal( "Exception:" ) + + cc.error( err.toString() ) + "\n" ); - } - g_is_single_transfer_loop = false; - return false; -} -async function single_transfer_loop_with_repeat() { - await single_transfer_loop(); - setTimeout( single_transfer_loop_with_repeat, imaState.nLoopPeriodSeconds * 1000 ); -}; -async function run_transfer_loop( isDelayFirstRun ) { - isDelayFirstRun = owaspUtils.toBoolean( isDelayFirstRun ); - if( isDelayFirstRun ) - setTimeout( single_transfer_loop_with_repeat, imaState.nLoopPeriodSeconds * 1000 ); - else - await single_transfer_loop_with_repeat(); - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function wait_until_s_chain_started() { - log.write( cc.debug( "Checking " ) + cc.info( "S-Chain" ) + cc.debug( " is accessible and sane..." ) + "\n" ); - if( ( !imaState.strURL_s_chain ) || imaState.strURL_s_chain.length === 0 ) { - log.write( cc.warning( "Skipped, " ) + cc.info( "S-Chain" ) + cc.warning( " URL was not provided." ) + "\n" ); - return; - } - let bSuccess = false; - let idxWaitAttempt = 0; - for( ; !bSuccess; ) { - try { - const joSChainNetworkInfo = await discover_s_chain_network( function( err, joSChainNetworkInfo ) { - if( ! err ) - bSuccess = true; - }, true, null, -1 ).catch( ( err ) => { - log.write( - cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " S-Chain network discovery failed: " ) + - cc.warning( err ) + "\n" - ); - } ); - if( ! joSChainNetworkInfo ) - bSuccess = false; - } catch ( err ) { - bSuccess = false; - } - if( !bSuccess ) - ++ idxWaitAttempt; - if( idxWaitAttempt >= imaState.nMaxWaitSChainAttempts ) { - log.write( cc.warning( "Incomplete, " ) + cc.info( "S-Chain" ) + cc.warning( " sanity check failed after " ) + cc.info( idxWaitAttempt ) + cc.warning( " attempts." ) + "\n" ); - return; - } - await IMA.sleep( 1000 ); - } - log.write( cc.success( "Done, " ) + cc.info( "S-Chain" ) + cc.success( " is accessible and sane." ) + "\n" ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/agent/main.mjs b/agent/main.mjs new file mode 100644 index 000000000..1abbc6dc9 --- /dev/null +++ b/agent/main.mjs @@ -0,0 +1,499 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file main.mjs + * @copyright SKALE Labs 2019-Present + */ + +import express from "express"; +import bodyParser from "body-parser"; + +import * as ws from "ws"; + +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as imaCLI from "./cli.mjs"; +import * as loop from "./loop.mjs"; +import * as imaUtils from "./utils.mjs"; +import * as imaHelperAPIs from "../npms/skale-ima/imaHelperAPIs.mjs"; +import * as imaTransferErrorHandling from "../npms/skale-ima/imaTransferErrorHandling.mjs"; +import * as imaBLS from "./bls.mjs"; +import * as pwa from "./pwa.mjs"; +import * as clpTools from "./clpTools.mjs"; +import * as discoveryTools from "./discoveryTools.mjs"; + +import * as state from "./state.mjs"; + +// allow self-signed wss and https +process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; + +function parseCommandLine() { + const imaState = state.get(); + cc.autoEnableFromCommandLineArgs(); + let strPrintedArguments = cc.normal( process.argv.join( " " ) ); + strPrintedArguments = imaUtils.replaceAll( strPrintedArguments, "--", cc.bright( "--" ) ); + strPrintedArguments = imaUtils.replaceAll( strPrintedArguments, "=", cc.sunny( "=" ) ); + strPrintedArguments = imaUtils.replaceAll( strPrintedArguments, "/", cc.info( "/" ) ); + strPrintedArguments = imaUtils.replaceAll( strPrintedArguments, ":", cc.info( ":" ) ); + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.debug( "Agent was started with " ) + cc.info( process.argv.length ) + + cc.debug( " command line argument(s) as: " ) + strPrintedArguments + "\n" ); + } + imaCLI.parse( { + "register": clpTools.commandLineTaskRegister, + "register1": clpTools.commandLineTaskRegister1, + "check-registration": clpTools.commandLineTaskCheckRegistration, + "check-registration1": clpTools.commandLineTaskCheckRegistration1, + "mint-erc20": clpTools.commandLineTaskMintErc20, + "mint-erc721": clpTools.commandLineTaskMintErc721, + "mint-erc1155": clpTools.commandLineTaskMintErc1155, + "burn-erc20": clpTools.commandLineTaskBurnErc20, + "burn-erc721": clpTools.commandLineTaskBurnErc721, + "burn-erc1155": clpTools.commandLineTaskBurnErc1155, + "show-balance": clpTools.commandLineTaskShowBalance, + "m2s-payment": clpTools.commandLineTaskPaymentM2S, + "s2m-payment": clpTools.commandLineTaskPaymentS2M, + "s2s-payment": clpTools.commandLineTaskPaymentS2S, + "s2m-receive": clpTools.commandLineTaskReceiveS2M, + "s2m-view": clpTools.commandLineTaskViewS2M, + "m2s-transfer": clpTools.commandLineTaskTransferM2S, + "s2m-transfer": clpTools.commandLineTaskTransferS2M, + "s2s-transfer": clpTools.commandLineTaskTransferS2S, + "transfer": clpTools.commandLineTaskTransfer, + "loop": clpTools.commandLineTaskLoop, + "simple-loop": clpTools.commandLineTaskLoopSimple, + "browse-s-chain": clpTools.commandLineTaskBrowseSChain, + "browse-skale-network": clpTools.commandLineTaskBrowseSkaleNetwork, + "browse-connected-schains": clpTools.commandLineTaskBrowseConnectedSChains, + "discover-cid": clpTools.commandLineTaskDiscoverChainId + } ); + let haveReimbursementCommands = false; + if( imaState.isShowReimbursementBalance ) { + haveReimbursementCommands = true; + clpTools.commandLineTaskReimbursementShowBalance(); + } + if( imaState.nReimbursementEstimate ) { + haveReimbursementCommands = true; + clpTools.commandLineTaskReimbursementEstimateAmount(); + } + if( imaState.nReimbursementRecharge ) { + haveReimbursementCommands = true; + clpTools.commandLineTaskReimbursementRecharge(); + } + if( imaState.nReimbursementWithdraw ) { + haveReimbursementCommands = true; + clpTools.commandLineTaskReimbursementWithdraw(); + } + if( haveReimbursementCommands ) { + if( imaState.strReimbursementChain == "" ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "RUNTIME INIT ERROR:" ) + + cc.error( " missing value for " ) + cc.info( "reimbursement-chain" ) + + cc.error( " parameter, must be non-empty chain name" ) + "\n" ); + } + process.exit( 163 ); + } + } + if( imaState.nReimbursementRange >= 0 ) + clpTools.commandLineTaskReimbursementSetRange(); + if( imaState.nAutoExitAfterSeconds > 0 ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Automatic exit after " ) + + cc.info( imaState.nAutoExitAfterSeconds ) + + cc.warning( " second(s) is requested." ) + "\n" ); + } + const iv = setInterval( function() { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Performing automatic exit after " ) + + cc.info( imaState.nAutoExitAfterSeconds ) + cc.warning( " second(s)..." ) + + "\n" ); + } + clearInterval( iv ); + process.exit( 0 ); + }, imaState.nAutoExitAfterSeconds * 1000 ); + } else + log.write( cc.warning( "Automatic exit was not requested, skipping it." ) + "\n" ); + if( imaState.strLogFilePath.length > 0 ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.debug( "Will print message to file " ) + + cc.info( imaState.strLogFilePath ) + "\n" ); + } + log.add( + imaState.strLogFilePath, imaState.nLogMaxSizeBeforeRotation, + imaState.nLogMaxFilesCount ); + } + if( imaState.bIsNeededCommonInit ) { + imaCLI.commonInit(); + imaCLI.initContracts(); + } + if( imaState.bShowConfigMode ) { + // just show configuration values and exit + process.exit( 0 ); + } +} + +let gServerMonitoringWS = null; + +function initMonitoringServer() { + const imaState = state.get(); + if( imaState.nMonitoringPort <= 0 ) + return; + const strLogPrefix = cc.attention( "Monitoring:" ) + " "; + if( log.verboseGet() >= log.verboseReversed().trace ) { + log.write( strLogPrefix + cc.normal( "Will start monitoring WS server on port " ) + + cc.info( imaState.nMonitoringPort ) + "\n" ); + } + gServerMonitoringWS = new ws.WebSocketServer( { port: 0 + imaState.nMonitoringPort } ); + gServerMonitoringWS.on( "connection", function( wsPeer, req ) { + const ip = req.socket.remoteAddress; + if( log.verboseGet() >= log.verboseReversed().debug ) + log.write( strLogPrefix + cc.normal( "New connection from " ) + cc.info( ip ) + "\n" ); + wsPeer.on( "message", function( message ) { + const joAnswer = { + "method": null, + "id": null, + "error": null + }; + try { + const joMessage = JSON.parse( message ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + log.write( strLogPrefix + cc.sunny( "<<<" ) + " " + + cc.normal( "message from " ) + cc.info( ip ) + cc.normal( ": " ) + + cc.j( joMessage ) + "\n" ); + } + if( ! ( "method" in joMessage ) ) + throw new Error( "\"method\" field was not specified" ); + joAnswer.method = joMessage.method; + if( ! ( "id" in joMessage ) ) + throw new Error( "\"id\" field was not specified" ); + joAnswer.id = joMessage.id; + switch ( joMessage.method ) { + case "echo": + case "ping": + break; + case "get_schain_network_info": + joAnswer.schain_network_info = imaState.joSChainNetworkInfo; + break; + case "get_runtime_params": + { + joAnswer.runtime_params = {}; + const arrRuntimeParamNames = [ + "bNoWaitSChainStarted", + "nMaxWaitSChainAttempts", + + "nTransferBlockSizeM2S", + "nTransferBlockSizeS2M", + "nTransferBlockSizeS2S", + "nTransferStepsM2S", + "nTransferStepsS2M", + "nTransferStepsS2S", + "nMaxTransactionsM2S", + "nMaxTransactionsS2M", + "nMaxTransactionsS2S", + + "nBlockAwaitDepthM2S", + "nBlockAwaitDepthS2M", + "nBlockAwaitDepthS2S", + "nBlockAgeM2S", + "nBlockAgeS2M", + "nBlockAgeS2S", + + "nLoopPeriodSeconds", + + "nNodeNumber", + "nNodesCount", + "nTimeFrameSeconds", + "nNextFrameGap", + + "isPWA", + + "nMonitoringPort" + ]; + for( const param_name of arrRuntimeParamNames ) { + if( param_name in imaState ) + joAnswer.runtime_params[param_name] = imaState[param_name]; + + } + } break; + case "get_last_transfer_errors": + joAnswer.last_transfer_errors = imaTransferErrorHandling.getLastTransferErrors( + ( ( "isIncludeTextLog" in joMessage ) && joMessage.isIncludeTextLog ) + ? true : false ); + joAnswer.last_error_categories = + imaTransferErrorHandling.getLastErrorCategories(); + break; + default: + throw new Error( + "Unknown method name \"" + joMessage.method + "\" was specified" ); + } // switch( joMessage.method ) + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.error( "Bad message from " ) + cc.info( ip ) + + cc.error( ": " ) + cc.warning( message ) + cc.error( ", error is: " ) + + cc.warning( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + } + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + log.write( strLogPrefix + cc.sunny( ">>>" ) + " " + cc.normal( "answer to " ) + + cc.info( ip ) + cc.normal( ": " ) + cc.j( joAnswer ) + "\n" ); + } + wsPeer.send( JSON.stringify( joAnswer ) ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.error( "Failed to sent answer to " ) + + cc.info( ip ) + cc.error( ", error is: " ) + cc.warning( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + } ); + } ); +} + +let gExpressJsonRpcAppIMA = null; + +function initJsonRpcServer() { + const imaState = state.get(); + if( imaState.nJsonRpcPort <= 0 ) + return; + const strLogPrefix = cc.attention( "JSON RPC:" ) + " "; + gExpressJsonRpcAppIMA = express(); + gExpressJsonRpcAppIMA.use( bodyParser.urlencoded( { extended: true } ) ); + gExpressJsonRpcAppIMA.use( bodyParser.json() ); + gExpressJsonRpcAppIMA.post( "/", async function( req, res ) { + const isSkipMode = false; + const message = JSON.stringify( req.body ); + const ip = req.connection.remoteAddress.split( ":" ).pop(); + const fnSendAnswer = function( joAnswer ) { + try { + res.header( "Content-Type", "application/json" ); + res.status( 200 ).send( JSON.stringify( joAnswer ) ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + log.write( strLogPrefix + cc.sunny( ">>>" ) + " " + + cc.normal( "did sent answer to " ) + cc.info( ip ) + cc.normal( ": " ) + + cc.j( joAnswer ) + "\n" ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.error( "Failed to sent answer " ) + + cc.j( joAnswer ) + cc.error( " to " ) + cc.info( ip ) + + cc.error( ", error is: " ) + cc.warning( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + }; + let joAnswer = { + "method": null, + "id": null, + "error": null + }; + try { + const joMessage = JSON.parse( message ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + log.write( strLogPrefix + cc.sunny( "<<<" ) + " " + + cc.normal( "Peer message from " ) + cc.info( ip ) + cc.normal( ": " ) + + cc.j( joMessage ) + "\n" ); + } + if( ! ( "method" in joMessage ) ) + throw new Error( "\"method\" field was not specified" ); + joAnswer.method = joMessage.method; + if( ! ( "id" in joMessage ) ) + throw new Error( "\"id\" field was not specified" ); + if( "id" in joMessage ) + joAnswer.id = joMessage.id; + if( "method" in joMessage ) + joAnswer.method = "" + joMessage.method; + switch ( joMessage.method ) { + case "echo": + joAnswer.result = "echo"; + fnSendAnswer( joAnswer ); + break; + case "ping": + joAnswer.result = "pong"; + fnSendAnswer( joAnswer ); + break; + case "skale_imaVerifyAndSign": + joAnswer = await imaBLS.handleSkaleImaVerifyAndSign( joMessage ); + break; + case "skale_imaBSU256": + joAnswer = await imaBLS.handleSkaleImaBSU256( joMessage ); + break; + case "skale_imaNotifyLoopWork": + if( await pwa.handleLoopStateArrived( + imaState, + owaspUtils.toInteger( joMessage.params.nNodeNumber ), + joMessage.params.strLoopWorkType, + joMessage.params.nIndexS2S, + joMessage.params.isStart ? true : false, + owaspUtils.toInteger( joMessage.params.ts ), + joMessage.params.signature + ) ) + await loop.spreadArrivedStateOfPendingWorkAnalysis( joMessage ); + + break; + default: + throw new Error( "Unknown method name \"" + joMessage.method + "\" was specified" ); + } // switch( joMessage.method ) + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.error( "Bad message from " ) + cc.info( ip ) + + cc.error( ": " ) + cc.warning( message ) + cc.error( ", error is: " ) + + cc.warning( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + } + if( ! isSkipMode ) + fnSendAnswer( joAnswer ); + } ); + gExpressJsonRpcAppIMA.listen( imaState.nJsonRpcPort ); +} + +async function doTheJob() { + const imaState = state.get(); + const strLogPrefix = cc.info( "Job 1:" ) + " "; + let idxAction = 0; + const cntActions = imaState.arrActions.length; + let cntFalse = 0; + let cntTrue = 0; + for( idxAction = 0; idxAction < cntActions; ++idxAction ) { + if( log.verboseGet() >= log.verboseReversed().information ) + log.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + const joAction = imaState.arrActions[idxAction]; + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( strLogPrefix + cc.notice( "Will execute action:" ) + " " + + cc.info( joAction.name ) + cc.debug( " (" ) + cc.info( idxAction + 1 ) + + cc.debug( " of " ) + cc.info( cntActions ) + cc.debug( ")" ) + "\n" ); + } + try { + if( await joAction.fn() ) { + ++cntTrue; + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + cc.success( "Succeeded action:" ) + " " + + cc.info( joAction.name ) + "\n" ); + } + } else { + ++cntFalse; + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( strLogPrefix + cc.warning( "Failed action:" ) + " " + + cc.info( joAction.name ) + "\n" ); + } + } + } catch ( err ) { + ++cntFalse; + if( log.verboseGet() >= log.verboseReversed().critical ) { + log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Exception occurred while executing action: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + log.write( strLogPrefix + cc.info( "FINISH:" ) + "\n" ); + log.write( strLogPrefix + cc.info( cntActions ) + cc.notice( " task(s) executed" ) + "\n" ); + log.write( strLogPrefix + cc.info( cntTrue ) + cc.success( " task(s) succeeded" ) + "\n" ); + log.write( strLogPrefix + cc.info( cntFalse ) + cc.error( " task(s) failed" ) + "\n" ); + log.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + } + process.exitCode = ( cntFalse > 0 ) ? cntFalse : 0; + if( ! state.isPreventExitAfterLastAction() ) + process.exit( process.exitCode ); +} + +async function main() { + cc.autoEnableFromCommandLineArgs(); + const imaState = state.get(); + const strTmpAddressFromEnvMainNet = + owaspUtils.toEthPrivateKey( process.env.ACCOUNT_FOR_ETHEREUM ); + const strTmpAddressFromEnvSChain = + owaspUtils.toEthPrivateKey( process.env.ACCOUNT_FOR_SCHAIN ); + const strTmpAddressFromEnvSChainTarget = + owaspUtils.toEthPrivateKey( process.env.ACCOUNT_FOR_SCHAIN_TARGET ); + if( strTmpAddressFromEnvMainNet && + typeof strTmpAddressFromEnvMainNet == "string" && + strTmpAddressFromEnvMainNet.length > 0 ) + imaState.chainProperties.mn.joAccount.address_ = "" + strTmpAddressFromEnvMainNet; + if( strTmpAddressFromEnvSChain && + typeof strTmpAddressFromEnvSChain == "string" && + strTmpAddressFromEnvSChain.length > 0 ) + imaState.chainProperties.sc.joAccount.address_ = "" + strTmpAddressFromEnvSChain; + if( strTmpAddressFromEnvSChainTarget && + typeof strTmpAddressFromEnvSChainTarget == "string" && + strTmpAddressFromEnvSChainTarget.length > 0 ) + imaState.chainProperties.tc.joAccount.address_ = "" + strTmpAddressFromEnvSChainTarget; + parseCommandLine(); + initMonitoringServer(); + initJsonRpcServer(); + if( imaState.bSignMessages ) { + if( imaState.strPathBlsGlue.length == 0 ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( " please specify --bls-glue parameter." ) + "\n" ); + } + process.exit( 164 ); + } + if( imaState.strPathHashG1.length == 0 ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + + cc.error( " please specify --hash-g1 parameter." ) + "\n" ); + } + process.exit( 165 ); + } + if( ! imaState.bNoWaitSChainStarted ) { + const isSilent = imaState.joSChainDiscovery.isSilentReDiscovery; + discoveryTools.waitUntilSChainStarted().then( function() { + // uses call to discoveryTools.discoverSChainNetwork() + discoveryTools.discoverSChainNetwork( function( err, joSChainNetworkInfo ) { + if( err ) { + // error information is printed by discoveryTools.discoverSChainNetwork() + process.exit( 166 ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.success( "S-Chain network was discovered: " ) + + cc.j( joSChainNetworkInfo ) + "\n" ); + } + imaState.joSChainNetworkInfo = joSChainNetworkInfo; + discoveryTools.continueSChainDiscoveryInBackgroundIfNeeded( isSilent ); + doTheJob(); + return 0; // FINISH + }, isSilent, imaState.joSChainNetworkInfo, -1 ).catch( ( err ) => { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " S-Chain network discovery failed: " ) + + cc.warning( strError ) + "\n" ); + } + } ); + } ); + } + } else + doTheJob(); + // FINISH!!! (skip exit here to avoid early termination while tasks ase still running) +} + +main(); diff --git a/agent/oracle.js b/agent/oracle.js deleted file mode 100644 index a1fd223af..000000000 --- a/agent/oracle.js +++ /dev/null @@ -1,199 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file oracle.js - * @copyright SKALE Labs 2019-Present - */ - -const numberToBN = require( "number-to-bn" ); -const { keccak256 } = require( "js-sha3" ); - -const MIN_POW_RESULT = 10000; -const MAX_POW_NUMBER = 100000; - -const g_bnMIN_POW_RESULT = numberToBN( MIN_POW_RESULT ); -const g_bn1 = numberToBN( 1 ); -const g_bn2 = numberToBN( 2 ); -const g_bn256 = numberToBN( 256 ); -const g_bnUpperPart = g_bn2.pow( g_bn256 ).sub( g_bn1 ); -// log.write( cc.debug( "using " ) + cc.info( "2**256-1" ) + cc.debug( "=" ) + cc.info( "0x" + g_bnUpperPart.toString( 16 ) ) + cc.debug( "=" ) + cc.info( g_bnUpperPart.toString() ) + "\n" ); - -const sleep = ( milliseconds ) => { return new Promise( resolve => setTimeout( resolve, milliseconds ) ); }; - -function oracle_init() { -} - -function get_utc_timestamp_string( d ) { - d = d || new Date(); // use now time if d is not specified - const nUtcUnixTimeStampWithMilliseconds = d.getTime(); - const t = "" + nUtcUnixTimeStampWithMilliseconds; - // const t = "" + parseInt( nUtcUnixTimeStampWithMilliseconds / 1000, 10 ) + "000"; - return t; -} - -function find_pow_number( strRequestPart, details, isVerbose ) { - details = details || log; - if( isVerbose ) - details.write( cc.debug( "source part of request to find " ) + cc.sunny( "PoW number" ) + cc.debug( " is " ) + cc.notice( strRequestPart ) + "\n" ); - const t = get_utc_timestamp_string(); - let i = 0, n = 0, s = ""; - if( isVerbose ) - details.write( cc.debug( "source " ) + cc.sunny( "t" ) + cc.debug( "=" ) + cc.info( t ) + cc.debug( ", this is " ) + cc.sunny( "UTC timestamp" ) + "\n" ); - for( ; i < MAX_POW_NUMBER; ++ i ) { - n = "" + i; - s = "{" + strRequestPart + ",\"time\":" + t + ",\"pow\":" + n + "}"; - const f = numberToBN( "0x" + keccak256( s ) ); - const r = g_bnUpperPart.div( f ); // r = ( 2 ** 256 - 1 ) / f; - if( r.gt( g_bnMIN_POW_RESULT ) ) { // if( r > MIN_POW_RESULT ) - if( isVerbose ) { - details.write( cc.debug( "computed " ) + cc.sunny( "n" ) + cc.debug( "=" ) + cc.info( i ) + cc.debug( ", this is resulting " ) + cc.sunny( "PoW number" ) + "\n" ); - details.write( cc.debug( "computed " ) + cc.sunny( "f" ) + cc.debug( "=" ) + cc.info( f.toString() ) + cc.debug( "=" ) + cc.info( "0x" + f.toString( 16 ) ) + "\n" ); - details.write( cc.debug( "computed " ) + cc.sunny( "r" ) + cc.debug( "=" ) + cc.info( "(2**256-1)/f" ) + cc.debug( "=" ) + cc.info( r.toString() ) + cc.debug( "=" ) + cc.info( "0x" + r.toString( 16 ) ) + "\n" ); - details.write( cc.debug( "computed " ) + cc.sunny( "s" ) + cc.debug( "=" ) + cc.info( s ) + "\n" ); - } - break; - } - } - return s; -} - -function oracle_get_gas_price( oracleOpts, details ) { - details = details || log; - const promise_complete = new Promise( ( resolve, reject ) => { - try { - const url = oracleOpts.url; - const isVerbose = "isVerbose" in oracleOpts ? oracleOpts.isVerbose : false; - const isVerboseTraceDetails = "isVerboseTraceDetails" in oracleOpts ? oracleOpts.isVerboseTraceDetails : false; - const callOpts = "callOpts" in oracleOpts ? oracleOpts.callOpts : { }; - const nMillisecondsSleepBefore = "nMillisecondsSleepBefore" in oracleOpts ? oracleOpts.nMillisecondsSleepBefore : 1000; - const nMillisecondsSleepPeriod = "nMillisecondsSleepPeriod" in oracleOpts ? oracleOpts.nMillisecondsSleepPeriod : 3000; - let cntAttempts = "cntAttempts" in oracleOpts ? oracleOpts.cntAttempts : 40; - if( cntAttempts < 1 ) - cntAttempts = 1; - rpcCall.create( url, callOpts || { }, async function( joCall, err ) { - if( err ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " RPC connection problem for url " ) + cc.u( url ) + cc.error( ", error description: " ) + cc.warning( err.toString() ) + "\n" ); - details.write( err.stack + "\n" ); - reject( new Error( "CRITICAL ORACLE CALL ERROR: RPC connection problem for url \"" + url + "\", error description: " + err.toString() ) ); - return; - } - try { - const s = find_pow_number( - "\"cid\":1000,\"uri\":\"geth://\",\"jsps\":[\"/result\"],\"post\":\"{\\\"jsonrpc\\\":\\\"2.0\\\",\\\"method\\\":\\\"eth_gasPrice\\\",\\\"params\\\":[],\\\"id\\\":1}\"", - details, - isVerbose - ); - const joIn = { - method: "oracle_submitRequest", - params: [ s ] - }; - if( isVerboseTraceDetails ) - details.write( cc.debug( "RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_submitRequest" ) + cc.normal( ")" ) + cc.debug( " is " ) + cc.j( joIn ) + "\n" ); - await joCall.call( joIn, async function( joIn, joOut, err ) { - if( err ) { - if( isVerboseTraceDetails ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " JSON RPC call" ) + cc.debug( "(" ) + cc.attention( "oracle_submitRequest" ) + cc.normal( ")" ) + cc.error( " failed, error: " ) + cc.warning( err.toString() ) + "\n" ); - details.write( err.stack + "\n" ); - } - reject( new Error( "CRITICAL ORACLE CALL ERROR: JSON RPC call(oracle_submitRequest) failed, error: " + err.toString() ) ); - return; - } - if( isVerboseTraceDetails ) - details.write( cc.debug( "RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_submitRequest" ) + cc.normal( ")" ) + cc.debug( " result is: " ) + cc.j( joOut ) + "\n" ); - if( !( "result" in joOut && typeof joOut.result == "string" && joOut.result.length > 0 ) ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " bad unexpecected result" ) + cc.normal( "(" ) + cc.attention( "oracle_submitRequest" ) + cc.normal( ")" ) + "\n" ); - details.write( err.stack + "\n" ); - reject( new Error( "CRITICAL ORACLE CALL ERROR: bad unexpecected result(oracle_submitRequest)" ) ); - return; - } - for( let idxAttempt = 0; idxAttempt < cntAttempts; ++idxAttempt ) { - const nMillisecondsToSleep = ( ! idxAttempt ) ? nMillisecondsSleepBefore : nMillisecondsSleepPeriod; - if( nMillisecondsToSleep > 0 ) - await sleep( nMillisecondsToSleep ); - try { - joIn = { - method: "oracle_checkResult", - params: [ joOut.result ] - }; - if( isVerboseTraceDetails ) { - details.write( cc.debug( "RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + cc.debug( " attempt " ) + cc.info( idxAttempt ) + cc.debug( " of " ) + cc.info( cntAttempts ) + cc.debug( "..." ) + "\n" ); - details.write( cc.debug( "RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + cc.debug( " is " ) + cc.j( joIn ) + "\n" ); - } - await joCall.call( joIn, async function( joIn, joOut, err ) { - if( err ) { - if( isVerboseTraceDetails ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " JSON RPC call" ) + cc.debug( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + cc.error( " failed, error: " ) + cc.warning( err.toString() ) + "\n" ); - details.write( err.stack + "\n" ); - } - //reject( new Error( "CRITICAL ORACLE CALL ERROR: JSON RPC call(oracle_checkResult) failed, error: " + err.toString() ) ); - return; - } - if( isVerboseTraceDetails ) - details.write( cc.debug( "RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + cc.debug( " result is: " ) + cc.j( joOut ) + "\n" ); - if( !( "result" in joOut && typeof joOut.result == "string" && joOut.result.length > 0 ) ) { - if( isVerboseTraceDetails ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " bad unexpecected result" ) + cc.normal( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + "\n" ); - details.write( err.stack + "\n" ); - } - // reject( new Error( "CRITICAL ORACLE CALL ERROR: bad unexpecected result(oracle_checkResult)" ) ); - return; - } - const joResult = JSON.parse( joOut.result ); - if( isVerboseTraceDetails ) - details.write( cc.debug( "RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + cc.debug( " parsed " ) + cc.sunny( "result" ) + cc.debug( " field is: " ) + cc.j( joResult ) + "\n" ); - const gp = numberToBN( joResult.rslts[0] ); - if( isVerbose ) - details.write( cc.success( "success, computed " ) + cc.sunny( "Gas Price" ) + cc.success( "=" ) + cc.info( gp.toString() ) + cc.success( "=" ) + cc.info( "0x" + gp.toString( 16 ) ) + "\n" ); - resolve( gp ); - return; - } ); - } catch ( err ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + cc.error( " exception is: " ) + cc.warning( err.toString() ) + "\n" ); - details.write( err.stack + "\n" ); - reject( err ); - return; - } - } // for( let idxAttempt = 0; idxAttempt < cntAttempts; ++idxAttempt ) - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_checkResult" ) + cc.normal( ")" ) + cc.error( " all attempts timed out" ) + "\n" ); - reject( new Error( "RPC call(oracle_checkResult) all attempts timed out" ) ); - return; - } ); - } catch ( err ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " RPC call" ) + cc.normal( "(" ) + cc.attention( "oracle_submitRequest" ) + cc.normal( ")" ) + cc.error( " exception is: " ) + cc.warning( err.toString() ) + "\n" ); - details.write( err.stack + "\n" ); - reject( err ); - return; - } - } ); - } catch ( err ) { - details.write( cc.fatal( "CRITICAL ORACLE CALL ERROR:" ) + cc.error( " RPC call object creation failed, error is: " ) + cc.warning( err.toString() ) + "\n" ); - details.write( err.stack + "\n" ); - reject( err ); - return; - } - } ); - return promise_complete; -} - -module.exports = { - init: oracle_init, - get_gas_price: oracle_get_gas_price -}; // module.exports diff --git a/agent/oracle.mjs b/agent/oracle.mjs new file mode 100644 index 000000000..00922fba4 --- /dev/null +++ b/agent/oracle.mjs @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file oracle.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as rpcCall from "./rpcCall.mjs"; +import numberToBN from "number-to-bn"; + +import * as sha3Module from "sha3"; + +const Keccak = sha3Module.Keccak; + +export const gConstMinPowResultLimit = 10000; +export const gConstMaxPowResultLimit = 100000; + +const gBigNumMinPowResult = numberToBN( gConstMinPowResultLimit ); +const gBigNum1 = numberToBN( 1 ); +const gBigNum2 = numberToBN( 2 ); +const gBigNum256 = numberToBN( 256 ); +const gBigNumUpperPart = gBigNum2.pow( gBigNum256 ).sub( gBigNum1 ); + +const sleep = ( milliseconds ) => { + return new Promise( resolve => setTimeout( resolve, milliseconds ) ); +}; + +function getUtcTimestampString( d ) { + d = d || new Date(); // use now time if d is not specified + const nUtcUnixTimeStampWithMilliseconds = d.getTime(); + const t = "" + nUtcUnixTimeStampWithMilliseconds; + return t; +} + +export function findPowNumber( strRequestPart, details, isVerbose ) { + details = details || log; + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( cc.debug( "source part of request to find " ) + + cc.sunny( "PoW number" ) + cc.debug( " is " ) + cc.notice( strRequestPart ) + + "\n" ); + } + } + const t = getUtcTimestampString(); + let i = 0, n = 0, s = ""; + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( cc.debug( "source " ) + cc.sunny( "t" ) + cc.debug( "=" ) + + cc.info( t ) + cc.debug( ", this is " ) + cc.sunny( "UTC timestamp" ) + "\n" ); + } + } + for( ; i < gConstMaxPowResultLimit; ++ i ) { + n = "" + i; + s = "{" + strRequestPart + ",\"time\":" + t + ",\"pow\":" + n + "}"; + + const hash = new Keccak( 256 ); + hash.update( s ); + let strHash = hash.digest( "hex" ); + strHash = owaspUtils.ensureStartsWith0x( strHash ); + + const f = numberToBN( strHash ); + const r = gBigNumUpperPart.div( f ); + if( r.gt( gBigNumMinPowResult ) ) { + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( cc.debug( "computed " ) + cc.sunny( "n" ) + cc.debug( "=" ) + + cc.info( i ) + cc.debug( ", this is resulting " ) + + cc.sunny( "PoW number" ) + "\n" ); + details.write( cc.debug( "computed " ) + cc.sunny( "f" ) + cc.debug( "=" ) + + cc.info( f.toString() ) + cc.debug( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( f.toString( 16 ) ) ) + "\n" ); + details.write( cc.debug( "computed " ) + cc.sunny( "r" ) + cc.debug( "=" ) + + cc.info( "(2**256-1)/f" ) + cc.debug( "=" ) + cc.info( r.toString() ) + + cc.debug( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( r.toString( 16 ) ) ) + "\n" ); + details.write( cc.debug( "computed " ) + cc.sunny( "s" ) + cc.debug( "=" ) + + cc.info( s ) + "\n" ); + } + } + break; + } + } + return s; +} + +export function oracleGetGasPrice( oracleOpts, details ) { + details = details || log; + const promiseComplete = new Promise( ( resolve, reject ) => { + try { + const url = oracleOpts.url; + const isVerbose = "isVerbose" in oracleOpts ? oracleOpts.isVerbose : false; + let isVerboseTraceDetails = "isVerboseTraceDetails" in oracleOpts + ? oracleOpts.isVerboseTraceDetails : false; + if( ! ( log.verboseGet() >= log.verboseReversed().trace ) ) + isVerboseTraceDetails = false; + const callOpts = "callOpts" in oracleOpts ? oracleOpts.callOpts : { }; + const nMillisecondsSleepBefore = "nMillisecondsSleepBefore" in oracleOpts + ? oracleOpts.nMillisecondsSleepBefore : 1000; + const nMillisecondsSleepPeriod = "nMillisecondsSleepPeriod" in oracleOpts + ? oracleOpts.nMillisecondsSleepPeriod : 3000; + let cntAttempts = "cntAttempts" in oracleOpts ? oracleOpts.cntAttempts : 40; + if( cntAttempts < 1 ) + cntAttempts = 1; + rpcCall.create( url, callOpts || { }, async function( joCall, err ) { + if( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " RPC connection problem for url " ) + cc.u( url ) + + cc.error( ", error description: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n" ); + } + if( joCall ) + await joCall.disconnect(); + reject( new Error( + "CRITICAL ORACLE ERROR: RPC connection problem for url \"" + + url + "\", error description: " + owaspUtils.extractErrorMessage( err ) ) ); + return; + } + try { + const s = findPowNumber( + "\"cid\":1000,\"uri\":\"geth://\",\"jsps\":[\"/result\"]," + + "\"post\":\"{\\\"jsonrpc\\\":\\\"2.0\\\"," + + "\\\"method\\\":\\\"eth_gasPrice\\\",\\\"params\\\":[],\\\"id\\\":1}\"", + details, + isVerbose + ); + const joIn = { "method": "oracle_submitRequest", "params": [ s ] }; + if( isVerboseTraceDetails ) { + details.write( cc.debug( "RPC call" ) + + cc.attention( "oracle_submitRequest" ) + cc.debug( " is " ) + + cc.j( joIn ) + "\n" ); + } + await joCall.call( joIn, async function( joIn, joOut, err ) { + if( err ) { + if( isVerboseTraceDetails ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " JSON RPC call " ) + + cc.attention( "oracle_submitRequest" ) + + cc.error( " failed, error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + "\n" ); + } + await joCall.disconnect(); + reject( new Error( "CRITICAL ORACLE ERROR: " + + "JSON RPC call(oracle_submitRequest) failed, error: " + + owaspUtils.extractErrorMessage( err ) ) ); + return; + } + if( isVerboseTraceDetails ) { + details.write( cc.debug( "RPC call" ) + cc.normal( "(" ) + + cc.attention( "oracle_submitRequest" ) + cc.normal( ")" ) + + cc.debug( " result is: " ) + cc.j( joOut ) + "\n" ); + } + if( !( "result" in joOut && typeof joOut.result == "string" && + joOut.result.length > 0 ) ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " bad unexpected result" ) + + cc.normal( "(" ) + cc.attention( "oracle_submitRequest" ) + + cc.normal( ")" ) + cc.error( ", error description is" ) + + owaspUtils.extractErrorMessage( err ) + "\n" ); + } + await joCall.disconnect(); + reject( new Error( "CRITICAL ORACLE ERROR: " + + "bad unexpected result(oracle_submitRequest)" ) ); + return; + } + for( let idxAttempt = 0; idxAttempt < cntAttempts; ++idxAttempt ) { + const nMillisecondsToSleep = ( ! idxAttempt ) + ? nMillisecondsSleepBefore : nMillisecondsSleepPeriod; + if( nMillisecondsToSleep > 0 ) + await sleep( nMillisecondsToSleep ); + try { + joIn = { + "method": "oracle_checkResult", "params": [ joOut.result ] + }; + if( isVerboseTraceDetails ) { + details.write( cc.debug( "RPC call " ) + + cc.attention( "oracle_checkResult" ) + + cc.debug( " attempt " ) + cc.info( idxAttempt ) + + cc.debug( " of " ) + cc.info( cntAttempts ) + + cc.debug( "..." ) + "\n" ); + details.write( cc.debug( "RPC call " ) + + cc.attention( "oracle_checkResult" ) + cc.debug( " is " ) + + cc.j( joIn ) + "\n" ); + } + await joCall.call( joIn, async function( joIn, joOut, err ) { + if( err ) { + if( isVerboseTraceDetails ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " JSON RPC call" ) + cc.debug( "(" ) + + cc.attention( "oracle_checkResult" ) + + cc.normal( ")" ) + cc.error( " failed, error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) + ) + "\n" ); + } + await joCall.disconnect(); + return; + } + if( isVerboseTraceDetails ) { + details.write( cc.debug( "RPC call " ) + + cc.attention( "oracle_checkResult" ) + + cc.debug( " result is: " ) + cc.j( joOut ) + "\n" ); + } + if( !( "result" in joOut && typeof joOut.result == "string" && + joOut.result.length > 0 ) ) { + if( isVerboseTraceDetails ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " bad unexpected result in " ) + + cc.attention( "oracle_checkResult" ) + "\n" ); + } + await joCall.disconnect(); + return; + } + const joResult = JSON.parse( joOut.result ); + if( isVerboseTraceDetails ) { + details.write( cc.debug( "RPC call " ) + + cc.attention( "oracle_checkResult" ) + + cc.debug( " parsed " ) + cc.sunny( "result" ) + + cc.debug( " field is: " ) + cc.j( joResult ) + "\n" ); + } + const gp = numberToBN( joResult.rslts[0] ); + if( isVerbose && + log.verboseGet() >= log.verboseReversed().information ) { + details.write( cc.success( "success, computed " ) + + cc.sunny( "Gas Price" ) + cc.success( "=" ) + + cc.info( gp.toString() ) + cc.success( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( + gp.toString( 16 ) ) ) + "\n" ); + } + resolve( gp ); + await joCall.disconnect(); + return; + } ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " RPC call " ) + + cc.attention( "oracle_checkResult" ) + + cc.error( " exception is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n" ); + } + reject( err ); + await joCall.disconnect(); + return; + } + } + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " RPC call " ) + + cc.attention( "oracle_checkResult" ) + + cc.error( " all attempts timed out" ) + "\n" ); + } + reject( new Error( + "RPC call(oracle_checkResult) all attempts timed out" ) ); + await joCall.disconnect(); + return; + } ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " RPC call" ) + + cc.attention( "oracle_submitRequest" ) + + cc.error( " exception is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + reject( err ); + } + await joCall.disconnect(); + } ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + details.write( cc.fatal( "CRITICAL ORACLE ERROR:" ) + + cc.error( " RPC call object creation failed, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + reject( err ); + return; + } + } ); + return promiseComplete; +} diff --git a/agent/package.json b/agent/package.json index c0f40499b..6b8065da5 100644 --- a/agent/package.json +++ b/agent/package.json @@ -4,19 +4,23 @@ "license": "AGPL-3.0", "author": "SKALE Labs and contributors", "scripts": { - "postinstall": "echo \"----- installing in OWASP\n\" && cd ../npms/skale-owasp && yarn install && cd ../../agent && echo \"----- installing in IMA CORE\n\" && cd ../npms/skale-ima && yarn install && cd ../../agent && echo \"----- installing in IMA OBSERVER\n\" && cd ../npms/skale-observer && yarn install && cd ../../agent && echo \"----- installing in SKALE COOL SOCKET\n\" && cd ../npms/skale-cool-socket && yarn install && cd ../../agent" + "postinstall": "./postinstall.sh", + "check-outdated": "yarn outdated", + "upgrade-to-latest": "yarn upgrade --latest" }, "dependencies": { - "js-sha3": "^0.8.0", "number-to-bn": "^1.7.0", - "ethereumjs-tx": "2.1.2", - "ethereumjs-wallet": "^1.0.2", - "ethereumjs-util": "^7.1.4", - "web3": "^1.6.1", - "uuid": "8.3.2", - "ws": "^8.6.0", - "urllib": "2.38.0", + "ethers": "^5.7.2", + "@ethersproject/experimental": "^5.7.0", + "solc": "0.8.6", + "uuid": "^9.0.0", + "express": "^4.18.2", + "body-parser": "^1.20.1", + "jayson": "^4.0.0", + "ws": "^8.12.0", + "urllib": "^3.10.1", "sha3": "2.1.4", + "serve-static": "^1.15.0", "shelljs": "^0.8.5" }, "devDependencies": {}, @@ -28,3 +32,5 @@ "scrypt.js/scrypt": "file:../npms/scrypt/node-scrypt" } } + + diff --git a/agent/postinstall.sh b/agent/postinstall.sh new file mode 100755 index 000000000..f52eba73c --- /dev/null +++ b/agent/postinstall.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +echo " " +echo "----- installing in OWASP ------------------------------------------------------------------" +echo " " +cd ../npms/skale-owasp +yarn install +cd ../../agent + +echo " " +echo "----- installing in IMA CORE ---------------------------------------------------------------" +echo " " +cd ../npms/skale-ima +yarn install +cd ../../agent + +echo " " +echo "----- installing in IMA OBSERVER -----------------------------------------------------------" +echo " " +cd ../npms/skale-observer +yarn install +cd ../../agent + +echo " " +echo "----- installing in SKALE COOL SOCKET ------------------------------------------------------" +echo " " +cd ../npms/skale-cool-socket +yarn install +cd ../../agent diff --git a/agent/pwa.mjs b/agent/pwa.mjs new file mode 100644 index 000000000..0d04225e6 --- /dev/null +++ b/agent/pwa.mjs @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file pwa.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import { extractErrorMessage } from "../npms/skale-owasp/owaspUtils.mjs"; +import * as rpcCall from "./rpcCall.mjs"; +import * as imaBLS from "./bls.mjs"; +import * as imaUtils from "./utils.mjs"; + +function computeWalkNodeIndices( nNodeNumber, nNodesCount ) { + if( nNodesCount <= 1 ) + return []; // PWA is N/A + if( !( nNodeNumber >= 0 && nNodeNumber < nNodesCount ) ) + return []; // PWA is N/A + let i = nNodeNumber - 1; + if( i < 0 ) + i = nNodesCount - 1; + const arrWalkNodeIndices = []; + for( ; true; ) { + if( i == nNodeNumber ) + break; + arrWalkNodeIndices.push( i ); + -- i; + if( i < 0 ) + i = nNodesCount - 1; + } + return arrWalkNodeIndices; +} + +export function checkLoopWorkTypeStringIsCorrect( strLoopWorkType ) { + if( ! strLoopWorkType ) + return false; + switch ( strLoopWorkType.toString().toLowerCase() ) { + case "oracle": + case "m2s": + case "s2m": + case "s2s": + return true; + } + return false; +} + +function composeEmptyStateForPendingWorkAnalysis() { + return { + "oracle": { + "isInProgress": false, + "ts": 0 + }, + "m2s": { + "isInProgress": false, + "ts": 0 + }, + "s2m": { + "isInProgress": false, + "ts": 0 + }, + "s2s": { + "mapS2S": { + } + } + }; +} + +function getNodeProgressAndTimestamp( joNode, strLoopWorkType, nIndexS2S ) { + if( ! ( "pwaState" in joNode ) ) + joNode.pwaState = composeEmptyStateForPendingWorkAnalysis(); + strLoopWorkType = strLoopWorkType.toLowerCase(); + if( ! ( strLoopWorkType in joNode.pwaState ) ) { + throw new Error( + "Specified value \"" + strLoopWorkType + + "\" is not a correct loop work type, cannot access info" + ); + } + if( strLoopWorkType != "s2s" ) + return joNode.pwaState[strLoopWorkType]; + if( ! ( nIndexS2S in joNode.pwaState[strLoopWorkType].mapS2S ) ) { + joNode.pwaState[strLoopWorkType].mapS2S[nIndexS2S] = { + "isInProgress": false, + "ts": 0 + }; + } + return joNode.pwaState[strLoopWorkType].mapS2S[nIndexS2S]; +} + +export async function checkOnLoopStart( imaState, strLoopWorkType, nIndexS2S ) { + try { + nIndexS2S = nIndexS2S || 0; // convert to number if undefined + if( ! checkLoopWorkTypeStringIsCorrect( strLoopWorkType ) ) { + throw new Error( + "Specified value \"" + strLoopWorkType + "\" is not a correct loop work type" + ); + } + if( ! imaState.isPWA ) + return true; // PWA is N/A + if( imaState.nNodesCount <= 1 ) + return true; // PWA is N/A + if( !( imaState.nNodeNumber >= 0 && imaState.nNodeNumber < imaState.nNodesCount ) ) + return true; // PWA is N/A + if( ! imaState.joSChainNetworkInfo ) + return true; // PWA is N/A + const jarrNodes = imaState.joSChainNetworkInfo.network; + if( ! jarrNodes ) + throw new Error( "S-Chain network info is not available yet to PWA" ); + const arrBusyNodeIndices = []; + const arrWalkNodeIndices = + computeWalkNodeIndices( imaState.nNodeNumber, imaState.nNodesCount ); + if( log.verboseGet() >= log.verboseReversed().information ) { + if( imaState.isPrintPWA ) { + log.write( cc.debug( "PWA will check loop start condition via node(s) sequence " ) + + cc.j( arrBusyNodeIndices ) + cc.debug( "..." ) + "\n" ); + } + } + const nUtcUnixTimeStamp = Math.floor( ( new Date() ).getTime() / 1000 ); + for( let i = 0; i < arrWalkNodeIndices.length; ++i ) { + const walk_node_index = arrWalkNodeIndices[i]; + const joNode = jarrNodes[walk_node_index]; + const joProps = getNodeProgressAndTimestamp( joNode, strLoopWorkType, nIndexS2S ); + if( joProps && typeof joProps == "object" && + "isInProgress" in joProps && joProps.isInProgress && + joProps.ts != 0 && nUtcUnixTimeStamp >= joProps.ts + ) { + const d = nUtcUnixTimeStamp - joProps.ts; + if( d >= imaState.nTimeoutSecondsPWA ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + if( imaState.isPrintPWA ) { + log.write( cc.warning( "PWA busy state timeout for node #" ) + + cc.info( walk_node_index ) + cc.debug( ", old timestamp is " ) + + cc.info( joProps.ts ) + + cc.debug( ", current system timestamp is " ) + + cc.info( nUtcUnixTimeStamp ) + cc.debug( ", duration " ) + + cc.info( d ) + + cc.debug( " is greater than conditionally allowed " ) + + cc.info( imaState.nTimeoutSecondsPWA ) + + cc.debug( " and exceeded by " ) + + cc.info( d - imaState.nTimeoutSecondsPWA ) + + cc.debug( " second(s)" ) + "\n" ); + } + } + joProps.isInProgress = false; + joProps.ts = 0; + continue; + } + arrBusyNodeIndices.push( walk_node_index ); + } + } + if( arrBusyNodeIndices.length > 0 ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + if( imaState.isPrintPWA ) { + log.write( + cc.warning( "PWA loop start condition check failed, busy node(s): " ) + + cc.j( arrBusyNodeIndices ) + "\n" ); + } + } + return false; + } + if( log.verboseGet() >= log.verboseReversed().information ) { + if( imaState.isPrintPWA ) + log.write( cc.success( "PWA loop start condition check passed" ) + "\n" ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + log.write( cc.error( "Exception in PWA check on loop start: " ) + + cc.error( extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return true; +} + +export async function handleLoopStateArrived( + imaState, nNodeNumber, strLoopWorkType, nIndexS2S, isStart, ts, signature +) { + const se = isStart ? "start" : "end"; + let isSuccess = false; + let joNode = null; + try { + if( ! checkLoopWorkTypeStringIsCorrect( strLoopWorkType ) ) { + throw new Error( + "Arrived value \"" + strLoopWorkType + "\" is not a correct loop work type" ); + } + if( ! imaState.isPWA ) + return true; + if( imaState.nNodesCount <= 1 ) + return true; // PWA is N/A + if( !( imaState.nNodeNumber >= 0 && imaState.nNodeNumber < imaState.nNodesCount ) ) + return true; // PWA is N/A + if( ! imaState.joSChainNetworkInfo ) + return true; // PWA is N/A + const jarrNodes = imaState.joSChainNetworkInfo.network; + if( ! jarrNodes ) + throw new Error( "S-Chain network info is not available yet to PWA" ); + joNode = jarrNodes[nNodeNumber]; + const joProps = getNodeProgressAndTimestamp( joNode, strLoopWorkType, nIndexS2S ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + if( imaState.isPrintPWA ) { + log.write( cc.debug( "PWA loop-" ) + cc.attention( se ) + + cc.debug( " state arrived for node " ) + cc.info( nNodeNumber ) + + cc.debug( ", PWA state " ) + cc.j( joNode.pwaState ) + + cc.debug( ", arrived signature is " ) + cc.j( signature ) + "\n" ); + } + } + const strMessageHash = + imaBLS.keccak256ForPendingWorkAnalysis( + nNodeNumber, strLoopWorkType, isStart, 0 + ts ); + const isSignatureOK = + await imaBLS.doVerifyReadyHash( + strMessageHash, nNodeNumber, signature, imaState.isPrintPWA ); + if( ! isSignatureOK ) + throw new Error( "BLS verification failed" ); + joProps.isInProgress = isStart ? true : false; + joProps.ts = 0 + ts; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( imaState.isPrintPWA ) { + log.write( cc.success( "PWA loop-" ) + cc.attention( se ) + + cc.success( " state successfully verified for node " ) + + cc.info( nNodeNumber ) + cc.success( ", now have PWA state " ) + + cc.j( joNode.pwaState ) + cc.success( ", arrived signature is " ) + + cc.j( signature ) + "\n" ); + } + } + isSuccess = true; + } catch ( err ) { + isSuccess = false; + if( log.verboseGet() >= log.verboseReversed().critical ) { + log.write( cc.error( "Exception in PWA handler for loop-" ) + cc.attention( se ) + + cc.error( " for node " ) + cc.info( nNodeNumber ) + cc.error( ", PWA state " ) + + cc.j( ( joNode && "pwaState" in joNode ) ? joNode.pwaState : "N/A" ) + + cc.error( ", arrived signature is " ) + cc.j( signature ) + + cc.error( ", error is: " ) + cc.error( extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return isSuccess; +} + +async function notifyOnLoopImpl( imaState, strLoopWorkType, nIndexS2S, isStart ) { + const se = isStart ? "start" : "end"; + try { + nIndexS2S = nIndexS2S || 0; // convert to number if undefined + if( ! checkLoopWorkTypeStringIsCorrect( strLoopWorkType ) ) { + throw new Error( + "Specified value \"" + strLoopWorkType + "\" is not a correct loop work type" ); + } + if( ! imaState.isPWA ) + return true; + if( imaState.nNodesCount <= 1 ) + return true; // PWA is N/A + if( !( imaState.nNodeNumber >= 0 && imaState.nNodeNumber < imaState.nNodesCount ) ) + return true; // PWA is N/A + if( ! imaState.joSChainNetworkInfo ) + return true; // PWA is N/A + const jarrNodes = imaState.joSChainNetworkInfo.network; + if( ! jarrNodes ) + throw new Error( "S-Chain network info is not available yet to PWA" ); + const nUtcUnixTimeStamp = Math.floor( ( new Date() ).getTime() / 1000 ); + + const strMessageHash = + imaBLS.keccak256ForPendingWorkAnalysis( + 0 + imaState.nNodeNumber, strLoopWorkType, isStart, nUtcUnixTimeStamp ); + const signature = await imaBLS.doSignReadyHash( strMessageHash, imaState.isPrintPWA ); + await handleLoopStateArrived( + imaState, imaState.nNodeNumber, strLoopWorkType, + nIndexS2S, isStart, nUtcUnixTimeStamp, signature + ); // save own started + for( let i = 0; i < jarrNodes.length; ++i ) { + if( i == imaState.nNodeNumber ) + continue; // skip this node + const joNode = jarrNodes[i]; + const strNodeURL = imaUtils.composeImaAgentNodeUrl( joNode ); + const rpcCallOpts = null; + rpcCall.create( // NOTICE: no await here, executed async + strNodeURL, rpcCallOpts, async function( joCall, err ) { + if( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "PWA failed to create loop-" ) + + cc.attention( se ) + + cc.error( " notification RPC call to node #" ) + + cc.info( i ) + cc.error( " with URL " ) + cc.u( strNodeURL ) + + cc.error( ", error is: " ) + + cc.error( extractErrorMessage( err ) ) + "\n" ); + } + return; + } + joCall.call( { // NOTICE: no await here, executed async + "method": "skale_imaNotifyLoopWork", + "params": { + "nNodeNumber": 0 + imaState.nNodeNumber, + "strLoopWorkType": "" + strLoopWorkType, + "nIndexS2S": 0 + nIndexS2S, + "isStart": isStart ? true : false, + "ts": nUtcUnixTimeStamp, + "signature": signature + } + }, async function( joIn, joOut, err ) { + if( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "PWA failed to perform loop-" ) + + cc.attention( se ) + + cc.error( " notification RPC call to node #" ) + + cc.info( i ) + cc.error( " with URL " ) + cc.u( strNodeURL ) + + cc.error( ", error is: " ) + + cc.error( extractErrorMessage( err ) ) + "\n" ); + } + await joCall.disconnect(); + return; + } + if( log.verboseGet() >= log.verboseReversed().information ) { + if( imaState.isPrintPWA ) { + log.write( cc.success( "Was successfully sent PWA loop-" ) + + cc.attention( se ) + cc.success( " notification to node #" ) + + cc.info( i ) + cc.success( " with URL " ) + cc.u( strNodeURL ) + + "\n" ); + } + } + await joCall.disconnect(); + } ); // joCall.call ... + } ); // rpcCall.create ... + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Exception in PWA notify on loop " ) + cc.attention( se ) + + cc.error( ": " ) + cc.error( extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return true; +} + +export async function notifyOnLoopStart( imaState, strLoopWorkType, nIndexS2S ) { + return await notifyOnLoopImpl( imaState, strLoopWorkType, nIndexS2S, true ); +} + +export async function notifyOnLoopEnd( imaState, strLoopWorkType, nIndexS2S ) { + return await notifyOnLoopImpl( imaState, strLoopWorkType, nIndexS2S, false ); +} diff --git a/agent/rpc-call.js b/agent/rpc-call.js deleted file mode 100644 index cb703d3ae..000000000 --- a/agent/rpc-call.js +++ /dev/null @@ -1,449 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file rpc-call.js - * @copyright SKALE Labs 2019-Present - */ - -const ws = require( "ws" ); // https://www.npmjs.com/package/ws -const urllib = require( "urllib" ); // https://www.npmjs.com/package/urllib -const net = require( "net" ); - -const g_nConnectionTimeoutSeconds = 60; - -function is_http_url( strURL ) { - try { - if( !owaspUtils.validateURL( strURL ) ) - return false; - const u = new URL( strURL ); - if( u.protocol == "http:" || u.protocol == "https:" ) - return true; - } catch ( err ) { - } - return false; -} - -function is_ws_url( strURL ) { - try { - if( !owaspUtils.validateURL( strURL ) ) - return false; - const u = new URL( strURL ); - if( u.protocol == "ws:" || u.protocol == "wss:" ) - return true; - } catch ( err ) { - } - return false; -} - -function rpc_call_init() { - owaspUtils.owaspAddUsageRef(); -} - -async function wait_web_socket_is_open( socket, fnDone, fnStep ) { - fnDone = fnDone || async function( nStep ) {}; - fnDone = fnStep || async function( nStep ) { return true; }; - const nStep = 0; - const promiseComplete = new Promise( function( resolve, reject ) { - let isInsideAsyncHandler = false; - const fn_async_handler = async function() { - if( isInsideAsyncHandler ) - return; - isInsideAsyncHandler = true; - if( socket.readyState === 1 ) { - // console.log( "Connection is made" ) - clearInterval( iv ); - await fnDone( nStep ); - resolve(); - } else { - if( ! await fnStep( nStep ) ) { - clearInterval( iv ); - reject( new Error( "web socket wait timout by callback on step " + nStep ) ); - } - } - isInsideAsyncHandler = false; - }; - const iv = setInterval( function() { - if( isInsideAsyncHandler ) - return; - fn_async_handler() - .then( () => { - } ).catch( () => { - } ); - }, 1000 ); // 1 second - } ); - await Promise.all( [ promiseComplete ] ); -} - -async function do_connect( joCall, opts, fn ) { - try { - fn = fn || async function() {}; - if( !owaspUtils.validateURL( joCall.url ) ) - throw new Error( "JSON RPC CALLER cannot connect web socket to invalid URL: " + joCall.url ); - if( is_ws_url( joCall.url ) ) { - let strWsError = null; - joCall.wsConn = new ws( joCall.url ); - joCall.wsConn.on( "open", async function() { - await fn( joCall, null ); - } ); - joCall.wsConn.on( "close", async function() { - strWsError = "web socket was closed, please check provided URL is valid and accessible"; - joCall.wsConn = 0; - } ); - joCall.wsConn.on( "error", async function( err ) { - strWsError = err.toString() || "internal web socket error"; - log.write( cc.u( joCall.url ) + cc.error( " web socket error: " ) + cc.warning( err.toString() ) + "\n" ); - } ); - joCall.wsConn.on( "fail", async function( err ) { - strWsError = err.toString() || "internal web socket failure"; - log.write( cc.u( joCall.url ) + cc.error( " web socket fail: " ) + cc.warning( err.toString() ) + "\n" ); - } ); - joCall.wsConn.on( "message", async function incoming( data ) { - // log.write( cc.info( "WS message " ) + cc.attention( data ) + "\n" ); - const joOut = JSON.parse( data ); - if( joOut.id in joCall.mapPendingByCallID ) { - const entry = joCall.mapPendingByCallID[joOut.id]; - delete joCall.mapPendingByCallID[joOut.id]; - if( entry.iv ) { - clearTimeout( entry.iv ); - entry.iv = null; - } - clearTimeout( entry.out ); - await entry.fn( entry.joIn, joOut, null ); - } - } ); - await wait_web_socket_is_open( joCall.wsConn, - async function( nStep ) { // done - }, - async function( nStep ) { // step - if( strWsError && typeof strWsError == "string" && strWsError.length > 0 ) { - log.write( cc.u( joCall.url ) + cc.error( " web socket wait error detected: " ) + cc.warning( strWsError ) + "\n" ); - return false; - } - if( nStep >= g_nConnectionTimeoutSeconds ) { - strWsError = "wait timeout, web socket is connecting too long"; - log.write( cc.u( joCall.url ) + cc.error( " web socket wait timeout detected" ) + "\n" ); - return false; // stop waiting - } - return true; // continue waiting - } ); - if( strWsError && typeof strWsError == "string" && strWsError.length > 0 ) { - const err = new Error( strWsError ); - await fn( joCall, err ); - return; - } - } - await fn( joCall, null ); - } catch ( err ) { - joCall.wsConn = null; - await fn( joCall, err ); - } -} - -async function do_connect_if_needed( joCall, opts, fn ) { - try { - fn = fn || async function() {}; - if( !owaspUtils.validateURL( joCall.url ) ) - throw new Error( "JSON RPC CALLER cannot connect web socket to invalid URL: " + joCall.url ); - if( is_ws_url( joCall.url ) && ( !joCall.wsConn ) ) { - await joCall.reconnect( fn ); - return; - } - await fn( joCall, null ); - } catch ( err ) { - await fn( joCall, err ); - } -} - -const impl_sleep = ( milliseconds ) => { return new Promise( resolve => setTimeout( resolve, milliseconds ) ); }; - -async function do_call( joCall, joIn, fn ) { - // console.log( "--- --- --- initial joIn is", joIn ); - joIn = enrich_top_level_json_fields( joIn ); - // console.log( "--- --- --- enriched joIn is", joIn ); - fn = fn || async function() {}; - if( joCall.wsConn ) { - const entry = { - joIn: joIn, - fn: fn, - out: null - }; - joCall.mapPendingByCallID[joIn.id] = entry; - entry.iv = setTimeout( function() { - clearTimeout( entry.iv ); - entry.iv = null; - delete joCall.mapPendingByCallID[joIn.id]; - }, 20 * 1000 ); - joCall.wsConn.send( JSON.stringify( joIn ) ); - } else { - // console.log( "--- --- --- call URL is", joCall.url ); - if( !owaspUtils.validateURL( joCall.url ) ) { - // throw new Error( "JSON RPC CALLER cannot do query post to invalid URL: " + joCall.url ); - await fn( joIn, null, "JSON RPC CALLER cannot do query post to invalid URL: " + joCall.url ); - return; - } - const strBody = JSON.stringify( joIn ); - // console.log( "--- --- --- agentOptions is", agentOptions ); - // console.log( "--- --- --- joIn is", strBody ); - let bCompleteFlag = false; - let errCall = null, joOut = null; - urllib.request( joCall.url, { - "method": "POST", - "timeout": g_nConnectionTimeoutSeconds * 1000, // in milliseconds - "headers": { - "content-type": "application/json" - // "Accept": "*/*", - // "Content-Length": strBody.length, - }, - "content": strBody, - "ca": ( joCall.joRpcOptions && joCall.joRpcOptions.ca && typeof joCall.joRpcOptions.ca == "string" ) ? joCall.joRpcOptions.ca : null, - "cert": ( joCall.joRpcOptions && joCall.joRpcOptions.cert && typeof joCall.joRpcOptions.cert == "string" ) ? joCall.joRpcOptions.cert : null, - "key": ( joCall.joRpcOptions && joCall.joRpcOptions.key && typeof joCall.joRpcOptions.key == "string" ) ? joCall.joRpcOptions.key : null - }, function( err, body, response ) { - // console.log( "--- --- --- err is", err ); - // console.log( "--- --- --- response is", response ); - // console.log( "--- --- --- body is", body ); - if( response && response.statusCode && response.statusCode !== 200 ) - log.write( cc.error( "WARNING:" ) + cc.warning( " REST call status code is " ) + cc.info( response.statusCode ) + "\n" ); - if( err ) { - log.write( cc.u( joCall.url ) + cc.error( " REST error " ) + cc.warning( err.toString() ) + "\n" ); - bCompleteFlag = true; - joOut = null; - errCall = "RPC call error: " + err.toString(); - return; - } - try { - joOut = JSON.parse( body ); - errCall = null; - } catch ( err ) { - bCompleteFlag = true; - joOut = null; - errCall = "Responce body parse error: " + err.toString(); - return; - } - bCompleteFlag = true; - } ); - for( let idxWait = 0; ! bCompleteFlag; ++ idxWait ) { - if( idxWait < 50 ) - await impl_sleep( 5 ); - else if( idxWait < 100 ) - await impl_sleep( 10 ); - else if( idxWait < 1000 ) - await impl_sleep( 100 ); - else { - const nLastWaitPeriod = 200; - if( ( idxWait - 1000 ) * nLastWaitPeriod > g_nConnectionTimeoutSeconds ) - bCompleteFlag = true; - else - await impl_sleep( nLastWaitPeriod ); - } - } // for( let idxWait = 0; ! bCompleteFlag; ++ idxWait ) - try { - await fn( joIn, joOut, errCall ); - } catch ( err ) { - } - } -} - -async function rpc_call_create( strURL, opts, fn ) { - if( !owaspUtils.validateURL( strURL ) ) - throw new Error( "JSON RPC CALLER cannot create a call object invalid URL: " + strURL ); - fn = fn || async function() {}; - if( !( strURL && typeof strURL == "string" && strURL.length > 0 ) ) - throw new Error( "rpc_call_create() was invoked with bad parameters: " + JSON.stringify( arguments ) ); - const joCall = { - "url": "" + strURL, - "joRpcOptions": opts ? opts : null, - "mapPendingByCallID": { }, - "wsConn": null, - "reconnect": async function( fnAfter ) { - await do_connect( joCall, fnAfter ); - }, - "reconnect_if_needed": async function( fnAfter ) { - await do_connect_if_needed( joCall, opts, fnAfter ); - }, - "call": async function( joIn, fnAfter ) { - const self = this; - await self.reconnect_if_needed( async function( joCall, err ) { - if( err ) { - await fnAfter( joIn, null, err ); - return; - } - await do_call( joCall, joIn, fnAfter ); - } ); - } - }; - await do_connect( joCall, opts, fn ); -} - -function generate_random_integer_in_range( min, max ) { - min = Math.ceil( min ); - max = Math.floor( max ); - return Math.floor( Math.random() * ( max - min + 1 ) ) + min; -} - -function generate_random_rpc_call_id() { - return generate_random_integer_in_range( 1, Number.MAX_SAFE_INTEGER ); -} - -function enrich_top_level_json_fields( jo ) { - if( ( !( "jsonrpc" in jo ) ) || ( typeof jo.jsonrpc !== "string" ) || jo.jsonrpc.length === 0 ) - jo.jsonrpc = "2.0"; - if( ( !( "id" in jo ) ) || ( typeof jo.id !== "number" ) || jo.id <= 0 ) - jo.id = generate_random_rpc_call_id(); - return jo; -} - -function is_valid_url( s ) { - if( ! s ) - return false; - try { - const u = new URL( s.toString() ); - if( u ) - return true; - } catch ( err ) { - } - return false; -} - -function get_valid_url( s ) { - if( ! s ) - return null; - try { - return new URL( s.toString() ); - } catch ( err ) { - } - return null; -} - -function get_default_port( strProtocol ) { - if( ! strProtocol ) - return 80; - switch ( strProtocol.toString().toLowerCase() ) { - case "http:": - case "ws:": - return 80; - case "https:": - case "wss:": - return 443; - } - return 80; -} - -function get_valid_host_and_port( s ) { - const u = get_valid_url( s ); - if( ! u ) - return null; - const jo = { - strHost: u.hostname, - nPort: u.port ? parseInt( u.port, 10 ) : get_default_port( u.protocol ) - }; - return jo; -} - -const g_strTcpConnectionHeader = "TCP connection checker: "; - -function check_tcp_promise( strHost, nPort, nTimeoutMilliseconds, isLog ) { - return new Promise( ( resolve, reject ) => { - if( isLog ) - console.log( `${g_strTcpConnectionHeader}Will establish TCP connection to ${strHost}:${nPort}...` ); - const conn = net.createConnection( { host: strHost, port: nPort }, () => { - if( isLog ) - console.log( `${g_strTcpConnectionHeader}Done, TCP connection to ${strHost}:${nPort} established` ); - conn.end(); - resolve(); - } ); - if( isLog ) - console.log( `${g_strTcpConnectionHeader}Did created NET object for TCP connection to ${strHost}:${nPort}...` ); - if( nTimeoutMilliseconds ) - nTimeoutMilliseconds = parseInt( nTimeoutMilliseconds.toString(), 10 ); - if( nTimeoutMilliseconds > 0 ) { - if( isLog ) - console.log( `${g_strTcpConnectionHeader}Will use TCP connection to ${strHost}:${nPort} timeout ${nTimeoutMilliseconds} milliseconds...` ); - conn.setTimeout( nTimeoutMilliseconds ); - } else { - if( isLog ) - console.log( `${g_strTcpConnectionHeader}Will use default TCP connection to ${strHost}:${nPort} timeout...` ); - } - conn.on( "timeout", err => { - if( isLog ) - console.log( `${g_strTcpConnectionHeader}TCP connection to ${strHost}:${nPort} timed out` ); - conn.destroy(); - reject( err ); - } ); - conn.on( "error", err => { - if( isLog ) - console.log( `${g_strTcpConnectionHeader}TCP connection to ${strHost}:${nPort} failed` ); - reject( err ); - } ); - if( isLog ) - console.log( `${g_strTcpConnectionHeader}TCP connection to ${strHost}:${nPort} check started...` ); - } ); -} - -async function check_tcp( strHost, nPort, nTimeoutMilliseconds, isLog ) { - let isOnline = false; - try { - const promise_tcp = check_tcp_promise( strHost, nPort, nTimeoutMilliseconds, isLog ) - .then( () => ( isOnline = true ) ) - .catch( () => ( isOnline = false ) ) - //.finally( () => console.log( { isOnline } ) ) - ; - if( isLog ) - console.log( `${g_strTcpConnectionHeader}Waiting for TCP connection to ${strHost}:${nPort} check done...` ); - await Promise.all( [ promise_tcp ] ); - if( isLog ) - console.log( `${g_strTcpConnectionHeader}TCP connection to ${strHost}:${nPort} check finished` ); - } catch ( err ) { - isOnline = false; - console.log( `${g_strTcpConnectionHeader}TCP connection to ${strHost}:${nPort} check failed with error: ` + err.toString() ); - } - return isOnline; -} - -async function check_url( u, nTimeoutMilliseconds, isLog ) { - if( ! u ) - return false; - const jo = get_valid_host_and_port( u ); - if( isLog ) - console.log( g_strTcpConnectionHeader + "Extracted from URL \"" + u.toString() + "\" data fields are: " + JSON.stringify( jo ) ); - if( ! ( jo && jo.strHost && "nPort" in jo ) ) { - console.log( g_strTcpConnectionHeader + "Extracted from URL \"" + u.toString() + "\" data fields are bad, returning \"false\" as result of TCP connection check" ); - return false; - } - return await check_tcp( jo.strHost, jo.nPort, nTimeoutMilliseconds, isLog ); -} - -module.exports = { - rpcCallAddUsageRef: function() { }, - is_http_url: is_http_url, - is_ws_url: is_ws_url, - init: rpc_call_init, - create: rpc_call_create, - generate_random_integer_in_range: generate_random_integer_in_range, - generate_random_rpc_call_id: generate_random_rpc_call_id, - enrich_top_level_json_fields: enrich_top_level_json_fields, - is_valid_url: is_valid_url, - get_valid_url: get_valid_url, - get_valid_host_and_port: get_valid_host_and_port, - check_tcp_promise: check_tcp_promise, - check_tcp: check_tcp, - check_url: check_url -}; // module.exports diff --git a/agent/rpcCall.mjs b/agent/rpcCall.mjs new file mode 100644 index 000000000..fcaf44350 --- /dev/null +++ b/agent/rpcCall.mjs @@ -0,0 +1,587 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file rpcCall.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as ws from "ws"; +import * as urllib from "urllib"; +import * as https from "https"; +import * as net from "net"; +import { validateURL, isUrlWS } from "../npms/skale-owasp/owaspUtils.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as cc from "../npms/skale-cc/cc.mjs"; + +const gSecondsConnectionTimeout = 60; + +export async function waitWebSocketIsOpen( socket, fnDone, fnStep ) { + fnDone = fnDone || async function( nStep ) {}; + fnDone = fnStep || async function( nStep ) { return true; }; + let nStep = 0; + const promiseComplete = new Promise( function( resolve, reject ) { + let isInsideAsyncHandler = false; + const fnAsyncHandler = async function() { + if( isInsideAsyncHandler ) + return; + isInsideAsyncHandler = true; + ++ nStep; + if( socket.readyState === 1 ) { + // Notice, connection is made if we are here + clearInterval( iv ); + await fnDone( nStep ); + resolve(); + } else { + if( ! await fnStep( nStep ) ) { + clearInterval( iv ); + reject( new Error( + "web socket wait timeout by callback on step " + nStep ) ); + } + } + isInsideAsyncHandler = false; + }; + const iv = setInterval( function() { + if( isInsideAsyncHandler ) + return; + fnAsyncHandler() + .then( () => { + } ).catch( () => { + } ); + }, 1000 ); // 1 second + } ); + await Promise.all( [ promiseComplete ] ); +} + +export async function doConnect( joCall, opts, fn ) { + try { + fn = fn || async function() {}; + if( !validateURL( joCall.url ) ) { + throw new Error( + "JSON RPC CALLER cannot connect web socket to invalid URL: " + joCall.url ); + } + if( isUrlWS( joCall.url ) ) { + let strWsError = null; + joCall.wsConn = new ws.WebSocket( joCall.url ); + joCall.wsConn.on( "open", async function() { + await fn( joCall, null ); + } ); + joCall.wsConn.on( "close", async function() { + strWsError = + "web socket was closed, please check provided URL is valid and accessible"; + joCall.wsConn = null; + } ); + joCall.wsConn.on( "error", async function( err ) { + strWsError = err.toString() || "internal web socket error"; + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.u( joCall.url ) + cc.error( " web socket error: " ) + + cc.warning( err.toString() ) + "\n" ); + } + const wsConn = joCall.wsConn; + joCall.wsConn = null; + wsConn.close(); + doReconnectWsStep( joCall, opts ); + } ); + joCall.wsConn.on( "fail", async function( err ) { + strWsError = err.toString() || "internal web socket failure"; + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.u( joCall.url ) + cc.error( " web socket fail: " ) + + cc.warning( err.toString() ) + "\n" ); + } + const wsConn = joCall.wsConn; + joCall.wsConn = null; + wsConn.close(); + doReconnectWsStep( joCall, opts ); + } ); + joCall.wsConn.on( "message", async function incoming( data ) { + const joOut = JSON.parse( data ); + if( joOut.id in joCall.mapPendingByCallID ) { + const entry = joCall.mapPendingByCallID[joOut.id]; + delete joCall.mapPendingByCallID[joOut.id]; + if( entry.iv ) { + clearTimeout( entry.iv ); + entry.iv = null; + } + clearTimeout( entry.out ); + await entry.fn( entry.joIn, joOut, null ); + } + } ); + await waitWebSocketIsOpen( joCall.wsConn, + async function( nStep ) { // work done handler + }, + async function( nStep ) { // step handler + if( strWsError && typeof strWsError == "string" && strWsError.length > 0 ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.u( joCall.url ) + + cc.error( " web socket wait error detected: " ) + + cc.warning( strWsError ) + "\n" ); + } + return false; + } + if( nStep >= gSecondsConnectionTimeout ) { + strWsError = "wait timeout, web socket is connecting too long"; + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.u( joCall.url ) + + cc.error( " web socket wait timeout detected" ) + "\n" ); + } + const wsConn = joCall.wsConn; + joCall.wsConn = null; + wsConn.close(); + doReconnectWsStep( joCall, opts ); + return false; // stop waiting + } + return true; // continue waiting + } ); + if( strWsError && typeof strWsError == "string" && strWsError.length > 0 ) { + const err = new Error( strWsError ); + await fn( joCall, err ); + return; + } + } + await fn( joCall, null ); + } catch ( err ) { + joCall.wsConn = null; + await fn( joCall, err ); + } + return joCall; +} + +export async function doConnectIfNeeded( joCall, opts, fn ) { + try { + fn = fn || async function() {}; + if( !validateURL( joCall.url ) ) { + throw new Error( + "JSON RPC CALLER cannot connect web socket to invalid URL: " + joCall.url ); + } + if( isUrlWS( joCall.url ) && ( !joCall.wsConn ) ) { + await joCall.reconnect( fn ); + return; + } + await fn( joCall, null ); + } catch ( err ) { + await fn( joCall, err ); + } + return joCall; +} + +async function doReconnectWsStep( joCall, opts, fn ) { + if( ! joCall.isAutoReconnect ) + return; + if( joCall.isDisconnectMode ) + return; + fn = fn || async function() {}; + doConnect( joCall, opts, async function( joCall, err ) { + if( err ) { + doReconnectWsStep( joCall, opts ); + return; + } + await fn( joCall, null ); + } ); +} + +async function doDisconnect( joCall, fn ) { + fn = fn || async function() {}; + try { + joCall.isDisconnectMode = true; + const wsConn = joCall.wsConn ? joCall.wsConn : null; + joCall.wsConn = null; + if( wsConn ) + wsConn.close(); + joCall.isDisconnectMode = false; + try { + await fn( joCall, null ); + } catch ( err ) { + } + } catch ( err ) { + await await fn( joCall, err ); + } +} + +export async function doCall( joCall, joIn, fn ) { + joIn = enrichTopLevelFieldsInJSON( joIn ); + fn = fn || async function() {}; + if( joCall.wsConn ) { + const entry = { + joIn: joIn, + fn: fn, + out: null + }; + joCall.mapPendingByCallID[joIn.id] = entry; + entry.iv = setTimeout( function() { + clearTimeout( entry.iv ); + entry.iv = null; + delete joCall.mapPendingByCallID[joIn.id]; + }, 200 * 1000 ); + joCall.wsConn.send( JSON.stringify( joIn ) ); + } else { + if( !validateURL( joCall.url ) ) { + await fn( + joIn, + null, + "JSON RPC CALLER cannot do query post to invalid URL: " + joCall.url + ); + return; + } + const strBody = JSON.stringify( joIn ); + let errCall = null, joOut = null; + if( joCall.joRpcOptions && + joCall.joRpcOptions.cert && typeof joCall.joRpcOptions.cert == "string" && + joCall.joRpcOptions.key && typeof joCall.joRpcOptions.key == "string" + ) { + const u = new URL( joCall.url ); + const options = { + "hostname": u.hostname, + "port": u.port, + "path": "/", + "method": "POST", + "headers": { + "Content-Type": "application/json" + }, + "ca": ( joCall.joRpcOptions && joCall.joRpcOptions.ca && + typeof joCall.joRpcOptions.ca == "string" ) + ? joCall.joRpcOptions.ca : null, + "cert": ( joCall.joRpcOptions && joCall.joRpcOptions.cert && + typeof joCall.joRpcOptions.cert == "string" ) + ? joCall.joRpcOptions.cert : null, + "key": ( joCall.joRpcOptions && joCall.joRpcOptions.key && + typeof joCall.joRpcOptions.key == "string" ) + ? joCall.joRpcOptions.key : null + }; + let accumulatedBody = ""; + const promiseComplete = new Promise( ( resolve, reject ) => { + const req = https.request( options, res => { + res.setEncoding( "utf8" ); + res.on( "data", body => { + accumulatedBody += body; + } ); + res.on( "end", function() { + if( res.statusCode !== 200 ) { + joOut = null; + errCall = + "Response ends with bad status code: " + + res.statusCode.toString(); + reject( errCall ); + } + try { + joOut = JSON.parse( accumulatedBody ); + errCall = null; + resolve( joOut ); + } catch ( err ) { + joOut = null; + errCall = "Response body parse error: " + err.toString(); + reject( errCall ); + } + } ); + } ); + req.on( "error", err => { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.u( joCall.url ) + cc.error( " REST error " ) + + cc.warning( err.toString() ) + "\n" ); + } + joOut = null; + errCall = "RPC call error: " + err.toString(); + reject( errCall ); + } ); + req.write( strBody ); + req.end(); + } ); + await promiseComplete; + } else { + try { + const response = await urllib.request( joCall.url, { + "method": "POST", + "timeout": gSecondsConnectionTimeout * 1000, // in milliseconds + "headers": { + "Content-Type": "application/json" + }, + "content": strBody, + "rejectUnauthorized": false, + // "requestCert": true, + "agent": false, + "httpsAgent": false, + "ca": ( joCall.joRpcOptions && joCall.joRpcOptions.ca && + typeof joCall.joRpcOptions.ca == "string" ) + ? joCall.joRpcOptions.ca : null, + "cert": ( joCall.joRpcOptions && joCall.joRpcOptions.cert && + typeof joCall.joRpcOptions.cert == "string" ) + ? joCall.joRpcOptions.cert : null, + "key": ( joCall.joRpcOptions && joCall.joRpcOptions.key && + typeof joCall.joRpcOptions.key == "string" ) + ? joCall.joRpcOptions.key : null + } ); + const body = response.data.toString( "utf8" ); + if( response && response.statusCode && response.statusCode !== 200 ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "WARNING:" ) + + cc.warning( " REST call status code is " ) + + cc.info( response.statusCode ) + "\n" ); + } + } + joOut = JSON.parse( body ); + errCall = null; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.u( joCall.url ) + cc.error( " request error " ) + + cc.warning( err.toString() ) + "\n" ); + } + joOut = null; + errCall = "request error: " + err.toString(); + } + } + try { + await fn( joIn, joOut, errCall ); + } catch ( err ) { + } + } +} + +export async function rpcCallCreate( strURL, opts, fn ) { + if( !validateURL( strURL ) ) + throw new Error( "JSON RPC CALLER cannot create a call object invalid URL: " + strURL ); + fn = fn || async function() {}; + if( !( strURL && typeof strURL == "string" && strURL.length > 0 ) ) { + throw new Error( + "rpcCallCreate() was invoked with bad parameters: " + JSON.stringify( arguments ) ); + } + const joCall = { + "url": "" + strURL, + "joRpcOptions": opts ? opts : null, + "mapPendingByCallID": { }, + "wsConn": null, + "isAutoReconnect": + ( opts && "isAutoReconnect" in opts && opts.isAutoReconnect ) ? true : false, + "isDisconnectMode": false, + "reconnect": async function( fnAfter ) { + await doConnect( joCall, fnAfter ); + }, + "reconnect_if_needed": async function( fnAfter ) { + await doConnectIfNeeded( joCall, opts, fnAfter ); + }, + "call": async function( joIn, fnAfter ) { + const self = this; + await self.reconnect_if_needed( async function( joCall, err ) { + if( err ) { + await fnAfter( joIn, null, err ); + return; + } + await doCall( joCall, joIn, fnAfter ); + } ); + }, + "disconnect": async function( fnAfter ) { + await doDisconnect( joCall, fnAfter ); + } + }; + await doConnect( joCall, opts, fn ); + return joCall; +} + +export { rpcCallCreate as create }; + +export function generateRandomIntegerInRange( min, max ) { + min = Math.ceil( min ); + max = Math.floor( max ); + return Math.floor( Math.random() * ( max - min + 1 ) ) + min; +} + +export function generateRandomRpcCallId() { + return generateRandomIntegerInRange( 1, Number.MAX_SAFE_INTEGER ); +} + +export function enrichTopLevelFieldsInJSON( jo ) { + if( ( !( "jsonrpc" in jo ) ) || + ( typeof jo.jsonrpc !== "string" ) || + jo.jsonrpc.length === 0 + ) + jo.jsonrpc = "2.0"; + if( ( !( "id" in jo ) ) || ( typeof jo.id !== "number" ) || jo.id <= 0 ) + jo.id = generateRandomRpcCallId(); + return jo; +} + +export function isValidUrl( s ) { + if( ! s ) + return false; + try { + const u = new URL( s.toString() ); + if( u ) + return true; + } catch ( err ) { + } + return false; +} + +export function getValidUrl( s ) { + if( ! s ) + return null; + try { + return new URL( s.toString() ); + } catch ( err ) { + } + return null; +} + +export function getDefaultPort( strProtocol ) { + if( ! strProtocol ) + return 80; + switch ( strProtocol.toString().toLowerCase() ) { + case "http:": + case "ws:": + return 80; + case "https:": + case "wss:": + return 443; + } + return 80; +} + +export function getValidHostAndPort( s ) { + const u = getValidUrl( s ); + if( ! u ) + return null; + const jo = { + strHost: u.hostname, + nPort: u.port ? parseInt( u.port, 10 ) : getDefaultPort( u.protocol ) + }; + return jo; +} + +const gStrTcpConnectionHeader = "TCP connection checker: "; + +export function checkTcpPromise( strHost, nPort, nTimeoutMilliseconds, isLog ) { + return new Promise( ( resolve, reject ) => { + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}Will establish " + + "TCP connection to ${strHost}:${nPort}...` + ); + } + const conn = net.createConnection( { host: strHost, port: nPort }, () => { + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}Done, " + + "TCP connection to ${strHost}:${nPort} established` + ); + } + conn.end(); + resolve(); + } ); + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}Did created NET object " + + "for TCP connection to ${strHost}:${nPort}...` + ); + } + if( nTimeoutMilliseconds ) + nTimeoutMilliseconds = parseInt( nTimeoutMilliseconds.toString(), 10 ); + if( nTimeoutMilliseconds > 0 ) { + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}Will use " + + "TCP connection to ${strHost}:${nPort} " + + "timeout ${nTimeoutMilliseconds} milliseconds...` + ); + } + conn.setTimeout( nTimeoutMilliseconds ); + } else { + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}Will use " + + "default TCP connection to ${strHost}:${nPort} timeout...` + ); + } + } + conn.on( "timeout", err => { + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}TCP connection " + + "to ${strHost}:${nPort} timed out` + ); + } + conn.destroy(); + reject( err ); + } ); + conn.on( "error", err => { + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}TCP connection " + + "to ${strHost}:${nPort} failed` + ); + } + reject( err ); + } ); + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}TCP connection " + + "to ${strHost}:${nPort} check started...` + ); + } + } ); +} + +export async function checkTcp( strHost, nPort, nTimeoutMilliseconds, isLog ) { + let isOnline = false; + try { + const promiseCompleteTcpCheck = checkTcpPromise( + strHost, nPort, nTimeoutMilliseconds, isLog ) + .then( () => ( isOnline = true ) ) + .catch( () => ( isOnline = false ) ) + ; + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}Waiting for " + + "TCP connection to ${strHost}:${nPort} check done...` + ); + } + await Promise.all( [ promiseCompleteTcpCheck ] ); + if( isLog ) { + console.log( + `${gStrTcpConnectionHeader}TCP connection " + + "to ${strHost}:${nPort} check finished` + ); + } + } catch ( err ) { + isOnline = false; + console.log( + `${gStrTcpConnectionHeader}TCP connection " + + "to ${strHost}:${nPort} check failed with error: ` + err.toString() + ); + } + return isOnline; +} + +export async function checkUrl( u, nTimeoutMilliseconds, isLog ) { + if( ! u ) + return false; + const jo = getValidHostAndPort( u ); + if( isLog ) { + console.log( gStrTcpConnectionHeader + + "Extracted from URL \"" + u.toString() + "\" data fields are: " + + JSON.stringify( jo ) + ); + } + if( ! ( jo && jo.strHost && "nPort" in jo ) ) { + console.log( gStrTcpConnectionHeader + + "Extracted from URL \"" + u.toString() + + "\" data fields are bad, returning \"false\" as result of TCP connection check" + ); + return false; + } + return await checkTcp( jo.strHost, jo.nPort, nTimeoutMilliseconds, isLog ); +} diff --git a/agent/run.sh b/agent/run.sh index 75495e01a..06805c649 100644 --- a/agent/run.sh +++ b/agent/run.sh @@ -34,6 +34,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" # Optional IMA variables export GAS_PRICE_MULTIPLIER=${GAS_PRICE_MULTIPLIER:-2} +export GAS_MULTIPLIER=${GAS_MULTIPLIER:-2} export VERBOSE=${VERBOSE:-9} export M2S_TRANSFER_BLOCK_SIZE=${M2S_TRANSFER_BLOCK_SIZE:-4} @@ -67,6 +68,7 @@ echo "NODE_NUMBER: $NODE_NUMBER" echo "NODES_COUNT: $NODES_COUNT" BASE_OPTIONS="--gas-price-multiplier=$GAS_PRICE_MULTIPLIER \ +--gas-multiplier=$GAS_MULTIPLIER \ --verbose=$VERBOSE \ --s2s-enable \ --abi-skale-manager=$MANAGER_ABI_PATH \ @@ -85,7 +87,9 @@ BASE_OPTIONS="--gas-price-multiplier=$GAS_PRICE_MULTIPLIER \ --address-main-net=$NODE_ADDRESS \ --address-s-chain=$NODE_ADDRESS \ --sign-messages \ +--gathered \ --expose \ +--no-expose-security-info \ --skip-dry-run \ --bls-glue=/ima/bls_binaries/bls_glue \ --hash-g1=/ima/bls_binaries/hash_g1 \ @@ -109,13 +113,9 @@ BASE_OPTIONS="--gas-price-multiplier=$GAS_PRICE_MULTIPLIER \ --tm-url-main-net=$TM_URL_MAIN_NET \ --time-gap=$TIME_GAP \ --monitoring-port=$MONITORING_PORT \ ---ptx \ ---ptx-attempt=3 " - -#echo "Base options:" -#echo "$BASE_OPTIONS" +--pwa \ +--no-expose-pwa" echo "Running loop cmd..." -#echo "Going to run: node $DIR/main.js --loop $BASE_OPTIONS" -echo "Going to run: node $DIR/main.js --loop ... ... ..." -node "$DIR/main.js" --loop $BASE_OPTIONS +echo "Going to run: node $DIR/main.mjs --loop $BASE_OPTIONS" +node "$DIR/main.mjs" --loop "$BASE_OPTIONS" diff --git a/agent/state.mjs b/agent/state.mjs new file mode 100644 index 000000000..f6ddcd263 --- /dev/null +++ b/agent/state.mjs @@ -0,0 +1,301 @@ +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as imaTx from "../npms/skale-ima/imaTx.mjs"; + +export const gDefaultValueForLoopState = { + "oracle": { + "isInProgress": false, + "wasInProgress": false + }, + "m2s": { + "isInProgress": false, + "wasInProgress": false + }, + "s2m": { + "isInProgress": false, + "wasInProgress": false + }, + "s2s": { + "isInProgress": false, + "wasInProgress": false + } +}; + +function constructChainProperties() { + return { + "mn": { + "joAccount": { + "privateKey": + owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_ETHEREUM ), + "address": owaspUtils.fnAddressImpl_, + "strTransactionManagerURL": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_URL_ETHEREUM ), + "nTmPriority": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_PRIORITY_ETHEREUM ) || 5, + "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_ETHEREUM ), + "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_ETHEREUM ), + "strPathSslKey": + ( process.env.SGX_SSL_KEY_FILE_ETHEREUM || "" ).toString().trim(), + "strPathSslCert": + ( process.env.SGX_SSL_CERT_FILE_ETHEREUM || "" ).toString().trim(), + "strBlsKeyName": owaspUtils.toStringURL( process.env.BLS_KEY_ETHEREUM ) + }, + "transactionCustomizer": imaTx.getTransactionCustomizerForMainNet(), + "ethersProvider": null, + "strURL": owaspUtils.toStringURL( process.env.URL_W3_ETHEREUM ), + "strChainName": + ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), + "chainId": owaspUtils.toInteger( process.env.CID_ETHEREUM ) || -4, + "strPathAbiJson": null, + "joAbiIMA": { }, + "bHaveAbiIMA": false, + "joErc20": null, + "joErc721": null, + "joErc1155": null, + "strCoinNameErc20": "", // in-JSON coin name + "strCoinNameErc721": "", // in-JSON coin name + "strCoinNameErc1155": "", // in-JSON coin name + "strPathJsonErc20": "", + "strPathJsonErc721": "", + "strPathJsonErc1155": "" + }, + "sc": { + "joAccount": { + "privateKey": + owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN ), + "address": owaspUtils.fnAddressImpl_, + "strTransactionManagerURL": + owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_S_CHAIN ), + "nTmPriority": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_PRIORITY_S_CHAIN ) || 5, + "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN ), + "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN ), + "strPathSslKey": + ( process.env.SGX_SSL_KEY_FILE_S_CHAIN || "" ).toString().trim(), + "strPathSslCert": + ( process.env.SGX_SSL_CERT_FILE_S_CHAIN || "" ).toString().trim(), + "strBlsKeyName": owaspUtils.toStringURL( process.env.BLS_KEY_S_CHAIN ) + }, + "transactionCustomizer": imaTx.getTransactionCustomizerForSChain(), + "ethersProvider": null, + "strURL": owaspUtils.toStringURL( process.env.URL_W3_S_CHAIN ), + "strChainName": + ( process.env.CHAIN_NAME_SCHAIN || "id-S-chain" ).toString().trim(), + "chainId": owaspUtils.toInteger( process.env.CID_SCHAIN ) || -4, + "strPathAbiJson": null, + "joAbiIMA": { }, + "bHaveAbiIMA": false, + "joErc20": null, + "joErc721": null, + "joErc1155": null, + "strCoinNameErc20": "", // in-JSON coin name + "strCoinNameErc721": "", // in-JSON coin name + "strCoinNameErc1155": "", // in-JSON coin name + "strPathJsonErc20": "", + "strPathJsonErc721": "", + "strPathJsonErc1155": "" + }, + "tc": { + "joAccount": { + "privateKey": + owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN_TARGET ), + "address": owaspUtils.fnAddressImpl_, + "strTransactionManagerURL": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_URL_S_CHAIN_TARGET ), + "nTmPriority": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_PRIORITY_S_CHAIN_TARGET ) || 5, + "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN_TARGET ), + "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN_TARGET ), + "strPathSslKey": + ( process.env.SGX_SSL_KEY_FILE_S_CHAIN_TARGET || "" ).toString().trim(), + "strPathSslCert": + ( process.env.SGX_SSL_CERT_FILE_S_CHAIN_TARGET || "" ).toString().trim(), + "strBlsKeyName": owaspUtils.toStringURL( process.env.BLS_KEY_T_CHAIN ) + }, + "transactionCustomizer": imaTx.getTransactionCustomizerForSChainTarget(), + "ethersProvider": null, + "strURL": owaspUtils.toStringURL( process.env.URL_W3_S_CHAIN_TARGET ), + "strChainName": + ( process.env.CHAIN_NAME_SCHAIN_TARGET || "id-T-chain" ).toString().trim(), + "chainId": owaspUtils.toInteger( process.env.CID_SCHAIN_TARGET ) || -4, + "strPathAbiJson": null, + "joAbiIMA": { }, + "bHaveAbiIMA": false, + "joErc20": null, + "joErc721": null, + "joErc1155": null, + "strCoinNameErc20": "", // in-JSON coin name + "strCoinNameErc721": "", // in-JSON coin name + "strCoinNameErc1155": "", // in-JSON coin name + "strPathJsonErc20": "", + "strPathJsonErc721": "", + "strPathJsonErc1155": "" + } + }; +} + +let imaState = null; + +export function get() { + if( imaState ) + return imaState; + imaState = { + "loopState": gDefaultValueForLoopState, + + "strLogFilePath": "", + "nLogMaxSizeBeforeRotation": -1, + "nLogMaxFilesCount": -1, + "isPrintGathered": true, + "isPrintSecurityValues": false, + "isPrintPWA": false, + "isDynamicLogInDoTransfer": true, + "isDynamicLogInBlsSigner": false, + + "bIsNeededCommonInit": true, + // use BLS message signing, turned on with --sign-messages + "bSignMessages": false, + // scanned S-Chain network description + "joSChainNetworkInfo": null, + // path to bls_glue app, must have if --sign-messages specified + "strPathBlsGlue": "", + // path to hash_g1 app, must have if --sign-messages specified + "strPathHashG1": "", + // path to verify_bls app, optional, + // if specified then we will verify gathered BLS signature + "strPathBlsVerify": "", + + // true - just show configuration values and exit + "bShowConfigMode": false, + + "isEnabledMultiCall": true, + + "bNoWaitSChainStarted": false, + "nMaxWaitSChainAttempts": 0 + Number.MAX_SAFE_INTEGER, // 20 + + "nAmountOfWei": 0, + "nAmountOfToken": 0, + "arrAmountsOfTokens": null, + "idToken": 0, + + "nTransferBlockSizeM2S": 4, + "nTransferBlockSizeS2M": 4, + "nTransferBlockSizeS2S": 4, + "nTransferStepsM2S": 8, + "nTransferStepsS2M": 8, + "nTransferStepsS2S": 8, + "nMaxTransactionsM2S": 0, + "nMaxTransactionsS2M": 0, + "nMaxTransactionsS2S": 0, + + "nBlockAwaitDepthM2S": 0, + "nBlockAwaitDepthS2M": 0, + "nBlockAwaitDepthS2S": 0, + "nBlockAgeM2S": 0, + "nBlockAgeS2M": 0, + "nBlockAgeS2S": 0, + + "nLoopPeriodSeconds": 10, + + "nNodeNumber": 0, // S-Chain node number(zero based) + "nNodesCount": 1, + "nTimeFrameSeconds": 0, // 0-disable, 60-recommended + "nNextFrameGap": 10, + + "nAutoExitAfterSeconds": 3600, // 0-disable + + "joCommunityPool": null, // only main net + "joDepositBoxETH": null, // only main net + "joDepositBoxERC20": null, // only main net + "joDepositBoxERC721": null, // only main net + "joDepositBoxERC1155": null, // only main net + "joDepositBoxERC721WithMetadata": null, // only main net + "joLinker": null, // only main net + + "isWithMetadata721": false, + + "joTokenManagerETH": null, // only s-chain + "joTokenManagerERC20": null, // only s-chain + "joTokenManagerERC20Target": null, // only s-chain + "joTokenManagerERC721": null, // only s-chain target + "joTokenManagerERC721Target": null, // only s-chain target + "joTokenManagerERC1155": null, // only s-chain + "joTokenManagerERC1155Target": null, // only s-chain target + "joTokenManagerERC721WithMetadata": null, // only s-chain target + "joTokenManagerERC721WithMetadataTarget": null, // only s-chain target + "joCommunityLocker": null, // only s-chain + "joCommunityLockerTarget": null, // only s-chain target + "joMessageProxyMainNet": null, + "joMessageProxySChain": null, + "joMessageProxySChainTarget": null, // only s-chain target + "joTokenManagerLinker": null, + "joTokenManagerLinkerTarget": null, // only s-chain target + "joEthErc20": null, // only s-chain + "joEthErc20Target": null, // only s-chain target + + "chainProperties": constructChainProperties(), + + "strPathAbiJsonSkaleManager": "", + "joAbiSkaleManager": { }, + "bHaveSkaleManagerABI": false, + + "strChainNameOriginChain": + ( process.env.CHAIN_NAME_SCHAIN_ORIGIN || "Mainnet" ).toString().trim(), + + "strAddrErc20Explicit": "", + "strAddrErc20ExplicitTarget": "", // S<->S target + "strAddrErc721Explicit": "", + "strAddrErc721ExplicitTarget": "", // S<->S target + "strAddrErc1155Explicit": "", + "strAddrErc1155ExplicitTarget": "", // S<->S target + + "isPWA": true, + "nTimeoutSecondsPWA": 60, + + "nMonitoringPort": 0, // 0 - default, means monitoring server is disabled + + "strReimbursementChain": "", + "isShowReimbursementBalance": false, + "nReimbursementRecharge": 0, + "nReimbursementWithdraw": 0, + "nReimbursementRange": -1, // < 0 - do not change anything + + "joSChainDiscovery": { + "isSilentReDiscovery": true, + // zero to disable (for debugging only) + "repeatIntervalMilliseconds": 10 * 1000 + }, + + // S-Chain to S-Chain transfer options + "optsS2S": { + // is S-Chain to S-Chain transfers enabled + "isEnabled": true, + // seconds to re-discover SKALE network, 0 to disable + "secondsToReDiscoverSkaleNetwork": 1 * 60 * 60 + }, + + "nJsonRpcPort": 0, // 0 to disable + "isCrossImaBlsMode": false, + + "arrActions": [] // array of actions to run + }; + return imaState; +} + +export function set( imaStateNew ) { + imaState = imaStateNew; + return imaState; +} + +let gFlagIsPreventExitAfterLastAction = false; + +export function isPreventExitAfterLastAction() { + return gFlagIsPreventExitAfterLastAction; +} + +export function setPreventExitAfterLastAction( isPrevent ) { + gFlagIsPreventExitAfterLastAction = isPrevent; +} diff --git a/agent/test/agentUnitTests.js b/agent/test/agentUnitTests.js new file mode 100644 index 000000000..00158e3bd --- /dev/null +++ b/agent/test/agentUnitTests.js @@ -0,0 +1,571 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file agentUnitTests.js + * @copyright SKALE Labs 2019-Present + */ + +const assert = require( "chai" ).assert; +const expect = require( "chai" ).expect; +const IMA = require( "../../npms/skale-ima/index.mjs" ); +const imaTx = require( "../../npms/skale-ima/imaTx.mjs" ); +const imaReg = require( "../../npms/skale-ima/imaRegistrationOperations.mjs" ); +const imaEth = require( "../../npms/skale-ima/imaEthOperations.mjs" ); +const imaToken = require( "../../npms/skale-ima/imaTokenOperations.mjs" ); +const w3mod = IMA.w3mod; +const transactionCustomizerMainNet = imaTx.getTransactionCustomizerForMainNet(); +const transactionCustomizerSChain = imaTx.getTransactionCustomizerForSChain(); + +const chainNameMainNet = "Mainnet"; +const chainNameSChain = "blah_blah_blah_schain_name"; // 1; + +// mockup for `ethersProviderSrc` +const ethersProviderSrc = { eth: { getBlockNumber: getBlockNumber, getBlock: getBlock } }; +function getBlockNumber( string ) { + return 2; +} +function getBlock( number ) { + return { timestamp: "1469021581" }; +} + +// mockup for `ethersProviderDst` +const ethersProviderDst = { + eth: { + sendSignedTransaction: sendSignedTransaction, + getTransactionCount: getTransactionCount + }, + utils: { hexToAscii: hexToAscii, asciiToHex: asciiToHex } +}; +function hexToAscii( string ) { + return "0"; +} +function asciiToHex( string ) { + return "0x0"; +} + +// mockup for `ethersProviderMainNet` +const ethersProviderMainNet = { + eth: { + sendSignedTransaction: sendSignedTransaction, + Contract: Contract, + getTransactionCount: getTransactionCount + }, + utils: { fromAscii: fromAscii, fromWei: fromWei, toBN: toBN, toHex: toHex, toWei: toWei } +}; +// mockup for `ethersProviderSChain` +const ethersProviderSChain = { + eth: { + sendSignedTransaction: sendSignedTransaction, + Contract: Contract, + getTransactionCount: getTransactionCount + }, + utils: { fromAscii: fromAscii, fromWei: fromWei, toBN: toBN, toHex: toHex, toWei: toWei } +}; +function sendSignedTransaction( string ) { + return true; +} +function getTransactionCount( string ) { + assert( string !== undefined ); + return 1; +} +function fromAscii( string ) { + return "0"; +} +function fromWei( stringA, stringB ) { + return "0"; +} +function toBN( string ) { + return "0"; +} +function Contract( stringA, stringB ) { + return { "methods": { "approve": approve } }; +} +function approve( stringA, stringB ) { + return { "encodeABI": encodeABI }; +} +function toHex( string ) { + return "0x9a"; +} +function toWei( stringA, stringB ) { + return 100; +} + +// mockup for `joAccountDst` +const joAccountDst = { + "address": IMA.owaspUtils.fnAddressImpl_, + privateKey: "6270720ecca0185a979b6791bea433e9dbf23345e5b5b1b0258b1fbaf32b4390" +}; +// mockup for `joAccountSrc` +const joAccountSrc = { + "address": IMA.owaspUtils.fnAddressImpl_, + privateKey: "6270720ecca0185a979b6791bea433e9dbf23345e5b5b1b0258b1fbaf32b4390" +}; +// mockup for `joMainNetAccount` +const joMainNetAccount = { + "address": IMA.owaspUtils.fnAddressImpl_, + privateKey: "6270720ecca0185a979b6791bea433e9dbf23345e5b5b1b0258b1fbaf32b4390" +}; +// mockup for `joDepositBox` +const joDepositBox = { + "methods": { + deposit: deposit, + depositERC20: depositERC20, + rawDepositERC20: rawDepositERC20 + }, + options: { "address": "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82" } +}; +function deposit( stringA, stringB, stringC ) { + return { "encodeABI": encodeABI }; +} +function depositERC20( stringA, stringB, stringC, stringD ) { + return { "encodeABI": encodeABI }; +} +function rawDepositERC20( stringA, stringB, stringC, stringD, stringE ) { + return { "encodeABI": encodeABI }; +} + +// mockup for `joLockAndDataMainNet` +const joLockAndDataMainNet = { + "methods": { + hasSchain: hasSchain, + addSchain: addSchain, + getMyEth: getMyEth, + approveTransfers: approveTransfers + }, + options: { "address": "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82" } +}; +function hasSchain( string ) { + return { "call": call }; +} +function approveTransfers( string ) { + return { "call": call }; +} +function addSchain( string, arr ) { + return { "encodeABI": encodeABI }; +} +function getMyEth() { + return { "encodeABI": encodeABI }; +} + +// mockup for `joLockAndDataSChain` +const joLockAndDataSChain = { + "methods": { hasDepositBox: hasDepositBox, addDepositBox: addDepositBox }, + options: { "address": "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82" } +}; +function hasDepositBox() { + return { "call": call }; +} +function addDepositBox( string ) { + return { "encodeABI": encodeABI }; +} +function encodeABI() { + return "0x0"; +} + +// mockup for `joMessageProxyDst` +const joMessageProxyDst = { + "methods": { + getIncomingMessagesCounter: getIncomingMessagesCounter, + postIncomingMessages: postIncomingMessages + }, + options: { "address": "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82" } +}; +function getIncomingMessagesCounter( string ) { + return { "call": callNum }; +} +function postIncomingMessages( string, obj ) { + return { "encodeABI": encodeABI }; +} + +// mockup for `joMessageProxySrc` +const joMessageProxySrc = { + "methods": { getOutgoingMessagesCounter: getOutgoingMessagesCounter }, + getPastEvents: getPastEvents +}; +function getOutgoingMessagesCounter( string ) { + return { "call": callNum }; +} +function callNum() { + return 3; +} + +// mockup for `joTokenManager` +const joTokenManager = { + "methods": { + exitToMain: exitToMain, + exitToMainERC20: exitToMainERC20, + rawExitToMainERC20: rawExitToMainERC20 + }, + options: { "address": "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82" }, + getPastEvents: getPastEvents +}; +function exitToMain( string ) { + return { "encodeABI": encodeABI }; +} +function getPastEvents( string, obj ) { + return "events stub"; +} +function rawExitToMainERC20( string, obj ) { + return { "encodeABI": encodeABI }; +} +function exitToMainERC20( string, obj ) { + return { "encodeABI": encodeABI }; +} + +describe( "tests for `npms/skale-ima` 1", function() { + + it( "should invoke `verboseGet`", async function() { + expect( log.verboseGet() ).to.equal( "3" ); + } ); + + it( "should invoke `verboseSet`", async function() { + log.verboseSet( "0" ); + expect( log.verboseGet() ).to.equal( "0" ); + } ); + + it( "should invoke `verboseParse`", async function() { + // return 5 by default + expect( log.verboseParse() ).to.equal( 5 ); + // return 6 when `info` in parameters + expect( log.verboseParse( "info" ) ).to.equal( "6" ); + } ); + + it( "should invoke `ensureStartsWith0x`", async function() { + const string = "123456789"; + expect( IMA.owaspUtils.ensureStartsWith0x( string ) ).to.be.equal( "0" + "x" + string ); + } ); + + it( "should invoke `removeStarting0x`", async function() { + const string = "0x123456789"; + expect( IMA.owaspUtils.removeStarting0x( string ) ).to.be.equal( string.substr( 2 ) ); + // not string + expect( IMA.owaspUtils.removeStarting0x( 321 ) ).to.be.equal( 321 ); + // short string less than 2 + expect( IMA.owaspUtils.removeStarting0x( "1" ) ).to.be.equal( "1" ); + } ); + + it( "should invoke `privateKeyToPublicKey`", async function() { + const keyPrivate = "23abdbd3c61b5330af61ebe8bef582f4e5cc08e554053a718bdce7813b9dc1fc"; + let keyPrivateUnd; // undefined + let w3mod_undefined; // undefined + // if w3mod `undefined` or `null` + // eslint-disable-next-line no-unused-expressions + expect( IMA.owaspUtils.privateKeyToPublicKey( w3mod_undefined, keyPrivate ) ).to.be.empty; + // if keyPrivate `undefined` or `null` + // eslint-disable-next-line no-unused-expressions + expect( IMA.owaspUtils.privateKeyToPublicKey( w3mod, keyPrivateUnd ) ).to.be.empty; + // when all parameters is OK + expect( IMA.owaspUtils.privateKeyToPublicKey( w3mod, keyPrivate ) ).to.have.lengthOf( 128 ); + } ); + +} ); + +describe( "tests for `npms/skale-ima` 2", function() { + + it( "should invoke `publicKeyToAccountAddress`", async function() { + const keyPublic = "5dd431d36ce6b88f27d351051b31a26848c4a886f0dd0bc87a7d5a9d821417c9" + + "e807e8589f680ab0f2ab29831231ad7b3d6659990ee830582fede785fc3c33c4"; + let keyPublicUnd; // undefined + // if keyPrivate `undefined` or `null` + // eslint-disable-next-line no-unused-expressions + expect( IMA.owaspUtils.publicKeyToAccountAddress( keyPublicUnd ) ).to.be.empty; + // when all parameters is OK + expect( IMA.owaspUtils.publicKeyToAccountAddress( keyPublic ) ).to.include( "0x" ); + } ); + + it( "should invoke `privateKeyToAccountAddress`", async function() { + const keyPrivate = "23abdbd3c61b5330af61ebe8bef582f4e5cc08e554053a718bdce7813b9dc1fc"; + expect( IMA.owaspUtils.privateKeyToAccountAddress( keyPrivate ) ).to.include( "0x" ); + } ); + + it( "should return `false` invoke `checkIsRegisteredSChainInDepositBoxes`", async function() { + let joLinker; // for `false` output + // eslint-disable-next-line no-unused-expressions + expect( await imaReg.checkIsRegisteredSChainInDepositBoxes( + ethersProviderMainNet, joLinker, joMainNetAccount, chainNameSChain + ) ).to.be.false; + } ); + + it( "should return `true` invoke `checkIsRegisteredSChainInDepositBoxes`", async function() { + // eslint-disable-next-line no-unused-expressions + expect( await imaReg.checkIsRegisteredSChainInDepositBoxes( + ethersProviderMainNet, joLinker, joMainNetAccount, chainNameSChain + ) ).to.be.true; + } ); + + it( "should return `false` invoke `registerSChainInDepositBoxes`", async function() { + let joLinker; // for `false` output + let joTokenManagerETH; // only s-chain + let joTokenManagerERC20; // only s-chain + let joTokenManagerERC721; // only s-chain + let joTokenManagerERC1155; // only s-chain + let joTokenManagerERC721WithMetadata; // only s-chain + let joCommunityLocker; // only s-chain + let joTokenManagerLinker; + // eslint-disable-next-line no-unused-expressions + expect( await imaReg.registerSChainInDepositBoxes( + ethersProviderMainNet, + joLinker, + joMainNetAccount, + joTokenManagerETH, // only s-chain + joTokenManagerERC20, // only s-chain + joTokenManagerERC721, // only s-chain + joTokenManagerERC1155, // only s-chain + joTokenManagerERC721WithMetadata, // only s-chain + joCommunityLocker, // only s-chain + joTokenManagerLinker, + chainNameSChain, + chainNameMainNet, + transactionCustomizerMainNet, + 1, + 1000 + ) ).to.be.false; + } ); + + it( "should return `false` invoke `doEthPaymentFromMainNet`", async function() { + let joAccountSrc, wei_how_much; // for `false` output + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.doEthPaymentFromMainNet( + ethersProviderMainNet, + joAccountSrc, + joAccountDst, + joDepositBox, + chainNameSChain, + wei_how_much, // how much WEI money to send + transactionCustomizerMainNet + ) ).to.be.false; + } ); + + it( "should return `true` invoke `doEthPaymentFromMainNet`", async function() { + let wei_how_much; + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.doEthPaymentFromMainNet( + ethersProviderMainNet, + joAccountSrc, + joAccountDst, + joDepositBox, + chainNameSChain, + wei_how_much, // how much WEI money to send + transactionCustomizerMainNet + ) ).to.be.true; + } ); + + it( "should return `false` invoke `doEthPaymentFromSChain`", async function() { + let joAccountSrc, wei_how_much; // for `false` output + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.doEthPaymentFromSChain( + ethersProviderSChain, + joAccountSrc, + joAccountDst, + joTokenManager, + joLockAndDataSChain, + wei_how_much, // how much WEI money to send + transactionCustomizerSChain + ) ).to.be.false; + } ); + + it( "should return `true` invoke `doEthPaymentFromSChain`", async function() { + let wei_how_much; + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.doEthPaymentFromSChain( + ethersProviderSChain, + joAccountSrc, + joAccountDst, + joTokenManager, + joLockAndDataSChain, + wei_how_much, // how much WEI money to send + transactionCustomizerSChain + ) ).to.be.true; + } ); + + it( "should return `false` invoke `receiveEthPaymentFromSchainOnMainNet`", async function() { + let joMainNetAccount; // for `false` output + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.receiveEthPaymentFromSchainOnMainNet( + ethersProviderMainNet, + joMainNetAccount, + joLockAndDataMainNet, + transactionCustomizerMainNet + ) ).to.be.false; + } ); + + it( "should return `true` invoke `receiveEthPaymentFromSchainOnMainNet`", async function() { + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.receiveEthPaymentFromSchainOnMainNet( + ethersProviderMainNet, + joMainNetAccount, + joLockAndDataMainNet, + transactionCustomizerMainNet + ) ).to.be.true; + } ); + + it( "should return `null` invoke `viewEthPaymentFromSchainOnMainNet`", async function() { + let joMainNetAccount; // for `false` output + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.viewEthPaymentFromSchainOnMainNet( + ethersProviderMainNet, + joMainNetAccount, + joLockAndDataMainNet + ) ).to.be.null; + } ); + + it( "should return `true` invoke `viewEthPaymentFromSchainOnMainNet`", async function() { + // eslint-disable-next-line no-unused-expressions + expect( await imaEth.viewEthPaymentFromSchainOnMainNet( + ethersProviderMainNet, + joMainNetAccount, + joLockAndDataMainNet + ) ).to.be.true; + } ); + +} ); + +describe( "tests for `npms/skale-ima` 3", function() { + + it( "should return `false` invoke `doErc20PaymentFromMainNet`", async function() { + let nAmountOfToken; + let strCoinNameErc20MainNet; + let erc20PrivateTestnetJsonMainNet; + let strCoinNameErc20SChain; + let erc20PrivateTestnetJsonSChain; + // eslint-disable-next-line no-unused-expressions + expect( await imaToken.doErc20PaymentFromMainNet( + ethersProviderMainNet, + ethersProviderSChain, + joAccountSrc, + joAccountDst, + joDepositBox, + chainNameSChain, + nAmountOfToken, // how much ERC20 tokens to send + joTokenManager, // only s-chain + strCoinNameErc20MainNet, + erc20PrivateTestnetJsonMainNet, + strCoinNameErc20SChain, + erc20PrivateTestnetJsonSChain, + transactionCustomizerMainNet + ) ).to.be.false; + } ); + + it( "should return `false` invoke `doErc20PaymentFromSChain`", async function() { + let nAmountOfToken; + let strCoinNameErc20MainNet; + let joErc20MainNet; + let strCoinNameErc20SChain; + let joErc20SChain; + // eslint-disable-next-line no-unused-expressions + expect( await imaToken.doErc20PaymentFromSChain( + ethersProviderMainNet, + ethersProviderSChain, + joAccountSrc, + joAccountDst, + joTokenManager, // only s-chain + joLockAndDataSChain, + joDepositBox, // only main net + nAmountOfToken, // how much ERC20 tokens to send + strCoinNameErc20MainNet, + joErc20MainNet, + strCoinNameErc20SChain, + joErc20SChain, + transactionCustomizerSChain + ) ).to.be.false; + } ); + + it( "should return `false` invoke `doTransfer`", async function() { + let joMessageProxySrc; // for `false` output + const chainNameSrc = "test"; + const chainNameDst = "test"; + const nTransactionsCountInBlock = 4; + const nTransferSteps = 0; + const nMaxTransactionsCount = 0; + const nBlockAwaitDepth = 0; + const nBlockAge = 0; + const joRuntimeOpts = { + isInsideWorker: false, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }; + // eslint-disable-next-line no-unused-expressions + expect( await IMA.doTransfer( + "M2S", + joRuntimeOpts, + ethersProviderSrc, + joMessageProxySrc, + joAccountSrc, + ethersProviderDst, + joMessageProxyDst, + joAccountDst, + chainNameSrc, + chainNameDst, + -4, + -4, + null, // joDepositBox - for logs validation on mainnet + null, // joTokenManager - for logs validation on s-chain + nTransactionsCountInBlock, + nTransferSteps, + nMaxTransactionsCount, + nBlockAwaitDepth, + nBlockAge, + null, + transactionCustomizerMainNet, // or transactionCustomizerSChain + null + ) ).to.be.false; + } ); + + it( "should return `true` invoke `doTransfer`", async function() { + const chainNameSrc = "test"; + const chainNameDst = "test"; + const nTransactionsCountInBlock = 4; + const nTransferSteps = 0; + const nMaxTransactionsCount = 0; + const nBlockAwaitDepth = 0; + const nBlockAge = 0; + const joRuntimeOpts = { + isInsideWorker: false, + idxChainKnownForS2S: 0, + cntChainsKnownForS2S: 0 + }; + // eslint-disable-next-line no-unused-expressions + expect( await IMA.doTransfer( + "M2S", + joRuntimeOpts, + ethersProviderSrc, + joMessageProxySrc, + joAccountSrc, + ethersProviderDst, + joMessageProxyDst, + joAccountDst, + chainNameSrc, + chainNameDst, + -4, + -4, + null, // joDepositBox - for logs validation on mainnet + null, // joTokenManager - for logs validation on s-chain + nTransactionsCountInBlock, + nTransferSteps, + nMaxTransactionsCount, + nBlockAwaitDepth, + nBlockAge, + null, + transactionCustomizerMainNet, // or transactionCustomizerSChain + null + ) ).to.be.true; + } ); +} ); diff --git a/agent/test/get_main_net.spec.js b/agent/test/get_main_net.spec.js deleted file mode 100644 index 962f74c8a..000000000 --- a/agent/test/get_main_net.spec.js +++ /dev/null @@ -1,625 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file get_main_net.spec.js - * @copyright SKALE Labs 2019-Present - */ - -const assert = require('chai').assert; -const expect = require('chai').expect; -const IMA = require( "../../npms/skale-ima" ); -// const w3 = require("web3") -const w3mod = IMA.w3mod -const tc_main_net = IMA.tc_main_net; -const tc_s_chain = IMA.tc_s_chain; - -// -let chain_id_s_chain = "blah_blah_blah_schain_name"; // 1; - -// mockup for `w3_src` -let w3_src = {eth: {getBlockNumber: getBlockNumber, getBlock: getBlock}}; -function getBlockNumber(string) { - return 2 -} -function getBlock(number) { - return {timestamp: "1469021581"} -} - -// mockup for `w3_dst` -let w3_dst = {eth: {sendSignedTransaction: sendSignedTransaction, - getTransactionCount: getTransactionCount}, - utils: {hexToAscii: hexToAscii, asciiToHex: asciiToHex} -}; -function hexToAscii(string) { - return "0" -} -function asciiToHex(string) { - return "0x0" -} - -// mockup for `w3_main_net` -let w3_main_net = {eth: {sendSignedTransaction: sendSignedTransaction, Contract: Contract, - getTransactionCount: getTransactionCount}, - utils: {fromAscii: fromAscii, fromWei: fromWei, toBN: toBN, toHex: toHex, toWei: toWei} -}; -// mockup for `w3_s_chain` -let w3_s_chain = {eth: {sendSignedTransaction: sendSignedTransaction, Contract: Contract, - getTransactionCount: getTransactionCount}, - utils: {fromAscii: fromAscii, fromWei: fromWei, toBN: toBN, toHex: toHex, toWei: toWei} -}; -function sendSignedTransaction(string) { - return true -} -function getTransactionCount(string) { - return 1 -} -function fromAscii(string) { - return "0" -} -function fromWei(string, string) { - return "0" -} -function toBN(string) { - return "0" -} -function Contract(string, string) { - return {methods: {approve: approve}} -} -function approve(string, string) { - return {encodeABI: encodeABI} -} -function toHex(string) { - return "0x9a" -} -function toWei(string, string) { - return 100 -} - -// mockup for `joAccountDst` -let joAccountDst = { address: IMA.owaspUtils.fn_address_impl_, - privateKey: "6270720ecca0185a979b6791bea433e9dbf23345e5b5b1b0258b1fbaf32b4390", -}; -// mockup for `joAccountSrc` -let joAccountSrc = { address: IMA.owaspUtils.fn_address_impl_, - privateKey: "6270720ecca0185a979b6791bea433e9dbf23345e5b5b1b0258b1fbaf32b4390", -}; -// mockup for `joAccount` -let joAccount = { address: IMA.owaspUtils.fn_address_impl_, - privateKey: "6270720ecca0185a979b6791bea433e9dbf23345e5b5b1b0258b1fbaf32b4390", -}; -// mockup for `joAccount_main_net` -let joAccount_main_net = { address: IMA.owaspUtils.fn_address_impl_, - privateKey: "6270720ecca0185a979b6791bea433e9dbf23345e5b5b1b0258b1fbaf32b4390", -}; -// mockup for `jo_deposit_box` -let jo_deposit_box = {methods: {deposit: deposit, depositERC20: depositERC20, - rawDepositERC20: rawDepositERC20}, - options: {address: "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82"} -}; -function deposit(string, string, string) { - return {encodeABI: encodeABI} -} -function depositERC20(string, string, string, string) { - return {encodeABI: encodeABI} -} -function rawDepositERC20(string, string, string, string, string) { - return {encodeABI: encodeABI} -} - -// mockup for `jo_message_proxy_main_net` -let jo_message_proxy_main_net = {methods: {isConnectedChain: isConnectedChain, addConnectedChain: addConnectedChain}, - options: {address: "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82"} -}; -function isConnectedChain(string) { - return {call: call} -} -function call({}) { - return true -} -function addConnectedChain(string) { - return {encodeABI: encodeABI} -} - -// mockup for `jo_lock_and_data_main_net` -let jo_lock_and_data_main_net = {methods: {hasSchain: hasSchain, addSchain: addSchain, getMyEth: getMyEth, - approveTransfers: approveTransfers}, - options: {address: "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82"} -}; -function hasSchain(string) { - return {call: call} -} -function approveTransfers(string) { - return {call: call} -} -function addSchain(string, []) { - return {encodeABI: encodeABI} -} -function getMyEth() { - return {encodeABI: encodeABI} -} - -// mockup for `jo_lock_and_data_s_chain` -let jo_lock_and_data_s_chain = {methods: {hasDepositBox: hasDepositBox, addDepositBox: addDepositBox}, - options: {address: "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82"} -}; -function hasDepositBox() { - return {call: call} -} -function addDepositBox(string) { - return {encodeABI: encodeABI} -} -function encodeABI() { - return "0x0" -} - -// mockup for `jo_message_proxy_dst` -let jo_message_proxy_dst = {methods: {getIncomingMessagesCounter: getIncomingMessagesCounter, - postIncomingMessages: postIncomingMessages}, - options: {address: "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82"} -}; -function getIncomingMessagesCounter(string) { - return {call: callNum} -} -function postIncomingMessages(string, {}) { - return {encodeABI: encodeABI} -} - -// mockup for `jo_message_proxy_src` -let jo_message_proxy_src = {methods: {getOutgoingMessagesCounter: getOutgoingMessagesCounter}, - getPastEvents: getPastEvents -}; -function getOutgoingMessagesCounter(string) { - return {call: callNum} -} -function callNum() { - return 3 -} - -// mockup for `jo_token_manager` -let jo_token_manager = {methods: {exitToMain: exitToMain, exitToMainERC20: exitToMainERC20, - rawExitToMainERC20: rawExitToMainERC20}, - options: {address: "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82"}, - getPastEvents: getPastEvents -}; -function exitToMain(string) { - return {encodeABI: encodeABI} -} -function getPastEvents(string, {}) { - return "events stub" -} -function rawExitToMainERC20(string, {}) { - return {encodeABI: encodeABI} -} -function exitToMainERC20(string, {}) { - return {encodeABI: encodeABI} -} - -describe('tests for `npms/skale-ima`', function () { - - it('should invoke `verbose_get`', async function () { - expect(IMA.verbose_get()).to.equal("3"); - }); - - it('should invoke `verbose_set`', async function () { - IMA.verbose_set("0"); - expect(IMA.verbose_get()).to.equal("0"); - }); - - it('should invoke `verbose_parse`', async function () { - // return 5 by default - expect(IMA.verbose_parse()).to.equal(5); - // return 6 when `info` in parameters - expect(IMA.verbose_parse("info")).to.equal("6"); - }); - - it('should invoke `ensure_starts_with_0x`', async function () { - let string = "123456789" - expect(IMA.owaspUtils.ensure_starts_with_0x(string)).to.be.equal("0x" + string); - }); - - it('should invoke `remove_starting_0x`', async function () { - let string = "0x123456789" - expect(IMA.owaspUtils.remove_starting_0x(string)).to.be.equal(string.substr(2)); - // not string - expect(IMA.owaspUtils.remove_starting_0x(321)).to.be.equal(321); - // short string less than 2 - expect(IMA.owaspUtils.remove_starting_0x("1")).to.be.equal("1"); - }); - - it('should invoke `private_key_2_public_key`', async function () { - let keyPrivate = "23abdbd3c61b5330af61ebe8bef582f4e5cc08e554053a718bdce7813b9dc1fc"; - let keyPrivateUnd; // undefined - let w3mod_undefined; // undefined - // if w3mod `undefined` or `null` - expect(IMA.owaspUtils.private_key_2_public_key(w3mod_undefined, keyPrivate)).to.be.empty; - // if keyPrivate `undefined` or `null` - expect(IMA.owaspUtils.private_key_2_public_key(w3mod, keyPrivateUnd)).to.be.empty; - // when all parameters is OK - expect(IMA.owaspUtils.private_key_2_public_key(w3mod, keyPrivate)).to.have.lengthOf(128); - }); - - it('should invoke `public_key_2_account_address`', async function () { - let keyPublic = "5dd431d36ce6b88f27d351051b31a26848c4a886f0dd0bc87a7d5a9d821417c9" + - "e807e8589f680ab0f2ab29831231ad7b3d6659990ee830582fede785fc3c33c4"; - let keyPublicUnd; // undefined - let w3mod_undefined; // undefined - // if w3mod `undefined` or `null` - expect(IMA.owaspUtils.public_key_2_account_address(w3mod_undefined, keyPublic)).to.be.empty; - // if keyPrivate `undefined` or `null` - expect(IMA.owaspUtils.public_key_2_account_address(w3mod, keyPublicUnd)).to.be.empty; - // when all parameters is OK - expect(IMA.owaspUtils.public_key_2_account_address(w3mod, keyPublic)).to.include("0x"); - }); - - it('should invoke `private_key_2_account_address`', async function () { - let keyPrivate = "23abdbd3c61b5330af61ebe8bef582f4e5cc08e554053a718bdce7813b9dc1fc"; - // - expect(IMA.owaspUtils.private_key_2_account_address(w3mod, keyPrivate)).to.include("0x"); - }); - - it('should return `false` invoke `check_is_registered_s_chain_in_deposit_box`', async function () { - let jo_lock_and_data_main_net; // for `false` output - // - expect(await IMA. - check_is_registered_s_chain_in_deposit_box( - w3_main_net, - jo_lock_and_data_main_net, - joAccount_main_net, - chain_id_s_chain - ) - ).to.be.false; - }); - - it('should return `true` invoke `check_is_registered_s_chain_in_deposit_box`', async function () { - // - expect(await IMA. - check_is_registered_s_chain_in_deposit_box( - w3_main_net, - jo_lock_and_data_main_net, - joAccount_main_net, - chain_id_s_chain - ) - ).to.be.true; - }); - - it('should return `false` invoke `register_s_chain_in_deposit_box`', async function () { - let jo_lock_and_data_main_net; // for `false` output - // - expect(await IMA. - register_s_chain_in_deposit_box( - w3_main_net, - jo_lock_and_data_main_net, - joAccount_main_net, - jo_token_manager, - chain_id_s_chain, - tc_main_net //, - // cntWaitAttempts, - // nSleepMilliseconds - ) - ).to.be.false; - }); - - it('should return `true` invoke `register_s_chain_in_deposit_box`', async function () { - // - expect(await IMA. - register_s_chain_in_deposit_box( - w3_main_net, - jo_lock_and_data_main_net, - joAccount_main_net, - jo_token_manager, - chain_id_s_chain, - tc_main_net //, - // cntWaitAttempts, - // nSleepMilliseconds - ) - ).to.be.true; - }); - - it('should return `false` invoke `check_is_registered_main_net_depositBox_on_s_chain`', async function () { - let jo_lock_and_data_s_chain; // for `false` output - // - expect(await IMA. - check_is_registered_main_net_depositBox_on_s_chain( - w3_main_net, - jo_lock_and_data_s_chain, - joAccount - ) - ).to.be.false; - }); - - it('should return `true` invoke `check_is_registered_main_net_depositBox_on_s_chain`', async function () { - // - expect(await IMA. - check_is_registered_main_net_depositBox_on_s_chain( - w3_main_net, - jo_lock_and_data_s_chain, - joAccount - ) - ).to.be.true; - }); - - it('should return `false` invoke `register_main_net_depositBox_on_s_chain`', async function () { - let jo_deposit_box_main_net; // for `false` output - // - expect(await IMA. - register_main_net_depositBox_on_s_chain( - w3_s_chain, - jo_deposit_box_main_net, - jo_lock_and_data_s_chain, - joAccount, - -4, - tc_s_chain - ) - ).to.be.false; - }); - - it('should return `true` invoke `register_main_net_depositBox_on_s_chain`', async function () { - let jo_deposit_box_main_net = {options: {address: "0xd34e38f830736DB41CC6E10aA37A3C851A7a2B82"}}; - // - expect(await IMA. - register_main_net_depositBox_on_s_chain( - w3_s_chain, - jo_deposit_box_main_net, - jo_lock_and_data_s_chain, - joAccount, - -4, - tc_s_chain - ) - ).to.be.true; - }); - - it('should return `false` invoke `do_eth_payment_from_main_net`', async function () { - let joAccountSrc, wei_how_much; // for `false` output - // - expect(await IMA. - do_eth_payment_from_main_net( - w3_main_net, - joAccountSrc, - joAccountDst, - jo_deposit_box, - chain_id_s_chain, - wei_how_much, // how much WEI money to send - tc_main_net - ) - ).to.be.false; - }); - - it('should return `true` invoke `do_eth_payment_from_main_net`', async function () { - let wei_how_much; - // - expect(await IMA. - do_eth_payment_from_main_net( - w3_main_net, - joAccountSrc, - joAccountDst, - jo_deposit_box, - chain_id_s_chain, - wei_how_much, // how much WEI money to send - tc_main_net - ) - ).to.be.true; - }); - - it('should return `false` invoke `do_eth_payment_from_s_chain`', async function () { - let joAccountSrc, wei_how_much; // for `false` output - // - expect(await IMA. - do_eth_payment_from_s_chain( - w3_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager, - jo_lock_and_data_s_chain, - wei_how_much, // how much WEI money to send - tc_s_chain - ) - ).to.be.false; - }); - - it('should return `true` invoke `do_eth_payment_from_s_chain`', async function () { - let wei_how_much; - // - expect(await IMA. - do_eth_payment_from_s_chain( - w3_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager, - jo_lock_and_data_s_chain, - wei_how_much, // how much WEI money to send - tc_s_chain - ) - ).to.be.true; - }); - - it('should return `false` invoke `receive_eth_payment_from_s_chain_on_main_net`', async function () { - let joAccount_main_net; // for `false` output - // - expect(await IMA. - receive_eth_payment_from_s_chain_on_main_net( - w3_main_net, - joAccount_main_net, - jo_lock_and_data_main_net, - tc_main_net - ) - ).to.be.false; - }); - - it('should return `true` invoke `receive_eth_payment_from_s_chain_on_main_net`', async function () { - // - expect(await IMA. - receive_eth_payment_from_s_chain_on_main_net( - w3_main_net, - joAccount_main_net, - jo_lock_and_data_main_net, - tc_main_net - ) - ).to.be.true; - }); - - it('should return `null` invoke `view_eth_payment_from_s_chain_on_main_net`', async function () { - let joAccount_main_net; // for `false` output - // - expect(await IMA. - view_eth_payment_from_s_chain_on_main_net( - w3_main_net, - joAccount_main_net, - jo_lock_and_data_main_net - ) - ).to.be.null; - }); - - it('should return `true` invoke `view_eth_payment_from_s_chain_on_main_net`', async function () { - // - expect(await IMA. - view_eth_payment_from_s_chain_on_main_net( - w3_main_net, - joAccount_main_net, - jo_lock_and_data_main_net - ) - ).to.be.true; - }); - - it('should return `false` invoke `do_erc20_payment_from_main_net`', async function () { - let token_amount; - let strCoinNameErc20_main_net; - let erc20PrivateTestnetJson_main_net; - let strCoinNameErc20_s_chain; - let erc20PrivateTestnetJson_s_chain; - // - expect(await IMA. - do_erc20_payment_from_main_net( - w3_main_net, - w3_s_chain, - joAccountSrc, - joAccountDst, - jo_deposit_box, - chain_id_s_chain, - token_amount, // how much ERC20 tokens to send - jo_token_manager, // only s-chain - strCoinNameErc20_main_net, - erc20PrivateTestnetJson_main_net, - strCoinNameErc20_s_chain, - erc20PrivateTestnetJson_s_chain, - tc_main_net - ) - ).to.be.false; - }); - - it('should return `false` invoke `do_erc20_payment_from_s_chain`', async function () { - let token_amount; - let strCoinNameErc20_main_net; - let joErc20_main_net; - let strCoinNameErc20_s_chain; - let joErc20_s_chain; - // - expect(await IMA. - do_erc20_payment_from_s_chain( - w3_main_net, - w3_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager, // only s-chain - jo_lock_and_data_s_chain, - jo_deposit_box, // only main net - token_amount, // how much ERC20 tokens to send - strCoinNameErc20_main_net, - joErc20_main_net, - strCoinNameErc20_s_chain, - joErc20_s_chain, - tc_s_chain - ) - ).to.be.false; - }); - - it('should return `false` invoke `do_transfer`', async function () { - let jo_message_proxy_src; // for `false` output - let chain_id_src = "test"; - let chain_id_dst = "test"; - let nTransactionsCountInBlock; - let nMaxTransactionsCount; - let nBlockAwaitDepth; - let nBlockAge; - // - expect(await IMA. - do_transfer( - w3_src, - jo_message_proxy_src, - joAccountSrc, - // - w3_dst, - jo_message_proxy_dst, - joAccountDst, - // - chain_id_src, - chain_id_dst, - -4, - -4, - null, // jo_deposit_box - for logs validation on mainnet - null, //jo_token_manager - for logs validation on s-chain - // - nTransactionsCountInBlock, - nMaxTransactionsCount, - nBlockAwaitDepth, - nBlockAge, - null, // fn_sign_messages or null - tc_main_net, // or tc_s_chain - null // optsPendingTxAnalysis - ) - ).to.be.false; - }); - - it('should return `true` invoke `do_transfer`', async function () { - let chain_id_src = "test"; - let chain_id_dst = "test"; - let nTransactionsCountInBlock; - let nMaxTransactionsCount; - let nBlockAwaitDepth; - let nBlockAge; - // - expect(await IMA. - do_transfer( - w3_src, - jo_message_proxy_src, - joAccountSrc, - // - w3_dst, - jo_message_proxy_dst, - joAccountDst, - // - chain_id_src, - chain_id_dst, - -4, - -4, - null, // jo_deposit_box - for logs validation on mainnet - null, //jo_token_manager - for logs validation on s-chain - // - nTransactionsCountInBlock, - nMaxTransactionsCount, - nBlockAwaitDepth, - nBlockAge, - null, // fn_sign_messages or null - tc_main_net, // or tc_s_chain - null // optsPendingTxAnalysis - ) - ).to.be.true; - }); -}); \ No newline at end of file diff --git a/agent/utils.js b/agent/utils.js deleted file mode 100644 index e9e7201e5..000000000 --- a/agent/utils.js +++ /dev/null @@ -1,437 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file utils.js - * @copyright SKALE Labs 2019-Present - */ - -const fs = require( "fs" ); -const path = require( "path" ); -// const url = require( "url" ); -const os = require( "os" ); -const { v4: uuid } = require( "uuid" ); - -const log = require( "../npms/skale-log/log.js" ); -const cc = log.cc; - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -function replaceAll( str, find, replace ) { - return str.replace( new RegExp( find, "g" ), replace ); -} - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -function normalizePath( strPath ) { - strPath = strPath.replace( /^~/, os.homedir() ); - strPath = path.normalize( strPath ); - strPath = path.resolve( strPath ); - return strPath; -} - -function getRandomFileName() { - const timestamp = new Date().toISOString().replace( /[-:.]/g,"" ); - const random = ( "" + Math.random() ).substring( 2, 8 ); - const random_number = timestamp + random; - return random_number; -} - -function fileExists( strPath ) { - try { - if( fs.existsSync( strPath ) ) { - const stats = fs.statSync( strPath ); - if( stats.isFile() ) - return true; - } - } catch ( err ) {} - return false; -} - -function fileLoad( strPath, strDefault ) { - strDefault = strDefault || ""; - if( !fileExists( strPath ) ) - return strDefault; - try { - const s = fs.readFileSync( strPath ); - return s; - } catch ( err ) {} - return strDefault; -} - -function fileSave( strPath, s ) { - try { - fs.writeFileSync( strPath, s ); - return true; - } catch ( err ) {} - return false; -} - -function jsonFileLoad( strPath, joDefault, bLogOutput ) { - if( bLogOutput == undefined || bLogOutput == null ) - bLogOutput = false; - joDefault = joDefault || {}; - if( bLogOutput ) - log.write( cc.normal( "Will load JSON file " ) + cc.info( strPath ) + cc.normal( "..." ) + "\n" ); - if( !fileExists( strPath ) ) { - if( bLogOutput ) - log.write( cc.error( "Cannot load JSON file " ) + cc.info( strPath ) + cc.error( ", it does not exist" ) + "\n" ); - return joDefault; - } - try { - const s = fs.readFileSync( strPath ); - if( bLogOutput ) - log.write( cc.normal( "Did loaded content of JSON file " ) + cc.info( strPath ) + cc.normal( ", will parse it..." ) + "\n" ); - const jo = JSON.parse( s ); - if( bLogOutput ) - log.write( cc.success( "Done, loaded content of JSON file " ) + cc.info( strPath ) + cc.success( "." ) + "\n" ); - return jo; - } catch ( err ) { - log.write( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " failed to load JSON file " ) + cc.info( strPath ) + cc.error( ": " ) + cc.warning( err ) + "\n" ); - } - return joDefault; -} - -function jsonFileSave( strPath, jo, bLogOutput ) { - if( bLogOutput == undefined || bLogOutput == null ) - bLogOutput = false; - if( bLogOutput ) - log.write( cc.normal( "Will save JSON file " ) + cc.info( strPath ) + cc.normal( "..." ) + "\n" ); - try { - const s = JSON.stringify( jo, null, 4 ); - fs.writeFileSync( strPath, s ); - if( bLogOutput ) - log.write( cc.success( "Done, saved content of JSON file " ) + cc.info( strPath ) + cc.success( "." ) + "\n" ); - return true; - } catch ( err ) { - log.write( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " failed to save JSON file " ) + cc.info( strPath ) + cc.error( ": " ) + cc.warning( err ) + "\n" ); - } - return false; -} - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -function encodeUTF8( s ) { // marshals a string to an Uint8Array, see https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330 - let i = 0; const arrBytes = new Uint8Array( s.length * 4 ); - for( let ci = 0; ci != s.length; ci++ ) { - let c = s.charCodeAt( ci ); - if( c < 128 ) { - arrBytes[i++] = c; - continue; - } - if( c < 2048 ) - arrBytes[i++] = c >> 6 | 192; else { - if( c > 0xd7ff && c < 0xdc00 ) { - if( ++ci >= s.length ) - throw new Error( "UTF-8 encode: incomplete surrogate pair" ); - const c2 = s.charCodeAt( ci ); - if( c2 < 0xdc00 || c2 > 0xdfff ) - throw new Error( "UTF-8 encode: second surrogate character 0x" + c2.toString( 16 ) + " at index " + ci + " out of range" ); - c = 0x10000 + ( ( c & 0x03ff ) << 10 ) + ( c2 & 0x03ff ); - arrBytes[i++] = c >> 18 | 240; - arrBytes[i++] = c >> 12 & 63 | 128; - } else - arrBytes[i++] = c >> 12 | 224; - arrBytes[i++] = c >> 6 & 63 | 128; - } - arrBytes[i++] = c & 63 | 128; - } - return arrBytes.subarray( 0, i ); -} - -function decodeUTF8( arrBytes ) { // un-marshals a string from an Uint8Array, see https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330 - let i = 0; let s = ""; - while( i < arrBytes.length ) { - let c = arrBytes[i++]; - if( c > 127 ) { - if( c > 191 && c < 224 ) { - if( i >= arrBytes.length ) - throw new Error( "UTF-8 decode: incomplete 2-byte sequence" ); - c = ( c & 31 ) << 6 | arrBytes[i++] & 63; - } else if( c > 223 && c < 240 ) { - if( i + 1 >= arrBytes.length ) - throw new Error( "UTF-8 decode: incomplete 3-byte sequence" ); - c = ( c & 15 ) << 12 | ( arrBytes[i++] & 63 ) << 6 | arrBytes[i++] & 63; - } else if( c > 239 && c < 248 ) { - if( i + 2 >= arrBytes.length ) - throw new Error( "UTF-8 decode: incomplete 4-byte sequence" ); - c = ( c & 7 ) << 18 | ( arrBytes[i++] & 63 ) << 12 | ( arrBytes[i++] & 63 ) << 6 | arrBytes[i++] & 63; - } else - throw new Error( "UTF-8 decode: unknown multi-byte start 0x" + c.toString( 16 ) + " at index " + ( i - 1 ) ); - } - if( c <= 0xffff ) - s += String.fromCharCode( c ); else if( c <= 0x10ffff ) { - c -= 0x10000; - s += String.fromCharCode( c >> 10 | 0xd800 ); - s += String.fromCharCode( c & 0x3FF | 0xdc00 ); - } else - throw new Error( "UTF-8 decode: code point 0x" + c.toString( 16 ) + " exceeds UTF-16 reach" ); - } - return s; -} - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -function hexToBytes( strHex, isInversiveOrder ) { // convert a hex string to a byte array - isInversiveOrder = !!( ( isInversiveOrder != null && isInversiveOrder != undefined && isInversiveOrder ) ); - strHex = strHex || ""; - strHex = "" + strHex; - strHex = strHex.trim().toLowerCase(); - if( strHex.length > 1 && strHex[0] == "0" && ( strHex[1] == "x" || strHex[1] == "X" ) ) - strHex = strHex.substr( 2, strHex.length - 2 ); - if( ( strHex.length & 1 ) !== 0 ) - strHex = "0" + strHex; - const cnt = strHex.length; - let i, j; - const arrBytes = new Uint8Array( cnt / 2 ); - for( i = 0, j = 0; i < cnt; ++j, i += 2 ) - arrBytes[j] = parseInt( strHex.substr( i, 2 ), 16 ); - if( isInversiveOrder ) - invertArrayItemsLR( arrBytes ); - return arrBytes; -} - -function bytesToHex( arrBytes, isInversiveOrder ) { // convert a byte array to a hex string - isInversiveOrder = !!( ( isInversiveOrder != null && isInversiveOrder != undefined && isInversiveOrder ) ); - const hex = []; - for( let i = 0; i < arrBytes.length; i++ ) { - const current = arrBytes[i] < 0 ? arrBytes[i] + 256 : arrBytes[i]; - const c0 = ( current >>> 4 ).toString( 16 ); - const c1 = ( current & 0xF ).toString( 16 ); - if( isInversiveOrder ) { - hex.splice( 0, 0, c0 ); - hex.splice( 1, 0, c1 ); - } else { - hex.push( c0 ); - hex.push( c1 ); - } - } - return hex.join( "" ); -} - -function bytesAlignLeftWithZeroes( arrBytes, cntMin ) { - const arrOneZeroByte = new Uint8Array( 1 ); - arrOneZeroByte[0] = 0; - while( arrBytes.length < cntMin ) - arrBytes = bytesConcat( arrOneZeroByte, arrBytes ); - return arrBytes; -} - -function bytesAlignRightWithZeroes( arrBytes, cntMin ) { - const arrOneZeroByte = new Uint8Array( 1 ); - arrOneZeroByte[0] = 0; - while( arrBytes.length < cntMin ) - arrBytes = bytesConcat( arrBytes, arrOneZeroByte ); - return arrBytes; -} - -function concatTypedArrays( a, b ) { // a, b TypedArray of same type - const c = new ( a.constructor )( a.length + b.length ); - c.set( a, 0 ); - c.set( b, a.length ); - return c; -} - -function concatByte( ui8a, byte ) { - const b = new Uint8Array( 1 ); - b[0] = byte; - return concatTypedArrays( ui8a, b ); -} - -function bytesConcat( a1, a2 ) { - a1 = a1 || new Uint8Array(); - a2 = a2 || new Uint8Array(); - return concatTypedArrays( a1, a2 ); -} - -function toArrayBuffer( buf ) { // see https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer - const ab = new ArrayBuffer( buf.length ); - const view = new Uint8Array( ab ); - for( let i = 0; i < buf.length; ++i ) - view[i] = buf[i]; - return ab; -} - -function toBuffer( ab ) { - const buf = Buffer.alloc( ab.byteLength ); - const view = new Uint8Array( ab ); - for( let i = 0; i < buf.length; ++i ) - buf[i] = view[i]; - return buf; -} - -function invertArrayItemsLR( arr ) { - let i; const cnt = arr.length / 2; - for( i = 0; i < cnt; ++i ) { - const e1 = arr[i]; - const e2 = arr[arr.length - i - 1]; - arr[i] = e2; - arr[arr.length - i - 1] = e1; - } - return arr; -} - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -function discover_in_json_coin_name( jo ) { - if( typeof jo !== "object" ) - return ""; - const arrKeys = Object.keys( jo ); - let s1 = ""; - let s2 = ""; - let i; const cnt = arrKeys.length; - let j; - for( i = 0; i < cnt; ++i ) { - if( s1.length > 0 && s2.length > 0 ) - break; - const k = arrKeys[i]; - j = k.indexOf( "_address" ); - if( j > 0 ) { - s1 = k.substring( 0, j ); - continue; - } - j = k.indexOf( "_abi" ); - if( j > 0 ) { - s2 = k.substring( 0, j ); - continue; - } - } - if( s1.length === 0 || s2.length === 0 ) - return ""; - if( s1 !== s2 ) - return ""; - return s1; -} - -function check_key_exist_in_abi( strName, strFile, joABI, strKey, isExitOnError ) { - if( isExitOnError == null || isExitOnError == undefined ) - isExitOnError = true; - try { - if( strKey in joABI ) - return true; - } catch ( err ) { - } - if( isExitOnError ) { - log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Loaded " ) + cc.warning( strName ) + cc.error( " ABI JSON file " ) + cc.info( strFile ) + cc.error( " does not contain needed key " ) + cc.warning( strKey ) + "\n" ); - process.exit( 126 ); - } - return false; -} - -function check_keys_exist_in_abi( strName, strFile, joABI, arrKeys, isExitOnError ) { - const cnt = arrKeys.length; - for( let i = 0; i < cnt; ++i ) { - const strKey = arrKeys[i]; - if( ! check_key_exist_in_abi( strName, strFile, joABI, strKey, isExitOnError ) ) - return false; - } - return true; -} - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -function compose_schain_node_url( joNode ) { - // if( "ip" in joNode && typeof joNode.ip === "string" && joNode.ip.length > 0 ) { - // if( "wssRpcPort" in joNode && typeof joNode.wssRpcPort === "number" && joNode.wssRpcPort > 0 ) - // return "wss://" + joNode.ip + ":" + joNode.wssRpcPort; - // if( "wsRpcPort" in joNode && typeof joNode.wsRpcPort === "number" && joNode.wsRpcPort > 0 ) - // return "ws://" + joNode.ip + ":" + joNode.wsRpcPort; - // if( "httpsRpcPort" in joNode && typeof joNode.httpsRpcPort === "number" && joNode.httpsRpcPort > 0 ) - // return "https://" + joNode.ip + ":" + joNode.httpsRpcPort; - // if( "httpRpcPort" in joNode && typeof joNode.httpRpcPort === "number" && joNode.httpRpcPort > 0 ) - // return "http://" + joNode.ip + ":" + joNode.httpRpcPort; - // } - // if( "ip6" in joNode && typeof joNode.ip6 === "string" && joNode.ip6.length > 0 ) { - // if( "wssRpcPort6" in joNode && typeof joNode.wssRpcPort6 === "number" && joNode.wssRpcPort6 > 0 ) - // return "wss://[" + joNode.ip6 + "]:" + joNode.wssRpcPort6; - // if( "wsRpcPort6" in joNode && typeof joNode.wsRpcPort6 === "number" && joNode.wsRpcPort6 > 0 ) - // return "ws://[" + joNode.ip6 + "]:" + joNode.wsRpcPort6; - // if( "httpsRpcPort6" in joNode && typeof joNode.httpsRpcPort6 === "number" && joNode.httpsRpcPort6 > 0 ) - // return "https://[" + joNode.ip6 + "]:" + joNode.httpsRpcPort6; - // if( "httpRpcPort6" in joNode && typeof joNode.httpRpcPort6 === "number" && joNode.httpRpcPort6 > 0 ) - // return "http://[" + joNode.ip6 + "]:" + joNode.httpRpcPort6; - // } - if( "ip" in joNode && typeof joNode.ip === "string" && joNode.ip.length > 0 ) { - if( "httpRpcPort" in joNode && typeof joNode.httpRpcPort === "number" && joNode.httpRpcPort > 0 ) - return "http://" + joNode.ip + ":" + joNode.httpRpcPort; - if( "wsRpcPort" in joNode && typeof joNode.wsRpcPort === "number" && joNode.wsRpcPort > 0 ) - return "ws://" + joNode.ip + ":" + joNode.wsRpcPort; - if( "httpsRpcPort" in joNode && typeof joNode.httpsRpcPort === "number" && joNode.httpsRpcPort > 0 ) - return "https://" + joNode.ip + ":" + joNode.httpsRpcPort; - if( "wssRpcPort" in joNode && typeof joNode.wssRpcPort === "number" && joNode.wssRpcPort > 0 ) - return "wss://" + joNode.ip + ":" + joNode.wssRpcPort; - } - if( "ip6" in joNode && typeof joNode.ip6 === "string" && joNode.ip6.length > 0 ) { - if( "httpRpcPort6" in joNode && typeof joNode.httpRpcPort6 === "number" && joNode.httpRpcPort6 > 0 ) - return "http://[" + joNode.ip6 + "]:" + joNode.httpRpcPort6; - if( "wsRpcPort6" in joNode && typeof joNode.wsRpcPort6 === "number" && joNode.wsRpcPort6 > 0 ) - return "ws://[" + joNode.ip6 + "]:" + joNode.wsRpcPort6; - if( "httpsRpcPort6" in joNode && typeof joNode.httpsRpcPort6 === "number" && joNode.httpsRpcPort6 > 0 ) - return "https://[" + joNode.ip6 + "]:" + joNode.httpsRpcPort6; - if( "wssRpcPort6" in joNode && typeof joNode.wssRpcPort6 === "number" && joNode.wssRpcPort6 > 0 ) - return "wss://[" + joNode.ip6 + "]:" + joNode.wssRpcPort6; - } - return ""; -} - -//////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////// - -module.exports = { - uuid: uuid, - log: log, - cc: cc, - // - replaceAll: replaceAll, - // - normalizePath: normalizePath, - getRandomFileName: getRandomFileName, - fileExists: fileExists, - fileLoad: fileLoad, - fileSave: fileSave, - jsonFileLoad: jsonFileLoad, - jsonFileSave: jsonFileSave, - // - encodeUTF8: encodeUTF8, - decodeUTF8: decodeUTF8, - // - hexToBytes: hexToBytes, - bytesToHex: bytesToHex, - bytesAlignLeftWithZeroes: bytesAlignLeftWithZeroes, - bytesAlignRightWithZeroes: bytesAlignRightWithZeroes, - concatTypedArrays: concatTypedArrays, - concatByte: concatByte, - bytesConcat: bytesConcat, - toArrayBuffer: toArrayBuffer, - toBuffer: toBuffer, - invertArrayItemsLR: invertArrayItemsLR, - // - discover_in_json_coin_name: discover_in_json_coin_name, - check_key_exist_in_abi: check_key_exist_in_abi, - check_keys_exist_in_abi: check_keys_exist_in_abi, - // - compose_schain_node_url: compose_schain_node_url -}; // module.exports diff --git a/agent/utils.mjs b/agent/utils.mjs new file mode 100644 index 000000000..7411c6758 --- /dev/null +++ b/agent/utils.mjs @@ -0,0 +1,548 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file utils.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as fs from "fs"; +import * as path from "path"; +import * as os from "os"; +import * as log from "../npms/skale-log/log.mjs"; +import * as cc from "../npms/skale-cc/cc.mjs"; +import * as imaHelperAPIs from "../npms/skale-ima/imaHelperAPIs.mjs"; + +import { v4 as uuid } from "uuid"; +export { uuid }; + +const ethersMod = owaspUtils.ethersMod; +export { ethersMod }; + +export function replaceAll( str, find, replace ) { + return str.replace( new RegExp( find, "g" ), replace ); +} + +export function normalizePath( strPath ) { + strPath = strPath.replace( /^~/, os.homedir() ); + strPath = path.normalize( strPath ); + strPath = path.resolve( strPath ); + return strPath; +} + +export function getRandomFileName() { + const timestamp = new Date().toISOString().replace( /[-:.]/g,"" ); + const random = ( "" + Math.random() ).substring( 2, 8 ); + const randomNumber = timestamp + random; + return randomNumber; +} + +export function fileExists( strPath ) { + try { + if( fs.existsSync( strPath ) ) { + const stats = fs.statSync( strPath ); + if( stats.isFile() ) + return true; + } + } catch ( err ) {} + return false; +} + +export function fileLoad( strPath, strDefault ) { + strDefault = strDefault || ""; + if( !fileExists( strPath ) ) + return strDefault; + try { + const s = fs.readFileSync( strPath ); + return s; + } catch ( err ) {} + return strDefault; +} + +export function fileSave( strPath, s ) { + try { + fs.writeFileSync( strPath, s ); + return true; + } catch ( err ) {} + return false; +} + +export function jsonFileLoad( strPath, joDefault, bLogOutput ) { + if( bLogOutput == undefined || bLogOutput == null ) + bLogOutput = false; + joDefault = joDefault || {}; + if( bLogOutput ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( cc.normal( "Will load JSON file " ) + + cc.info( strPath ) + cc.normal( "..." ) + "\n" ); + } + } + if( !fileExists( strPath ) ) { + if( bLogOutput ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Cannot load JSON file " ) + + cc.info( strPath ) + cc.error( ", it does not exist" ) + "\n" ); + } + } + return joDefault; + } + try { + const s = fs.readFileSync( strPath ); + if( bLogOutput ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( cc.normal( "Did loaded content of JSON file " ) + + cc.info( strPath ) + cc.normal( ", will parse it..." ) + "\n" ); + } + } + const jo = JSON.parse( s ); + if( bLogOutput ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( cc.success( "Done, loaded content of JSON file " ) + + cc.info( strPath ) + cc.success( "." ) + "\n" ); + } + } + return jo; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " failed to load JSON file " ) + + cc.info( strPath ) + cc.error( ": " ) + + cc.warning( strError ) + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n" ); + } + } + return joDefault; +} + +export function jsonFileSave( strPath, jo, bLogOutput ) { + if( bLogOutput == undefined || bLogOutput == null ) + bLogOutput = false; + if( bLogOutput ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( cc.normal( "Will save JSON file " ) + + cc.info( strPath ) + cc.normal( "..." ) + "\n" ); + } + } + try { + const s = JSON.stringify( jo, null, 4 ); + fs.writeFileSync( strPath, s ); + if( bLogOutput ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( cc.success( "Done, saved content of JSON file " ) + + cc.info( strPath ) + cc.success( "." ) + "\n" ); + } + } + return true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " failed to save JSON file " ) + + cc.info( strPath ) + cc.error( ": " ) + + cc.warning( strError ) + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n" ); + } + } + return false; +} + +const gMillisecondsToSleepStepWaitForClonedTokenToAppear = 1000; + +export async function waitForClonedTokenToAppear( + sc, + strTokenSuffix, // example "erc20" + addressCallFrom, + cntAttempts, + tokensMN, + strMainnetName +) { + const strTokenSuffixLC = strTokenSuffix.toLowerCase(); + const strTokenSuffixUC = + owaspUtils.replaceAll( strTokenSuffix.toUpperCase(), "_WITH_METADATA", "_with_metadata" ); + const strTokenSuffixLCshort = owaspUtils.replaceAll( strTokenSuffixLC, "_with_metadata", "" ); + const ts0 = cc.timestampHR(); + let ts1; + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.debug( "Waiting for " ) + cc.notice( strTokenSuffixUC ) + + cc.debug( " token to appear automatically deployed on S-Chain " ) + + cc.attention( sc.chainName ) + cc.debug( "..." ) + "\n" ); + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + log.write( cc.debug( "... source chain name is " ) + + cc.attention( strMainnetName ) + "\n" ); + log.write( cc.debug( "... destination " ) + cc.notice( "TokenManager" + strTokenSuffixUC ) + + cc.debug( " address is " ) + cc.notice( sc.joABI["token_manager_" + + strTokenSuffixLC + "_address"] ) + "\n" ); + } + const contractTokenManager = new owaspUtils.ethersMod.ethers.Contract( + sc.joABI["token_manager_" + strTokenSuffixLC + "_address"], + sc.joABI["token_manager_" + strTokenSuffixLC + "_abi"], + sc.ethersProvider + ); + for( let idxAttempt = 0; idxAttempt < cntAttempts; ++ idxAttempt ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.debug( "Discovering " ) + cc.notice( strTokenSuffixUC ) + + cc.debug( " step " ) + cc.info( idxAttempt ) + cc.debug( "..." ) + "\n" ); + } + if( gMillisecondsToSleepStepWaitForClonedTokenToAppear > 0 ) + await imaHelperAPIs.sleep( gMillisecondsToSleepStepWaitForClonedTokenToAppear ); + const addressOnSChain = + await contractTokenManager.callStatic[ + "clones" + cc.capitalizeFirstLetter( strTokenSuffixLCshort )]( + sc.ethersMod.ethers.utils.id( strMainnetName ), + tokensMN.joABI[strTokenSuffixUC + "_address"], + { from: addressCallFrom } + ); + if( addressOnSChain != "0x0000000000000000000000000000000000000000" ) { + ts1 = cc.timestampHR(); + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.success( "Done, duration is " ) + + cc.info( cc.getDurationString( ts0, ts1 ) ) + "\n" ); + log.write( cc.success( "Discovered " ) + cc.notice( strTokenSuffixUC ) + + cc.success( " instantiated on S-Chain " ) + cc.attention( sc.chainName ) + + cc.success( " at address " ) + cc.notice( addressOnSChain ) + "\n" ); + } + return addressOnSChain; + } + } + ts1 = cc.timestampHR(); + const strError = + cc.error( "Failed to discover " ) + cc.notice( strTokenSuffixUC ) + + cc.error( " instantiated on S-Chain " ) + cc.attention( sc.chainName ); + if( log.verboseGet() >= log.verboseReversed().error ) + log.write( strError + "\n" ); + throw new Error( strError ); +} + +export async function waitForClonedTokenAppearErc20( + sc, tokenERC20SC, joAccountSC, tokensMN, strMainnetName +) { + if( "abi" in tokenERC20SC && typeof tokenERC20SC.abi == "object" && + "address" in tokenERC20SC && typeof tokenERC20SC.address == "string" + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Skipping automatic " ) + cc.notice( "ERC20" ) + + cc.warning( " instantiation discovery, already done before" ) + "\n" ); + } + return; + } + const addressCallFrom = joAccountSC.address(); + const addressOnSChain = + await waitForClonedTokenToAppear( + sc, "erc20", addressCallFrom, 40, tokensMN, strMainnetName ); + tokenERC20SC.abi = JSON.parse( JSON.stringify( tokensMN.joABI.ERC20_abi ) ); + tokenERC20SC.address = "" + addressOnSChain; +} + +export async function waitForClonedTokenAppearErc721( + sc, tokenERC721SC, joAccountSC, tokensMN, strMainnetName +) { + if( "abi" in tokenERC721SC && typeof tokenERC721SC.abi == "object" && + "address" in tokenERC721SC && typeof tokenERC721SC.address == "string" + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Skipping automatic " ) + cc.notice( "ERC721" ) + + cc.warning( "instantiation discovery, already done before" ) + "\n" ); + } + return; + } + const addressCallFrom = joAccountSC.address(); + const addressOnSChain = + await waitForClonedTokenToAppear( + sc, "erc721", addressCallFrom, 40, tokensMN, strMainnetName ); + tokenERC721SC.abi = JSON.parse( JSON.stringify( tokensMN.joABI.ERC721_abi ) ); + tokenERC721SC.address = "" + addressOnSChain; +} + +export async function waitForClonedTokenAppearErc721WithMetadata( + sc, tokenERC721SC, joAccountSC, tokensMN, strMainnetName +) { + if( "abi" in tokenERC721SC && typeof tokenERC721SC.abi == "object" && + "address" in tokenERC721SC && typeof tokenERC721SC.address == "string" + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Skipping automatic " ) + cc.notice( "ERC721_with_metadata" ) + + cc.warning( " instantiation discovery, already done before" ) + "\n" ); + } + return; + } + const addressCallFrom = joAccountSC.address(); + const addressOnSChain = + await waitForClonedTokenToAppear( + sc, "erc721_with_metadata", addressCallFrom, 40, tokensMN, strMainnetName ); + tokenERC721SC.abi = JSON.parse( JSON.stringify( tokensMN.joABI.ERC721_with_metadata_abi ) ); + tokenERC721SC.address = "" + addressOnSChain; +} + +export async function waitForClonedTokenAppearErc1155( + sc, tokenERC1155SC, joAccountSC, tokensMN, strMainnetName +) { + if( "abi" in tokenERC1155SC && typeof tokenERC1155SC.abi == "object" && + "address" in tokenERC1155SC && typeof tokenERC1155SC.address == "string" + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + log.write( cc.warning( "Skipping automatic " ) + cc.notice( "ERC1155" ) + + cc.warning( " instantiation discovery, already done before" ) + "\n" ); + } + return; + } + const addressCallFrom = joAccountSC.address(); + const addressOnSChain = + await waitForClonedTokenToAppear( + sc, "erc1155", addressCallFrom, 40, tokensMN, strMainnetName ); + tokenERC1155SC.abi = JSON.parse( JSON.stringify( tokensMN.joABI.ERC1155_abi ) ); + tokenERC1155SC.address = "" + addressOnSChain; +} + +export function hexToBytes( strHex, isInversiveOrder ) { // convert a hex string to a byte array + isInversiveOrder = !!( + ( isInversiveOrder != null && isInversiveOrder != undefined && isInversiveOrder ) + ); + strHex = strHex || ""; + strHex = "" + strHex; + strHex = strHex.trim().toLowerCase(); + if( strHex.length > 1 && strHex[0] == "0" && ( strHex[1] == "x" || strHex[1] == "X" ) ) + strHex = strHex.substr( 2, strHex.length - 2 ); + if( ( strHex.length & 1 ) !== 0 ) + strHex = "0" + strHex; + const cnt = strHex.length; + let i, j; + const arrBytes = new Uint8Array( cnt / 2 ); + for( i = 0, j = 0; i < cnt; ++j, i += 2 ) + arrBytes[j] = parseInt( strHex.substr( i, 2 ), 16 ); + if( isInversiveOrder ) + return arrBytes.reverse(); + return arrBytes; +} + +export function bytesToHex( arrBytes, isInversiveOrder ) { // convert a byte array to a hex string + isInversiveOrder = !!( + ( isInversiveOrder != null && isInversiveOrder != undefined && isInversiveOrder ) + ); + const hex = []; + for( let i = 0; i < arrBytes.length; i++ ) { + const current = arrBytes[i] < 0 ? arrBytes[i] + 256 : arrBytes[i]; + const c0 = ( current >>> 4 ).toString( 16 ); + const c1 = ( current & 0xF ).toString( 16 ); + if( isInversiveOrder ) { + hex.splice( 0, 0, c0 ); + hex.splice( 1, 0, c1 ); + } else { + hex.push( c0 ); + hex.push( c1 ); + } + } + return hex.join( "" ); +} + +export function bytesAlignLeftWithZeroes( arrBytes, cntMin ) { + if( arrBytes.length >= cntMin ) + return arrBytes; + const cntNewZeros = cntMin - arrBytes.length; + // By default Uint8Array, Uint16Array and Uint32Array classes keep zeros as it's values. + const arrNewZeros = new Uint8Array( cntNewZeros ); + arrBytes = bytesConcat( arrNewZeros, arrBytes ); + return arrBytes; +} + +export function bytesAlignRightWithZeroes( arrBytes, cntMin ) { + if( arrBytes.length >= cntMin ) + return arrBytes; + const cntNewZeros = cntMin - arrBytes.length; + // By default Uint8Array, Uint16Array and Uint32Array classes keep zeros as it's values. + const arrNewZeros = new Uint8Array( cntNewZeros ); + arrBytes = bytesConcat( arrBytes, arrNewZeros ); + return arrBytes; +} + +export function concatTypedArrays( a, b ) { // a, b TypedArray of same type + if( typeof a == "string" ) + a = hexToBytes( a ); + if( typeof b == "string" ) + b = hexToBytes( b ); + const c = new ( a.constructor )( a.length + b.length ); + c.set( a, 0 ); + c.set( b, a.length ); + return c; +} + +export function concatByte( ui8a, byte ) { + const b = new Uint8Array( 1 ); + b[0] = byte; + return concatTypedArrays( ui8a, b ); +} + +export function bytesConcat( a1, a2 ) { + a1 = a1 || new Uint8Array(); + a2 = a2 || new Uint8Array(); + return concatTypedArrays( a1, a2 ); +} + +export function toBuffer( ab ) { + return Buffer.from( new Uint8Array( ab ) ); +} + +export function discoverCoinNameInJSON( jo ) { + if( typeof jo !== "object" ) + return ""; + const arrKeys = Object.keys( jo ); + let s1 = ""; + let s2 = ""; + let i; const cnt = arrKeys.length; + let j; + for( i = 0; i < cnt; ++i ) { + if( s1.length > 0 && s2.length > 0 ) + break; + const k = arrKeys[i]; + j = k.indexOf( "_address" ); + if( j > 0 ) { + s1 = k.substring( 0, j ); + continue; + } + j = k.indexOf( "_abi" ); + if( j > 0 ) { + s2 = k.substring( 0, j ); + continue; + } + } + if( s1.length === 0 || s2.length === 0 ) + return ""; + if( s1 !== s2 ) + return ""; + return s1; +} + +export function checkKeyExistInABI( strName, strFile, joABI, strKey, isExitOnError ) { + if( isExitOnError == null || isExitOnError == undefined ) + isExitOnError = true; + try { + if( strKey in joABI ) + return true; + } catch ( err ) { + } + if( isExitOnError ) { + if( log.verboseGet() >= log.verboseReversed().fatal ) { + log.write( cc.fatal( "FATAL, CRITICAL ERROR:" ) + cc.error( "Loaded " ) + + cc.warning( strName ) + cc.error( " ABI JSON file " ) + cc.info( strFile ) + + cc.error( " does not contain needed key " ) + cc.warning( strKey ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + process.exit( 126 ); + } + return false; +} + +export function checkKeysExistInABI( strName, strFile, joABI, arrKeys, isExitOnError ) { + const cnt = arrKeys.length; + for( let i = 0; i < cnt; ++i ) { + const strKey = arrKeys[i]; + if( ! checkKeyExistInABI( strName, strFile, joABI, strKey, isExitOnError ) ) + return false; + } + return true; +} + +export function composeSChainNodeUrl( joNode ) { + if( "ip" in joNode && typeof joNode.ip === "string" && joNode.ip.length > 0 ) { + if( "httpRpcPort" in joNode && + typeof joNode.httpRpcPort === "number" && + joNode.httpRpcPort > 0 ) + return "http://" + joNode.ip + ":" + joNode.httpRpcPort; + if( "wsRpcPort" in joNode && + typeof joNode.wsRpcPort === "number" && + joNode.wsRpcPort > 0 ) + return "ws://" + joNode.ip + ":" + joNode.wsRpcPort; + if( "httpsRpcPort" in joNode && + typeof joNode.httpsRpcPort === "number" && + joNode.httpsRpcPort > 0 ) + return "https://" + joNode.ip + ":" + joNode.httpsRpcPort; + if( "wssRpcPort" in joNode && + typeof joNode.wssRpcPort === "number" && + joNode.wssRpcPort > 0 ) + return "wss://" + joNode.ip + ":" + joNode.wssRpcPort; + } + if( "ip6" in joNode && typeof joNode.ip6 === "string" && + joNode.ip6.length > 0 ) { + if( "httpRpcPort6" in joNode && + typeof joNode.httpRpcPort6 === "number" && + joNode.httpRpcPort6 > 0 ) + return "http://[" + joNode.ip6 + "]:" + joNode.httpRpcPort6; + if( "wsRpcPort6" in joNode && + typeof joNode.wsRpcPort6 === "number" && + joNode.wsRpcPort6 > 0 ) + return "ws://[" + joNode.ip6 + "]:" + joNode.wsRpcPort6; + if( "httpsRpcPort6" in joNode && + typeof joNode.httpsRpcPort6 === "number" && + joNode.httpsRpcPort6 > 0 ) + return "https://[" + joNode.ip6 + "]:" + joNode.httpsRpcPort6; + if( "wssRpcPort6" in joNode && + typeof joNode.wssRpcPort6 === "number" && + joNode.wssRpcPort6 > 0 ) + return "wss://[" + joNode.ip6 + "]:" + joNode.wssRpcPort6; + } + return ""; +} + +export function composeImaAgentNodeUrl( joNode ) { + let nPort = -1; + if( "imaAgentRpcPort" in joNode && + typeof joNode.imaAgentRpcPort === "number" && + joNode.imaAgentRpcPort > 0 + ) + nPort = joNode.imaAgentRpcPort; + // PROPOSAL = 0 + // CATCHUP = 1 + // WS_JSON = 2 + // HTTP_JSON = 3 + // BINARY_CONSENSUS = 4 + // ZMQ_BROADCAST = 5 + // IMA_MONITORING = 6 + // WSS_JSON = 7 + // HTTPS_JSON = 8 + // INFO_HTTP_JSON = 9 + // IMA_AGENT_JSON = 10 + if( nPort < 0 && + "httpRpcPort" in joNode && + typeof joNode.httpRpcPort === "number" && + joNode.httpRpcPort > 0 + ) + nPort = joNode.httpRpcPort - 3 + 10; + if( nPort < 0 && + "wsRpcPort" in joNode && + typeof joNode.wsRpcPort === "number" && + joNode.wsRpcPort > 0 + ) + nPort = joNode.wsRpcPort - 2 + 10; + if( nPort < 0 && + "httpsRpcPort" in joNode && + typeof joNode.httpsRpcPort === "number" && + joNode.httpsRpcPort > 0 + ) + nPort = joNode.httpsRpcPort - 8 + 10; + if( nPort < 0 && + "wssRpcPort" in joNode && + typeof joNode.wssRpcPort === "number" && + joNode.wssRpcPort > 0 + ) + nPort = joNode.wssRpcPort - 7 + 10; + if( nPort > 0 ) + return "http://" + joNode.ip + ":" + nPort; + return ""; +} diff --git a/agent/yarn.lock b/agent/yarn.lock index dedabf2bc..a9cd928dc 100644 --- a/agent/yarn.lock +++ b/agent/yarn.lock @@ -2,300 +2,406 @@ # yarn lockfile v1 -"@ethereumjs/common@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" - integrity sha512-DEHjW6e38o+JmB/NO3GZBpW4lpaiBpkFgXF6jLcJ6gETBYpEyaA5nTimsWBUJR3Vmtm/didUEbNjajskugZORg== - dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.1" +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + 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" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/experimental@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" + integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== + dependencies: + "@ethersproject/web" "^5.7.0" + ethers "^5.7.0" + scrypt-js "3.0.1" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" -"@ethereumjs/common@^2.6.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348" - integrity sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA== +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.3" - -"@ethereumjs/tx@^3.3.2": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.4.0.tgz#7eb1947eefa55eb9cf05b3ca116fb7a3dbd0bce7" - integrity sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw== - dependencies: - "@ethereumjs/common" "^2.6.0" - ethereumjs-util "^7.1.3" - -"@ethersproject/abi@5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" - integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== - dependencies: - "@ethersproject/address" "^5.0.4" - "@ethersproject/bignumber" "^5.0.7" - "@ethersproject/bytes" "^5.0.4" - "@ethersproject/constants" "^5.0.4" - "@ethersproject/hash" "^5.0.4" - "@ethersproject/keccak256" "^5.0.3" - "@ethersproject/logger" "^5.0.5" - "@ethersproject/properties" "^5.0.3" - "@ethersproject/strings" "^5.0.4" - -"@ethersproject/abstract-provider@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e" - integrity sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/networks" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/web" "^5.4.0" - -"@ethersproject/abstract-signer@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz#e4e9abcf4dd4f1ba0db7dff9746a5f78f355ea81" - integrity sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA== - dependencies: - "@ethersproject/abstract-provider" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - -"@ethersproject/address@^5.0.4", "@ethersproject/address@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.4.0.tgz#ba2d00a0f8c4c0854933b963b9a3a9f6eb4a37a3" - integrity sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - -"@ethersproject/base64@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.4.0.tgz#7252bf65295954c9048c7ca5f43e5c86441b2a9a" - integrity sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ== - dependencies: - "@ethersproject/bytes" "^5.4.0" - -"@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.0": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.2.tgz#44232e015ae4ce82ac034de549eb3583c71283d8" - integrity sha512-oIBDhsKy5bs7j36JlaTzFgNPaZjiNDOXsdSgSpXRucUl+UA6L/1YLlFeI3cPAoodcenzF4nxNPV13pcy7XbWjA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - bn.js "^4.11.9" - -"@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.4.0.tgz#56fa32ce3bf67153756dbaefda921d1d4774404e" - integrity sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.4.0.tgz#ee0bdcb30bf1b532d2353c977bf2ef1ee117958a" - integrity sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - -"@ethersproject/hash@^5.0.4": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0" - integrity sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA== - dependencies: - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" - integrity sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - js-sha3 "0.5.7" - -"@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.4.1.tgz#503bd33683538b923c578c07d1c2c0dd18672054" - integrity sha512-DZ+bRinnYLPw1yAC64oRl0QyVZj43QeHIhVKfD/+YwSz4wsv1pfwb5SOFjz+r710YEWzU6LrhuSjpSO+6PeE4A== - -"@ethersproject/networks@^5.4.0": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.2.tgz#2247d977626e97e2c3b8ee73cd2457babde0ce35" - integrity sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.1.tgz#9f051f976ce790142c6261ccb7b826eaae1f2f36" - integrity sha512-cyCGlF8wWlIZyizsj2PpbJ9I7rIlUAfnHYwy/T90pdkSn/NFTa5YWZx2wTJBe9V7dD65dcrrEMisCRUJiq6n3w== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/rlp@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" - integrity sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/signing-key@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.4.0.tgz#2f05120984e81cf89a3d5f6dec5c68ee0894fbec" - integrity sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - bn.js "^4.11.9" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" - integrity sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.4.0.tgz#a159d035179334bd92f340ce0f77e83e9e1522e0" - integrity sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ== - dependencies: - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - "@ethersproject/signing-key" "^5.4.0" - -"@ethersproject/web@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" - integrity sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og== - dependencies: - "@ethersproject/base64" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@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== - -"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - -"@types/bn.js@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" - integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@types/connect@^3.4.33": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== dependencies: "@types/node" "*" "@types/node@*": - version "16.10.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.1.tgz#f3647623199ca920960006b3dccf633ea905f243" - integrity sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w== + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== -"@types/node@^12.12.6": - version "12.20.27" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.27.tgz#4141fcad57c332a120591de883e26fe4bb14aaea" - integrity sha512-qZdePUDSLAZRXXV234bLBEUM0nAQjoxbcSwp1rqSMUe1rZ47mwU6OjciR/JvF1Oo8mc0ys6GE0ks0HGgqAZoGg== +"@types/node@^12.12.54": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== -"@types/pbkdf2@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" - integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== +"@types/ws@^7.4.4": + version "7.4.7" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== dependencies: "@types/node" "*" -"@types/secp256k1@^4.0.1": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" - integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== +JSONStream@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== dependencies: - "@types/node" "*" + jsonparse "^1.2.0" + through ">=2.2.7 <3" 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== -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +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.24" - negotiator "0.6.2" - -acorn-walk@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - -address@>=0.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + mime-types "~2.1.34" + negotiator "0.6.3" -aes-js@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== - -agent-base@6, agent-base@^6.0.0, 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" +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== ajv@^6.12.3: version "6.12.6" @@ -310,17 +416,17 @@ ajv@^6.12.3: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +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== -any-promise@^1.0.0, any-promise@^1.3.0: +any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== aproba@^1.0.3: version "1.2.0" @@ -338,74 +444,40 @@ are-we-there-yet@~1.1.2: array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -ast-types@^0.13.2: - version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" - integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== - dependencies: - tslib "^2.0.1" - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== 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== -base-x@^3.0.2, base-x@^3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" - integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== - dependencies: - safe-buffer "^5.0.1" - base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -414,62 +486,54 @@ base64-js@^1.3.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" -bignumber.js@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" - integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== - -blakejs@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" - integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + integrity sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ== dependencies: inherits "~2.0.0" -bluebird@^3.5.0: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.9: +bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.19.0, body-parser@^1.16.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== +body-parser@1.20.1, 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.0" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" brace-expansion@^1.1.7: version "1.1.11" @@ -479,90 +543,10 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brorand@^1.0.1, brorand@^1.1.0: +brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= - dependencies: - base-x "^3.0.2" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - -buffer-to-arraybuffer@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== buffer@6.0.3: version "6.0.3" @@ -572,45 +556,19 @@ buffer@6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -bufferutil@^4.0.1: - version "4.0.4" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.4.tgz#ab81373d313a6ead0d734e98c448c722734ae7bb" - integrity sha512-VNxjXUCrF3LvbLgwfkTb5LsFvk6pGIn7OBb9x+3o+iJ6mKw0JTUp4chBFc88hi1aspeZGeZG9jAIbpFYPQSLZw== +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== dependencies: - node-gyp-build "^4.2.0" - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + streamsearch "^1.1.0" bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: +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== @@ -621,48 +579,17 @@ call-bind@^1.0.0, call-bind@^1.0.2: caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -cids@^0.7.1: - version "0.7.5" - resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" - integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== - dependencies: - buffer "^5.5.0" - class-is "^1.1.0" - multibase "~0.6.0" - multicodec "^1.0.0" - multihashes "~0.4.15" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -class-is@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" - integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -671,33 +598,39 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +commander@^2.20.3: + 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== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + 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 sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== +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.1.2" + safe-buffer "5.2.1" -content-hash@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" - integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== - dependencies: - cids "^0.7.1" - multicodec "^0.5.5" - multihashes "^0.4.15" - -content-type@^1.0.2, content-type@~1.0.4: +content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== @@ -705,131 +638,42 @@ content-type@^1.0.2, content-type@~1.0.4: cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookiejar@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== +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-to@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5" - integrity sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU= + integrity sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w== core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== 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== -cors@^2.8.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -crc-32@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" - integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - 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" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - 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" - -crypto-browserify@3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" -data-uri-to-buffer@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" - integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== - -debug@2.6.9, debug@^2.2.0, debug@^2.6.9: +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: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -837,135 +681,69 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - deep-extend@^0.6.0: version "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: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - default-user-agent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/default-user-agent/-/default-user-agent-1.0.0.tgz#16c46efdcaba3edc45f24f2bd4868b01b7c2adc6" - integrity sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY= + integrity sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw== dependencies: os-name "~1.0.3" -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -degenerator@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.1.tgz#7ef78ec0c8577a544477308ddf1d2d6e88d51f5b" - integrity sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ== - dependencies: - ast-types "^0.13.2" - escodegen "^1.8.1" - esprima "^4.0.0" - vm2 "^3.9.3" +delay@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" + integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -destroy@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.1.0.tgz#b77ae22e472d85437141319d32ae40b344dff38a" - integrity sha512-R5QZrOXxSs0JDUIU/VANvRJlQVMts9C0L76HToQdPdlftfZCE7W6dyH0G4GZ5UW9fRqUOhAoCE2aGekuu+3HjQ== +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== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0, destroy@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -digest-header@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/digest-header/-/digest-header-0.0.1.tgz#11ccf6deec5766ac379744d901c12cba49514be6" - integrity sha1-Ecz23uxXZqw3l0TZAcEsuklRS+Y= +digest-header@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/digest-header/-/digest-header-1.0.0.tgz#60227a57b55e5f0b023055a875111a247662189d" + integrity sha512-sRTuakZ2PkOUCuAaVv+SLjhr/hRf8ldZP0XnGEQ69RFGxmll5fVaMsnRXWKKK4XsUTnJf8+eRPSFNgE/lWa9wQ== dependencies: - utility "0.1.11" - -dom-walk@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" - integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + utility "^1.17.0" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1, ee-first@~1.1.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 sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: +elliptic@6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -978,10 +756,15 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +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== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== end-of-stream@^1.1.0: version "1.4.4" @@ -990,314 +773,105 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -es-abstract@^1.18.5: - version "1.18.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" - integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-string "^1.0.7" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== dependencies: - d "^1.0.1" - ext "^1.1.2" + es6-promise "^4.0.3" escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escodegen@^1.8.1: - version "1.14.3" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" - integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== - dependencies: - esprima "^4.0.1" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -esprima@^4.0.0, esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eth-ens-namehash@2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - -eth-lib@0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" - integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -eth-lib@^0.1.26: - version "0.1.29" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" - integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -ethereum-bloom-filters@^1.0.6: - version "1.0.10" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" - integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== - dependencies: - js-sha3 "^0.8.0" - -ethereum-cryptography@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" - integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== - dependencies: - "@types/pbkdf2" "^3.0.0" - "@types/secp256k1" "^4.0.1" - blakejs "^1.1.0" - browserify-aes "^1.2.0" - bs58check "^2.1.2" - create-hash "^1.2.0" - create-hmac "^1.1.7" - hash.js "^1.1.7" - keccak "^3.0.0" - pbkdf2 "^3.0.17" - randombytes "^2.1.0" - safe-buffer "^5.1.2" - scrypt-js "^3.0.0" - secp256k1 "^4.0.1" - setimmediate "^1.0.5" - -ethereumjs-common@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" - integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== - -ethereumjs-tx@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" - integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== - dependencies: - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.0.0" - -ethereumjs-util@^6.0.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.1.tgz#236ef435f46820f0c420a708c0559b5897952069" - integrity sha512-1CGBmCp3m8IMGHhAJF/icH8qjCJrfQtaZ9KW+cAVV8kyN5Lc1IRq3KjV77ILOutrCwiyf5y2gMyCrAUMoCf2Ag== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.4" - -ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23" - integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethereumjs-util@^7.1.4: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethereumjs-wallet@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz#2c000504b4c71e8f3782dabe1113d192522e99b6" - integrity sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA== - dependencies: - aes-js "^3.1.2" - bs58check "^2.1.2" - ethereum-cryptography "^0.1.3" - ethereumjs-util "^7.1.2" - randombytes "^2.1.0" - scrypt-js "^3.0.1" - utf8 "^3.0.0" - uuid "^8.3.2" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" - integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== - -express@^4.14.0: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +ethers@^5.7.0, ethers@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +express@^4.18.2: + 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.19.0" - content-disposition "0.5.3" + body-parser "1.20.1" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.0" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + 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.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" + proxy-addr "~2.0.7" + qs "6.11.0" range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" + 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" -ext@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" - integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== - dependencies: - type "^2.5.0" - extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" @@ -1309,12 +883,17 @@ extend@~3.0.2: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +eyes@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== fast-deep-equal@^3.1.1: version "3.1.3" @@ -1326,38 +905,33 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -file-uri-to-path@2: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba" - integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg== - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +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.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +follow-redirects@^1.12.1: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data-encoder@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" + integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A== form-data@~2.3.2: version "2.3.3" @@ -1368,7 +942,15 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -formstream@^1.1.0: +formdata-node@^4.3.3: + version "4.4.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" + integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.3" + +formstream@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/formstream/-/formstream-1.1.1.tgz#17259d2440c35ca9736db9f45fb3ba3f8669c750" integrity sha512-yHRxt3qLFnhsKAfhReM4w17jP+U1OlhUjnKPPtonwKbIJO7oBP0MvoxkRUwb8AU9n0MIkYy5X5dK6pQnbj+R2Q== @@ -1385,25 +967,18 @@ forwarded@0.2.0: fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== dependencies: graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" fs-minipass@^1.2.7: version "1.2.7" @@ -1415,7 +990,7 @@ fs-minipass@^1.2.7: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fstream@^1.0.0, fstream@^1.0.12: version "1.0.12" @@ -1427,14 +1002,6 @@ fstream@^1.0.0, fstream@^1.0.12: mkdirp ">=0.5 0" rimraf "2" -ftp@^0.3.10: - version "0.3.10" - resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d" - integrity sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0= - dependencies: - readable-stream "1.1.x" - xregexp "2.0.0" - function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -1443,7 +1010,7 @@ function-bind@^1.1.1: gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -1454,132 +1021,43 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== +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.1" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -get-uri@3: - version "3.0.2" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c" - integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg== - dependencies: - "@tootallnate/once" "1" - data-uri-to-buffer "3" - debug "4" - file-uri-to-path "2" - fs-extra "^8.1.0" - ftp "^0.3.10" + has-symbols "^1.0.3" getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" glob@^7.0.0, glob@^7.0.3, glob@^7.1.3: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + 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.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -global@~4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" - integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== - dependencies: - min-document "^2.19.0" - process "^0.11.10" - -got@9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -got@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== - -graceful-fs@^4.2.0: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" @@ -1589,39 +1067,15 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" +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-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== has@^1.0.3: version "1.0.3" @@ -1630,16 +1084,7 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -1650,103 +1095,40 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== +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 "~1.1.2" + depd "2.0.0" inherits "2.0.4" setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" + statuses "2.0.1" toidentifier "1.0.1" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= - -http-proxy-agent@^4.0.0, 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" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@5, https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - -humanize-ms@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= - dependencies: - ms "^2.0.0" - -iconv-lite@0.4.24, iconv-lite@^0.4.15, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.4: 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" -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== - dependencies: - punycode "2.1.0" - -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -1761,230 +1143,104 @@ ignore-walk@^3.0.1: inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + 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.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, 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 sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - 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== -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-core-module@^2.2.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" - integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== +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-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-function@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" - integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" +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-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= - -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - -is-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" - integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== - -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" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-stream@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.3, is-typed-array@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" - integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + 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 sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isomorphic-ws@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" - -js-sha3@0.5.7, js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= +jayson@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.0.0.tgz#145a0ced46f900934c9b307e1332bcb0c7dbdb17" + integrity sha512-v2RNpDCMu45fnLzSk47vx7I+QUaOsox6f5X0CUlabAFwxoP+8MfAY0NQRFwOEYXIxm8Ih5y6OaEa5KYiQMkyAA== + dependencies: + "@types/connect" "^3.4.33" + "@types/node" "^12.12.54" + "@types/ws" "^7.4.4" + JSONStream "^1.3.5" + commander "^2.20.3" + delay "^5.0.0" + es6-promisify "^5.0.0" + eyes "^0.1.8" + isomorphic-ws "^4.0.1" + json-stringify-safe "^5.0.1" + uuid "^8.3.2" + ws "^7.4.5" -js-sha3@^0.8.0: +js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== @@ -1992,129 +1248,83 @@ js-sha3@^0.8.0: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== 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@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== -json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== optionalDependencies: graceful-fs "^4.1.6" -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -keccak@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-db@1.49.0: - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== - -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.32" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== +mime-types@^2.1.12, mime-types@^2.1.35, mime-types@~2.1.19, 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.49.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" @@ -2126,18 +1336,6 @@ mime@^2.5.2: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= - dependencies: - dom-walk "^0.1.0" - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -2146,19 +1344,19 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@^3.0.4, 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" -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" @@ -2175,90 +1373,23 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= - dependencies: - mkdirp "*" - -mkdirp@*: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "^1.2.5" - -mock-fs@^4.1.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" - integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + minimist "^1.2.6" ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -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, ms@^2.1.1: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multibase@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" - integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multibase@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" - integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multicodec@^0.5.5: - version "0.5.7" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" - integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== - dependencies: - varint "^5.0.0" - -multicodec@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" - integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== - dependencies: - buffer "^5.6.0" - varint "^5.0.0" - -multihashes@^0.4.15, multihashes@~0.4.15: - version "0.4.21" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" - integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== - dependencies: - buffer "^5.5.0" - multibase "^0.7.0" - varint "^5.0.0" - mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -2269,14 +1400,9 @@ mz@^2.7.0: thenify-all "^1.0.0" nan@^2.14.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== needle@^2.2.1: version "2.9.1" @@ -2287,35 +1413,20 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -netmask@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" - integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +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== node-addon-api@^3.0.0: version "3.2.1" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== -node-gyp-build@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" - integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== +node-domexception@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== node-gyp@3.x: version "3.8.0" @@ -2354,7 +1465,7 @@ node-pre-gyp@^0.11.0: "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== dependencies: abbrev "1" @@ -2366,11 +1477,6 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - npm-bundled@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -2405,9 +1511,9 @@ npm-packlist@^1.1.6: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== -number-to-bn@1.7.0, number-to-bn@^1.7.0: +number-to-bn@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== @@ -2420,81 +1526,47 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -oboe@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" - integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= - dependencies: - http-https "^1.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== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +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" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== os-name@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/os-name/-/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf" - integrity sha1-GzefZINa98Wn9JizV8uVIVwVnt8= + integrity sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew== dependencies: osx-release "^1.0.0" win-release "^1.0.0" -os-tmpdir@^1.0.0: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== osenv@0, osenv@^0.1.4: version "0.1.5" @@ -2507,72 +1579,10 @@ osenv@0, osenv@^0.1.4: osx-release@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/osx-release/-/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c" - integrity sha1-8heRGigTaUmvG/kwiyQeJzfTzWw= + integrity sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A== dependencies: minimist "^1.1.0" -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= - dependencies: - p-finally "^1.0.0" - -pac-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz#b718f76475a6a5415c2efbe256c1c971c84f635e" - integrity sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - get-uri "3" - http-proxy-agent "^4.0.1" - https-proxy-agent "5" - pac-resolver "^5.0.0" - raw-body "^2.2.0" - socks-proxy-agent "5" - -pac-resolver@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-5.0.0.tgz#1d717a127b3d7a9407a16d6e1b012b13b9ba8dc0" - integrity sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA== - dependencies: - degenerator "^3.0.1" - ip "^1.1.5" - netmask "^2.0.1" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-headers@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" - integrity sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw== - parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -2581,9 +1591,9 @@ parseurl@~1.3.3: 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 sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-parse@^1.0.6: +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== @@ -2591,62 +1601,26 @@ path-parse@^1.0.6: 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 sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== pause-stream@~0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= + integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== dependencies: through "~2.3" -pbkdf2@^3.0.17, pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - 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" - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -printj@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" - integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== 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== -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -proxy-addr@~2.0.5: +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== @@ -2654,41 +1628,10 @@ proxy-addr@~2.0.5: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-5.0.0.tgz#d31405c10d6e8431fde96cba7a0c027ce01d633b" - integrity sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g== - dependencies: - agent-base "^6.0.0" - debug "4" - http-proxy-agent "^4.0.0" - https-proxy-agent "^5.0.0" - lru-cache "^5.1.1" - pac-proxy-agent "^5.0.0" - proxy-from-env "^1.0.0" - socks-proxy-agent "^5.0.0" - -proxy-from-env@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== pump@^3.0.0: version "3.0.0" @@ -2698,79 +1641,35 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= - punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -qs@^6.4.0: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== +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" qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, 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" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== 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.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -raw-body@^2.2.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" - integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== +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 "1.8.1" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" @@ -2784,16 +1683,6 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -readable-stream@1.1.x: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readable-stream@^2.0.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -2807,23 +1696,14 @@ readable-stream@^2.0.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== dependencies: resolve "^1.1.6" -request@^2.79.0, request@^2.87.0: +request@^2.87.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -2849,53 +1729,37 @@ request@^2.79.0, request@^2.87.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -resolve@^1.1.6: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" +require-from-string@^2.0.0: + 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== -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= +resolve@^1.1.6: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - lowercase-keys "^1.0.0" + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" -rimraf@2, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.2.3, rlp@^2.2.4: - version "2.2.6" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c" - integrity sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg== - dependencies: - bn.js "^4.11.1" +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +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.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, 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", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -2906,7 +1770,7 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scrypt-js@^3.0.0, scrypt-js@^3.0.1: +scrypt-js@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== @@ -2916,16 +1780,7 @@ scrypt-js@^3.0.0, scrypt-js@^3.0.1: dependencies: nan "^2.14.0" -secp256k1@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.2.tgz#15dd57d0f0b9fdb54ac1fa1694f40e5e9a54f4a1" - integrity sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg== - dependencies: - elliptic "^6.5.2" - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - -semver@^5.0.1, semver@^5.3.0: +semver@^5.0.1, semver@^5.3.0, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2933,76 +1788,47 @@ semver@^5.0.1, semver@^5.3.0: semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= + integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw== -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +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 "~1.1.2" - destroy "~1.0.4" + 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 "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-static@1.15.0, 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.17.1" - -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" + send "0.18.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 sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - sha3@2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/sha3/-/sha3-2.1.4.tgz#000fac0fe7c2feac1f48a25e7a31b52a6492cc8f" @@ -3029,50 +1855,24 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" - integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== - -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@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== - dependencies: - decompress-response "^3.3.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@5, socks-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz#032fb583048a29ebffec2e6a73fca0761f48177e" - integrity sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ== - dependencies: - agent-base "^6.0.2" - debug "4" - socks "^2.3.3" - -socks@^2.3.3: - version "2.6.2" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" - integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== - dependencies: - ip "^1.1.5" - smart-buffer "^4.2.0" - -source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + 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== + +solc@0.8.6: + version "0.8.6" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.6.tgz#e4341fa6780137df97b94a0cfbd59b3f2037d0e0" + integrity sha512-miiDaWdaUnD7A6Cktb/2ug9f+ajcOCDYRr7vgbPEsMoutSlBtp5rca57oMg8iHSuM7jilwdxePujWI/+rbNftQ== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" sqlite3@5.0.2: version "5.0.2" @@ -3085,9 +1885,9 @@ sqlite3@5.0.2: node-gyp "3.x" sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -3099,60 +1899,33 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -"statuses@>= 1.5.0 < 2", statuses@^1.3.1, statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +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== -strict-uri-encode@^1.0.0: +streamsearch@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -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== +"string-width@^1.0.2 || 2 || 3 || 4": + 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: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" string_decoder@~1.1.1: version "1.1.1" @@ -3164,45 +1937,33 @@ string_decoder@~1.1.1: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= +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 "^3.0.0" + ansi-regex "^5.0.1" strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== dependencies: is-hex-prefixed "1.0.0" strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -swarm-js@^0.1.40: - version "0.1.40" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" - integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +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== tar@^2.0.0: version "2.2.2" @@ -3213,7 +1974,7 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4, tar@^4.0.2: +tar@^4: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -3229,7 +1990,7 @@ tar@^4, tar@^4.0.2: thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== dependencies: thenify ">= 3.1.0 < 4" @@ -3240,25 +2001,17 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" -through@~2.3: +"through@>=2.2.7 <3", through@~2.3: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" toidentifier@1.0.1: version "1.0.1" @@ -3273,31 +2026,24 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -tslib@^2.0.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -type-is@~1.6.17, type-is@~1.6.18: +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== @@ -3305,37 +2051,12 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" - integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +undici@^5.6.0: + version "5.15.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.15.1.tgz#5292454b1441da486a80c0f3ada1e88f1765ff8d" + integrity sha512-XLk8g0WAngdvFqTI+VKfBtM4YWXgdxkf1WezC771Es0Dd+Pm1KmNx8t93WTC+Hh9tnghmVxkclU1HN+j+CvIUA== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" + busboy "^1.6.0" unescape@^1.0.1: version "1.0.1" @@ -3344,15 +2065,10 @@ unescape@^1.0.1: dependencies: extend-shallow "^2.0.1" -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - 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 sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== uri-js@^4.2.2: version "4.4.1" @@ -3361,88 +2077,27 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= - -urllib@2.38.0: - version "2.38.0" - resolved "https://registry.yarnpkg.com/urllib/-/urllib-2.38.0.tgz#5c0088f42091ef1cef07bb2547677487170414f5" - integrity sha512-8nim/hlS5GXtWe2BJ6usPimKx5VE3nenXgcG26ip5Ru+MKPddINH8uLpZ948n6ADhlus6A0AYj8xTYNmGQi8yA== +urllib@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/urllib/-/urllib-3.10.1.tgz#83d855773a9be67979dc5eb4674176e954779c1d" + integrity sha512-Ool8rFaHPEjLzZEFHcoemKitJomgDf1QgkX/38iuNbuiYCjJ/3NWVzpB8Gl43RNxFk6QyVGHocOwYxpg7yiU0w== dependencies: - any-promise "^1.3.0" - content-type "^1.0.2" - debug "^2.6.9" default-user-agent "^1.0.0" - digest-header "^0.0.1" - ee-first "~1.1.1" - formstream "^1.1.0" - humanize-ms "^1.2.0" - iconv-lite "^0.4.15" - ip "^1.1.5" - proxy-agent "^5.0.0" + digest-header "^1.0.0" + form-data-encoder "^1.7.2" + formdata-node "^4.3.3" + formstream "^1.1.1" + mime-types "^2.1.35" pump "^3.0.0" - qs "^6.4.0" - statuses "^1.3.1" - utility "^1.16.1" - -utf-8-validate@^5.0.2: - version "5.0.6" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.6.tgz#e1b3e0a5cc8648a3b44c1799fbb170d1aaaffe80" - integrity sha512-hoY0gOf9EkCw+nimK21FVKHUIG1BMqSiRwxB/q3A9yKZOrOI99PP77BxmarDqWz6rG3vVYiBWfhG8z2Tl+7fZA== - dependencies: - node-gyp-build "^4.2.0" - -utf8@3.0.0, utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + tslib "^2.4.0" + undici "^5.6.0" -util-deprecate@^1.0.1, 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 sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util@^0.12.0: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -utility@0.1.11: - version "0.1.11" - resolved "https://registry.yarnpkg.com/utility/-/utility-0.1.11.tgz#fde60cf9b4e4751947a0cf5d104ce29367226715" - integrity sha1-/eYM+bTkdRlHoM9dEEzik2ciZxU= - dependencies: - address ">=0.0.1" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -utility@^1.16.1: +utility@^1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/utility/-/utility-1.17.0.tgz#60819f712a6e0ce774f52fb1d691992a5f59d362" integrity sha512-KdVkF9An/0239BJ4+dqOa7NPrPIOeQE9AGfx0XS16O9DBiHNHRJMoeU5nL6pRGAkgJOqdOu8R4gBRcXnAocJKw== @@ -3456,312 +2111,41 @@ utility@^1.16.1: utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -uuid@8.3.2, 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== + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -varint@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" - integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== +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, vary@~1.1.2: +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + +vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -vm2@^3.9.3: - version "3.9.7" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.7.tgz#bb87aa677c97c61e23a6cb6547e44e990517a6f6" - integrity sha512-g/GZ7V0Mlmch3eDVOATvAXr1GsJNg6kQ5PjvYy3HbJMCRn5slNbo/u73Uy7r5yUej1cRa3ZjtoVwcWSQuQ/fow== - dependencies: - acorn "^8.7.0" - acorn-walk "^8.2.0" - -web3-bzz@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.1.tgz#8430eb3cbb69baaee4981d190b840748c37a9ec2" - integrity sha512-JbnFNbRlwwHJZPtVuCxo7rC4U4OTg+mPsyhjgPQJJhS0a6Y54OgVWYk9UA/95HqbmTJwTtX329gJoSsseEfrng== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - -web3-core-helpers@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.1.tgz#cb21047306871f4cf0fedfece7d47ea2aa96141b" - integrity sha512-om2PZvK1uoWcgMq6JfcSx3241LEIVF6qi2JuHz2SLKiKEW5UsBUaVx0mNCmcZaiuYQCyOsLS3r33q5AdM+v8ng== - dependencies: - web3-eth-iban "1.6.1" - web3-utils "1.6.1" - -web3-core-method@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.1.tgz#4ae91c639bf1da85ebfd8b99595da6a2235d7b98" - integrity sha512-szH5KyIWIaULQDBdDvevQUCHV9lsExJ/oV0ePqK+w015D2SdMPMuhii0WB+HCePaksWO+rr/GAypvV9g2T3N+w== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-utils "1.6.1" - -web3-core-promievent@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.1.tgz#f650dea9361e2edf02691015b213fcc8ea499992" - integrity sha512-byJ5s2MQxrWdXd27pWFmujfzsTZK4ik8rDgIV1RFDFc+rHZ2nZhq+VWk7t/Nkrj7EaVXncEgTdPEHc18nx+ocQ== - dependencies: - eventemitter3 "4.0.4" - -web3-core-requestmanager@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.1.tgz#d9c08b0716c9cda546a0c02767b7e08deb04448a" - integrity sha512-4y7etYEUtkfflyYVBfN1oJtCbVFNhNX1omlEYzezhTnPj3/dT7n+dhUXcqvIhx9iKA13unGfpFge80XNFfcB8A== - dependencies: - util "^0.12.0" - web3-core-helpers "1.6.1" - web3-providers-http "1.6.1" - web3-providers-ipc "1.6.1" - web3-providers-ws "1.6.1" - -web3-core-subscriptions@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.1.tgz#4dfc1f74137354d4ac9eaa628aa916c5e2cc8741" - integrity sha512-WZwxsYttIojyGQ5RqxuQcKg0IJdDCFpUe4EncS3QKZwxPqWzGmgyLwE0rm7tP+Ux1waJn5CUaaoSCBxWGSun1g== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - -web3-core@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.1.tgz#b41f08fdc9ea1082d15384a3d6fa93a47c3fc1b4" - integrity sha512-m+b7UfYvU5cQUAh6NRfxRzH/5B3to1AdEQi1HIQt570cDWlObOOmoO9tY6iJnI5w4acxIO19LqjDMqEJGBYyRQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-requestmanager "1.6.1" - web3-utils "1.6.1" - -web3-eth-abi@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.6.1.tgz#15b937e3188570754d50bbac51a4bb0578600d1d" - integrity sha512-svhYrAlXP9XQtV7poWKydwDJq2CaNLMtmKydNXoOBLcQec6yGMP+v20pgrxF2H6wyTK+Qy0E3/5ciPOqC/VuoQ== - dependencies: - "@ethersproject/abi" "5.0.7" - web3-utils "1.6.1" - -web3-eth-accounts@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.1.tgz#aeb0dfb52c4391773550569732975b471212583f" - integrity sha512-rGn3jwnuOKwaQRu4SiShz0YAQ87aVDBKs4HO43+XTCI1q1Y1jn3NOsG3BW9ZHaOckev4+zEyxze/Bsh2oEk24w== - dependencies: - "@ethereumjs/common" "^2.5.0" - "@ethereumjs/tx" "^3.3.2" - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-util "^7.0.10" - scrypt-js "^3.0.1" - uuid "3.3.2" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-eth-contract@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.1.tgz#4b0a2c0b37015d70146e54c7cb3f035a58fbeec0" - integrity sha512-GXqTe3mF6kpbOAakiNc7wtJ120/gpuKMTZjuGFKeeY8aobRLfbfgKzM9IpyqVZV2v5RLuGXDuurVN2KPgtu3hQ== - dependencies: - "@types/bn.js" "^4.11.5" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-utils "1.6.1" - -web3-eth-ens@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.1.tgz#801bd5fb5237377ec2ed8517a9fe4634f2269c7a" - integrity sha512-ngprtbnoRgxg8s1wXt9nXpD3h1P+p7XnKXrp/8GdFI9uDmrbSQPRfzBw86jdZgOmy78hAnWmrHI6pBInmgi2qQ== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-contract "1.6.1" - web3-utils "1.6.1" - -web3-eth-iban@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.1.tgz#20bbed75723e3e9ff98e624979629d26329462b6" - integrity sha512-91H0jXZnWlOoXmc13O9NuQzcjThnWyAHyDn5Yf7u6mmKOhpJSGF/OHlkbpXt1Y4v2eJdEPaVFa+6i8aRyagE7Q== - dependencies: - bn.js "^4.11.9" - web3-utils "1.6.1" - -web3-eth-personal@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.1.tgz#9b524fb9f92b51163f46920ee2663d34a4897c8d" - integrity sha512-ItsC89Ln02+irzJjK6ALcLrMZfbVUCqVbmb/ieDKJ+eLW3pNkBNwoUzaydh92d5NzxNZgNxuQWVdlFyYX2hkEw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-eth@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.1.tgz#a25aba1ac213d872ecf3f81c7b4ab8072ecae224" - integrity sha512-kOV1ZgCKypSo5BQyltRArS7ZC3bRpIKAxSgzl7pUFinUb/MxfbM9KGeNxUXoCfTSErcCQJaDjcS6bSre5EMKuQ== - dependencies: - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-accounts "1.6.1" - web3-eth-contract "1.6.1" - web3-eth-ens "1.6.1" - web3-eth-iban "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-net@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.1.tgz#7a630a804ec9f81908ae52ccbb4ebbb9530b3906" - integrity sha512-gpnqKEIwfUHh5ik7wsQFlCje1DfcmGv+Sk7LCh1hCqn++HEDQxJ/mZCrMo11ZZpZHCH7c87imdxTg96GJnRxDw== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-providers-http@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.1.tgz#b59b14eefef23b98c327806f5f566303a73bd435" - integrity sha512-xBoKOJxu10+kO3ikamXmBfrWZ/xpQOGy0ocdp7Y81B17En5TXELwlmMXt1UlIgWiyYDhjq4OwlH/VODYqHXy3A== - dependencies: - web3-core-helpers "1.6.1" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.1.tgz#7ba460589d46896bb3d124288deed1b6a72d517e" - integrity sha512-anyoIZlpMzwEQI4lwylTzDrHsVp20v0QUtSTp2B5jInBinmQtyCE7vnbX20jEQ4j5uPwfJabKNtoJsk6a3O4WQ== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.6.1" - -web3-providers-ws@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.1.tgz#f7ee71f158971102b865e99ea7911f483e0507e9" - integrity sha512-FWMEFYb4rYFYRgSFBf/O1Ex4p/YKSlN+JydCtdlJwRimd89qm95CTfs4xGjCskwvXMjV2sarH+f1NPwJXicYpg== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - websocket "^1.0.32" - -web3-shh@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.1.tgz#eebaab2e5e6be80fe2585c6c094fa10a03349ca7" - integrity sha512-oP00HbAtybLCGlLOZUYXOdeB9xq88k2l0TtStvKBtmFqRt+zVk5TxEeuOnVPRxNhcA2Un8RUw6FtvgZlWStu9A== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-net "1.6.1" - -web3-utils@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.6.1.tgz#befcb23922b00603ab56d8c5b4158468dc494aca" - integrity sha512-RidGKv5kOkcerI6jQqDFDoTllQQqV+rPhTzZHhmbqtFObbYpU93uc+yG1LHivRTQhA6llIx67iudc/vzisgO+w== - dependencies: - bn.js "^4.11.9" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - -web3@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.1.tgz#c9e68fe7b3073adddf35393441f950ec69b92735" - integrity sha512-c299lLiyb2/WOcxh7TinwvbATaMmrgNIeAzbLbmOKHI0LcwyfsB1eu2ReOIrfrCYDYRW2KAjYr7J7gHawqDNPQ== - dependencies: - web3-bzz "1.6.1" - web3-core "1.6.1" - web3-eth "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-shh "1.6.1" - web3-utils "1.6.1" - -websocket@^1.0.32: - version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" - integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - 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" - -which-typed-array@^1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" - integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.7" +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== which@1: version "1.3.1" @@ -3771,96 +2155,40 @@ which@1: isexe "^2.0.0" wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + 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" + string-width "^1.0.2 || 2 || 3 || 4" win-release@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209" - integrity sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk= + integrity sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw== dependencies: semver "^5.0.1" -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -ws@^8.6.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.9.0.tgz#2a994bb67144be1b53fe2d23c53c028adeb7f45e" - integrity sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg== - -xhr-request-promise@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" - integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== - dependencies: - xhr-request "^1.1.0" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -xhr-request@^1.0.1, xhr-request@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== - dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= - dependencies: - cookiejar "^2.1.1" - -xhr@^2.0.4, xhr@^2.3.3: - version "2.6.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" - integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== - dependencies: - global "~4.4.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xregexp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" - integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM= +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +ws@^7.4.5: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= +ws@^8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" + integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: +yallist@^3.0.0, yallist@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== diff --git a/audits/SKALE_Audit_Bramah.pdf b/audits/SKALE_Audit_Bramah.pdf new file mode 100644 index 000000000..66a9fbaf5 Binary files /dev/null and b/audits/SKALE_Audit_Bramah.pdf differ diff --git a/deployer/deployer.py b/deployer/deployer.py index 66d014958..fa713aeb6 100644 --- a/deployer/deployer.py +++ b/deployer/deployer.py @@ -19,7 +19,7 @@ # along with SKALE IMA. If not, see . import os -import time +from time import sleep from helper import get_random_endpoint, get_schain_creds_file, get_abi_filename, get_abi_project_path, \ get_schain_dir_path @@ -55,7 +55,7 @@ def copy_abi_on_nodes(schain_nodes, schain_name): cmd = f'scp -o StrictHostKeyChecking=no {abi_project_path} {node_user}@{node_ip}:{abi_path_on_node}/proxy.json' print(f'Uploading to {node_ip}...', '\n', cmd) os.system(cmd) - time.sleep(20) + sleep( 20 ) if __name__ == '__main__': diff --git a/docs/deployment.md b/docs/deployment.md index 28ab2e482..24d179e20 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -20,11 +20,11 @@ Deploy process includes: 3) Preliminary deployed **Skale Manager** software with known address of **ContractManager** smart contract saved into the `proxy/data/skaleManagerComponents.json` file like shown in the following example: - ```json - { - "contract_manager_address": "0xe89d660C1a4642C12A2846e8AF4d3F76c6BDbeF2" - } - ``` +```json +{ + "contract_manager_address": "0xe89d660C1a4642C12A2846e8AF4d3F76c6BDbeF2" +} +``` 4) `libBLS` command utilities @@ -379,8 +379,6 @@ node ./main.js --verbose=9 \ --nodes-count=value.............S-Chain nodes count. --time-framing=value............Specifies period(in seconds) for time framing. Zero means disable time framing. --time-gap=value................Specifies gap(in seconds) before next time frame. ---ptx...........................Enable pending transaction analysis to avoid transaction conflicts. ---no-ptx........................Disable pending transaction analysis. Not recommended for slow and overloaded blockchains. ``` #### S-Chain specific Configuration for Multi-node S-Chains diff --git a/npms/skale-cc/cc.js b/npms/skale-cc/cc.js deleted file mode 100644 index 10f5dc410..000000000 --- a/npms/skale-cc/cc.js +++ /dev/null @@ -1,811 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * SKALE IMA is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * SKALE IMA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with SKALE IMA. If not, see . - */ - -/** - * @file cc.js - * @copyright SKALE Labs 2019-Present - */ - -// const url = require( "url" ); - -let g_bEnabled = true; - -function replaceAll( str, find, replace ) { - return str.replace( new RegExp( find, "g" ), replace ); -} - -function toBoolean( value ) { - let b = false; - try { - if( typeof value === "boolean" ) - return value; - if( typeof value === "string" ) { - const ch = value[0].toLowerCase(); - if( ch == "y" || ch == "t" ) - b = true; else if( validateInteger( value ) ) - b = !!toInteger( value ); else if( validateFloat( value ) ) - b = !!toFloat( value ); else - b = !!b; - } else - b = !!b; - } catch ( err ) { - b = false; - } - b = !!b; - return b; -} - -function _yn_( flag ) { - if( !g_bEnabled ) - return flag; - return toBoolean( flag ) ? module.exports.yes( "yes" ) : module.exports.no( "no" ); -} - -function _tf_( flag ) { - if( !g_bEnabled ) - return flag; - return toBoolean( flag ) ? module.exports.yes( "true" ) : module.exports.no( "false" ); -} - -// function isInt( n ) { -// return !( ( Number( n ) === n && n % 1 === 0 ) ); -// } - -// function isFloat( n ) { -// return !( ( Number( n ) === n && n % 1 !== 0 ) ); -// } -const g_map_color_definitions = { - reset: "\x1b[0m", - enlight: "\x1b[1m", - dim: "\x1b[2m", - underscore: "\x1b[4m", - blink: "\x1b[5m", - reverse: "\x1b[7m", - hidden: "\x1b[8m", - fgBlack: "\x1b[30m", - fgRed: "\x1b[31m", - fgGreen: "\x1b[32m", - fgYellow: "\x1b[33m", - fgBlue: "\x1b[34m", - fgMagenta: "\x1b[35m", - fgCyan: "\x1b[36m", - fgWhite: "\x1b[37m", - bgBlack: "\x1b[40m", - bgRed: "\x1b[41m", - bgGreen: "\x1b[42m", - bgYellow: "\x1b[43m", - bgBlue: "\x1b[44m", - bgMagenta: "\x1b[45m", - bgCyan: "\x1b[46m", - bBgWhite: "\x1b[47m" -}; - -const g_arrRainbowParts = [ - g_map_color_definitions.enlight + g_map_color_definitions.fgRed, - g_map_color_definitions.fgRed, - g_map_color_definitions.enlight + g_map_color_definitions.fgYellow, - g_map_color_definitions.fgYellow, - g_map_color_definitions.enlight + g_map_color_definitions.fgGreen, - g_map_color_definitions.fgGreen, - g_map_color_definitions.enlight + g_map_color_definitions.fgCyan, - g_map_color_definitions.fgCyan, - g_map_color_definitions.enlight + g_map_color_definitions.fgBlue, - g_map_color_definitions.fgBlue, - g_map_color_definitions.enlight + g_map_color_definitions.fgMagenta, - g_map_color_definitions.fgMagenta -]; - -function raibow_part( s, i ) { - if( !g_bEnabled ) - return s; - const j = i % g_arrRainbowParts.length; - return g_arrRainbowParts[j] + s + g_map_color_definitions.reset; -} - -function rainbow( s ) { - if( ( !g_bEnabled ) || ( !s ) || ( typeof s != "string" ) || s.length == 0 ) - return s; - let res = ""; - const cnt = s.length; - for( let i = 0; i < cnt; ++ i ) - res = res + raibow_part( s[i], i ); - return res; -} - -function isInt2( n ) { - const intRegex = /^-?\d+$/; - if( !intRegex.test( n ) ) - return false; - - const intVal = parseInt( n, 10 ); - return parseFloat( n ) == intVal && !isNaN( intVal ); -} - -function isFloat2( n ) { - const val = parseFloat( n ); - return !isNaN( val ); -} - -// function url2str( objURL ) { -// const strProtocol = ( objURL.protocol && objURL.protocol.length > 0 ) ? ( "" + objURL.protocol + "//" ) : ""; -// let strUP = ""; -// const strHost = ( objURL.hostname && objURL.hostname.length > 0 ) ? ( "" + objURL.hostname.toString() ) : ""; -// const strPort = objURL.port ? ( ":" + objURL.port ) : ""; -// const strPath = ( objURL.pathname && objURL.pathname.length > 0 ) ? ( "" + objURL.pathname ) : ""; -// const strSearch = ( objURL.search && objURL.search.length > 0 ) ? ( "" + objURL.search ) : ""; -// if( objURL.username && objURL.username.length > 0 ) { -// strUP += "" + objURL.username; -// if( objURL.password && objURL.password.length > 0 ) { -// strUP += ":" + objURL.password; -// } -// strUP += "@"; -// } -// const strURL = "" + strProtocol + strUP + strHost + strPort + strPath + strSearch; -// return strURL; -// } - -function url_obj_colorized( objURL ) { - let strURL = ""; - if( !objURL ) - return strURL; - // if( objURL.strStrippedStringComma ) - // strURL += module.exports.normal(objURL.strStrippedStringComma); - if( objURL.protocol && objURL.protocol !== null && objURL.protocol !== undefined ) - strURL += "" + module.exports.yellow( objURL.protocol ) + module.exports.normal( "//" ); - if( objURL.username && objURL.username !== null && objURL.username !== undefined ) { - strURL += "" + module.exports.magenta( objURL.username ); - if( objURL.password && objURL.password !== null && objURL.password !== undefined ) - strURL += module.exports.normal( ":" ) + module.exports.yellow( objURL.password ); - strURL += module.exports.normal( "@" ); - } - if( objURL.hostname ) - strURL += "" + module.exports.magenta( log_arg_to_str_as_ipv4( objURL.hostname ) ); - if( objURL.port && objURL.port !== null && objURL.port !== undefined ) - strURL += module.exports.normal( ":" ) + log_arg_to_str( objURL.port ); - if( objURL.pathname && objURL.pathname !== null && objURL.pathname !== undefined && objURL.pathname !== "/" ) - strURL += "" + module.exports.yellow( replaceAll( objURL.pathname, "/", module.exports.normal( "/" ) ) ); - if( objURL.search && objURL.search !== null && objURL.search !== undefined ) - strURL += "" + module.exports.magenta( objURL.search ); - // if( objURL.strStrippedStringComma ) - // strURL += module.exports.normal(objURL.strStrippedStringComma); - return strURL; -} - -function url_str_colorized( s ) { - const objURL = safeURL( s ); - if( !objURL ) - return ""; - return url_obj_colorized( objURL ); -} - -function url_colorized( x ) { - if( typeof x === "string" || x instanceof String ) - return url_str_colorized( x ); - return url_obj_colorized( x ); -} - -// function url2strWithoutCredentials( objURL ) { -// const strProtocol = ( objURL.protocol && objURL.protocol.length > 0 ) ? ( "" + objURL.protocol + "//" ) : ""; -// const strUP = ""; -// const strHost = ( objURL.hostname && objURL.hostname.length > 0 ) ? ( "" + objURL.hostname.toString() ) : ""; -// const strPort = objURL.port ? ( ":" + objURL.port ) : ""; -// const strPath = ( objURL.pathname && objURL.pathname.length > 0 ) ? ( "" + objURL.pathname ) : ""; -// const strSearch = ( objURL.search && objURL.search.length > 0 ) ? ( "" + objURL.search ) : ""; -// const strURL = "" + strProtocol + strUP + strHost + strPort + strPath + strSearch; -// return strURL; -// } - -function safeURL( arg ) { - try { - const sc = arg[0]; - if( sc == "\"" || sc == "'" ) { - const cnt = arg.length; - if( arg[cnt - 1] == sc ) { - const ss = arg.substring( 1, cnt - 1 ); - const objURL = safeURL( ss ); - if( objURL != null && objURL != undefined ) - objURL.strStrippedStringComma = sc; - - return objURL; - } - return null; - } - const objURL = new URL( arg ); - if( !objURL.hostname ) - return null; - - if( objURL.hostname.length === 0 ) - return null; - - objURL.strStrippedStringComma = null; - return objURL; - } catch ( err ) { - return null; - } -} - -function to_ipv4_arr( s ) { - if( /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test( s ) ) { - const arr = s.split( "." ); - if( ( !arr ) || arr.length !== 4 ) - return null; - - return arr; - } - return null; -} - -function log_arg_to_str_as_ipv4( arg ) { - const arr = to_ipv4_arr( arg ); - if( !arr ) - return arg; - - let s = ""; - for( let i = 0; i < 4; ++i ) { - if( i > 0 ) - s += module.exports.normal( "." ); - - s += log_arg_to_str( arr[i] ); - } - return s; -} - -function log_arg_to_str() { - let i; - const cnt = arguments.length; - let s = ""; - for( i = 0; i < cnt; ++i ) { - const arg = arguments[i]; - if( arg === undefined ) { - s += "" + module.exports.undefval( arg ); - continue; - } - if( arg === null ) { - s += "" + module.exports.nullval( arg ); - continue; - } - if( isNaN( arg ) ) { - s += "" + module.exports.nanval( arg ); - continue; - } - if( typeof arg === "boolean" ) { - s += "" + _tf_( arg ); - continue; - } - if( typeof arg === "object" && typeof arg.valueOf() === "boolean" ) - s += "" + _tf_( arg.valueOf() ); - - if( typeof arg === "number" ) { - s += "" + module.exports.number( arg ); - continue; - } - if( typeof arg === "object" && typeof arg.valueOf() === "number" ) { - s += "" + module.exports.number( arg.valueOf() ); - continue; - } - // if( isNaN( arg ) ) { - // s += "" + module.exports.nanval( arg ); - // continue; - // } - if( typeof arg === "string" || arg instanceof String ) { - const objURL = safeURL( arg ); - if( objURL != null && objURL != undefined ) { - let strURL = ""; - if( objURL.strStrippedStringComma ) - strURL += module.exports.normal( objURL.strStrippedStringComma ); - - if( objURL.protocol ) - strURL += "" + module.exports.yellow( objURL.protocol ) + module.exports.normal( "//" ); - - if( objURL.username ) { - strURL += "" + module.exports.magenta( objURL.username ); - if( objURL.password ) - strURL += module.exports.normal( ":" ) + module.exports.yellow( objURL.password ); - - strURL += module.exports.normal( "@" ); - } - if( objURL.hostname ) - strURL += "" + module.exports.magenta( log_arg_to_str_as_ipv4( objURL.hostname ) ); - - if( objURL.port ) - strURL += module.exports.normal( ":" ) + log_arg_to_str( objURL.port ); - - if( objURL.pathname ) - strURL += "" + module.exports.yellow( replaceAll( objURL.pathname, "/", module.exports.normal( "/" ) ) ); - - if( objURL.search ) - strURL += "" + module.exports.magenta( objURL.search ); - - if( objURL.strStrippedStringComma ) - strURL += module.exports.normal( objURL.strStrippedStringComma ); - - s += strURL; - continue; - } - if( ( arg.length > 1 && arg[0] == "-" && arg[1] != "-" ) || - ( arg.length > 2 && arg[0] == "-" && arg[1] == "-" && arg[2] != "-" ) - ) { - s += "" + module.exports.cla( arg ); - continue; - } - if( arg.length > 0 && ( arg[0] == "\"" || arg[0] == "'" ) ) { - s += "" + module.exports.strval( arg ); - continue; - } - // if( isFloat( arg ) ) { - // s += "" + module.exports.real( arg ); - // continue; - // } - // if( isInt( arg ) ) { - // s += "" + module.exports.number( arg ); - // continue; - // } - if( isFloat2( arg ) ) { - s += "" + module.exports.real( arg ); - continue; - } - if( isInt2( arg ) ) { - s += "" + module.exports.number( arg ); - continue; - } - } - if( Array.isArray( arg ) || typeof arg === "object" ) { - // s += JSON.stringify(arg); - s += jsonColorizer.prettyPrintConsole( arg ); - continue; - } - s += "" + module.exports.kk( arg ); - } - return s; -} - -const getCircularReplacerForJsonStringify = () => { - const seen = new WeakSet(); - return ( key, value ) => { - if( typeof value === "object" && value !== null ) { - if( seen.has( value ) ) - return; - seen.add( value ); - } - return value; - }; -}; - -// Traverses a javascript object, and deletes all circular values -// @param source object to remove circular references from -// @param censoredMessage optional: what to put instead of censored values -// @param censorTheseItems should be kept null, used in recursion -// @returns {undefined} -// function preventCircularJson( source, censoredMessage, censorTheseItems ) { -// // init recursive value if this is the first call -// censorTheseItems = censorTheseItems || [source]; -// // default if none is specified -// censoredMessage = censoredMessage || "CIRCULAR_REFERENCE_REMOVED"; -// // values that have already appeared will be placed here: -// const recursiveItems = {}; -// // initialize a censored clone to return back -// const ret = {}; -// // traverse the object: -// for( const key in source ) { -// const value = source[key]; -// if( typeof value === "object" ) { -// // re-examine all complex children again later: -// recursiveItems[key] = value; -// } else { -// // simple values copied as is -// ret[key] = value; -// } -// } -// // create list of values to censor: -// const censorChildItems = []; -// for( const key in recursiveItems ) { -// const value = source[key]; -// // all complex child objects should not appear again in children: -// censorChildItems.push( value ); -// } -// // censor all circular values -// for( const key in recursiveItems ) { -// let value = source[key]; -// let censored = false; -// censorTheseItems.forEach( function( item ) { -// if( item === value ) { -// censored = true; -// } -// } ); -// if( censored ) { -// // change circular values to this -// value = censoredMessage; -// } else { -// // recursion: -// value = preventCircularJson( value, censoredMessage, censorChildItems.concat( censorTheseItems ) ); -// } -// ret[key] = value; -// } -// return ret; -// } - -const jsonColorizer = { // see http://jsfiddle.net/unLSJ/ - cntCensoredMax: 30000, // zero to disable censoring - censor: ( censor ) => { - let i = 0; - return ( key, value ) => { - if( i !== 0 && typeof ( censor ) === "object" && typeof ( value ) === "object" && censor == value ) - return "[Circular]"; - - if( i >= jsonColorizer.cntCensoredMax ) - return "[Unknown]"; - - ++i; // so we know we aren't using the original object anymore - return value; - }; - }, - replacerHTML: ( match, pIndent, pKey, pVal, pEnd ) => { - const key = ""; - const val = ""; - const str = ""; - let r = pIndent || ""; - if( pKey ) - r = r + key + pKey.replace( /[": ]/g, "" ) + ": "; - - if( pVal ) - r = r + ( pVal[0] == "\"" ? str : val ) + pVal + ""; - - return r + ( pEnd || "" ); - }, - prettyPrintHTML: ( obj ) => { - const jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg; - const s = - JSON.stringify( obj, ( jsonColorizer.cntCensoredMax > 0 ) ? jsonColorizer.censor( obj ) : null, 4 ) - .replace( /&/g, "&" ).replace( /\\"/g, """ ) - .replace( //g, ">" ) - .replace( jsonLine, jsonColorizer.replacerHTML ); - return s; - }, - replacerConsole: ( match, pIndent, pKey, pVal, pEnd ) => { - let r = pIndent || ""; - if( pKey ) - r = r + log_arg_to_str( pKey.replace( /[": ]/g, "" ) ) + ": "; - - if( pVal ) - r = r + log_arg_to_str( pVal ); - - return r + ( pEnd || "" ); - }, - prettyPrintConsole: ( obj ) => { - if( !g_bEnabled ) { - if( obj === null ) - return "null"; - if( obj === undefined ) - return "undefined"; - try { - const s = JSON.stringify( obj ); - return s; - } catch ( err ) { } - try { - const s = JSON.stringify( obj, getCircularReplacerForJsonStringify() ); - return s; - } catch ( err ) { } - try { - const s = obj.toString(); - return s; - } catch ( err ) { } - return obj; - } - const cntSpaces = 4; - const jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg; - try { - const tmp = JSON.stringify( obj, ( jsonColorizer.cntCensoredMax > 0 ) ? jsonColorizer.censor( obj ) : null, cntSpaces ); - const s = tmp ? tmp.replace( jsonLine, jsonColorizer.replacerConsole ) : ( "" + tmp ); - return s; - } catch ( err ) { } - obj = JSON.parse( JSON.stringify( obj, getCircularReplacerForJsonStringify() ) ); - const tmp = JSON.stringify( obj, ( jsonColorizer.cntCensoredMax > 0 ) ? jsonColorizer.censor( obj ) : null, cntSpaces ); - const s = tmp ? tmp.replace( jsonLine, jsonColorizer.replacerConsole ) : ( "" + tmp ); - return s; - } -}; - -// see: -// http://jsfiddle.net/KJQ9K/554 -// https://qastack.ru/programming/4810841/pretty-print-json-using-javascript -function syntaxHighlightJSON( jo, strKeyNamePrefix ) { - strKeyNamePrefix = strKeyNamePrefix || ""; - jo = jo.replace( /&/g, "&" ).replace( //g, ">" ); - return jo.replace( /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, function( match ) { - if( ! g_bEnabled ) - return match; - let cls = "number"; - if( /^"/.test( match ) ) { - if( /:$/.test( match ) ) - cls = "key"; - else - cls = "string"; - } else if( /true|false/.test( match ) ) - cls = "boolean"; - else if( /null/.test( match ) ) - cls = "null"; - else if( /NaN/.test( match ) ) - cls = "nan"; - else if( /undefined/.test( match ) ) - cls = "undefined"; - else if( ( typeof match === "string" || match instanceof String ) && - match.length >= 2 && - ( ( match[0] == "\"" && match[match.length - 1] == "\"" ) || - ( match[0] == "'" && match[match.length - 1] == "'" ) ) - ) - cls = "string"; - // return "" + match + ""; - switch ( cls ) { - case "key": - return "" + strKeyNamePrefix + log_arg_to_str( match.replace( /[": ]/g, "" ) ) + ": "; - case "boolean": - return _tf_( match ); - case "null": - return "" + module.exports.nullval( match ); - case "undefined": - return "" + module.exports.undefval( match ); - case "nan": - return "" + module.exports.nanval( match ); - case "string": - return "" + module.exports.strval( match ); - // case "number": - } - return log_arg_to_str( match ); - } ); -} - -function safeStringifyJSON( jo, n ) { - try { - const s = "" + JSON.stringify( jo, getCircularReplacerForJsonStringify(), n ); - return s; - } catch ( err ) { - } - return undefined; -} - -function jn( x ) { - return "" + jsonColorizer.prettyPrintConsole( x ); -} - -function j1( x, n, strKeyNamePrefix ) { - let isDefaultKeyNamePrefix = false; - if( typeof strKeyNamePrefix !== "string" ) { - strKeyNamePrefix = " "; - isDefaultKeyNamePrefix = true; - } - let s = safeStringifyJSON( x, n ); - if( ! g_bEnabled ) - return s; - s = "" + syntaxHighlightJSON( s, strKeyNamePrefix ); - if( isDefaultKeyNamePrefix && s.length > 9 && s[0] == " " ) - s = s.substring( 1, s.length ); - return s; -} - -module.exports = { - enable: function( b ) { - g_bEnabled = !!b; - }, - isEnabled: function() { - return !!g_bEnabled; - }, - safeStringifyJSON: safeStringifyJSON, - reset: g_map_color_definitions.reset, - enlight: g_map_color_definitions.enlight, - dim: g_map_color_definitions.dim, - underscore: g_map_color_definitions.underscore, - blink: g_map_color_definitions.blink, - reverse: g_map_color_definitions.reverse, - hidden: g_map_color_definitions.hidden, - fgBlack: g_map_color_definitions.fgBlack, - fgRed: g_map_color_definitions.fgRed, - fgGreen: g_map_color_definitions.fgGreen, - fgYellow: g_map_color_definitions.fgYellow, - fgBlue: g_map_color_definitions.fgBlue, - fgMagenta: g_map_color_definitions.fgMagenta, - fgCyan: g_map_color_definitions.fgCyan, - fgWhite: g_map_color_definitions.fgWhite, - bgBlack: g_map_color_definitions.bgBlack, - bgRed: g_map_color_definitions.bgRed, - bgGreen: g_map_color_definitions.bgGreen, - bgYellow: g_map_color_definitions.bgYellow, - bgBlue: g_map_color_definitions.bgBlue, - bgMagenta: g_map_color_definitions.bgMagenta, - bgCyan: g_map_color_definitions.bgCyan, - bBgWhite: g_map_color_definitions.bBgWhite, - normal: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgWhite + s + this.reset; - }, - trace: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgWhite + s + this.reset; - }, - debug: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgBlack + this.enlight + s + this.reset; - }, - note: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgBlue + s + this.reset; - }, - notice: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgMagenta + s + this.reset; - }, - info: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgBlue + this.enlight + s + this.reset; - }, - warning: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgYellow + s + this.reset; - }, - warn: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgYellow + s + this.reset; - }, - error: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgRed + s + this.reset; - }, - fatal: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.bgRed + this.fgYellow + this.enlight + s + this.reset; - }, - success: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgGreen + this.enlight + s + this.reset; - }, - attention: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgCyan + s + this.reset; - }, - bright: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgWhite + this.enlight + s + this.reset; - }, - sunny: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgYellow + this.enlight + s + this.reset; - }, - rx: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgMagenta + s + this.reset; - }, - rxa: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgMagenta + this.enlight + s + this.reset; - }, - tx: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgGreen + s + this.reset; - }, - txa: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgGreen + this.enlight + s + this.reset; - }, - date: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgYellow + s + this.reset; - }, - time: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgMagenta + this.enlight + s + this.reset; - }, - frac_time: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgMagenta + s + this.reset; - }, - yes: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgGreen + this.enlight + s + this.reset; - }, - no: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgBlue + s + this.reset; - }, - real: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgMagenta + s + this.reset; - }, - undefval: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgGreen + this.enlight + s + this.reset; - }, - nullval: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgGreen + this.enlight + s + this.reset; - }, - nanval: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgGreen + this.enlight + s + this.reset; - }, - yellow: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgYellow + s + this.reset; - }, - magenta: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgMagenta + s + this.reset; - }, - cla: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgBlue + this.dim + s + this.reset; - }, - kk: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgYellow + this.enlight + s + this.reset; - }, - strval: function( s ) { - if( !g_bEnabled ) - return s; - return "" + this.fgYellow + s + this.reset; - }, - jn: jn, - j1: j1, - j: j1, // jn - yn: function( x ) { - return _yn_( x ); - }, - tf: function( x ) { - return _tf_( x ); - }, - u: function( x ) { - return url_colorized( x ); - }, - rainbow: rainbow, - syntaxHighlightJSON: syntaxHighlightJSON, - safeURL: safeURL, - getCircularReplacerForJsonStringify: getCircularReplacerForJsonStringify, - toBoolean: toBoolean, - replaceAll: replaceAll -}; // module.exports diff --git a/npms/skale-cc/cc.mjs b/npms/skale-cc/cc.mjs new file mode 100644 index 000000000..87c105868 --- /dev/null +++ b/npms/skale-cc/cc.mjs @@ -0,0 +1,992 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file cc.mjs + * @copyright SKALE Labs 2019-Present + */ + +let gFlagIsEnabled = true; + +export function autoEnableFromCommandLineArgs() { + const b = + ( process.argv.indexOf( "--colors" ) >= 0 || process.argv.indexOf( "-colors" ) >= 0 ) + ? true : false; + enable( b ); +} + +export function enable( b ) { + gFlagIsEnabled = !!b; +} + +export function isEnabled() { + return !!gFlagIsEnabled; +} + +export function replaceAll( str, find, replace ) { + return str.replace( new RegExp( find, "g" ), replace ); +} + +export function validateRadix( value, radix ) { + value = "" + ( value ? value.toString() : "10" ); + value = value.trim(); + radix = ( radix == null || radix == undefined ) + ? ( ( value.length > 2 && value[0] == "0" && ( value[1] == "x" || value[1] == "X" ) ) + ? 16 : 10 ) + : parseInt( radix, 10 ); + return radix; +} + +export function validateInteger( value, radix ) { + try { + value = "" + value; + value = value.trim(); + if( value.length < 1 ) + return false; + radix = validateRadix( value, radix ); + if( ( !isNaN( value ) ) && + ( parseInt( Number( value ), radix ) == value || radix !== 10 ) && + ( !isNaN( parseInt( value, radix ) ) ) + ) + return true; + } catch ( err ) { + } + return false; +} + +export function toInteger( value, radix ) { + try { + radix = validateRadix( value, radix ); + if( !validateInteger( value, radix ) ) + return NaN; + return parseInt( value, radix ); + } catch ( err ) { + } + return false; +} + +export function validateFloat( value ) { + try { + const f = parseFloat( value ); + if( isNaN( f ) ) + return false; + return true; + } catch ( err ) { + } + return false; +} + +function toFloat( value ) { + try { + const f = parseFloat( value ); + return f; + } catch ( err ) { + } + return false; +} + +export function toBoolean( value ) { + let b = false; + try { + if( typeof value === "boolean" ) + return value; + if( typeof value === "string" ) { + const ch = value[0].toLowerCase(); + if( ch == "y" || ch == "t" ) + b = true; + else if( /^-?\d+$/.test( value ) ) // check string is integer + b = !!parseInt( value, 10 ); + else if( /^-?\d+(?:[.,]\d*?)?$/.test( value ) ) // check string is float + b = !!toFloat( value ); else + b = !!b; + } else + b = !!b; + } catch ( err ) { + b = false; + } + b = !!b; + return b; +} + +export function yn( flag ) { + if( !gFlagIsEnabled ) + return flag; + return toBoolean( flag ) ? yes( "yes" ) : no( "no" ); +} + +export function tf( flag ) { + if( !gFlagIsEnabled ) + return flag; + return toBoolean( flag ) ? yes( "true" ) : no( "false" ); +} + +export function onOff( flag ) { + if( !gFlagIsEnabled ) + return flag; + return toBoolean( flag ) ? yes( "on" ) : no( "off" ); +} +const gMapColorDefinitions = { + reset: "\x1b[0m", + enlight: "\x1b[1m", + dim: "\x1b[2m", + underscore: "\x1b[4m", + blink: "\x1b[5m", + reverse: "\x1b[7m", + hidden: "\x1b[8m", + fgBlack: "\x1b[30m", + fgRed: "\x1b[31m", + fgGreen: "\x1b[32m", + fgYellow: "\x1b[33m", + fgBlue: "\x1b[34m", + fgMagenta: "\x1b[35m", + fgCyan: "\x1b[36m", + fgWhite: "\x1b[37m", + bgBlack: "\x1b[40m", + bgRed: "\x1b[41m", + bgGreen: "\x1b[42m", + bgYellow: "\x1b[43m", + bgBlue: "\x1b[44m", + bgMagenta: "\x1b[45m", + bgCyan: "\x1b[46m", + bBgWhite: "\x1b[47m" +}; + +const gArrRainbowParts = [ + gMapColorDefinitions.enlight + gMapColorDefinitions.fgRed, + gMapColorDefinitions.fgRed, + gMapColorDefinitions.enlight + gMapColorDefinitions.fgYellow, + gMapColorDefinitions.fgYellow, + gMapColorDefinitions.enlight + gMapColorDefinitions.fgGreen, + gMapColorDefinitions.fgGreen, + gMapColorDefinitions.enlight + gMapColorDefinitions.fgCyan, + gMapColorDefinitions.fgCyan, + gMapColorDefinitions.enlight + gMapColorDefinitions.fgBlue, + gMapColorDefinitions.fgBlue, + gMapColorDefinitions.enlight + gMapColorDefinitions.fgMagenta, + gMapColorDefinitions.fgMagenta +]; + +export function rainbowPart( s, i ) { + if( !gFlagIsEnabled ) + return s; + const j = i % gArrRainbowParts.length; + return gArrRainbowParts[j] + s + gMapColorDefinitions.reset; +} + +export function rainbow( s ) { + if( ( !gFlagIsEnabled ) || ( !s ) || ( typeof s != "string" ) || s.length == 0 ) + return s; + let res = ""; + const cnt = s.length; + for( let i = 0; i < cnt; ++ i ) + res = res + rainbowPart( s[i], i ); + return res; +} + +export function isInt2( n ) { + const intRegex = /^-?\d+$/; + if( !intRegex.test( n ) ) + return false; + + const intVal = parseInt( n, 10 ); + return parseFloat( n ) == intVal && !isNaN( intVal ); +} + +export function isFloat2( n ) { + const val = parseFloat( n ); + return !isNaN( val ); +} + +function urlObjColorized( objURL ) { + let strURL = ""; + if( !objURL ) + return strURL; + if( objURL.protocol && objURL.protocol !== null && objURL.protocol !== undefined ) + strURL += "" + yellow( objURL.protocol ) + normal( "//" ); + if( objURL.username && objURL.username !== null && objURL.username !== undefined ) { + strURL += "" + magenta( objURL.username ); + if( objURL.password && objURL.password !== null && objURL.password !== undefined ) + strURL += normal( ":" ) + yellow( objURL.password ); + strURL += normal( "@" ); + } + if( objURL.hostname ) + strURL += "" + magenta( logArgToStringAsIpv4( objURL.hostname ) ); + if( objURL.port && objURL.port !== null && objURL.port !== undefined ) + strURL += normal( ":" ) + logArgToString( objURL.port ); + if( objURL.pathname && objURL.pathname !== null && + objURL.pathname !== undefined && objURL.pathname !== "/" ) + strURL += "" + yellow( replaceAll( objURL.pathname, "/", normal( "/" ) ) ); + if( objURL.search && objURL.search !== null && objURL.search !== undefined ) + strURL += "" + magenta( objURL.search ); + return strURL; +} + +export function urlStrColorized( s ) { + const objURL = safeURL( s ); + if( !objURL ) + return ""; + return urlObjColorized( objURL ); +} + +export function urlColorized( x ) { + if( typeof x === "string" || x instanceof String ) + return urlStrColorized( x ); + return urlObjColorized( x ); +} + +export function u( x ) { + return urlColorized( x ); +} + +export function safeURL( arg ) { + try { + const sc = arg[0]; + if( sc == "\"" || sc == "'" ) { + const cnt = arg.length; + if( arg[cnt - 1] == sc ) { + const ss = arg.substring( 1, cnt - 1 ); + const objURL = safeURL( ss ); + if( objURL != null && objURL != undefined ) + objURL.strStrippedStringComma = sc; + + return objURL; + } + return null; + } + const objURL = new URL( arg ); + if( !objURL.hostname ) + return null; + + if( objURL.hostname.length === 0 ) + return null; + + objURL.strStrippedStringComma = null; + return objURL; + } catch ( err ) { + return null; + } +} + +export function toIpv4Arr( s ) { + // eslint-disable-next-line max-len + if( /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test( s ) ) { + const arr = s.split( "." ); + if( ( !arr ) || arr.length !== 4 ) + return null; + + return arr; + } + return null; +} + +export function logArgToStringAsIpv4( arg ) { + const arr = toIpv4Arr( arg ); + if( !arr ) + return arg; + + let s = ""; + for( let i = 0; i < 4; ++i ) { + if( i > 0 ) + s += normal( "." ); + + s += logArgToString( arr[i] ); + } + return s; +} + +export function logArgToString() { + let i; + const cnt = arguments.length; + let s = ""; + for( i = 0; i < cnt; ++i ) { + const arg = arguments[i]; + if( arg === undefined ) { + s += "" + undefval( arg ); + continue; + } + if( arg === null ) { + s += "" + nullval( arg ); + continue; + } + if( isNaN( arg ) ) { + s += "" + nanval( arg ); + continue; + } + if( typeof arg === "boolean" ) { + s += "" + tf( arg ); + continue; + } + if( typeof arg === "object" && typeof arg.valueOf() === "boolean" ) + s += "" + tf( arg.valueOf() ); + + if( typeof arg === "number" ) { + s += "" + number( arg ); + continue; + } + if( typeof arg === "object" && typeof arg.valueOf() === "number" ) { + s += "" + number( arg.valueOf() ); + continue; + } + if( typeof arg === "string" || arg instanceof String ) { + const objURL = safeURL( arg ); + if( objURL != null && objURL != undefined ) { + let strURL = ""; + if( objURL.strStrippedStringComma ) + strURL += normal( objURL.strStrippedStringComma ); + + if( objURL.protocol ) + strURL += "" + yellow( objURL.protocol ) + normal( "//" ); + + if( objURL.username ) { + strURL += "" + magenta( objURL.username ); + if( objURL.password ) + strURL += normal( ":" ) + yellow( objURL.password ); + + strURL += normal( "@" ); + } + if( objURL.hostname ) + strURL += "" + magenta( logArgToStringAsIpv4( objURL.hostname ) ); + + if( objURL.port ) + strURL += normal( ":" ) + logArgToString( objURL.port ); + + if( objURL.pathname ) + strURL += "" + yellow( replaceAll( objURL.pathname, "/", normal( "/" ) ) ); + + if( objURL.search ) + strURL += "" + magenta( objURL.search ); + + if( objURL.strStrippedStringComma ) + strURL += normal( objURL.strStrippedStringComma ); + + s += strURL; + continue; + } + if( ( arg.length > 1 && arg[0] == "-" && arg[1] != "-" ) || + ( arg.length > 2 && arg[0] == "-" && arg[1] == "-" && arg[2] != "-" ) + ) { + s += "" + cla( arg ); + continue; + } + if( arg.length > 0 && ( arg[0] == "\"" || arg[0] == "'" ) ) { + s += "" + strval( arg ); + continue; + } + if( isFloat2( arg ) ) { + s += "" + real( arg ); + continue; + } + if( isInt2( arg ) ) { + s += "" + number( arg ); + continue; + } + } + if( Array.isArray( arg ) || typeof arg === "object" ) { + s += jsonColorizer.prettyPrintConsole( arg ); + continue; + } + s += "" + kk( arg ); + } + return s; +} + +export const getCircularReplacerForJsonStringify = () => { + const seen = new WeakSet(); + return ( key, value ) => { + if( typeof value === "object" && value !== null ) { + if( seen.has( value ) ) + return; + seen.add( value ); + } + return value; + }; +}; + +export const jsonColorizer = { // see http://jsfiddle.net/unLSJ/ + cntCensoredMax: 30000, // zero to disable censoring + censor: ( censor ) => { + let i = 0; + return ( key, value ) => { + if( i !== 0 && typeof ( censor ) === "object" && + typeof ( value ) === "object" && censor == value + ) + return "[Circular]"; + + if( i >= jsonColorizer.cntCensoredMax ) + return "[Unknown]"; + + ++i; // so we know we aren't using the original object anymore + return value; + }; + }, + replacerHTML: ( match, pIndent, pKey, pVal, pEnd ) => { + const key = ""; + const val = ""; + const str = ""; + let r = pIndent || ""; + if( pKey ) + r = r + key + pKey.replace( /[": ]/g, "" ) + ": "; + + if( pVal ) + r = r + ( pVal[0] == "\"" ? str : val ) + pVal + ""; + + return r + ( pEnd || "" ); + }, + prettyPrintHTML: ( obj ) => { + const jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg; + const s = + JSON.stringify( + obj, ( jsonColorizer.cntCensoredMax > 0 ) + ? jsonColorizer.censor( obj ) : null, 4 + ) + .replace( /&/g, "&" ).replace( /\\"/g, """ ) + .replace( //g, ">" ) + .replace( jsonLine, jsonColorizer.replacerHTML ); + return s; + }, + replacerConsole: ( match, pIndent, pKey, pVal, pEnd ) => { + let r = pIndent || ""; + if( pKey ) + r = r + logArgToString( pKey.replace( /[": ]/g, "" ) ) + ": "; + + if( pVal ) + r = r + logArgToString( pVal ); + + return r + ( pEnd || "" ); + }, + prettyPrintConsole: ( obj ) => { + if( !gFlagIsEnabled ) { + if( obj === null ) + return "null"; + if( obj === undefined ) + return "undefined"; + try { + const s = JSON.stringify( obj ); + return s; + } catch ( err ) { } + try { + const s = JSON.stringify( obj, getCircularReplacerForJsonStringify() ); + return s; + } catch ( err ) { } + try { + const s = obj.toString(); + return s; + } catch ( err ) { } + return obj; + } + const cntSpaces = 4; + const jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg; + try { + const tmp = JSON.stringify( + obj, + ( jsonColorizer.cntCensoredMax > 0 ) ? jsonColorizer.censor( obj ) : null, + cntSpaces + ); + const s = tmp ? tmp.replace( jsonLine, jsonColorizer.replacerConsole ) : ( "" + tmp ); + return s; + } catch ( err ) { } + obj = JSON.parse( JSON.stringify( obj, getCircularReplacerForJsonStringify() ) ); + const tmp = JSON.stringify( + obj, + ( jsonColorizer.cntCensoredMax > 0 ) ? jsonColorizer.censor( obj ) : null, + cntSpaces + ); + const s = tmp ? tmp.replace( jsonLine, jsonColorizer.replacerConsole ) : ( "" + tmp ); + return s; + } +}; + +// see: +// http://jsfiddle.net/KJQ9K/554 +// https://qastack.ru/programming/4810841/pretty-print-json-using-javascript +export function syntaxHighlightJSON( jo, strKeyNamePrefix ) { + strKeyNamePrefix = strKeyNamePrefix || ""; + jo = jo.replace( /&/g, "&" ).replace( //g, ">" ); + return jo.replace( + // eslint-disable-next-line max-len + /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, + function( match ) { + if( ! gFlagIsEnabled ) + return match; + let cls = "number"; + if( /^"/.test( match ) ) { + if( /:$/.test( match ) ) + cls = "key"; + else + cls = "string"; + } else if( /true|false/.test( match ) ) + cls = "boolean"; + else if( /null/.test( match ) ) + cls = "null"; + else if( /NaN/.test( match ) ) + cls = "nan"; + else if( /undefined/.test( match ) ) + cls = "undefined"; + else if( ( typeof match === "string" || match instanceof String ) && + match.length >= 2 && + ( ( match[0] == "\"" && match[match.length - 1] == "\"" ) || + ( match[0] == "'" && match[match.length - 1] == "'" ) ) + ) + cls = "string"; + switch ( cls ) { + case "key": + return "" + + strKeyNamePrefix + logArgToString( match.replace( /[": ]/g, "" ) ) + ": "; + case "boolean": + return tf( match ); + case "null": + return "" + nullval( match ); + case "undefined": + return "" + undefval( match ); + case "nan": + return "" + nanval( match ); + case "string": + return "" + strval( match ); + // case "number": + } + return logArgToString( match ); + } ); +} + +export function safeStringifyJSON( jo, n ) { + try { + const s = "" + JSON.stringify( jo, getCircularReplacerForJsonStringify(), n ); + return s; + } catch ( err ) { + } + return undefined; +} + +export function jn( x ) { + return "" + jsonColorizer.prettyPrintConsole( x ); +} + +export function j1( x, n, strKeyNamePrefix ) { + let isDefaultKeyNamePrefix = false; + if( typeof strKeyNamePrefix !== "string" ) { + strKeyNamePrefix = " "; + isDefaultKeyNamePrefix = true; + } + let s = safeStringifyJSON( x, n ); + if( ! gFlagIsEnabled ) + return s; + s = "" + syntaxHighlightJSON( s, strKeyNamePrefix ); + if( isDefaultKeyNamePrefix && s.length > 9 && s[0] == " " ) + s = s.substring( 1, s.length ); + return s; +} + +export function j( x ) { + return j1( x ); // jn +} + +const reset = gMapColorDefinitions.reset; +const enlight = gMapColorDefinitions.enlight; +const dim = gMapColorDefinitions.dim; +const underscore = gMapColorDefinitions.underscore; +const blink = gMapColorDefinitions.blink; +const reverse = gMapColorDefinitions.reverse; +const hidden = gMapColorDefinitions.hidden; +const fgBlack = gMapColorDefinitions.fgBlack; +const fgRed = gMapColorDefinitions.fgRed; +const fgGreen = gMapColorDefinitions.fgGreen; +const fgYellow = gMapColorDefinitions.fgYellow; +const fgBlue = gMapColorDefinitions.fgBlue; +const fgMagenta = gMapColorDefinitions.fgMagenta; +const fgCyan = gMapColorDefinitions.fgCyan; +const fgWhite = gMapColorDefinitions.fgWhite; +const bgBlack = gMapColorDefinitions.bgBlack; +const bgRed = gMapColorDefinitions.bgRed; +const bgGreen = gMapColorDefinitions.bgGreen; +const bgYellow = gMapColorDefinitions.bgYellow; +const bgBlue = gMapColorDefinitions.bgBlue; +const bgMagenta = gMapColorDefinitions.bgMagenta; +const bgCyan = gMapColorDefinitions.bgCyan; +const bBgWhite = gMapColorDefinitions.bBgWhite; +export { + reset, + enlight, + dim, + underscore, + blink, + reverse, + hidden, + fgBlack, + fgRed, + fgGreen, + fgYellow, + fgBlue, + fgMagenta, + fgCyan, + fgWhite, + bgBlack, + bgRed, + bgGreen, + bgYellow, + bgBlue, + bgMagenta, + bgCyan, + bBgWhite +}; + +export function normal( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgWhite + s + reset; +} + +export function trace( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgWhite + s + reset; +} + +export function debug( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgBlack + enlight + s + reset; +} + +export function note( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgBlue + s + reset; +} + +export function notice( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgMagenta + s + reset; +} + +export function info( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgBlue + enlight + s + reset; +} + +export function warning( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgYellow + s + reset; +} + +export function warn( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgYellow + s + reset; +} + +export function error( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgRed + s + reset; +} + +export function fatal( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + bgRed + fgYellow + enlight + s + reset; +} + +export function success( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgGreen + enlight + s + reset; +} + +export function attention( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgCyan + s + reset; +} + +export function bright( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgWhite + enlight + s + reset; +} + +export function sunny( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgYellow + enlight + s + reset; +} + +export function rx( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgMagenta + s + reset; +} + +export function rxa( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgMagenta + enlight + s + reset; +} + +export function tx( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgGreen + s + reset; +} + +export function txa( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgGreen + enlight + s + reset; +} + +export function date( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgYellow + s + reset; +} + +export function time( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgMagenta + enlight + s + reset; +} + +export function frac_time( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgMagenta + s + reset; +} + +export function yes( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgGreen + enlight + s + reset; +} + +export function no( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgBlue + s + reset; +} + +export function real( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgMagenta + s + reset; +} + +export function undefval( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgGreen + enlight + s + reset; +} + +export function nullval( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgGreen + enlight + s + reset; +} + +export function nanval( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgGreen + enlight + s + reset; +} + +export function yellow( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgYellow + s + reset; +} + +export function magenta( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgMagenta + s + reset; +} + +export function cla( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgBlue + dim + s + reset; +} + +export function kk( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgYellow + enlight + s + reset; +} + +export function strval( s ) { + if( !gFlagIsEnabled ) + return s; + return "" + fgYellow + s + reset; +} + +export function n2s( n, sz ) { + let s = "" + n; + while( s.length < sz ) + s = "0" + s; + return s; +} + +export function timestampHR() { + const d = new Date(); + const ts = Math.floor( ( d ).getTime() ); + return ts; +} + +export function timestampUnix() { + const d = new Date(); + const ts = Math.floor( ( d ).getTime() / 1000 ); + return ts; +} + +function trimLeftUnneededTimestampZeros( s ) { + while( s.length >= 2 ) { + if( s[0] == "0" && s[1] >= "0" && s[1] <= "9" ) + s = s.substring( 1 ); + else + break; + } + return s; +} + +export function getDurationString( tsFrom, tsTo ) { + let s = ""; + let n = tsTo - tsFrom; + + const ms = n % 1000; + n = Math.floor( n / 1000 ); + s += "." + n2s( ms, 3 ); + if( n == 0 ) + return "0" + s; + + const secs = n % 60; + n = Math.floor( n / 60 ); + s = "" + n2s( secs, 2 ) + s; + if( n == 0 ) + return trimLeftUnneededTimestampZeros( s ); + s = ":" + s; + + const mins = n % 60; + n = Math.floor( n / 60 ); + s = "" + n2s( mins, 2 ) + s; + if( n == 0 ) + return trimLeftUnneededTimestampZeros( s ); + s = ":" + s; + + const hours = n % 24; + n = Math.floor( n / 24 ); + s = "" + n2s( hours, 2 ) + s; + if( n == 0 ) + return trimLeftUnneededTimestampZeros( s ); + + return "" + n + " " + ( ( n > 1 ) ? "days" : "day" ) + "," + s; +} + +export function capitalizeFirstLetter( s ) { + if( ! s ) + return s; + let s2 = s.toString(); + if( ! s2 ) + return s; + s2 = s2.charAt( 0 ).toUpperCase() + s2.slice( 1 ); + return s2; +} + +function errFnDottedName( s ) { + const arr = s.split( "." ); + const cnt = arr.length; + let i, s2 = ""; + for( i = 0; i < cnt; ++ i ) { + if( i > 0 ) + s2 += bright( "." ); + s2 += sunny( arr[i] ); + } + return s2; +} + +function errFnName( s ) { + if( s.indexOf( "async " ) == 0 ) + return bright( "async" ) + " " + errFnDottedName( s.substring( 6 ) ); + return errFnDottedName( s ); +} + +function errLocLn( s, isWithBraces ) { + let s2 = ""; + s = s.replace( "file://", "" ); + s = s.replace( "node:", "" ); + if( isWithBraces ) + s2 += " " + debug( "(" ); + const arrCodePoint = s.split( ":" ); + if( arrCodePoint.length > 0 ) { + s2 += trace( arrCodePoint[0] ); + for( let j = 1; j < arrCodePoint.length; ++j ) { + s2 += debug( ":" ); + if( j == 1 ) + s2 += info( arrCodePoint[j] ); + else + s2 += notice( arrCodePoint[j] ); + } + } else + s2 += trace( s ); + if( isWithBraces ) + s2 += debug( ")" ); + return s2; +} + +export function stack( strIn ) { + if( ! strIn ) + return strIn; + try { + const arr = ( typeof strIn == "string" ) ? strIn.split( "\n" ) : strIn; + const cnt = arr.length; + let i; + for( i = 0; i < cnt; ++ i ) { + let s = arr[i].replace( /\s+/g, " " ).trim(); + if( s.indexOf( "at " ) == 0 ) { + // stack entry + s = s.substring( 3 ); + let s2 = " " + debug( "-->" ) + " "; + const n = s.indexOf( " (" ); + if( n > 0 ) { + s2 += errFnName( s.substring( 0, n ) ); + s = s.substring( n + 2 ); + if( s[s.length - 1] == ")" ) + s = s.substring( 0, s.length - 1 ); + s2 += errLocLn( s, true ); + } else + s2 += errLocLn( s, false ); + s = s2; + } else { + // probably error description line + const n = s.indexOf( ":" ); + if( n >= 0 ) { + s = error( + s.substring( 0, n ) ) + normal( ":" ) + warning( s.substring( n + 1 ) ); + } else + s = error( s ); + } + arr[i] = s; + } + return arr.join( "\n" ); + } catch ( err ) { + return strIn; + } +} diff --git a/npms/skale-cool-socket/.eslintrc.js b/npms/skale-cool-socket/.eslintrc.js deleted file mode 100644 index a2a8d690f..000000000 --- a/npms/skale-cool-socket/.eslintrc.js +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE COOL SOCKET - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file .eslintrc.js - * @copyright SKALE Labs 2019-Present - */ - -module.exports = { - "env": { - "browser": true, - "es6": true - }, - "extends": "standard", - "globals": { - "Atomics": "readonly", - "SharedArrayBuffer": "readonly" - }, - "parserOptions": { - "ecmaVersion": 2018, - "sourceType": "module" - }, - "rules": { - "indent": [ "error", 4 ], - "linebreak-style": [ "error", "unix" ], - "quotes": [ "error", "double" ], - "semi": [ "error", "always" ], - "camelcase": "off", - // "no-unused-vars": "off", - "eqeqeq": "off", - "comma-dangle": [ "error", "never" ], - "comma-style": [ "error", "last" ], - "comma-spacing": "off", - "space-before-function-paren": [ "error", "never" ], - "space-in-parens": [ "error", "always" ], - "keyword-spacing": [ "error", { - "overrides": { - "if": { - "before": false, - "after": false - }, - "else": { - "before": true, - "after": true - }, - "for": { - "before": false, - "after": false - }, - "while": { - "before": false, - "after": false - } - } - } ], - "space-before-blocks": [ "error", "always" ], - "array-bracket-spacing": [ "error", "always" ], - "object-curly-spacing": [ "error", "always" ], - "space-unary-ops": "off", - "spaced-comment": "off", - "curly": [ "error", "multi-or-nest" ], - "nonblock-statement-body-position": [ "error", "below" ], - "one-var": "off", - "no-unneeded-ternary": "off", - "no-cond-assign": [ "error", "always" ], - "no-console": "off", - "new-cap": "off", - "no-tabs": "off", - "no-mixed-spaces-and-tabs": "off", - "no-prototype-builtins": "off", - "quote-props": "off", - "no-undef": "off", - "no-useless-return": "off", - "no-new": "off", - "no-useless-constructor": "off", - "no-lone-blocks": "off", - "no-fallthrough": "off", - "no-useless-catch": "off", - "padded-blocks": "off", - "no-use-before-define": "off", // [ "error", { "variables": false, "functions": false } ], - "lines-between-class-members": [ "error", "never" ], - "no-var": "error", - "no-unused-vars": "error" - } -}; diff --git a/npms/skale-cool-socket/event_dispatcher.js b/npms/skale-cool-socket/eventDispatcher.mjs similarity index 81% rename from npms/skale-cool-socket/event_dispatcher.js rename to npms/skale-cool-socket/eventDispatcher.mjs index 43e9e5f30..c28e5965a 100644 --- a/npms/skale-cool-socket/event_dispatcher.js +++ b/npms/skale-cool-socket/eventDispatcher.mjs @@ -19,11 +19,11 @@ */ /** - * @file event_dispatcher.js + * @file eventDispatcher.mjs * @copyright SKALE Labs 2019-Present */ -class UniversalDispatcherEvent { +export class UniversalDispatcherEvent { constructor( type, jo ) { this.type = type; for( const [ key, value ] of Object.entries( jo ) ) { @@ -36,7 +36,7 @@ class UniversalDispatcherEvent { } }; -class EventDispatcher { +export class EventDispatcher { // see https://stackoverflow.com/questions/36675693/eventtarget-interface-in-safari constructor() { this._listeners = []; @@ -48,7 +48,9 @@ class EventDispatcher { return; this.isDisposing = true; this.isDisposed = true; - this.dispatchEvent( new UniversalDispatcherEvent( "dispose", { detail: { ref: this } } ) ); + this.dispatchEvent( + new UniversalDispatcherEvent( "dispose", { "detail": { "ref": this } } ) + ); this.removeAllEventListeners(); } hasEventListener( type, listener ) { @@ -62,21 +64,21 @@ class EventDispatcher { options: { once: false } } ); } - // console.log( `${this}-listeners:`,this._listeners ); return this; } removeEventListener( type, listener ) { while( true ) { const index = ( listener != undefined ) - ? this._listeners.findIndex( item => item.type === type && item.listener === listener ) - : this._listeners.findIndex( item => item.type === type ); + ? this._listeners.findIndex( + item => item.type === type && item.listener === listener ) + : this._listeners.findIndex( + item => item.type === type ); if( index >= 0 ) { this._listeners.splice( index, 1 ); continue; } break; } - // console.log( `${this}-listeners:`, this._listeners ); return this; } removeAllEventListeners() { @@ -104,12 +106,6 @@ class EventDispatcher { if( once === true ) this.removeEventListener( type, listener ); } - // console.log( `${this}-listeners:`,this._listeners ); return this; } }; - -module.exports = { - UniversalDispatcherEvent: UniversalDispatcherEvent, - EventDispatcher: EventDispatcher -}; diff --git a/npms/skale-cool-socket/package.json b/npms/skale-cool-socket/package.json index e05e2f54a..9b3b44f41 100644 --- a/npms/skale-cool-socket/package.json +++ b/npms/skale-cool-socket/package.json @@ -6,9 +6,10 @@ "license": "AGPL-3.0", "author": "SKALE Labs and contributors", "scripts": { - "lint-check": "eslint *.js", - "lint-fix": "eslint ./*.js --fix", - "test": "echo \"Error: no test specified\" && exit 1" + "lint-check": "eslint *.*js", + "lint-fix": "eslint ./*.*js --fix", + "check-outdated": "yarn outdated", + "upgrade-to-latest": "yarn upgrade --latest" }, "keywords": [ "cool", @@ -21,8 +22,8 @@ ], "dependencies": { "connect": "^3.7.0", - "serve-static": "^1.14.1", - "ws": "^8.6.0" + "serve-static": "^1.15.0", + "ws": "^8.12.0" }, "devDependencies": { "eslint": "^6.8.0", diff --git a/npms/skale-cool-socket/socket.js b/npms/skale-cool-socket/socket.js deleted file mode 100644 index 6b2df9dd7..000000000 --- a/npms/skale-cool-socket/socket.js +++ /dev/null @@ -1,2703 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE COOL SOCKET - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file socket.js - * @copyright SKALE Labs 2019-Present - */ - -const { UniversalDispatcherEvent, EventDispatcher } = require( "./event_dispatcher.js" ); -const { settings } = require( "./settings.js" ); -const utils = require( "./utils.js" ); - -let https_mod = null; // server side only -let ws_mod = null; // server side only -let wrtc_mod = null; // server side only - -// if( typeof window == "undefined" ) { -// try { -// https_mod = require( "https" ); -// console.log( "Using pre-loaded HTTPS API in socket.js" ); -// } catch ( err ) { -// } -// try { -// ws_mod = WebSocket; -// console.log( "Using pre-loaded WebSocket API in socket.js" ); -// } catch ( err ) { -// } -// } else { -// try { -// wrtc_mod = window; -// console.log( "Using pre-loaded WebSocket API in socket.js" ); -// } catch ( err ) { -// } -// } - -// needed to init from outside: import * as https_loaded_mod from "https"; -// const https_mod = https_loaded_mod.default; -// needed to init from outside: import * as ws_loaded_mod from "ws"; -// const ws_mod = ws_loaded_mod.default; - -function set_https_mod( mod ) { - https_mod = mod ? mod : null; -} -function set_ws_mod( mod ) { - ws_mod = mod ? mod : null; -} -function set_wrtc_mod( mod ) { - wrtc_mod = mod ? mod : null; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const g_mapLocalServers = { }; // used both for local and in-worker servers - -const socket_sent_data_marshall = function( data ) { - const s = data - ? ( ( typeof data == "string" ) - ? data - : ( ( typeof data == "object" ) ? JSON.stringify( data ) : data.toString() ) - ) - : ""; - return s; -}; -const socket_received_data_reverse_marshall = function( data ) { - try { - const jo = data - ? ( ( typeof data == "object" ) - ? data - : ( ( typeof data == "string" ) ? JSON.parse( data ) : data ) - ) - : { }; - return jo; - } catch ( err ) { - return { - error: true, - message: "data un-marshal error", - data: data - }; - } -}; - -const update_socket_data_stats_for_message = function( joMessage, joStats ) { - let strMethod = "_N/A_"; - if( "method" in joMessage && - joMessage.method && - typeof joMessage.method == "string" - ) - strMethod = "" + joMessage.method; - if( strMethod in joStats ) - joStats[strMethod] ++; - else - joStats[strMethod] = 1; -}; -const generate_socket_data_stats_JSON = function( jo ) { - const joStats = {}; - //let cnt = 1; - if( "arr_packed_messages" in jo && - jo.arr_packed_messages && - typeof jo.arr_packed_messages == "object" - ) { - //cnt = jo.arr_packed_messages.length; - for( const joMessage of jo.arr_packed_messages ) - update_socket_data_stats_for_message( joMessage, joStats ); - - } else - update_socket_data_stats_for_message( jo, joStats ); - //joStats["_cnt_"] = cnt; - return joStats; -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class BasicServerAcceptor extends EventDispatcher { - constructor() { - super(); - this.socketType = "BasicAcceptor"; - this.socketSubtype = "acceptor"; - this.isListening = false; - this.strEndPoint = null; - this.nextClientNumber = 1; - this.mapClients = { }; - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.nextClientNumber = 1; - this.isListening = false; - this.disposeNotifyClients(); - super.dispose(); - } - disposeNotifyClients() { - for( const [ /*key*/, entry ] of Object.entries( this.mapClients ) ) { - if( ( "serverPipe" in entry ) && ( "clientPipe" in entry ) ) { - const pair = entry; - pair.serverPipe.handleServerDisposed(); - pair.clientPipe.handleServerDisposed(); - pair.serverPipe = null; - pair.clientPipe = null; - } else { - const pipe = entry; - pipe.handleServerDisposed(); - } - } - this.mapClients = { }; - } - unregisterClientByKey( key ) { - if( key in this.mapClients ) { - const entry = this.mapClients[key]; - if( entry ) { - if( ( "serverPipe" in entry ) && ( "clientPipe" in entry ) ) { - const pair = entry; - pair.serverPipe = null; - pair.clientPipe = null; - } - delete this.mapClients[key]; - } - } - } - flush() { - if( this.isDisposing || this.isDisposed ) - return; - for( const [ /*key*/, entry ] of Object.entries( this.mapClients ) ) { - if( ( "serverPipe" in entry ) && ( "clientPipe" in entry ) ) { - const pair = entry; - pair.serverPipe.flush(); - } else { - const pipe = entry; - pipe.flush(); - } - } - } - newDirectConnection() { - if( this.isDisposing || this.isDisposed ) - return null; - if( !this.isListening ) - return null; - const clientPipe = new DirectPipe( null, false ); - const serverPipe = new DirectPipe( clientPipe, false ); - serverPipe.acceptor = this; - this.mapClients["" + serverPipe.clientPort] = serverPipe; - const self = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - serverPipe.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: serverPipe } ) ); - self.dispatchEvent( new UniversalDispatcherEvent( "connection", { socket: serverPipe, remoteAddress: "" + self.url } ) ); - clientPipe.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: clientPipe } ) ); - }, 0 ); - return clientPipe; - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class BasicSocketPipe extends EventDispatcher { - constructor() { - super(); - this.socketType = "N/A"; - this.socketSubtype = "N/A"; - this.url = "N/A"; - this.isConnected = true; - this.arr_accumulated_messages = []; - this.maxAccumulatedMessagesCount = 0 + settings.net.pipe.maxAccumulatedMessagesCount; - this.relayClientSocket = null; // for relay only - this.mapImpersonatedEntries = { }; // for external in-app usage only - } - dispose() { - if( this.relayClientSocket ) { - this.relayClientSocket.dispose(); - this.relayClientSocket = null; - } - this.disposeImpersonatedEntries(); // for external in-app usage only - this.disconnect(); - this.arr_accumulated_messages = []; - super.dispose(); - } - disposeImpersonatedEntries() { // for external in-app usage only - for( const [ /*key*/, entry ] of Object.entries( this.mapImpersonatedEntries ) ) { - try { - if( entry && "dispose" in entry && typeof entry.dispose == "function" ) - entry.dispose(); - } catch ( err ) { - } - } - this.mapImpersonatedEntries = { }; // for app usage - } - impl_send( data ) { - throw new Error( "BasicSocketPipe.impl_send() must be overridden but calling it was attempted" ); - } - is_auto_flush() { - if( this.maxAccumulatedMessagesCount <= 1 ) - return true; - const cnt = this.arr_accumulated_messages.length; - if( cnt == 0 || cnt < this.maxAccumulatedMessagesCount ) - return false; - return true; - } - socketDescription() { - return "" + - // + this.socketType - // + " " - // + this.socketSubtype - // + " " - this.url; - } - socketLoggingTextPrefix( strLogEventName ) { - return "" + strLogEventName + " " + this.socketDescription() + " -"; - } - send( data, isFlush ) { - if( this.isDisposed || ( !this.isConnected ) ) - return; - if( this.is_auto_flush() ) { - if( settings.logging.net.socket.send || settings.logging.net.socket.flush ) - console.log( this.socketLoggingTextPrefix( "send+flush" ), data ); - this.impl_send( data ); - return; - } - isFlush = ( isFlush == undefined || isFlush == null ) ? true : ( isFlush ? true : false ); - const jo = socket_received_data_reverse_marshall( data ); - if( settings.logging.net.socket.accumulate ) - console.log( this.socketLoggingTextPrefix( "accumulate" ), data ); - this.arr_accumulated_messages.push( jo ); - if( isFlush ) - this.flush(); - } - flush() { - if( this.isDisposed || ( !this.isConnected ) ) - return; - const cnt = this.arr_accumulated_messages.length; - if( cnt == 0 ) - return; - if( settings.logging.net.socket.flushCount ) - console.log( this.socketLoggingTextPrefix( "flush-count(" + cnt + ")" ) ); - let joSend = null; - if( cnt == 1 ) { - joSend = this.arr_accumulated_messages[0]; - if( settings.logging.net.socket.flushOne || settings.logging.net.socket.flush ) - console.log( this.socketLoggingTextPrefix( "flush-one" ), joSend ); - } else { - joSend = { arr_packed_messages: this.arr_accumulated_messages }; - if( settings.logging.net.socket.flushBlock || settings.logging.net.socket.flush ) - console.log( this.socketLoggingTextPrefix( "flush-block(" + cnt + ")" ), joSend ); - } - if( settings.logging.net.socket.flushMethodStats ) - console.log( this.socketLoggingTextPrefix( "flush-method-stats(" + cnt + ")" ), generate_socket_data_stats_JSON( joSend ) ); - this.impl_send( joSend ); - this.arr_accumulated_messages = []; - if( this.relayClientSocket ) - this.relayClientSocket.flush(); - } - impl_receive( data ) { - const jo = socket_received_data_reverse_marshall( data ); - this.dispatchEvent( new UniversalDispatcherEvent( "message", { socket: this, message: jo } ) ); - } - receive( data ) { - if( settings.logging.net.socket.receiveBlock ) - console.log( this.socketLoggingTextPrefix( "receive-block" ), data ); - const jo = socket_received_data_reverse_marshall( data ); - if( "arr_packed_messages" in jo && - jo.arr_packed_messages && - typeof jo.arr_packed_messages == "object" - ) { - const cnt = jo.arr_packed_messages.length; - if( settings.logging.net.socket.receiveCount ) - console.log( this.socketLoggingTextPrefix( "receive-count(" + cnt + ")" ) ); - if( settings.logging.net.socket.receiveMethodStats ) - console.log( this.socketLoggingTextPrefix( "receive-method-stats(" + cnt + ")" ), generate_socket_data_stats_JSON( jo ) ); - for( let i = 0; i < cnt; ++ i ) { - const joMessage = jo.arr_packed_messages[i]; - if( settings.logging.net.socket.receive ) - console.log( this.socketLoggingTextPrefix( "receive" ), joMessage ); - this.impl_receive( joMessage ); - } - return; - } - if( settings.logging.net.socket.receiveCount ) - console.log( this.socketLoggingTextPrefix( "receive-count(" + 1 + ")" ) ); - if( settings.logging.net.socket.receiveMethodStats ) - console.log( this.socketLoggingTextPrefix( "receive-method-stats(" + 1 + ")" ), generate_socket_data_stats_JSON( jo ) ); - if( settings.logging.net.socket.receive ) - console.log( this.socketLoggingTextPrefix( "receive" ), jo ); - this.impl_receive( jo ); - } - disconnect() { - this.isConnected = false; - // if( this.relayClientSocket ) { - // this.relayClientSocket.disconnect(); - // this.relayClientSocket = null; - // } - } - reconnect() { - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class NullSocketPipe extends BasicSocketPipe { - constructor() { - super(); - this.socketType = "NULL"; - this.socketSubtype = "pipe"; - this.url = "NullUrl"; - this.isConnected = true; - } - dispose() { - this.isConnected = false; - super.dispose(); - } - impl_send( data ) { - } - impl_receive( data ) { - } - send( data ) { - } - receive( data ) { - } - flush() { - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const is_running_in_worker = function() { - if( self.document === undefined ) - return true; - return false; -}; - -const g_map_awaiting_in_worker_clients = { }; // in-worker clients in connecting state -const g_map_connected_in_worker_clients = { }; // in-worker clients in connecting state - -const out_of_worker_apis = { - on_message: function( worker, data ) { - const jo = socket_received_data_reverse_marshall( data ); - if( ! ( "worker_message_type" in jo ) || typeof jo.worker_message_type != "string" || jo.worker_message_type.length == 0 ) - return false; // not a socket message - if( ! ( "worker_endpoint" in jo ) || typeof jo.worker_endpoint != "string" || jo.worker_endpoint.length == 0 ) - return false; // TO-DO: send error answer and return true - if( ! ( "worker_uuid" in jo ) || typeof jo.worker_uuid != "string" || jo.worker_uuid.length == 0 ) - return false; // TO-DO: send error answer and return true - switch ( jo.worker_message_type ) { - case "in_worker_connect": { - if( !( jo.worker_uuid in g_map_awaiting_in_worker_clients ) ) - return false; - const pipe = g_map_awaiting_in_worker_clients[jo.worker_uuid]; - pipe.performSuccessfulConnection(); - } return true; - case "in_worker_disconnect": { - if( !( jo.worker_uuid in g_map_connected_in_worker_clients ) ) - return false; - const pipe = g_map_connected_in_worker_clients[jo.worker_uuid]; - pipe.performDisconnect(); - } return true; - case "in_worker_message": { - if( !( jo.worker_uuid in g_map_connected_in_worker_clients ) ) - return false; - const pipe = g_map_connected_in_worker_clients[jo.worker_uuid]; - pipe.receive( jo.data ); - } return true; - default: - return false; // TO-DO: send error answer and return true - } // switch( jo.worker_message_type ) - }, - on_send_message: function( worker, type, endpoint, worker_uuid, data ) { - const jo = socket_received_data_reverse_marshall( data ); - const joSend = { - worker_message_type: ( type && typeof type == "string" && type.length > 0 ) ? type : "in_worker_message", - worker_endpoint: endpoint, - worker_uuid: worker_uuid, - data: jo - }; - //worker.postMessage( socket_received_data_reverse_marshall( joSend ) ); - worker.postMessage( socket_sent_data_marshall( joSend ) ); - } -}; -const in_worker_apis = { - on_message: function( data ) { - const jo = socket_received_data_reverse_marshall( data ); - if( ! ( "worker_message_type" in jo ) || typeof jo.worker_message_type != "string" || jo.worker_message_type.length == 0 ) - return false; // not a socket message - if( ! ( "worker_endpoint" in jo ) || typeof jo.worker_endpoint != "string" || jo.worker_endpoint.length == 0 ) - return false; // TO-DO: send error answer and return true - if( ! ( "worker_uuid" in jo ) || typeof jo.worker_uuid != "string" || jo.worker_uuid.length == 0 ) - return false; // TO-DO: send error answer and return true - if( ! ( jo.worker_endpoint in g_mapLocalServers ) ) - return false; // TO-DO: send error answer and return true - const acceptor = g_mapLocalServers[jo.worker_endpoint]; - switch ( jo.worker_message_type ) { - case "in_worker_connect": - return acceptor.performAccept( jo ); - case "in_worker_disconnect": - return acceptor.performDisconnect( jo ); - case "in_worker_message": - return acceptor.receiveForClientPort( jo.worker_uuid, jo.data ); - default: - return false; // TO-DO: send error answer and return true - } // switch( jo.worker_message_type ) - }, - on_send_message: function( type, endpoint, worker_uuid, data ) { - const jo = socket_received_data_reverse_marshall( data ); - const joSend = { - worker_message_type: ( type && typeof type == "string" && type.length > 0 ) ? type : "in_worker_message", - worker_endpoint: endpoint, - worker_uuid: worker_uuid, - data: jo - }; - //postMessage( socket_received_data_reverse_marshall( joSend ) ); - postMessage( socket_sent_data_marshall( joSend ) ); - } -}; - -class InWorkerServerPipe extends BasicSocketPipe { - constructor( acceptor, clientPort, fnSend ) { - super(); - this.socketType = "InWorker"; - this.socketSubtype = "server"; - this.isConnected = true; - this.acceptor = acceptor; - this.clientPort = "" + clientPort; - this.fnSend = fnSend || in_worker_apis.on_send_message; - this.url = "in_worker_server_pipe://" + acceptor.strEndPoint + ":" + clientPort; - this.acceptor.mapClients[this.clientPort] = this; - this.fnSend( "in_worker_connect", this.acceptor.strEndPoint, this.clientPort, {} ); - const self = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - self.acceptor.dispatchEvent( new UniversalDispatcherEvent( "connection", { socket: self, remoteAddress: "" + self.url } ) ); - }, 0 ); - } - dispose() { - this.performDisconnect(); - super.dispose(); - } - handleServerDisposed() { - this.performDisconnect(); - this.isConnected = false; - this.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: this } ) ); - this.acceptor = null; - this.fnSend = null; - this.url = ""; - this.dispose(); - } - performDisconnect() { - if( ! this.isConnected ) - return; - this.fnSend( "in_worker_disconnect", this.acceptor.strEndPoint, this.clientPort, {} ); - this.isConnected = false; - if( this.acceptor ) - this.acceptor.unregisterClientByKey( this.clientPort ); - this.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: this } ) ); - this.acceptor = null; - this.fnSend = null; - this.url = ""; - } - impl_send( data ) { - if( ( !this.isConnected ) || ( !this.fnSend ) || typeof this.fnSend != "function" ) { - const s = "Cannot send messages to disconnected in-worker server pipe"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - const jo = socket_received_data_reverse_marshall( data ); - this.fnSend( "in_worker_message", this.acceptor.strEndPoint, this.clientPort, jo ); - } - disconnect() { - this.performDisconnect(); - super.disconnect(); - } -}; - -class InWorkerSocketServerAcceptor extends BasicServerAcceptor { - constructor( strEndPoint, fnSend ) { - super(); - this.socketType = "InWorker"; - this.strEndPoint = ( strEndPoint && typeof strEndPoint == "string" && strEndPoint.length > 0 ) ? strEndPoint : "default_local_endpoint"; - if( this.strEndPoint in g_mapLocalServers ) { - const s = "Cannot start in-worker socket server on already listening \"" + this.strEndPoint + "\" endpoint"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - g_mapLocalServers[this.strEndPoint] = this; - this.fnSend = fnSend || in_worker_apis.on_send_message; - this.isListening = true; - const self = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - }, 0 ); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.disposeNotifyClients(); - if( this.strEndPoint && typeof this.strEndPoint == "string" && this.strEndPoint.length > 0 ) { - if( this.strEndPoint in g_mapLocalServers ) - delete g_mapLocalServers[this.strEndPoint]; - } - super.dispose(); - } - performAccept( jo ) { - if( jo.worker_uuid in this.mapClients ) - return false; // TO-DO: send error answer and return true - // const pipe = - new InWorkerServerPipe( this, "" + jo.worker_uuid, this.fnSend ); - return true; - } - performDisconnect( jo ) { - if( ! ( jo.worker_uuid in this.mapClients ) ) - return false; // TO-DO: send error answer and return true - const pipe = this.mapClients[jo.worker_uuid]; - pipe.performDisconnect(); - return true; - } - receiveForClientPort( clientPort, jo ) { - if( ! ( clientPort in this.mapClients ) ) - return false; // TO-DO: send error answer and return true - const pipe = this.mapClients[clientPort]; - pipe.receive( jo ); - return true; - } -}; - -class OutOfWorkerSocketClientPipe extends BasicSocketPipe { - constructor( strEndPoint, worker, fnSend ) { - super(); - this.socketType = "InWorker"; - this.socketSubtype = "client"; - this.isConnected = false; - this.worker = worker; - this.clientPort = utils.uuid_v4(); - this.strEndPoint = ( strEndPoint && typeof strEndPoint == "string" && strEndPoint.length > 0 ) ? strEndPoint : "default_in_worker_endpoint"; - this.url = "out_of_worker_client_pipe://" + this.strEndPoint + ":" + this.clientPort; - this.fnSend = fnSend || out_of_worker_apis.on_send_message; - this.fnSend( this.worker, "in_worker_connect", this.strEndPoint, this.clientPort, {} ); - g_map_awaiting_in_worker_clients["" + this.clientPort] = this; - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.performDisconnect(); - if( this.clientPort in g_map_awaiting_in_worker_clients ) - delete g_map_awaiting_in_worker_clients[this.clientPort]; - super.dispose(); - } - performDisconnect() { - if( ! this.isConnected ) - return; - this.isConnected = false; - delete g_map_connected_in_worker_clients["" + this.clientPort]; - this.fnSend( this.worker, "in_worker_disconnect", this.strEndPoint, this.clientPort, {} ); - this.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: this } ) ); - this.worker = null; - this.clientPort = ""; - this.strEndPoint = ""; - this.url = ""; - } - performSuccessfulConnection() { - delete g_map_awaiting_in_worker_clients[this.clientPort]; - g_map_connected_in_worker_clients["" + this.clientPort] = this; - this.isConnected = true; - this.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: this } ) ); - } - impl_send( data ) { - if( ( !this.isConnected ) || ( !this.worker ) || ( !this.fnSend ) || typeof this.fnSend != "function" ) { - const s = "Cannot send messages to disconnected in-worker client pipe"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - const jo = socket_received_data_reverse_marshall( data ); - this.fnSend( this.worker, "in_worker_message", this.strEndPoint, this.clientPort, jo ); - } - disconnect() { - this.performDisconnect(); - super.disconnect(); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class OutOfWorkerRelay extends EventDispatcher { - constructor( strRelayName, acceptor, fnCreateClient, isAutoFlushIncoming, isAutoFlushOutgoing ) { - super(); - const self = this; - self.strRelayName = ( strRelayName != null && strRelayName != undefined && typeof strRelayName == "string" && strRelayName.length > 0 ) ? ( "" + strRelayName ) : "unnamed"; - self.isAutoFlushIncoming = ( isAutoFlushIncoming == null || isAutoFlushIncoming == undefined ) ? true : ( isAutoFlushIncoming ? true : false ); - self.isAutoFlushOutgoing = ( isAutoFlushOutgoing == null || isAutoFlushOutgoing == undefined ) ? true : ( isAutoFlushOutgoing ? true : false ); - if( ! acceptor ) - throw new Error( "OutOfWorkerRelay \"" + self.strRelayName + "\" needs acceptor for normal functionality" ); - if( typeof fnCreateClient != "function" ) - throw new Error( "OutOfWorkerRelay \"" + self.strRelayName + "\" needs callback to create connections to target server" ); - self.acceptor = acceptor; - self.fnCreateClient = fnCreateClient; - self.onConnection_ = function( eventData ) { - const pipeIncoming = eventData.socket; - let pipeOutgoing = null; - if( ( ! ( "remoteAddress" in eventData ) ) || eventData.remoteAddress == null || eventData.remoteAddress == undefined ) - pipeIncoming.strSavedRemoteAddress = pipeIncoming.constructor.name; - else - pipeIncoming.strSavedRemoteAddress = "" + eventData.remoteAddress; - if( settings.logging.net.relay.connect ) - console.log( "Relay \"" + self.strRelayName + "\" got new external-client connection \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "connection", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress } ) ); - // - // 1) configure incoming pipe - // - let _offAllPipeEventListeners = null; - let _onExternalPipeClose = function() { - if( settings.logging.net.relay.disconnect ) - console.warn( "Relay \"" + self.strRelayName + "\" external-client socket closed \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "close", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: true } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onRelayPipeClose = function() { - if( settings.logging.net.relay.disconnect ) - console.warn( "Relay \"" + self.strRelayName + "\" relay-client socket closed \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "close", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: false } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onExternalPipeError = function( eventData ) { - if( settings.logging.net.relay.error ) - console.warn( "Relay client \"" + self.strRelayName + "\" external-client socket error \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "error", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: true } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onRelayPipeError = function( eventData ) { - if( settings.logging.net.relay.error ) - console.warn( "Relay client \"" + self.strRelayName + "\" relay-client socket error \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "error", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: false } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onExternalPipeMessage = function( eventData ) { - if( settings.logging.net.relay.rawMessage ) - console.log( "Relay \"" + self.strRelayName + "\" external-client socket \"" + eventData.strSavedRemoteAddress + "\" raw message", eventData ); - const joMessage = eventData.message; - if( settings.logging.net.relay.message ) - console.log( "Relay \"" + self.strRelayName + "\" external-client socket \"" + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage ); - if( ! pipeOutgoing ) - throw new Error( "Relay \"" + self.strRelayName + "\" is not completely initialized and cannot transfer messages" ); - self.dispatchEvent( new UniversalDispatcherEvent( "message", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: true, message: joMessage } ) ); - pipeOutgoing.send( joMessage ); - if( self.isAutoFlushIncoming ) - pipeOutgoing.flush(); - }; - let _onRelayPipeMessage = function( eventData ) { - if( settings.logging.net.relay.rawMessage ) - console.log( "Relay \"" + self.strRelayName + "\" relay-client socket \"" + eventData.strSavedRemoteAddress + "\" raw message", eventData ); - const joMessage = eventData.message; - if( settings.logging.net.relay.message ) - console.log( "Relay \"" + self.strRelayName + "\" relay-client socket \"" + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage ); - if( ! pipeOutgoing ) - throw new Error( "Relay \"" + self.strRelayName + "\" is not completely initialized and cannot transfer messages" ); - self.dispatchEvent( new UniversalDispatcherEvent( "message", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: false, message: joMessage } ) ); - pipeOutgoing.send( joMessage ); - if( self.isAutoFlushOutgoing ) - pipeOutgoing.flush(); - }; - _offAllPipeEventListeners = function() { - if( _onExternalPipeClose ) { - pipeIncoming.off( "close", _onExternalPipeClose ); - _onExternalPipeClose = null; - } - if( _onExternalPipeError ) { - pipeIncoming.off( "error", _onExternalPipeError ); - _onExternalPipeError = null; - } - if( _onExternalPipeMessage ) { - pipeIncoming.off( "message", _onExternalPipeMessage ); - _onExternalPipeMessage = null; - } - if( pipeOutgoing.relayClientSocket ) { - if( _onRelayPipeClose ) { - pipeOutgoing.off( "close", _onRelayPipeClose ); - _onRelayPipeClose = null; - } - if( _onRelayPipeError ) { - pipeOutgoing.off( "error", _onRelayPipeError ); - _onRelayPipeError = null; - } - if( _onRelayPipeMessage ) { - pipeOutgoing.off( "message", _onRelayPipeMessage ); - _onRelayPipeMessage = null; - } - pipeOutgoing.disconnect(); - pipeOutgoing.dispose(); - } - pipeIncoming.disconnect(); - pipeIncoming.dispose(); - }; - pipeIncoming.on( "close", _onExternalPipeClose ); - pipeIncoming.on( "error", _onExternalPipeError ); - pipeIncoming.on( "message", _onExternalPipeMessage ); - // - // 2) configure outgoing relay client pipe - // - pipeOutgoing = pipeIncoming.relayClientSocket = self.fnCreateClient(); - if( ! pipeOutgoing ) { - pipeIncoming.dispose(); - throw new Error( "Relay \"" + self.strRelayName + "\" failed to initialize relay-client socket to target server" ); - } - pipeOutgoing.on( "close", _onRelayPipeClose ); - pipeOutgoing.on( "error", _onRelayPipeError ); - pipeOutgoing.on( "message", _onRelayPipeMessage ); - }; - self.acceptor.on( "connection", self.onConnection_ ); - } - dispose() { - this.isDisposing = true; - if( this.acceptor ) - this.acceptor.off( "connection", this.onConnection_ ); - this.onConnection_ = null; - super.dispose(); - } - flush() { - if( this.acceptor ) - this.acceptor.flush(); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class OneToOneRelay extends EventDispatcher { - constructor( strRelayName, pipeIncoming, pipeOutgoing, isAutoFlushIncoming, isAutoFlushOutgoing ) { - super(); - const self = this; - self.strRelayName = ( strRelayName != null && strRelayName != undefined && typeof strRelayName == "string" && strRelayName.length > 0 ) ? ( "" + strRelayName ) : "unnamed"; - self.isAutoFlushIncoming = ( isAutoFlushIncoming == null || isAutoFlushIncoming == undefined ) ? true : ( isAutoFlushIncoming ? true : false ); - self.isAutoFlushOutgoing = ( isAutoFlushOutgoing == null || isAutoFlushOutgoing == undefined ) ? true : ( isAutoFlushOutgoing ? true : false ); - self.pipeIncoming = pipeIncoming; - self.pipeOutgoing = pipeOutgoing; - if( ( !( "strSavedRemoteAddress" in pipeIncoming ) ) || pipeIncoming.strSavedRemoteAddress == null || pipeIncoming.strSavedRemoteAddress == undefined ) - pipeIncoming.strSavedRemoteAddress = "" + pipeIncoming.constructor.name; - if( ( !( "strSavedRemoteAddress" in pipeOutgoing ) ) || pipeOutgoing.strSavedRemoteAddress == null || pipeOutgoing.strSavedRemoteAddress == undefined ) - pipeOutgoing.strSavedRemoteAddress = "" + pipeOutgoing.constructor.name; - // - // 1) configure incoming pipe - // - let _offAllPipeEventListeners = null; - let _onIncomingPipeClose = function() { - if( settings.logging.net.relay.disconnect ) - console.warn( "Relay \"" + self.strRelayName + "\" incoming-client socket closed \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "close", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: true } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onOutgoingPipeClose = function() { - if( settings.logging.net.relay.disconnect ) - console.warn( "Relay \"" + self.strRelayName + "\" outgoing-client socket closed \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "close", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: false } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onIncomingPipeError = function( eventData ) { - if( settings.logging.net.relay.error ) - console.warn( "Relay client \"" + self.strRelayName + "\" incoming-client socket error \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "error", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: true } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onOutgoingPipeError = function( eventData ) { - if( settings.logging.net.relay.error ) - console.warn( "Relay client \"" + self.strRelayName + "\" outgoing-client socket error \"" + pipeIncoming.strSavedRemoteAddress + "\"" ); - self.dispatchEvent( new UniversalDispatcherEvent( "error", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: false } ) ); - if( _offAllPipeEventListeners ) { - _offAllPipeEventListeners(); - _offAllPipeEventListeners = null; - } - }; - let _onIncomingPipeMessage = function( eventData ) { - if( settings.logging.net.relay.rawMessage ) - console.log( "Relay \"" + self.strRelayName + "\" incoming-client socket \"" + eventData.strSavedRemoteAddress + "\" raw message", eventData ); - const joMessage = eventData.message; - if( settings.logging.net.relay.message ) - console.log( "Relay \"" + self.strRelayName + "\" incoming-client socket \"" + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage ); - if( ! pipeOutgoing ) - throw new Error( "Relay \"" + self.strRelayName + "\" is not completely initialized and cannot transfer messages" ); - self.dispatchEvent( new UniversalDispatcherEvent( "message", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: true, message: joMessage } ) ); - pipeOutgoing.send( joMessage ); - if( self.isAutoFlushIncoming ) - pipeOutgoing.flush(); - }; - let _onOutgoingPipeMessage = function( eventData ) { - if( settings.logging.net.relay.rawMessage ) - console.log( "Relay \"" + self.strRelayName + "\" outgoing-client socket \"" + eventData.strSavedRemoteAddress + "\" raw message", eventData ); - const joMessage = eventData.message; - if( settings.logging.net.relay.message ) - console.log( "Relay \"" + self.strRelayName + "\" outgoing-client socket \"" + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage ); - if( ! pipeOutgoing ) - throw new Error( "Relay \"" + self.strRelayName + "\" is not completely initialized and cannot transfer messages" ); - self.dispatchEvent( new UniversalDispatcherEvent( "message", { relay: self, socket: pipeIncoming, remoteAddress: "" + pipeIncoming.strSavedRemoteAddress, isExternalSocket: false, message: joMessage } ) ); - pipeIncoming.send( joMessage ); - if( self.isAutoFlushOutgoing ) - pipeIncoming.flush(); - }; - _offAllPipeEventListeners = function() { - if( _onIncomingPipeClose ) { - pipeIncoming.off( "close", _onIncomingPipeClose ); - _onIncomingPipeClose = null; - } - if( _onIncomingPipeError ) { - pipeIncoming.off( "error", _onIncomingPipeError ); - _onIncomingPipeError = null; - } - if( _onIncomingPipeMessage ) { - pipeIncoming.off( "message", _onIncomingPipeMessage ); - _onIncomingPipeMessage = null; - } - if( pipeOutgoing.relayClientSocket ) { - if( _onOutgoingPipeClose ) { - pipeOutgoing.off( "close", _onOutgoingPipeClose ); - _onOutgoingPipeClose = null; - } - if( _onOutgoingPipeError ) { - pipeOutgoing.off( "error", _onOutgoingPipeError ); - _onOutgoingPipeError = null; - } - if( _onOutgoingPipeMessage ) { - pipeOutgoing.off( "message", _onOutgoingPipeMessage ); - _onOutgoingPipeMessage = null; - } - pipeOutgoing.disconnect(); - pipeOutgoing.dispose(); - } - pipeIncoming.disconnect(); - pipeIncoming.dispose(); - }; - pipeIncoming.on( "close", _onIncomingPipeClose ); - pipeIncoming.on( "error", _onIncomingPipeError ); - pipeIncoming.on( "message", _onIncomingPipeMessage ); - // - // 2) configure outgoing relay client pipe - // - pipeOutgoing.on( "close", _onOutgoingPipeClose ); - pipeOutgoing.on( "error", _onOutgoingPipeError ); - pipeOutgoing.on( "message", _onOutgoingPipeMessage ); - } - dispose() { - this.isDisposing = true; - super.dispose(); - } - flush() { - if( this.pipeIncoming ) - this.pipeIncoming.flush(); - if( this.pipeOutgoing ) - this.pipeOutgoing.flush(); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class DirectPipe extends BasicSocketPipe { - constructor( counterPipe, isBroadcastOpenEvents ) { - super(); - isBroadcastOpenEvents = isBroadcastOpenEvents ? true : false; - this.socketType = "Direct"; - this.socketSubtype = "direct.not.initialized.yet"; - this.isConnected = false; - this.acceptor = null; - this.counterPipe = ( counterPipe != null && counterPipe != undefined ) ? counterPipe : null; // set outside after this constructor call - this.strEndPoint = this.counterPipe ? ( "2-" + this.counterPipe.strEndPoint ) : ( "1-" + utils.randomDirectPipeID() ); - this.clientPort = this.counterPipe ? 2 : 1; - this.socketSubtype = "direct." + this.clientPort; - this.url = "direct_pipe://" + this.strEndPoint + ":" + this.clientPort; - if( this.counterPipe ) { - this.counterPipe.counterPipe = this; - this.isConnected = true; - this.counterPipe.isConnected = true; - if( isBroadcastOpenEvents ) { - const self = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - // self.acceptor.dispatchEvent( new UniversalDispatcherEvent( "connection", { socket: serverPipe, remoteAddress: "" + self.url } ) ); - self.counterPipe.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self.counterPipe } ) ); - }, 0 ); - } - } - } - dispose() { - this.performDisconnect(); - super.dispose(); - } - handleServerDisposed() { // this method is for using in local client/server pipe pairs - this.performDisconnect(); - this.isConnected = false; - this.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: this } ) ); - this.acceptor = null; - this.counterPipe = null; - this.clientPort = 0; - this.url = ""; - this.dispose(); - } - performDisconnect() { - if( ! this.isConnected ) - return; - this.isConnected = false; - if( this.acceptor ) - this.acceptor.unregisterClientByKey( this.clientPort ); - this.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: this } ) ); - this.counterPipe.performDisconnect(); - this.acceptor = null; - this.counterPipe = null; - this.clientPort = 0; - this.url = ""; - } - impl_send( data ) { - if( ( !this.isConnected ) || ( !this.counterPipe ) || ( !this.counterPipe.isConnected ) ) { - const s = "Cannot send messages to disconnected local server pipe"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - const s = socket_sent_data_marshall( data ); - const jo = socket_received_data_reverse_marshall( s ); - this.counterPipe.receive( jo ); - } - disconnect() { - this.performDisconnect(); - super.disconnect(); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class LocalSocketServerPipe extends DirectPipe { - constructor( counterPipe, acceptor, clientPort ) { - super( counterPipe, false ); - this.socketType = "Local"; - this.socketSubtype = "server"; - this.isConnected = true; - this.acceptor = acceptor; - this.clientPort = 0 + parseInt( clientPort, 10 ); - this.url = "local_server_pipe://" + acceptor.strEndPoint + ":" + clientPort; - this.acceptor.mapClients["" + clientPort] = this; - const self = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - }, 0 ); - } - dispose() { - super.dispose(); - } -}; - -class LocalSocketServerAcceptor extends BasicServerAcceptor { - constructor( strEndPoint ) { - super(); - this.socketType = "Local"; - this.nextClientPort = 1; - this.strEndPoint = ( strEndPoint && typeof strEndPoint == "string" && strEndPoint.length > 0 ) ? strEndPoint : "default_local_endpoint"; - if( this.strEndPoint in g_mapLocalServers ) { - const s = "Cannot start local socket server on already listening \"" + this.strEndPoint + "\" endpoint"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - g_mapLocalServers[this.strEndPoint] = this; - this.isListening = true; - const self = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - }, 0 ); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.disposeNotifyClients(); - if( this.strEndPoint && typeof this.strEndPoint == "string" && this.strEndPoint.length > 0 ) { - if( this.strEndPoint in g_mapLocalServers ) - delete g_mapLocalServers[this.strEndPoint]; - } - super.dispose(); - } -}; - -class LocalSocketClientPipe extends DirectPipe { - constructor( strEndPoint ) { - super( null, false ); - this.socketType = "Local"; - this.socketSubtype = "client"; - this.isConnected = false; - this.clientPort = 0; - this.acceptor = null; - this.counterPipe = null; - this.strEndPoint = ( strEndPoint && typeof strEndPoint == "string" && strEndPoint.length > 0 ) ? strEndPoint : "default_local_endpoint"; - if( !( this.strEndPoint in g_mapLocalServers ) ) { - const s = "Cannot connect to local socket server \"" + this.strEndPoint + "\" endpoint, no such server"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - this.acceptor = g_mapLocalServers[this.strEndPoint]; - this.clientPort = 0 + this.acceptor.nextClientPort; - ++ this.acceptor.nextClientPort; - this.url = "local_client_pipe://" + this.strEndPoint + ":" + this.clientPort; - this.isConnected = true; - const serverPipe = new LocalSocketServerPipe( this, this.acceptor, 0 + this.clientPort ); - serverPipe.counterPipe = this; - this.counterPipe = serverPipe; - this.acceptor.mapClients[0 + this.clientPort] = { - serverPipe: serverPipe, - clientPipe: this - }; - const self = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - self.acceptor.dispatchEvent( new UniversalDispatcherEvent( "connection", { socket: serverPipe, remoteAddress: "" + self.url } ) ); - }, 0 ); - } - dispose() { - super.dispose(); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class WebSocketServerPipe extends BasicSocketPipe { - constructor( acceptor, ws_conn, remoteAddress ) { - super(); - this.socketType = "WS"; - this.socketSubtype = "server"; - const self = this; - this.isConnected = true; - this.acceptor = acceptor; - this.clientNumber = 0 + acceptor.nextClientNumber; - this.clientPort = 0 + this.clientNumber; - ++ acceptor.nextClientNumber; - this.ws_conn = ws_conn; - this.remoteAddress = "" + remoteAddress; - this.url = "ws_server_pipe(" + this.clientNumber + ")://" + remoteAddress; - this._onWsClose = function() { - self.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: self } ) ); - }; - this._onWsError = function( event ) { - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: event } ) ); - }; - this._onWsMessage = function( event ) { - self.receive( event.data ); - }; - this._removeWsEventListeners = function() { - if( self._onWsClose ) { - ws_conn.removeEventListener( "close", self._onWsClose ); - self._onWsClose = null; - } - if( self._onWsError ) { - ws_conn.removeEventListener( "error", self._onWsError ); - self._onWsError = null; - } - if( self._onWsMessage ) { - ws_conn.removeEventListener( "message", self._onWsMessage ); - self._onWsMessage = null; - } - }; - ws_conn.addEventListener( "close", this._onWsClose ); - ws_conn.addEventListener( "error", this._onWsError ); - ws_conn.addEventListener( "message", this._onWsMessage ); - this.acceptor.mapClients["" + this.clientPort] = this; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - self.acceptor.dispatchEvent( new UniversalDispatcherEvent( "connection", { socket: self, remoteAddress: "" + remoteAddress } ) ); - }, 0 ); - } - dispose() { - this.performDisconnect(); - super.dispose(); - } - handleServerDisposed() { - this.isConnected = false; - this.clientNumber = 0; - this.acceptor = null; - this.ws_conn = null; - this.url = ""; - this.remoteAddress = ""; - this.dispose(); - } - performDisconnect() { - if( ! this.isConnected ) - return; - this.isConnected = false; - if( this._removeWsEventListeners ) { - this._removeWsEventListeners(); - this._removeWsEventListeners = null; - } - if( this.ws_conn ) { - try { - this.ws_conn.terminate(); - } catch ( err ) { - console.warn( "Web socket server pipe termination error", err ); - } - this.ws_conn = null; - } - if( this.acceptor ) - this.acceptor.unregisterClientByKey( this.clientPort ); - this.clientNumber = 0; - this.acceptor = null; - this.url = ""; - this.remoteAddress = ""; - } - impl_send( data ) { - if( ( !this.isConnected ) || ( !this.ws_conn ) ) { - const s = "Cannot send messages to disconnected web socket server pipe"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - const s = socket_sent_data_marshall( data ); - this.ws_conn.send( s ); - } - disconnect() { - this.performDisconnect(); - super.disconnect(); - } - impl_receive( data ) { - const jo = socket_received_data_reverse_marshall( data ); - this.dispatchEvent( new UniversalDispatcherEvent( "message", { socket: this, message: jo } ) ); - } -}; - -class WebSocketServerAcceptor extends BasicServerAcceptor { - constructor( nTcpPort, key, cert ) { - super(); - this.socketType = "WS"; - this.ws_srv = null; - if( key != null && key != undefined && typeof key == "string" && key.length > 0 && - cert != null && cert != undefined && typeof cert == "string" && cert.length > 0 - ) { - const server = https_mod.createServer( { - key: "" + key, - cert: "" + cert - // , ca: ... - } ); - server.listen( nTcpPort ); - this.ws_srv = new ws_mod.Server( { server } ); - } else - this.ws_srv = new ws_mod.Server( { port: nTcpPort } ); - - const self = this; - self.ws_srv.on( "connection", function( ws_conn, req ) { - ws_conn.strSavedRemoteAddress = "" + req.connection.remoteAddress; - ws_conn.serverPipe = new WebSocketServerPipe( self, ws_conn, req.connection.remoteAddress ); - } ); - this.isListening = true; - const iv = setTimeout( function() { - clearTimeout( iv ); - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - }, 0 ); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.disposeNotifyClients(); - super.dispose(); - } -}; - -class WebSocketClientPipe extends BasicSocketPipe { - constructor( url ) { - super(); - this.socketType = "WS"; - this.socketSubtype = "client"; - this.isConnected = false; - this.ws_conn = null; - this._onWsOpen = null; - this._onWsClose = null; - this._onWsError = null; - this._onWsMessage = null; - this.ws_url = "" + ( ( url != null && url != undefined && typeof url == "string" ) ? url : "" ); - this.url = "ws_client_pipe-" + this.ws_url; - this.reconnect(); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.performDisconnect(); - this.ws_url = null; - super.dispose(); - } - impl_send( data ) { - if( ( !this.isConnected ) || ( !this.ws_conn ) ) { - const s = "Cannot send messages to disconnected web socket client pipe"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - const s = socket_sent_data_marshall( data ); - this.ws_conn.send( s ); - } - reconnect() { - this.performDisconnect(); - this.ws_connect( "" + this.ws_url ); - } - disconnect() { - this.performDisconnect(); - super.disconnect(); - } - performDisconnect() { - if( ! this.isConnected ) - return; - this.ws_disconnect(); - } - ws_connect_attempt( url, reconnectAfterMilliseconds, iv ) { - const self = this; - try { - if( this.isConnected || this.ws_conn ) - this.ws_disconnect(); - this.ws_conn = ws_mod - ? new ws_mod( url, { tlsOptions: { rejectUnauthorized: false } } ) // server side - : new WebSocket( url ); // client side - this.url = "" + url; - this._onWsOpen = function() { - self.isConnected = true; - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - }; - this._onWsClose = function( event ) { - // alert( JSON.stringify( event ) ); - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: self, message: event } ) ); - }; - this._onWsError = function( event ) { - // alert( JSON.stringify( event ) ); - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: event } ) ); - }; - this._onWsMessage = function( event ) { - self.receive( event.data ); - }; - this._removeWsEventListeners = function() { - if( self._onWsOpen ) { - self.ws_conn.removeEventListener( "open", self._onWsOpen ); - self._onWsOpen = null; - } - if( self._onWsClose ) { - self.ws_conn.removeEventListener( "close", self._onWsClose ); - self._onWsClose = null; - } - if( self._onWsError ) { - self.ws_conn.removeEventListener( "error", self._onWsError ); - self._onWsError = null; - } - if( self._onWsMessage ) { - self.ws_conn.removeEventListener( "message", self._onWsMessage ); - self._onWsMessage = null; - } - }; - this.ws_conn.addEventListener( "open", this._onWsOpen ); - this.ws_conn.addEventListener( "close", this._onWsClose ); - this.ws_conn.addEventListener( "error", this._onWsError ); - this.ws_conn.addEventListener( "message", this._onWsMessage ); - if( iv ) - clearTimeout( iv ); - return true; - } catch ( err ) { - console.warn( "WS client connect error:", err ); - } - if( reconnectAfterMilliseconds != null && reconnectAfterMilliseconds != undefined ) { - reconnectAfterMilliseconds = parseInt( reconnectAfterMilliseconds, 10 ); - if( reconnectAfterMilliseconds > 0 && ( !iv ) ) { - const iv = setTimeout( function() { - try { - if( self.ws_connect_attempt( url, reconnectAfterMilliseconds, iv ) ) - clearTimeout( iv ); - } catch ( err ) { - } - }, reconnectAfterMilliseconds ); - } - } - return false; - } - ws_connect( url ) { - if( url.length == 0 ) { - const s = "Cannot connect web socket server \"" + url + "\", bad url"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s } ) ); - throw new Error( s ); - } - this.ws_connect_attempt( url, settings.net.ws.client.reconnectAfterMilliseconds, null ); - } - ws_disconnect() { - if( this._removeWsEventListeners ) { - this._removeWsEventListeners(); - this._removeWsEventListeners = null; - } - if( this.ws_conn ) { - //try { this.ws_conn.close( 1000, "Good bye!" ); } catch( err ) { } // see codes here: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes - let bPass = false, anyError = null; - try { - this.ws_conn.close(); - bPass = true; - } catch ( err ) { - anyError = err; - } - if( ! bPass ) { - try { - this.ws_conn.terminate(); - bPass = true; - } catch ( err ) { - anyError = err; - } - } - if( ! bPass ) - console.warn( "Web socket client pipe termination error", anyError ); - this.ws_conn = null; - } - this.isConnected = false; - this.url = ""; - } - impl_receive( data ) { - const jo = socket_received_data_reverse_marshall( data ); - this.dispatchEvent( new UniversalDispatcherEvent( "message", { socket: this, message: jo } ) ); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class RTCConnection extends EventDispatcher { - constructor( strSignalingServerURL, idRtcParticipant ) { - super(); - this.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); - this.idRtcParticipant = "" + ( ( idRtcParticipant != null && idRtcParticipant != undefined && typeof idRtcParticipant == "string" && idRtcParticipant.length > 0 ) ? idRtcParticipant : utils.uuid_v4() ); - this.wasIdentified = false; - this.iceComplete = false; - this.pc = null; - this.dc = null; - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.closeDataChannel(); - this.closePeer(); - this.dc = null; - this.wasIdentified = false; - this.iceComplete = false; - this.idRtcParticipant = null; - super.dispose(); - } - describe( strInstanceType, arrAdditionalProps ) { - let strInstanceDescription = ( strInstanceType == null || strInstanceType == undefined || ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) - ? "participant" - : ( "" + strInstanceType ); - if( typeof this.idRtcParticipant == "string" && this.idRtcParticipant.length > 0 ) - strInstanceDescription += " " + this.idRtcParticipant; - const arrProps = []; - if( this.isDisposed ) - arrProps.push( "disposed" ); - if( this.wasIdentified ) - arrProps.push( "identified" ); - if( this.pc ) - arrProps.push( "pc" ); - if( this.dc ) - arrProps.push( "dc" ); - if( arrAdditionalProps != null && arrAdditionalProps != undefined && arrAdditionalProps.length > 0 ) { - for( let i = 0; i < arrAdditionalProps.length; ++ i ) - arrProps.push( arrAdditionalProps[i] ); - } - if( arrProps.length > 0 ) - strInstanceDescription += "(" + arrProps.join( ", " ) + ")"; - return strInstanceDescription; - } - closeDataChannel() { - if( this.dc ) { - try { - this.dc.ondatachannel = null; - this.dc.close(); - if( settings.logging.net.rtc.closeDataChannel ) - console.warn( this.describe() + " did closed RTC data channel" ); - } catch ( err ) { - if( settings.logging.net.rtc.error ) - console.warn( this.describe() + " error closing RTC data channel:", err ); - } - this.dc = null; - this.dispatchEvent( new UniversalDispatcherEvent( "dataChannelClose", { detail: { actor: this } } ) ); - } - } - closePeer() { - if( this.pc ) { - try { - this.pc.onicecandidate = null; - this.pc.oniceconnectionstatechange = null; - this.pc.close(); - if( settings.logging.net.rtc.closePeer ) - console.warn( this.describe() + " did closed RTC peer" ); - } catch ( err ) { - if( settings.logging.net.rtc.error ) - console.warn( this.describe() + " error closing RTC peer:", err ); - } - this.dispatchEvent( new UniversalDispatcherEvent( "peerClose", { detail: { actor: this } } ) ); - this.pc = null; - } - } - onError( err ) { - this.dispatchEvent( new UniversalDispatcherEvent( "rtcParticipantError", { detail: { actor: this, error: err } } ) ); - if( settings.logging.net.rtc.error ) - console.warn( " !!! " + this.describe() + " error:", err ); - this.closeDataChannel(); - this.closePeer(); - } - send( data ) { - const s = socket_sent_data_marshall( data ); - if( ! this.dc ) { - this.onError( "Attempt to send message to uninitialized RTC data channel: " + s ); - return; - } - try { - this.dc.send( s ); - } catch ( err ) { - this.onError( "Failed to send message to RTC data channel: " + err.toString() ); - } - } - onDataChannelOpen( event ) { - this.dispatchEvent( new UniversalDispatcherEvent( "dataChannelOpen", { detail: { actor: this } } ) ); - } - onDataChannelClose( event ) { - this.dispatchEvent( new UniversalDispatcherEvent( "dataChannelClose", { detail: { actor: this } } ) ); - // this.onError( "Data channel closed" ); - } - onDataChannelError( event ) { - this.dispatchEvent( new UniversalDispatcherEvent( "dataChannelError", { detail: { actor: this } } ) ); - this.onError( "Data channel error " + event.toString() ); - } - onDataChannelMessage( event ) { - if( event.data.size ) { - // fileReceiver.receive( event.data, { } ); - if( settings.logging.net.rtc.error ) - console.warn( this.describe() + " will ignore file transfer message of size", event.data.size ); - } else { - if( event.data.charCodeAt( 0 ) == 2 ) - return; - const data = JSON.parse( event.data ); - if( data.type === "file" ) { - // fileReceiver.receive( event.data, { } ); - if( settings.logging.net.rtc.error ) - console.warn( this.describe() + " will ignore file transfer message" ); - } else - this.dispatchEvent( new UniversalDispatcherEvent( "dataChannelMessage", { detail: { actor: this, data: data } } ) ); - } - } - onIceComplete( event ) { - } - onIceConnectionStateChange( event ) { // handler for self.pc.oniceconnectionstatechange, see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/oniceconnectionstatechange - if( settings.logging.net.rtc.iceConnectionStateChange ) - console.log( "Participant \"" + this.idRtcParticipant + "\" ICE connection state changed to \"" + this.pc.iceConnectionState + "\", event is:", event ); - else if( settings.logging.net.rtc.iceConnectionStateName ) // similar to previous but prints only connection state name - console.log( "Participant \"" + this.idRtcParticipant + "\" ICE connection state changed to \"" + this.pc.iceConnectionState + "\"" ); - if( this.pc.iceConnectionState === "failed" || - this.pc.iceConnectionState === "closed" || - this.pc.iceConnectionState === "disconnected" - ) - this.onError( "ICE connection state(oniceconnectionstatechange) changed to " + this.pc.iceConnectionState ); - } - onIceGatheringStateChange( event ) { // handler for self.pc.onicegatheringstatechange - this is recommended to handle in a same way as oniceconnectionstatechange, see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onicegatheringstatechange - if( ! this.pc ) { - console.log( "WARNING: Participant \"" + this.idRtcParticipant + "\" ICE gathering state changed event with no pc\", event is:", event ); - return; - } - if( settings.logging.net.rtc.iceGatheringStateChange ) - console.log( "Participant \"" + this.idRtcParticipant + "\" ICE gathering state changed to \"" + this.pc.iceGatheringState + "\", event is:", event ); - else if( settings.logging.net.rtc.iceGatheringStateName ) // similar to previous but prints only gathering state name - console.log( "Participant \"" + this.idRtcParticipant + "\" ICE gathering state changed to \"" + this.pc.iceGatheringState + "\"" ); - if( this.pc.iceConnectionState === "failed" || - this.pc.iceConnectionState === "closed" || - this.pc.iceConnectionState === "disconnected" - ) - this.onError( "ICE connection state(onicegatheringstatechange) changed to " + this.pc.iceConnectionState ); - } - onIceIdentifyResult( event ) { // handler for self.pc.onidentityresult, see https://developer.mozilla.org/en-US/docs/Web/API/RTCIdentityEvent - if( settings.logging.net.rtc.iceIceIdentifyResult ) { - if( "assertion" in event ) - console.warn( "Participant \"" + this.idRtcParticipant + "\" ICE identify result event with new identity assertion (blob: '" + event.assertion + "') has been generated." ); - else - console.warn( "Participant \"" + this.idRtcParticipant + "\" ICE identify result event is:", event ); - } - } - onIceSignalingStateChange( event ) { // handler for self.pc.onsignalingstatechange, see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onsignalingstatechange - if( settings.logging.net.rtc.iceSignalingStateChange ) { - console.log( "Participant \"" + this.idRtcParticipant + "\" ICE signaling state changed to \"" + - ( ( this.pc && "signalingState" in this.pc ) ? this.pc.signalingState : "N/A" ) + - "\", event is:", event ); - } - } - onIceNegotiationNeeded( event ) { // handler for self.pc.onnegotiationneeded, see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onnegotiationneeded - // TO-DO: improve this - if( settings.logging.net.rtc.iceNegotiationNeeded ) - console.log( "Participant \"" + this.idRtcParticipant + "\" ICE negotiation needed event is:", event ); - } -}; - -class RTCActor extends RTCConnection { - constructor( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions ) { - super( strSignalingServerURL, idRtcParticipant ); - this.isDisposed = false; - this.idSomebodyCreator = null; - this.bWasImpersonated = false; - this.isCreator = false; - this.isJoiner = false; - // - this.offerOptions = { - optional: [], - offerToReceiveAudio: false, // offer to the remote peer the opportunity to try to send audio - offerToReceiveVideo: false, // offer to the remote peer the opportunity to try to send video - voiceActivityDetection: false, - iceRestart: false - }; - if( offerOptions ) { - this.offerOptions.offerToReceiveAudio = ( "offerToReceiveAudio" in offerOptions && offerOptions.offerToReceiveAudio ) ? true : false; - this.offerOptions.offerToReceiveVideo = ( "offerToReceiveVideo" in offerOptions && offerOptions.offerToReceiveVideo ) ? true : false; - this.offerOptions.voiceActivityDetection = ( "voiceActivityDetection" in offerOptions && offerOptions.voiceActivityDetection ) ? true : false; - this.offerOptions.iceRestart = ( "iceRestart" in offerOptions && offerOptions.iceRestart ) ? true : false; - } - // - this.signalingOptions = { - idCategory: "" + settings.rtcSpace.defaultSpaceCategory, - idSpace: "" + settings.rtcSpace.defaultSpaceName - }; - if( signalingOptions ) { - if( "idCategory" in signalingOptions && typeof signalingOptions.idCategory == "string" && signalingOptions.idCategory.length > 0 ) - this.signalingOptions.idCategory = "" + signalingOptions.idCategory; - if( "idSpace" in signalingOptions && typeof signalingOptions.idSpace == "string" && signalingOptions.idSpace.length > 0 ) - this.signalingOptions.idSpace = "" + signalingOptions.idSpace; - } - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.signalingPipeClose(); - this.idSomebodyCreator = null; - this.strSignalingServerURL = null; - this.bWasImpersonated = false; - super.dispose(); - } - describe( strInstanceType, arrAdditionalProps ) { - strInstanceType = ( strInstanceType == null || strInstanceType == undefined || ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) - ? ( this.isCreator ? "creator" : ( this.isJoiner ? "joiner" : "actor" ) ) - : strInstanceType; - // arrAdditionalProps = arrAdditionalProps || []; - return super.describe( strInstanceType, arrAdditionalProps ); - } - onError( err ) { - super.onError( err ); - } - signalingPipeOpen() { - try { - const self = this; - self.signalingPipeClose(); - self.dispatchEvent( new UniversalDispatcherEvent( "signalingWillStart", { detail: { actor: this } } ) ); - self.signalingPipe = new WebSocketClientPipe( self.strSignalingServerURL ); - self.signalingPipe.on( "open", function( eventData ) { self.signalingPipeOnOpen( eventData ); } ); - self.signalingPipe.on( "close", function( eventData ) { self.signalingPipeOnClose( eventData ); } ); - self.signalingPipe.on( "error", function( eventData ) { self.signalingPipeOnError( eventData ); } ); - self.signalingPipe.on( "message", function( eventData ) { self.signalingPipeOnRawMessage( eventData ); } ); - self.dispatchEvent( new UniversalDispatcherEvent( "signalingDidStarted", { detail: { actor: this } } ) ); - } catch ( err ) { - if( settings.logging.net.signaling.error ) - console.warn( this.describe() + " error starting signaling pipe:", err ); - this.onError( err ); - } - } - signalingPipeClose() { - if( this.signalingPipe ) { - try { - if( settings.logging.net.signaling.disconnect ) - console.warn( this.describe() + " will close signaling pipe" ); - this.signalingPipe.offAll(); - this.signalingPipe.disconnect(); - if( settings.logging.net.signaling.disconnect ) - console.warn( this.describe() + " did closed signaling pipe" ); - } catch ( err ) { - if( settings.logging.net.signaling.error ) - console.warn( this.describe() + " error closing signaling pipe:", err ); - } - this.signalingPipe = null; - this.dispatchEvent( new UniversalDispatcherEvent( "signalingClosed", { detail: { actor: this } } ) ); - } - } - signalingPipeOnOpen( eventData ) { - try { - this.dispatchEvent( new UniversalDispatcherEvent( "signalingOpened", { detail: { actor: this } } ) ); - if( settings.logging.net.signaling.connect ) - console.log( "+++ " + this.describe() + " did connected to " + this.strSignalingServerURL ); - const joImpersonateMessage = { - id: utils.randomCallID(), - method: "signalingImpersonate", - idCategory: "" + this.signalingOptions.idCategory, - idSpace: "" + this.signalingOptions.idSpace, - idRtcParticipant: "" + this.idRtcParticipant, - role: this.isCreator ? "creator" : "joiner" - }; - if( settings.logging.net.signaling.message ) - console.log( " <<< " + this.describe() + " message out", joImpersonateMessage ); - this.signalingPipe.send( joImpersonateMessage ); - } catch ( err ) { - if( settings.logging.net.signaling.error ) - console.warn( this.describe() + " error sending impersonation to signaling pipe:", err ); - this.onError( err ); - } - } - signalingPipeOnClose( eventData ) { - this.dispatchEvent( new UniversalDispatcherEvent( "signalingPipeClose", { detail: { actor: this } } ) ); - if( settings.logging.net.signaling.disconnect ) - console.warn( " !!! " + this.describe() + " signaling pipe closed for " + this.strSignalingServerURL ); - this.signalingPipeClose(); - } - signalingPipeOnError( eventData ) { - // alert( JSON.stringify( eventData ) ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingPipeError", { detail: { actor: this, error: eventData } } ) ); - if( settings.logging.net.signaling.error ) - console.warn( " !!! " + this.describe() + " signaling pipe error for " + this.strSignalingServerURL + ", error is:", eventData ); - this.onError( eventData ); - this.signalingPipeClose(); - } - signalingPipeOnRawMessage( eventData ) { - try { - if( settings.logging.net.signaling.rawMessage ) - console.log( " >>> " + this.describe() + " raw signaling message received", eventData ); - const joMessage = eventData.message; - if( settings.logging.net.signaling.message ) - console.log( " >>> " + this.describe() + " signaling message received", joMessage ); - this.signalingPipeOnMessage( joMessage ); - } catch ( err ) { - if( settings.logging.net.signaling.error ) - console.warn( "Error handling raw message in " + this.describe() + ":", err ); - this.onError( err ); - } - } - signalingPipeOnMessage( joMessage ) { - switch ( joMessage.method ) { - case "signalingImpersonate": { - if( joMessage.error == null ) { - // OKay, impersonated - this.bWasImpersonated = true; - if( settings.logging.net.signaling.generic ) - console.log( "Success, " + this.describe() + " impersonated on signaling server" ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingPassedImpersonation", { detail: { actor: this } } ) ); - this.onImpersonationComplete(); - } else { - if( settings.logging.net.signaling.error ) - console.warn( " >>> " + this.describe() + " signaling impersonation error", joMessage.error ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingFailedImpersonation", { detail: { actor: this, error: joMessage.error } } ) ); - this.onError( joMessage.error ); - } - } break; - default: - if( settings.logging.net.signaling.error ) - console.warn( " >>> " + this.describe() + " unhandled signaling message", joMessage ); - break; - } // switch( joMessage.method ) - } - onImpersonationComplete() { } - onOtherSideIdentified( idSomebodyOtherSide, idOffer ) { } // generic implementation should never be called -}; - -class RTCServerPeer extends RTCConnection { - constructor( rtcCreator, timeToPublishMilliseconds, timeToSignalingNegotiationMilliseconds, peerConfiguration, peerAdditionalOptions, localMediaStream ) { - super(); - this.rtcCreator = rtcCreator; - this.idSomebodyOtherSide = null; - this.idOffer = this.rtcCreator.idOfferNext ++; - this.tsOfferCreated = null; - if( settings.logging.net.signaling.offerRegister ) - console.log( "Register offer", this.idOffer, "(RTCServerPeer constructor)" ); - this.rtcCreator.map_server_offers[0 + this.idOffer] = this; - this.isPublishing = false; - this.isSignalingNegotiation = false; - this.isPublishTimeout = false; - this.isSignalingNegotiationTimeout = false; - this.timerPublishing = null; - this.timerSignalingNegotiation = null; - this.timeToPublishMilliseconds = timeToPublishMilliseconds - ? parseInt( timeToPublishMilliseconds, 10 ) - : settings.net.rtc.timeToPublishMilliseconds; - this.timeToSignalingNegotiationMilliseconds = timeToSignalingNegotiationMilliseconds - ? parseInt( timeToSignalingNegotiationMilliseconds, 10 ) - : settings.net.rtc.timeToSignalingNegotiationMilliseconds; - this.peerConfiguration = ( peerConfiguration && typeof peerConfiguration == "object" ) ? peerConfiguration : settings.net.rtc.peerConfiguration; - this.peerAdditionalOptions = ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; - this.localMediaStream = ( localMediaStream != null && localMediaStream != undefined && typeof localMediaStream == "object" ) ? localMediaStream : null; - this.isOfferPublishedOnSignalingServer = false; - this.initPeer(); - this.publish(); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.publishCancel(); - this.signalingNegotiationCancel(); - if( this.rtcCreator ) { - if( this.idOffer in this.rtcCreator.map_server_offers ) { - if( settings.logging.net.signaling.offerUnregister ) - console.log( "Unregister offer", this.idOffer, "(RTCServerPeer dispose)" ); - delete this.rtcCreator.map_server_offers[this.idOffer]; - } - this.idOffer = 0; - } - this.idOffer = 0; - if( this.idSomebodyOtherSide != null ) { - if( this.idSomebodyOtherSide in this.rtcCreator.map_server_peers ) - delete this.rtcCreator.map_server_peers[this.idSomebodyOtherSide]; - - this.idSomebodyOtherSide = null; - } - this.rtcCreator = null; - this.tsOfferCreated = null; - super.dispose(); - } - describe( strInstanceType, arrAdditionalProps ) { - strInstanceType = ( strInstanceType == null || strInstanceType == undefined || ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) - ? "server-peer" - : strInstanceType; - // arrAdditionalProps = arrAdditionalProps || []; - return super.describe( strInstanceType, arrAdditionalProps ); - } - initPeer() { - if( this.isDisposed ) - return; - const self = this; - if( self.pc ) - return; - self.pc = new wrtc_mod.RTCPeerConnection( self.peerConfiguration, self.peerAdditionalOptions ); - if( self.localMediaStream ) { - for( const track of self.localMediaStream.getTracks() ) - self.pc.addTrack( track, self.localMediaStream ); - } else { - self.dc = self.pc.createDataChannel( settings.net.rtc.dataChannel.label, settings.net.rtc.dataChannel.opts ); - self.dc.addEventListener( "open", function( event ) { self.onDataChannelOpen( event ); } ); - self.dc.addEventListener( "close", function( event ) { self.onDataChannelClose( event ); } ); - self.dc.addEventListener( "error", function( event ) { self.onDataChannelError( event ); } ); - self.dc.addEventListener( "message", function( event ) { self.onDataChannelMessage( event ); } ); - } - } - publishCancel() { - if( ! this.isPublishing ) - return; - this.isOfferPublishedOnSignalingServer = false; - this.isPublishing = false; - if( this.timerPublishing ) { - clearTimeout( this.timerPublishing ); - this.timerPublishing = null; - } - this.signalingNegotiationCancel(); // mutual cancel - } - signalingNegotiationCancel() { - if( ! this.isSignalingNegotiation ) - return; - this.isSignalingNegotiation = false; - if( this.timerSignalingNegotiation ) { - clearTimeout( this.timerSignalingNegotiation ); - this.timerSignalingNegotiation = null; - } - this.publishCancel(); // mutual cancel - } - publish() { - if( this.isDisposed || this.isPublishing || this.isSignalingNegotiation || ( !this.rtcCreator ) || ( !this.rtcCreator.signalingPipe ) ) - return; - const self = this; - self.isPublishing = true; - if( self.timeToPublishMilliseconds > 0 ) { - self.isSignalingNegotiation = false; - self.timerPublishing = setTimeout( function() { - self.publishCancel(); - self.signalingNegotiationCancel(); - self.isPublishTimeout = true; - if( settings.logging.net.signaling.publishTimeout ) - console.warn( " !!! " + self.describe() + " offer publish timeout " + self.timeToPublishMilliseconds + " milliseconds reached" ); - self.dispatchEvent( new UniversalDispatcherEvent( "publishTimeout", { detail: { participant: self } } ) ); - if( self.rtcCreator ) - self.rtcCreator.dispatchEvent( new UniversalDispatcherEvent( "publishTimeout", { detail: { participant: self } } ) ); - }, self.timeToPublishMilliseconds ); - } // if( self.timeToPublishMilliseconds > 0 ) - self.dispatchEvent( new UniversalDispatcherEvent( "publishStart", { detail: { participant: self } } ) ); - self.pc.oniceconnectionstatechange = function( event ) { self.onIceConnectionStateChange( event ); }; - self.pc.onicegatheringstatechange = function( event ) { self.onIceGatheringStateChange( event ); }; - self.pc.onidentityresult = function( event ) { self.onIceIdentifyResult( event ); }; - self.pc.onsignalingstatechange = function( event ) { self.onIceSignalingStateChange( event ); }; - self.pc.onnegotiationneeded = function( event ) { self.onIceNegotiationNeeded( event ); }; - self.pc.createOffer( self.offerOptions ).then( - function( offerDescription ) { - // success - self.tsOfferCreated = new Date(); - if( settings.logging.net.signaling.offer ) - console.log( " <<< " + self.describe() + " offer created at " + utils.format_date_time( self.tsOfferCreated ) + " with description:", offerDescription ); - self.dispatchEvent( new UniversalDispatcherEvent( "offerCreated", { detail: { participant: self } } ) ); - self.pc.setLocalDescription( offerDescription ).then( - function() { - // success - if( settings.logging.net.signaling.localDescription ) - console.log( " <<< " + self.describe() + " local description set:", offerDescription ); - self.dispatchEvent( new UniversalDispatcherEvent( "localDescriptionSet", { detail: { participant: self } } ) ); - self.pc.onicecandidate = function( event ) { - self.iceComplete = true; - self.onIceComplete( event ); - }; // onicecandidate - }, function( err ) { - // error of setLocalDescription - self.publishCancel(); - self.signalingNegotiationCancel(); - self.onError( "Failed to set local description: " + err.toString() ); - } ); - }, function() { - self.publishCancel(); - self.signalingNegotiationCancel(); - // error of createOffer - self.onError( "Failed to create offer:" + err.toString() ); - } ); - } - onOtherSideIdentified( idSomebodyOtherSide ) { - this.publishCancel(); - this.signalingNegotiationCancel(); - this.idSomebodyOtherSide = "" + idSomebodyOtherSide; - this.wasIdentified = true; - this.dispatchEvent( new UniversalDispatcherEvent( "identified", { detail: { participant: this, idSomebodyOtherSide: "" + idSomebodyOtherSide } } ) ); - } - onError( err ) { - if( this.rtcCreator ) { - this.rtcCreator.onRtcPeerError( this, err ); - if( this.idOffer in this.rtcCreator.map_server_offers ) { - if( settings.logging.net.signaling.offerUnregister ) - console.log( "Unregister offer", this.idOffer, "due to RTCServerPeer error:".err ); - delete this.rtcCreator.map_server_offers[this.idOffer]; - } - this.idOffer = 0; - } - if( this.idSomebodyOtherSide != null ) { - if( this.idSomebodyOtherSide in this.rtcCreator.map_server_peers ) - delete this.rtcCreator.map_server_peers[this.idSomebodyOtherSide]; - this.idSomebodyOtherSide = null; - } - super.onError( err ); - } - onImpersonationCompleteForCreator() { // specific for server peer - if( settings.logging.net.signaling.creatorImpersonationComplete ) - console.log( "Creator impersonation complete" ); - } - publishOfferOnSignalingServer() { - const self = this; - try { - if( settings.logging.net.signaling.candidate ) - console.log( " <<< " + self.describe() + " got candidate", event ); - if( settings.logging.net.signaling.candidate ) - console.log( " <<< " + self.describe() + " got candidate", event ); - if( ! self.rtcCreator.signalingPipe ) - throw new Error( "no connection to signaling server" ); - const joPublishOfferMessage = { - id: utils.randomCallID(), - method: "signalingPublishOffer", - offer: self.pc.localDescription, - idSomebodyCreator: "" + self.rtcCreator.idRtcParticipant, - idOffer: 0 + self.idOffer - }; - if( settings.logging.net.signaling.message ) - console.log( " <<< " + self.describe() + " signaling message out", joPublishOfferMessage ); - self.rtcCreator.signalingPipe.send( joPublishOfferMessage ); - self.publishCancel(); - self.dispatchEvent( new UniversalDispatcherEvent( "signalingNegotiationStart", { detail: { participant: self } } ) ); - if( self.timeToSignalingNegotiationMilliseconds > 0 ) { - self.isSignalingNegotiation = true; - self.timerSignalingNegotiation = setTimeout( function() { - self.publishCancel(); - self.signalingNegotiationCancel(); - self.isSignalingNegotiationTimeout = true; - if( settings.logging.net.signaling.signalingNegotiationTimeout ) - console.warn( " !!! " + self.describe() + " signaling negotiation timeout " + self.timeToSignalingNegotiationMilliseconds + " milliseconds reached" ); - self.dispatchEvent( new UniversalDispatcherEvent( "signalingNegotiationTimeout", { detail: { participant: self } } ) ); - if( self.rtcCreator ) - self.rtcCreator.dispatchEvent( new UniversalDispatcherEvent( "signalingNegotiationTimeout", { detail: { participant: self } } ) ); - }, self.timeToSignalingNegotiationMilliseconds ); - } // if( self.timeToSignalingNegotiationMilliseconds > 0 ) - } catch ( err ) { - throw err; - } - } - onIceComplete( event ) { - super.onIceComplete( event ); - const self = this; - try { - if( event.candidate == null || settings.net.rtc.fastPublishMode.serverPeer ) { - if( ! self.isOfferPublishedOnSignalingServer ) { - self.isOfferPublishedOnSignalingServer = true; - self.publishOfferOnSignalingServer(); - } - } - if( event.candidate != null ) { - if( settings.logging.net.signaling.candidateWalk ) - console.log( " <<< " + self.describe() + " got candidate", event ); - } - } catch ( err ) { - self.publishCancel(); - self.signalingNegotiationCancel(); - self.onError( "Failed to process ICE candidate: " + err.toString() ); - } - } -}; - -class RTCCreator extends RTCActor { - constructor( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions ) { - super( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions ); - const self = this; - self.idOfferNext = 1; - self.isCreator = true; - self.map_server_offers = { }; // idOffer -> RTCServerPeer - self.map_server_peers = { }; // idSomebodyOtherSide -> RTCServerPeer - self.signalingPipeOpen(); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - for( const [ idOffer, rtcPeer ] of Object.entries( this.map_server_offers ) ) { - if( settings.logging.net.signaling.offerUnregister ) - console.log( "Unregister offer", idOffer, "(one of all, RTCCreator dispose)" ); - rtcPeer.dispose(); - } - for( const [ /*idSomebodyOtherSide*/, rtcPeer ] of Object.entries( this.map_server_peers ) ) - rtcPeer.dispose(); - this.map_server_offers = { }; - // self.idOfferNext = 0; - super.dispose(); - } - describe( strInstanceType, arrAdditionalProps ) { - strInstanceType = ( strInstanceType == null || strInstanceType == undefined || ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) - ? "rtc-creator" - : strInstanceType; - // arrAdditionalProps = arrAdditionalProps || []; - return super.describe( strInstanceType, arrAdditionalProps ); - } - onOtherSideIdentified( idSomebodyOtherSide, idOffer ) { // server peer got result - if( settings.logging.net.signaling.impersonate ) - console.log( this.describe() + " did identified other side RTC joiner \"" + idSomebodyOtherSide + "\" via offer ID " + idOffer.toString() ); - if( ! ( idOffer in this.map_server_offers ) ) { - const strError = "not a registered pending offer(onOtherSideIdentified)"; - if( settings.logging.net.signaling.error ) - console.warn( " >>> " + this.describe() + " came across with incorrect other side identification for *somebody*", idSomebodyOtherSide, "and offer ID", idOffer, ":".strError ); - this.onError( strError ); - return; - } - const rtcPeer = this.map_server_offers[idOffer]; - if( settings.logging.net.signaling.offerUnregister ) - console.log( "Unregister offer", idOffer, "(onOtherSideIdentified in RTCCreator)" ); - delete this.map_server_offers[idOffer]; - this.map_server_peers["" + idSomebodyOtherSide] = rtcPeer; - rtcPeer.onOtherSideIdentified( "" + idSomebodyOtherSide ); - } - onRtcPeerError( rtcPeer, err ) { - if( settings.logging.net.rtc.error ) - console.warn( " !!! " + this.describe() + " rtc peer error", err ); - this.dispatchEvent( new UniversalDispatcherEvent( "rtcPeerError", { detail: { actor: this, peer: rtcPeer, error: err } } ) ); - } - signalingPipeOnMessage( joMessage ) { - const self = this; - switch ( joMessage.method ) { - case "signalingPublishOffer": { - if( joMessage.error == null ) { - // OKay, creator offer published - if( settings.logging.net.signaling.offer ) - console.log( "Success, " + this.describe() + " offer published (step 1)" ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingPassedOfferPublish", { detail: { actor: this } } ) ); - } else { - if( settings.logging.net.signaling.error ) - console.warn( " !!! " + this.describe() + " signaling offer publishing (step 1) error", joMessage.error ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingFailedOfferPublish", { detail: { actor: this, error: joMessage.error } } ) ); - this.onError( joMessage.error ); - } - } break; - case "signalingPublishAnswer": { // server peer got result - if( joMessage.error == null ) { - const idSomebodyOtherSide = "" + joMessage.idSomebody_joiner; - const idOffer = 0 + joMessage.idOffer; - if( ! ( idOffer in this.map_server_offers ) ) { - const strError = "not a registered pending offer(signalingPublishAnswer)"; - if( settings.logging.net.signaling.error ) - console.warn( " !!! " + this.describe() + " came across with incorrect signalingPublishAnswer message for *somebody*", idSomebodyOtherSide, "and offer ID", idOffer, ":", strError ); - this.onError( strError ); - return; - } - const rtcPeer = this.map_server_offers[idOffer]; - // OKay, finally got answer from candida - if( settings.logging.net.signaling.generic ) - console.log( "Success, " + this.describe() + " got answer from candidate (step 3)" ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingPassedPublishAnswer", { detail: { actor: this, idSomebodyOtherSide: "" + idSomebodyOtherSide, idOffer: 0 + idOffer } } ) ); - const answer = joMessage.answer; - if( settings.logging.net.signaling.offer ) - console.log( " >>> " + self.describe() + " got answer:", answer ); - const answerDescription = new wrtc_mod.RTCSessionDescription( answer ); - if( settings.logging.net.signaling.offer ) - console.log( " >>> " + self.describe() + " got answer description:", answerDescription ); - // console.log( "----- will set remote desc when in state", rtcPeer.pc.signalingState ); - if( rtcPeer.pc.signalingState != "have-local-offer" ) { - if( settings.logging.net.signaling.offerSkipPublishedAnswer ) - console.warn( " >>> " + self.describe() + " in \"" + rtcPeer.pc.signalingState + "\" state will skip setting remote description from answer", answerDescription ); - return; - } - rtcPeer.pc.setRemoteDescription( answerDescription ).then( - function() { - // success - if( settings.logging.net.signaling.remoteDescription ) - console.log( " >>> " + self.describe() + "did set remote description:", answerDescription ); - self.dispatchEvent( new UniversalDispatcherEvent( "remoteDescriptionSet", { detail: { participant: self } } ) ); - self.onOtherSideIdentified( idSomebodyOtherSide, idOffer ); // server peer got result - }, function( err ) { - // error - self.onError( "Failed to set remote description: " + err.toString() ); - } ); - } else { - if( settings.logging.net.signaling.error ) - console.warn( " !!! " + this.describe() + " error getting candidate answer (step 1) error", joMessage.error ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingFailedPublishAnswer", { detail: { actor: this, error: joMessage.error } } ) ); - this.onError( joMessage.error ); - } - } break; - default: - super.signalingPipeOnMessage( joMessage ); - break; - } // switch( joMessage.method ) - } - send( data ) { // implementation in RTCCreator does send to all - try { - const s = socket_sent_data_marshall( data ); - for( const [ /*idSomebodyOtherSide*/, rtcPeer ] of Object.entries( this.map_server_peers ) ) { - try { - rtcPeer.send( s ); - } catch ( err ) { - this.onRtcPeerError( rtcPeer, err ); - } - } - } catch ( err ) { - this.onError( err ); - } - } - onImpersonationComplete() { - super.onImpersonationComplete(); - for( const [ /*idOffer*/, rtcPeer ] of Object.entries( this.map_server_offers ) ) - rtcPeer.onImpersonationCompleteForCreator(); - for( const [ /*idSomebodyOtherSide*/, rtcPeer ] of Object.entries( this.map_server_peers ) ) - rtcPeer.onImpersonationCompleteForCreator(); - } -}; - -class RTCJoiner extends RTCActor { - constructor( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions, peerConfiguration, peerAdditionalOptions ) { - super( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions ); - this.idSomebodyOtherSide = null; - this.idOffer = 0; - this.isJoiner = true; - this.tsAnswerCreated = null; - this.isAnswerPublishedOnSignalingServer = false; - this.signalingPipeOpen(); - this.peerConfiguration = ( peerConfiguration && typeof peerConfiguration == "object" ) ? peerConfiguration : settings.net.rtc.peerConfiguration; - this.peerAdditionalOptions = ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; - // this.initPeer(); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.idSomebodyOtherSide = null; - this.idOffer = 0; - this.tsAnswerCreated = null; - this.isAnswerPublishedOnSignalingServer = false; - super.dispose(); - } - describe( strInstanceType, arrAdditionalProps ) { - strInstanceType = ( strInstanceType == null || strInstanceType == undefined || ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) - ? "rtc-joiner" - : strInstanceType; - // arrAdditionalProps = arrAdditionalProps || []; - return super.describe( strInstanceType, arrAdditionalProps ); - } - initPeer() { - if( this.isDisposed ) - return; - const self = this; - if( self.pc ) - return; - self.pc = new wrtc_mod.RTCPeerConnection( self.peerConfiguration, self.peerAdditionalOptions ); - self.pc.addEventListener( "track", function( event ) { - self.dispatchEvent( new UniversalDispatcherEvent( "trackAvailable", { detail: { participant: self, event: event } } ) ); - } ); - self.pc.oniceconnectionstatechange = function( event ) { self.onIceConnectionStateChange( event ); }; - self.pc.onicegatheringstatechange = function( event ) { self.onIceGatheringStateChange( event ); }; - self.pc.onidentityresult = function( event ) { self.onIceIdentifyResult( event ); }; - self.pc.onsignalingstatechange = function( event ) { self.onIceSignalingStateChange( event ); }; - self.pc.onnegotiationneeded = function( event ) { self.onIceNegotiationNeeded( event ); }; - self.pc.ondatachannel = function( event ) { - self.dispatchEvent( new UniversalDispatcherEvent( "dataChannelAvailable", { detail: { participant: self, event: event } } ) ); - const dataChannel = event.channel || event; - self.dc = dataChannel; - self.dc.addEventListener( "open", function( event ) { self.onDataChannelOpen( event ); } ); - self.dc.addEventListener( "close", function( event ) { self.onDataChannelClose( event ); } ); - self.dc.addEventListener( "error", function( event ) { self.onDataChannelError( event ); } ); - self.dc.addEventListener( "message", function( event ) { self.onDataChannelMessage( event ); } ); - }; - self.pc.onicecandidate = function( event ) { - self.iceComplete = true; - self.onIceComplete( event ); - try { - if( ! self.signalingPipe ) { - if( self.dc ) - return; // already connected, ignore (Firefox fix) - // if( self.pc && self.pc.onicecandidate ) - // self.pc.onicecandidate = null; - throw new Error( "no connection to signaling server" ); - } - if( ! self.isAnswerPublishedOnSignalingServer ) { - self.publishSignalingAnswer( event ); - self.iAnswerPublishedOnSignalingServer = true; - } - if( event.candidate != null ) { - if( settings.logging.net.signaling.candidateWalk ) - console.log( " <<< " + self.describe() + " got candidate", event ); - } - } catch ( err ) { - // self.publishCancel(); - // self.signalingNegotiationCancel(); - self.onError( "Failed to process ICE candidate: " + err.toString() ); - } - }; // onicecandidate - } - publishSignalingAnswer( event ) { - const self = this; - try { - if( event.candidate == null || settings.net.rtc.fastPublishMode.joiner ) { - if( settings.logging.net.signaling.candidate ) - console.log( " <<< " + self.describe() + " got candidate", event ); - if( ! self.signalingPipe ) - throw new Error( "no connection to signaling server" ); - const joPublishAnswerMessage = { - id: utils.randomCallID(), - method: "signalingPublishAnswer", - answer: self.pc.localDescription, - idRtcParticipant: "" + self.idRtcParticipant, - idSomebodyCreator: "" + self.idSomebodyCreator, - idOffer: 0 + self.idOffer - }; - if( settings.logging.net.signaling.message ) - console.log( " <<< " + self.describe() + " signaling client message out", joPublishAnswerMessage ); - self.signalingPipe.send( joPublishAnswerMessage ); - } - } catch ( err ) { - throw err; - } - } - delayedInitPeer() { - if( this.bWasImpersonated ) - this.initPeer(); - } - onImpersonationComplete() { - super.onImpersonationComplete(); - const joFetchOfferMessage = { - id: utils.randomCallID(), - method: "signalingFetchOffer" - }; - if( settings.logging.net.signaling.message ) - console.log( " <<< " + this.describe() + " signaling client message out", joFetchOfferMessage ); - this.signalingPipe.send( joFetchOfferMessage ); - } - onIceComplete( event ) { - super.onIceComplete( event ); - } - onOtherSideIdentified( idSomebodyOtherSide, idOffer ) { // client peer got result - if( settings.logging.net.signaling.impersonate ) - console.log( this.describe() + " did identified other side RTC creator \"" + idSomebodyOtherSide + "\" via offer ID " + idOffer.toString() ); - this.idSomebodyOtherSide = "" + idSomebodyOtherSide; - this.idOffer = 0 + idOffer; - this.wasIdentified = true; - this.dispatchEvent( new UniversalDispatcherEvent( "identified", { detail: { participant: this, idSomebodyOtherSide: "" + idSomebodyOtherSide } } ) ); - } - signalingPipeOnMessage( joMessage ) { - const self = this; - switch ( joMessage.method ) { - case "signalingFetchOffer": { - if( joMessage.error == null ) { - // OKay, fetched offer from creator - this.delayedInitPeer(); - this.idSomebodyCreator = "" + joMessage.idSomebodyCreator; - const idSomebodyOtherSide = "" + joMessage.idSomebodyCreator; - const idOffer = 0 + joMessage.idOffer; - if( settings.logging.net.signaling.generic ) - console.log( "Success, " + this.describe() + " fetched offer from creator (step 2)" ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingPassedFetchOffer", { detail: { actor: this, idSomebodyOtherSide: "" + idSomebodyOtherSide, idOffer: 0 + idOffer } } ) ); - const offer = joMessage.offer; - if( settings.logging.net.signaling.offer ) - console.log( " <<< " + self.describe() + " got offer:", offer ); - const offerDescription = new wrtc_mod.RTCSessionDescription( offer ); - if( settings.logging.net.signaling.offer ) - console.log( " <<< " + self.describe() + " got offer description:", offerDescription ); - this.pc.setRemoteDescription( offerDescription ).then( - function() { - // success - if( settings.logging.net.signaling.remoteDescription ) - console.log( " <<< " + self.describe() + "did set remote description:", offerDescription ); - self.dispatchEvent( new UniversalDispatcherEvent( "remoteDescriptionSet", { detail: { participant: self } } ) ); - self.pc.createAnswer( self.offerOptions ).then( - function( answerDescription ) { - // success - self.tsAnswerCreated = new Date(); - if( settings.logging.net.signaling.answer ) - console.log( " <<< " + self.describe() + "did created answer at " + utils.format_date_time( self.tsAnswerCreated ) + " with description:", answerDescription ); - self.dispatchEvent( new UniversalDispatcherEvent( "answerCreated", { detail: { participant: self } } ) ); - self.pc.setLocalDescription( answerDescription ).then( - function() { - // success - if( settings.logging.net.signaling.localDescription ) - console.log( " <<< " + self.describe() + " local description set:", answerDescription ); - self.dispatchEvent( new UniversalDispatcherEvent( "localDescriptionSet", { detail: { participant: self } } ) ); - self.onOtherSideIdentified( idSomebodyOtherSide, idOffer ); // client peer got result - }, function( err ) { - // error of setLocalDescription - self.onError( "Failed to set local description (while fetching offer for \"" + idSomebodyOtherSide + "\"): " + err.toString() ); - } ); - }, function( err ) { - // error of createAnswer - self.onError( "Failed to create answer (while fetching offer for \"" + idSomebodyOtherSide + "\"): " + err.toString() ); - } ); - }, function( err ) { - // error of setLocalDescription - self.onError( "Failed to set remote description: (while fetching offer for \"" + idSomebodyOtherSide + "\"): " + err.toString() ); - } ); - } else { - if( settings.logging.net.signaling.error ) - console.warn( " !!! " + this.describe() + " signaling offer publishing (step 1) error", joMessage.error ); - this.dispatchEvent( new UniversalDispatcherEvent( "signalingFailedFetchOffer", { detail: { actor: this, error: joMessage.error } } ) ); - this.onError( joMessage.error ); - } - } break; - default: - super.signalingPipeOnMessage( joMessage ); - break; - } // switch( joMessage.method ) - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class WebRTCServerPipe extends BasicSocketPipe { - constructor( acceptor, rtcPeer, strSignalingServerURL ) { - super(); - const self = this; - self.socketType = "WebRTC"; - self.socketSubtype = "server"; - self.isConnected = true; - self.acceptor = acceptor; - self.clientNumber = 0 + acceptor.nextClientNumber; - self.clientPort = 0 + self.clientNumber; - ++ acceptor.nextClientNumber; - self.rtcPeer = rtcPeer; - self.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); - self.url = "rtc_server_pipe(" + self.clientNumber + ")://" + strSignalingServerURL; - // self.rtcPeer.on( "identified", function( event ) { - // if( settings.logging.net.signaling.generic ) - // console.log( self.describe() + " is now identified peer", event.detail.idSomebodyOtherSide ); - // } ); - self.rtcPeer.on( "dataChannelOpen", function( jo ) { - self.isConnected = true; - self.acceptor.mapClients["" + self.clientPort] = self; - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - self.acceptor.dispatchEvent( new UniversalDispatcherEvent( "connection", { socket: self, strSignalingServerURL: "" + strSignalingServerURL } ) ); - } ); - self.rtcPeer.on( "dataChannelMessage", function( jo ) { - self.receive( jo.detail.data ); - } ); - self.rtcPeer.on( "rtcParticipantError", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: jo } ) ); - } ); - self.rtcPeer.on( "dataChannelError", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: jo } ) ); - } ); - self.rtcPeer.on( "dataChannelClose", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: self, message: jo } ) ); - } ); - self.rtcPeer.on( "peerClose", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: self, message: jo } ) ); - } ); - } - dispose() { - this.performDisconnect(); - super.dispose(); - } - handleServerDisposed() { - this.performDisconnect(); - this.isConnected = false; - this.clientNumber = 0; - this.acceptor = null; - this.rtcPeer = null; - this.url = ""; - this.strSignalingServerURL = ""; - super.handleServerDisposed(); - this.dispose(); - } - performDisconnect() { - if( ! this.isConnected ) - return; - this.isConnected = false; - if( this.acceptor ) - this.acceptor.unregisterClientByKey( this.clientPort ); - if( this.rtcPeer ) { - this.rtcPeer.offAll(); - this.rtcPeer = null; - } - this.clientNumber = 0; - this.acceptor = null; - this.url = ""; - this.strSignalingServerURL = ""; - } - impl_send( data ) { - if( ( !this.isConnected ) || ( !this.rtcPeer ) ) { - const err = "Cannot send messages to disconnected WebRTC socket server pipe"; - this.onError( err ); - throw err; - } - const s = socket_sent_data_marshall( data ); - this.rtcPeer.send( s ); - } - disconnect() { - this.performDisconnect(); - super.disconnect(); - } - impl_receive( data ) { - const jo = socket_received_data_reverse_marshall( data ); - this.dispatchEvent( new UniversalDispatcherEvent( "message", { socket: this, message: jo } ) ); - } -}; - -class WebRTCServerAcceptor extends BasicServerAcceptor { - constructor( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions, maxActiveOfferCount, timeToPublishMilliseconds, timeToSignalingNegotiationMilliseconds, peerConfiguration, peerAdditionalOptions ) { - super(); - this.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); - this.idRtcParticipant = "" + ( ( idRtcParticipant != null && idRtcParticipant != undefined && typeof idRtcParticipant == "string" && idRtcParticipant.length > 0 ) ? idRtcParticipant : utils.uuid_v4() ); - this.offerOptions = offerOptions ? offerOptions : null; - this.signalingOptions = signalingOptions ? signalingOptions : null; - this.peerConfiguration = ( peerConfiguration && typeof peerConfiguration == "object" ) ? peerConfiguration : settings.net.rtc.peerConfiguration; - this.peerAdditionalOptions = ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; - this.socketType = "WebRTC"; - this.maxActiveOfferCount = ( maxActiveOfferCount != null && maxActiveOfferCount != undefined ) ? parseInt( maxActiveOfferCount, 10 ) : settings.net.rtc.maxActiveOfferCount; - if( this.maxActiveOfferCount < 1 ) - this.maxActiveOfferCount = 1; - this.mapPendingOffers = { }; // idOffer -> RTCServerPeer - this.timeToPublishMilliseconds = timeToPublishMilliseconds - ? parseInt( timeToPublishMilliseconds, 10 ) - : settings.net.rtc.timeToPublishMilliseconds; - this.timeToSignalingNegotiationMilliseconds = timeToSignalingNegotiationMilliseconds - ? parseInt( timeToSignalingNegotiationMilliseconds, 10 ) - : settings.net.rtc.timeToSignalingNegotiationMilliseconds; - this.rtcCreator = new RTCCreator( "" + this.strSignalingServerURL, "" + this.idRtcParticipant, this.offerOptions, this.signalingOptions ); - this.isListening = true; - const self = this; - this.rtcCreator.on( "signalingPassedImpersonation", function( eventData ) { - self.updateAllPendingOffers(); - self.dispatchEvent( new UniversalDispatcherEvent( "signalingPassedImpersonation", { detail: { acceptor: self } } ) ); - } ); - this.rtcCreator.on( "signalingFailedImpersonation", function( eventData ) { - self.dispatchEvent( new UniversalDispatcherEvent( "signalingFailedImpersonation", { detail: { acceptor: self } } ) ); - } ); - this.rtcCreator.on( "error", function( eventData ) { - self.dispatchEvent( new UniversalDispatcherEvent( "error", { detail: { acceptor: self, eventData: eventData, errorType: "rtcCreatorError" } } ) ); - } ); - this.rtcCreator.on( "close", function( eventData ) { - self.dispatchEvent( new UniversalDispatcherEvent( "close", { detail: { acceptor: self, eventData: eventData } } ) ); - } ); - self.rtcCreator.on( "signalingPipeError", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: jo, errorType: "signalingPipeError" } ) ); - } ); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.removeAllPendingOffers(); - if( this.rtcCreator ) { - this.rtcCreator.dispose(); - this.rtcCreator = null; - } - this.disposeNotifyClients(); - super.dispose(); - } - // flush() { - // if( this.isDisposed ) - // return; - // if( this.rtcCreator ) { - // for( const [ /*idSomebodyOtherSide*/, rtcPeer ] of Object.entries( this.rtcCreator.map_server_peers ) ) { - // const serverPipe = rtcPeer.serverPipe; - // serverPipe.flush(); - // } - // } - // } - addPendingOffer() { - if( this.isDisposed ) - return; - const rtcPeer = new RTCServerPeer( this.rtcCreator, this.timeToPublishMilliseconds, this.timeToSignalingNegotiationMilliseconds, this.peerConfiguration, this.peerAdditionalOptions ); - const self = this; - rtcPeer.on( "identified", function( event ) { - if( rtcPeer.isDisposing || rtcPeer.isDisposed ) - return; - if( settings.logging.net.signaling.generic ) - console.log( self.rtcCreator.describe() + " is now identified peer", event.detail.idSomebodyOtherSide ); - rtcPeer.serverPipe = new WebRTCServerPipe( self, rtcPeer, self.strSignalingServerURL ); - self.detachPendingOffer( rtcPeer.idOffer ); - self.dispatchEvent( new UniversalDispatcherEvent( "identified", { detail: { peer: rtcPeer } } ) ); - self.updateAllPendingOffers(); - } ); - rtcPeer.on( "localDescriptionSet", function( event ) { - self.dispatchEvent( new UniversalDispatcherEvent( "peerLocalDescriptionSet", { detail: { acceptor: self, peerEvent: event } } ) ); - } ); - const onTimeoutHandler = function() { - self.disposePendingOffer( rtcPeer.idOffer ); - self.updateAllPendingOffers(); - }; - rtcPeer.on( "publishTimeout", onTimeoutHandler ); - rtcPeer.on( "signalingNegotiationTimeout", onTimeoutHandler ); - rtcPeer.on( "signalingNegotiationStart", function() { - self.updateAllPendingOffers(); - } ); - - const retranslateError = function( eventData ) { - self.dispatchEvent( new UniversalDispatcherEvent( "error", { detail: { acceptor: self, rtcPeer: rtcPeer, eventData: eventData, errorType: "rtcPeerError" } } ) ); - }; - rtcPeer.on( "error", retranslateError ); - rtcPeer.on( "rtcPeerError", retranslateError ); - - this.mapPendingOffers[rtcPeer.idOffer] = rtcPeer; - } - detachPendingOffer( idOffer ) { - if( idOffer in this.mapPendingOffers ) - delete this.mapPendingOffers[idOffer]; - } - disposePendingOffer( idOffer ) { - if( idOffer in this.mapPendingOffers ) { - const rtcPeer = this.mapPendingOffers[idOffer]; - rtcPeer.dispose(); - delete this.mapPendingOffers[idOffer]; - } - } - removeAllPendingOffers() { - for( const [ /*idOffer*/, rtcPeer ] of Object.entries( this.rtcCreator.map_server_peers ) ) { - const serverPipe = rtcPeer.serverPipe; - serverPipe.dispose(); - } - this.rtcCreator.map_server_peers = { }; - for( const [ /*idOffer*/, rtcPeer ] of Object.entries( this.rtcCreator.mapPendingOffers ) ) - rtcPeer.dispose(); - - this.mapPendingOffers = { }; - } - updateAllPendingOffers() { - if( this.isDisposed ) - return; - for( let n = Object.keys( this.mapPendingOffers ); n < this.maxActiveOfferCount; ++ n ) - this.addPendingOffer(); - } -}; - -class WebRTCClientPipe extends BasicSocketPipe { - constructor( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions, peerConfiguration, peerAdditionalOptions ) { - super(); - this.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); - this.idRtcParticipant = "" + ( ( idRtcParticipant != null && idRtcParticipant != undefined && typeof idRtcParticipant == "string" && idRtcParticipant.length > 0 ) ? idRtcParticipant : utils.uuid_v4() ); - this.offerOptions = offerOptions ? offerOptions : null; - this.signalingOptions = signalingOptions ? signalingOptions : null; - this.peerConfiguration = ( peerConfiguration && typeof peerConfiguration == "object" ) ? peerConfiguration : settings.net.rtc.peerConfiguration; - this.peerAdditionalOptions = ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; - this.socketType = "WebRTC"; - this.socketSubtype = "client"; - this.isConnected = false; - this.rtcPeer = null; - this.isAutoCloseSignalingPipeOnDataChannelOpen = settings.net.rtc.isAutoCloseSignalingPipeOnDataChannelOpen ? true : false; - this.url = "rtc_client_pipe-" + this.strSignalingServerURL; - this.reconnect(); - } - dispose() { - if( this.isDisposed ) - return; - this.isDisposing = true; - this.performDisconnect(); - this.strSignalingServerURL = null; - super.dispose(); - } - impl_send( data ) { - if( ( !this.isConnected ) || ( !this.rtcPeer ) ) { - const s = "Cannot send messages to disconnected WebRTC socket client pipe"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s, errorType: "dataSendError" } ) ); - throw new Error( s ); - } - const s = socket_sent_data_marshall( data ); - this.rtcPeer.send( s ); - } - reconnect() { - this.performDisconnect(); - this.rtc_connect( "" + this.strSignalingServerURL ); - } - disconnect() { - this.performDisconnect(); - super.disconnect(); - } - performDisconnect() { - if( ! this.isConnected ) - return; - this.rtc_disconnect(); - } - rtc_connect( strSignalingServerURL ) { - if( strSignalingServerURL.length == 0 ) { - const s = "Cannot connect signaling server \"" + strSignalingServerURL + "\", bad url"; - this.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: this, message: "" + s, errorType: "badSignalingServerURL" } ) ); - throw new Error( s ); - } - const self = this; - while( true ) { - try { - if( self.isConnected || self.rtcPeer ) - self.rtc_disconnect(); - self.rtcPeer = new RTCJoiner( "" + strSignalingServerURL, "" + self.idRtcParticipant, self.offerOptions, self.signalingOptions, self.peerConfiguration, self.peerAdditionalOptions ); // client side - self.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); - self.rtcPeer.on( "identified", function( event ) { - if( settings.logging.net.signaling.generic ) - console.log( self.rtcPeer.describe() + " is now identified peer", event.detail.idSomebodyOtherSide ); - } ); - self.rtcPeer.on( "dataChannelOpen", function( jo ) { - self.isConnected = true; - self.dispatchEvent( new UniversalDispatcherEvent( "open", { socket: self } ) ); - if( self.isAutoCloseSignalingPipeOnDataChannelOpen ) { - if( settings.logging.net.signaling.disconnect ) - console.warn( self.rtcPeer.describe() + " will auto-close signaling pipe(inside socket \"dataChannelOpen\" handler)" ); - self.rtcPeer.signalingPipeClose(); - } - } ); - self.rtcPeer.on( "dataChannelMessage", function( jo ) { - self.receive( jo.detail.data ); - } ); - self.rtcPeer.on( "rtcParticipantError", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: jo, errorType: "rtcParticipantError" } ) ); - } ); - self.rtcPeer.on( "dataChannelError", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: jo, errorType: "dataChannelError" } ) ); - } ); - self.rtcPeer.on( "dataChannelClose", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "close", { socket: self, message: jo } ) ); - } ); - self.rtcPeer.on( "signalingPipeError", function( jo ) { - self.isConnected = false; - self.dispatchEvent( new UniversalDispatcherEvent( "error", { socket: self, message: jo, errorType: "signalingPipeError" } ) ); - } ); - return; - } catch ( err ) { - console.warn( "WebRTC client connect error:", err ); - continue; - } - } // while( true ) - } - rtc_disconnect() { - if( this.rtcPeer ) { - this.rtcPeer.offAll(); - this.rtcPeer.dispose(); - this.rtcPeer = null; - } - this.isConnected = false; - this.url = ""; - } - impl_receive( data ) { - const jo = socket_received_data_reverse_marshall( data ); - this.dispatchEvent( new UniversalDispatcherEvent( "message", { socket: this, message: jo } ) ); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -module.exports = { - https_mod: https_mod, - ws_mod: ws_mod, - wrtc_mod: wrtc_mod, - set_https_mod: set_https_mod, - set_ws_mod: set_ws_mod, - set_wrtc_mod: set_wrtc_mod, - g_mapLocalServers: g_mapLocalServers, - socket_sent_data_marshall: socket_sent_data_marshall, - socket_received_data_reverse_marshall: socket_received_data_reverse_marshall, - update_socket_data_stats_for_message: update_socket_data_stats_for_message, - generate_socket_data_stats_JSON: generate_socket_data_stats_JSON, - BasicServerAcceptor: BasicServerAcceptor, - BasicSocketPipe: BasicSocketPipe, - NullSocketPipe: NullSocketPipe, - is_running_in_worker: is_running_in_worker, - g_map_awaiting_in_worker_clients: g_map_awaiting_in_worker_clients, - g_map_connected_in_worker_clients: g_map_connected_in_worker_clients, - out_of_worker_apis: out_of_worker_apis, - in_worker_apis: in_worker_apis, - InWorkerServerPipe: InWorkerServerPipe, - InWorkerSocketServerAcceptor: InWorkerSocketServerAcceptor, - OutOfWorkerSocketClientPipe: OutOfWorkerSocketClientPipe, - OutOfWorkerRelay: OutOfWorkerRelay, - OneToOneRelay: OneToOneRelay, - DirectPipe: DirectPipe, - LocalSocketServerPipe: LocalSocketServerPipe, - LocalSocketServerAcceptor: LocalSocketServerAcceptor, - LocalSocketClientPipe: LocalSocketClientPipe, - WebSocketServerPipe: WebSocketServerPipe, - WebSocketServerAcceptor: WebSocketServerAcceptor, - WebSocketClientPipe: WebSocketClientPipe, - RTCConnection: RTCConnection, - RTCActor: RTCActor, - RTCServerPeer: RTCServerPeer, - RTCCreator: RTCCreator, - RTCJoiner: RTCJoiner, - WebRTCServerPipe: WebRTCServerPipe, - WebRTCServerAcceptor: WebRTCServerAcceptor, - WebRTCClientPipe: WebRTCClientPipe -}; diff --git a/npms/skale-cool-socket/socket.mjs b/npms/skale-cool-socket/socket.mjs new file mode 100644 index 000000000..3b9ddf754 --- /dev/null +++ b/npms/skale-cool-socket/socket.mjs @@ -0,0 +1,3440 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE COOL SOCKET + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file socket.mjs + * @copyright SKALE Labs 2019-Present + */ + +import { UniversalDispatcherEvent, EventDispatcher } from "./eventDispatcher.mjs"; +import { settings } from "./socketSettings.mjs"; +import * as utils from "./socketUtils.mjs"; + +export let httpsModule = null; // server side only +export let wsModule = null; // server side only +export let webRtcModule = null; // server side only + +export function setHttpsModule( mod ) { + httpsModule = mod ? mod : null; +} +export function setWsModule( mod ) { + wsModule = mod ? mod : null; +} +export function setWebRtcModule( mod ) { + webRtcModule = mod ? mod : null; +} + +export const gMapLocalServers = { }; // used both for local and in-worker servers + +export const socketSentDataMarshall = function( data ) { + const s = data + ? ( ( typeof data == "string" ) + ? data + : ( ( typeof data == "object" ) ? JSON.stringify( data ) : data.toString() ) + ) + : ""; + return s; +}; +export const socketReceivedDataReverseMarshall = function( data ) { + try { + const jo = data + ? ( ( typeof data == "object" ) + ? data + : ( ( typeof data == "string" ) ? JSON.parse( data ) : data ) + ) + : { }; + return jo; + } catch ( err ) { + return { + "error": true, + "message": "data un-marshal error", + "data": data + }; + } +}; + +export const updateSocketDataStatsForMessage = function( joMessage, joStats ) { + let strMethod = "_N/A_"; + if( "method" in joMessage && + joMessage.method && + typeof joMessage.method == "string" + ) + strMethod = "" + joMessage.method; + if( strMethod in joStats ) + joStats[strMethod] ++; + else + joStats[strMethod] = 1; +}; +export const generateSocketDataStatsJSON = function( jo ) { + const joStats = {}; + if( "arrPackedMessages" in jo && + jo.arrPackedMessages && + typeof jo.arrPackedMessages == "object" + ) { + for( const joMessage of jo.arrPackedMessages ) + updateSocketDataStatsForMessage( joMessage, joStats ); + + } else + updateSocketDataStatsForMessage( jo, joStats ); + return joStats; +}; + +export class BasicServerAcceptor extends EventDispatcher { + constructor() { + super(); + this.socketType = "BasicAcceptor"; + this.socketSubtype = "acceptor"; + this.isListening = false; + this.strEndPoint = null; + this.nextClientNumber = 1; + this.mapClients = { }; + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.nextClientNumber = 1; + this.isListening = false; + this.disposeNotifyClients(); + super.dispose(); + } + disposeNotifyClients() { + for( const [ /*key*/, entry ] of Object.entries( this.mapClients ) ) { + if( ( "serverPipe" in entry ) && ( "clientPipe" in entry ) ) { + const pair = entry; + pair.serverPipe.handleServerDisposed(); + pair.clientPipe.handleServerDisposed(); + pair.serverPipe = null; + pair.clientPipe = null; + } else { + const pipe = entry; + pipe.handleServerDisposed(); + } + } + this.mapClients = { }; + } + unregisterClientByKey( key ) { + if( key in this.mapClients ) { + const entry = this.mapClients[key]; + if( entry ) { + if( ( "serverPipe" in entry ) && ( "clientPipe" in entry ) ) { + const pair = entry; + pair.serverPipe = null; + pair.clientPipe = null; + } + delete this.mapClients[key]; + } + } + } + flush() { + if( this.isDisposing || this.isDisposed ) + return; + for( const [ /*key*/, entry ] of Object.entries( this.mapClients ) ) { + if( ( "serverPipe" in entry ) && ( "clientPipe" in entry ) ) { + const pair = entry; + pair.serverPipe.flush(); + } else { + const pipe = entry; + pipe.flush(); + } + } + } + newDirectConnection() { + if( this.isDisposing || this.isDisposed ) + return null; + if( !this.isListening ) + return null; + const clientPipe = new DirectPipe( null, false ); + const serverPipe = new DirectPipe( clientPipe, false ); + serverPipe.acceptor = this; + this.mapClients["" + serverPipe.clientPort] = serverPipe; + const self = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + serverPipe.dispatchEvent( + new UniversalDispatcherEvent( "open", { "socket": serverPipe } ) ); + self.dispatchEvent( + new UniversalDispatcherEvent( + "connection", + { "socket": serverPipe, "remoteAddress": "" + self.url } ) ); + clientPipe.dispatchEvent( + new UniversalDispatcherEvent( "open", { "socket": clientPipe } ) ); + }, 0 ); + return clientPipe; + } +}; + +export class BasicSocketPipe extends EventDispatcher { + constructor() { + super(); + this.socketType = "N/A"; + this.socketSubtype = "N/A"; + this.url = "N/A"; + this.isConnected = true; + this.arrAccumulatedMessages = []; + this.maxAccumulatedMessagesCount = 0 + settings.net.pipe.maxAccumulatedMessagesCount; + this.relayClientSocket = null; // for relay only + this.mapImpersonatedEntries = { }; // for external in-app usage only + } + dispose() { + if( this.relayClientSocket ) { + this.relayClientSocket.dispose(); + this.relayClientSocket = null; + } + this.disposeImpersonatedEntries(); // for external in-app usage only + this.disconnect(); + this.arrAccumulatedMessages = []; + super.dispose(); + } + disposeImpersonatedEntries() { // for external in-app usage only + for( const [ /*key*/, entry ] of Object.entries( this.mapImpersonatedEntries ) ) { + try { + if( entry && "dispose" in entry && typeof entry.dispose == "function" ) + entry.dispose(); + } catch ( err ) { + } + } + this.mapImpersonatedEntries = { }; // for app usage + } + implSend( data ) { + throw new Error( + "BasicSocketPipe.implSend() must be overridden but calling it was attempted" ); + } + isAutoFlush() { + if( this.maxAccumulatedMessagesCount <= 1 ) + return true; + const cnt = this.arrAccumulatedMessages.length; + if( cnt == 0 || cnt < this.maxAccumulatedMessagesCount ) + return false; + return true; + } + socketDescription() { + return "" + + // + this.socketType + // + " " + // + this.socketSubtype + // + " " + this.url; + } + socketLoggingTextPrefix( strLogEventName ) { + return "" + strLogEventName + " " + this.socketDescription() + " -"; + } + send( data, isFlush ) { + if( this.isDisposed || ( !this.isConnected ) ) + return; + if( this.isAutoFlush() ) { + if( settings.logging.net.socket.send || settings.logging.net.socket.flush ) + console.log( this.socketLoggingTextPrefix( "send+flush" ), data ); + this.implSend( data ); + return; + } + isFlush = ( isFlush == undefined || isFlush == null ) ? true : ( isFlush ? true : false ); + const jo = socketReceivedDataReverseMarshall( data ); + if( settings.logging.net.socket.accumulate ) + console.log( this.socketLoggingTextPrefix( "accumulate" ), data ); + this.arrAccumulatedMessages.push( jo ); + if( isFlush ) + this.flush(); + } + flush() { + if( this.isDisposed || ( !this.isConnected ) ) + return; + const cnt = this.arrAccumulatedMessages.length; + if( cnt == 0 ) + return; + if( settings.logging.net.socket.flushCount ) + console.log( this.socketLoggingTextPrefix( "flush-count(" + cnt + ")" ) ); + let joSend = null; + if( cnt == 1 ) { + joSend = this.arrAccumulatedMessages[0]; + if( settings.logging.net.socket.flushOne || settings.logging.net.socket.flush ) + console.log( this.socketLoggingTextPrefix( "flush-one" ), joSend ); + } else { + joSend = { arrPackedMessages: this.arrAccumulatedMessages }; + if( settings.logging.net.socket.flushBlock || settings.logging.net.socket.flush ) + console.log( this.socketLoggingTextPrefix( "flush-block(" + cnt + ")" ), joSend ); + } + if( settings.logging.net.socket.flushMethodStats ) { + console.log( + this.socketLoggingTextPrefix( "flush-method-stats(" + cnt + ")" ), + generateSocketDataStatsJSON( joSend ) + ); + } + this.implSend( joSend ); + this.arrAccumulatedMessages = []; + if( this.relayClientSocket ) + this.relayClientSocket.flush(); + } + implReceive( data ) { + const jo = socketReceivedDataReverseMarshall( data ); + this.dispatchEvent( + new UniversalDispatcherEvent( "message", { "socket": this, "message": jo } ) ); + } + receive( data ) { + if( settings.logging.net.socket.receiveBlock ) + console.log( this.socketLoggingTextPrefix( "receive-block" ), data ); + const jo = socketReceivedDataReverseMarshall( data ); + if( "arrPackedMessages" in jo && + jo.arrPackedMessages && + typeof jo.arrPackedMessages == "object" + ) { + const cnt = jo.arrPackedMessages.length; + if( settings.logging.net.socket.receiveCount ) + console.log( this.socketLoggingTextPrefix( "receive-count(" + cnt + ")" ) ); + if( settings.logging.net.socket.receiveMethodStats ) { + console.log( + this.socketLoggingTextPrefix( "receive-method-stats(" + cnt + ")" ), + generateSocketDataStatsJSON( jo ) + ); + } + for( let i = 0; i < cnt; ++ i ) { + const joMessage = jo.arrPackedMessages[i]; + if( settings.logging.net.socket.receive ) + console.log( this.socketLoggingTextPrefix( "receive" ), joMessage ); + this.implReceive( joMessage ); + } + return; + } + if( settings.logging.net.socket.receiveCount ) + console.log( this.socketLoggingTextPrefix( "receive-count(" + 1 + ")" ) ); + if( settings.logging.net.socket.receiveMethodStats ) { + console.log( + this.socketLoggingTextPrefix( + "receive-method-stats(" + 1 + ")" ), generateSocketDataStatsJSON( jo ) ); + } + if( settings.logging.net.socket.receive ) + console.log( this.socketLoggingTextPrefix( "receive" ), jo ); + this.implReceive( jo ); + } + disconnect() { + this.isConnected = false; + } + reconnect() { + } +}; + +export class NullSocketPipe extends BasicSocketPipe { + constructor() { + super(); + this.socketType = "NULL"; + this.socketSubtype = "pipe"; + this.url = "NullUrl"; + this.isConnected = true; + } + dispose() { + this.isConnected = false; + super.dispose(); + } + implSend( data ) { + } + implReceive( data ) { + } + send( data ) { + } + receive( data ) { + } + flush() { + } +}; + +export const isRunningInWorker = function() { + if( self.document === undefined ) + return true; + return false; +}; + +// in-worker clients in connecting state +export const gMapAwaitingInWorkerClients = { }; +// in-worker clients in connecting state +export const gMapConnectedInWorkerClients = { }; + +export const outOfWorkerAPIs = { + "onMessage": function( worker, data ) { + const jo = socketReceivedDataReverseMarshall( data ); + if( ! ( "workerMessageType" in jo ) || + typeof jo.workerMessageType != "string" || + jo.workerMessageType.length == 0 ) + return false; // not a socket message + if( ! ( "workerEndPoint" in jo ) || + typeof jo.workerEndPoint != "string" || + jo.workerEndPoint.length == 0 ) + return false; // TO-DO: send error answer and return true + if( ! ( "workerUUID" in jo ) || + typeof jo.workerUUID != "string" || + jo.workerUUID.length == 0 ) + return false; // TO-DO: send error answer and return true + switch ( jo.workerMessageType ) { + case "inWorkerConnect": { + if( !( jo.workerUUID in gMapAwaitingInWorkerClients ) ) + return false; + const pipe = gMapAwaitingInWorkerClients[jo.workerUUID]; + pipe.performSuccessfulConnection(); + } return true; + case "inWorkerDisconnect": { + if( !( jo.workerUUID in gMapConnectedInWorkerClients ) ) + return false; + const pipe = gMapConnectedInWorkerClients[jo.workerUUID]; + pipe.performDisconnect(); + } return true; + case "inWorkerMessage": { + if( !( jo.workerUUID in gMapConnectedInWorkerClients ) ) + return false; + const pipe = gMapConnectedInWorkerClients[jo.workerUUID]; + pipe.receive( jo.data ); + } return true; + default: + return false; // TO-DO: send error answer and return true + } // switch( jo.workerMessageType ) + }, + "onSendMessage": function( worker, type, endpoint, workerUUID, data ) { + const jo = socketReceivedDataReverseMarshall( data ); + const joSend = { + "workerMessageType": + ( type && typeof type == "string" && type.length > 0 ) + ? type : "inWorkerMessage", + "workerEndPoint": endpoint, + "workerUUID": workerUUID, + "data": jo + }; + //worker.postMessage( socketReceivedDataReverseMarshall( joSend ) ); + worker.postMessage( socketSentDataMarshall( joSend ) ); + } +}; +export const inWorkerAPIs = { + "onMessage": function( data ) { + const jo = socketReceivedDataReverseMarshall( data ); + if( ! ( "workerMessageType" in jo ) || + typeof jo.workerMessageType != "string" || + jo.workerMessageType.length == 0 ) + return false; // not a socket message + if( ! ( "workerEndPoint" in jo ) || + typeof jo.workerEndPoint != "string" || + jo.workerEndPoint.length == 0 ) + return false; // TO-DO: send error answer and return true + if( ! ( "workerUUID" in jo ) || + typeof jo.workerUUID != "string" || + jo.workerUUID.length == 0 ) + return false; // TO-DO: send error answer and return true + if( ! ( jo.workerEndPoint in gMapLocalServers ) ) + return false; // TO-DO: send error answer and return true + const acceptor = gMapLocalServers[jo.workerEndPoint]; + switch ( jo.workerMessageType ) { + case "inWorkerConnect": + return acceptor.performAccept( jo ); + case "inWorkerDisconnect": + return acceptor.performDisconnect( jo ); + case "inWorkerMessage": + return acceptor.receiveForClientPort( jo.workerUUID, jo.data ); + default: + return false; // TO-DO: send error answer and return true + } // switch( jo.workerMessageType ) + }, + "onSendMessage": function( type, endpoint, workerUUID, data ) { + const jo = socketReceivedDataReverseMarshall( data ); + const joSend = { + "workerMessageType": + ( type && typeof type == "string" && type.length > 0 ) + ? type : "inWorkerMessage", + "workerEndPoint": endpoint, + "workerUUID": workerUUID, + "data": jo + }; + //postMessage( socketReceivedDataReverseMarshall( joSend ) ); + postMessage( socketSentDataMarshall( joSend ) ); + } +}; + +export class InWorkerServerPipe extends BasicSocketPipe { + constructor( acceptor, clientPort, fnSend ) { + super(); + this.socketType = "InWorker"; + this.socketSubtype = "server"; + this.isConnected = true; + this.acceptor = acceptor; + this.clientPort = "" + clientPort; + this.fnSend = fnSend || inWorkerAPIs.onSendMessage; + this.url = "in_worker_server_pipe://" + acceptor.strEndPoint + ":" + clientPort; + this.acceptor.mapClients[this.clientPort] = this; + this.fnSend( "inWorkerConnect", this.acceptor.strEndPoint, this.clientPort, {} ); + const self = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": self } ) ); + self.acceptor.dispatchEvent( + new UniversalDispatcherEvent( + "connection", { "socket": self, "remoteAddress": "" + self.url } ) ); + }, 0 ); + } + dispose() { + this.performDisconnect(); + super.dispose(); + } + handleServerDisposed() { + this.performDisconnect(); + this.isConnected = false; + this.dispatchEvent( new UniversalDispatcherEvent( "close", { "socket": this } ) ); + this.acceptor = null; + this.fnSend = null; + this.url = ""; + this.dispose(); + } + performDisconnect() { + if( ! this.isConnected ) + return; + this.fnSend( "inWorkerDisconnect", this.acceptor.strEndPoint, this.clientPort, {} ); + this.isConnected = false; + if( this.acceptor ) + this.acceptor.unregisterClientByKey( this.clientPort ); + this.dispatchEvent( new UniversalDispatcherEvent( "close", { "socket": this } ) ); + this.acceptor = null; + this.fnSend = null; + this.url = ""; + } + implSend( data ) { + if( ( !this.isConnected ) || ( !this.fnSend ) || typeof this.fnSend != "function" ) { + const s = "Cannot send messages to disconnected in-worker server pipe"; + this.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + const jo = socketReceivedDataReverseMarshall( data ); + this.fnSend( "inWorkerMessage", this.acceptor.strEndPoint, this.clientPort, jo ); + } + disconnect() { + this.performDisconnect(); + super.disconnect(); + } +}; + +export class InWorkerSocketServerAcceptor extends BasicServerAcceptor { + constructor( strEndPoint, fnSend ) { + super(); + this.socketType = "InWorker"; + this.strEndPoint = + ( strEndPoint && typeof strEndPoint == "string" && strEndPoint.length > 0 ) + ? strEndPoint : "default_local_endpoint"; + if( this.strEndPoint in gMapLocalServers ) { + const s = + "Cannot start in-worker socket server on already listening \"" + + this.strEndPoint + "\" endpoint"; + this.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + gMapLocalServers[this.strEndPoint] = this; + this.fnSend = fnSend || inWorkerAPIs.onSendMessage; + this.isListening = true; + const self = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": self } ) ); + }, 0 ); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.disposeNotifyClients(); + if( this.strEndPoint && + typeof this.strEndPoint == "string" && + this.strEndPoint.length > 0 + ) { + if( this.strEndPoint in gMapLocalServers ) + delete gMapLocalServers[this.strEndPoint]; + } + super.dispose(); + } + performAccept( jo ) { + if( jo.workerUUID in this.mapClients ) + return false; // TO-DO: send error answer and return true + new InWorkerServerPipe( this, "" + jo.workerUUID, this.fnSend ); + return true; + } + performDisconnect( jo ) { + if( ! ( jo.workerUUID in this.mapClients ) ) + return false; // TO-DO: send error answer and return true + const pipe = this.mapClients[jo.workerUUID]; + pipe.performDisconnect(); + return true; + } + receiveForClientPort( clientPort, jo ) { + if( ! ( clientPort in this.mapClients ) ) + return false; // TO-DO: send error answer and return true + const pipe = this.mapClients[clientPort]; + pipe.receive( jo ); + return true; + } +}; + +export class OutOfWorkerSocketClientPipe extends BasicSocketPipe { + constructor( strEndPoint, worker, fnSend ) { + super(); + this.socketType = "InWorker"; + this.socketSubtype = "client"; + this.isConnected = false; + this.worker = worker; + this.clientPort = utils.UUIDv4(); + this.strEndPoint = + ( strEndPoint && + typeof strEndPoint == "string" && + strEndPoint.length > 0 + ) + ? strEndPoint + : "default_in_worker_endpoint"; + this.url = "out_of_worker_client_pipe://" + this.strEndPoint + ":" + this.clientPort; + this.fnSend = fnSend || outOfWorkerAPIs.onSendMessage; + this.fnSend( this.worker, "inWorkerConnect", this.strEndPoint, this.clientPort, {} ); + gMapAwaitingInWorkerClients["" + this.clientPort] = this; + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.performDisconnect(); + if( this.clientPort in gMapAwaitingInWorkerClients ) + delete gMapAwaitingInWorkerClients[this.clientPort]; + super.dispose(); + } + performDisconnect() { + if( ! this.isConnected ) + return; + this.isConnected = false; + delete gMapConnectedInWorkerClients["" + this.clientPort]; + this.fnSend( this.worker, "inWorkerDisconnect", this.strEndPoint, this.clientPort, {} ); + this.dispatchEvent( new UniversalDispatcherEvent( "close", { "socket": this } ) ); + this.worker = null; + this.clientPort = ""; + this.strEndPoint = ""; + this.url = ""; + } + performSuccessfulConnection() { + delete gMapAwaitingInWorkerClients[this.clientPort]; + gMapConnectedInWorkerClients["" + this.clientPort] = this; + this.isConnected = true; + this.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": this } ) ); + } + implSend( data ) { + if( ( !this.isConnected ) || + ( !this.worker ) || + ( !this.fnSend ) || + typeof this.fnSend != "function" + ) { + const s = "Cannot send messages to disconnected in-worker client pipe"; + this.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { "socket": this, "message": "" + s } ) + ); + throw new Error( s ); + } + const jo = socketReceivedDataReverseMarshall( data ); + this.fnSend( this.worker, "inWorkerMessage", this.strEndPoint, this.clientPort, jo ); + } + disconnect() { + this.performDisconnect(); + super.disconnect(); + } +}; + +export class OutOfWorkerRelay extends EventDispatcher { + // eslint-disable-next-line max-lines-per-function + constructor( + strRelayName, acceptor, fnCreateClient, isAutoFlushIncoming, isAutoFlushOutgoing ) { + super(); + const self = this; + self.strRelayName = ( strRelayName != null && strRelayName != undefined && + typeof strRelayName == "string" && strRelayName.length > 0 ) + ? ( "" + strRelayName ) : "unnamed"; + self.isAutoFlushIncoming = + ( isAutoFlushIncoming == null || isAutoFlushIncoming == undefined ) + ? true : ( isAutoFlushIncoming ? true : false ); + self.isAutoFlushOutgoing = + ( isAutoFlushOutgoing == null || isAutoFlushOutgoing == undefined ) + ? true : ( isAutoFlushOutgoing ? true : false ); + if( ! acceptor ) { + throw new Error( "OutOfWorkerRelay \"" + self.strRelayName + + "\" needs acceptor for normal functionality" ); + } + if( typeof fnCreateClient != "function" ) { + throw new Error( "OutOfWorkerRelay \"" + self.strRelayName + + "\" needs callback to create connections to target server" ); + } + self.acceptor = acceptor; + self.fnCreateClient = fnCreateClient; + // eslint-disable-next-line max-lines-per-function + self.onConnection_ = function( eventData ) { + const pipeIncoming = eventData.socket; + let pipeOutgoing = null; + if( ( ! ( "remoteAddress" in eventData ) ) || + eventData.remoteAddress == null || eventData.remoteAddress == undefined ) + pipeIncoming.strSavedRemoteAddress = pipeIncoming.constructor.name; + else + pipeIncoming.strSavedRemoteAddress = "" + eventData.remoteAddress; + if( settings.logging.net.relay.connect ) { + console.log( "Relay \"" + self.strRelayName + + "\" got new external-client connection \"" + + pipeIncoming.strSavedRemoteAddress + "\"" ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "connection", { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress + } ) ); + // 1) configure incoming pipe + let _offAllPipeEventListeners = null; + let _onExternalPipeClose = function() { + if( settings.logging.net.relay.disconnect ) { + console.warn( "Relay \"" + self.strRelayName + + "\" external-client socket closed \"" + + pipeIncoming.strSavedRemoteAddress + "\"" ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "close", { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": true + } ) ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onRelayPipeClose = function() { + if( settings.logging.net.relay.disconnect ) { + console.warn( "Relay \"" + self.strRelayName + + "\" relay-client socket closed \"" + + pipeIncoming.strSavedRemoteAddress + "\"" ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "close", { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": false + } ) ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onExternalPipeError = function( eventData ) { + if( settings.logging.net.relay.error ) { + console.warn( "Relay client \"" + self.strRelayName + + "\" external-client socket error \"" + + pipeIncoming.strSavedRemoteAddress + "\"" ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "error", { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": true + } ) ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onRelayPipeError = function( eventData ) { + if( settings.logging.net.relay.error ) { + console.warn( "Relay client \"" + self.strRelayName + + "\" relay-client socket error \"" + + pipeIncoming.strSavedRemoteAddress + "\"" ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "error", { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": false + } ) ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onExternalPipeMessage = function( eventData ) { + if( settings.logging.net.relay.rawMessage ) { + console.log( "Relay \"" + self.strRelayName + "\" external-client socket \"" + + eventData.strSavedRemoteAddress + "\" raw message", eventData ); + } + const joMessage = eventData.message; + if( settings.logging.net.relay.message ) { + console.log( "Relay \"" + self.strRelayName + "\" external-client socket \"" + + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage ); + } + if( ! pipeOutgoing ) { + throw new Error( "Relay \"" + self.strRelayName + + "\" is not completely initialized and cannot transfer messages" ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "message", { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": true, + "message": joMessage + } ) ); + pipeOutgoing.send( joMessage ); + if( self.isAutoFlushIncoming ) + pipeOutgoing.flush(); + }; + let _onRelayPipeMessage = function( eventData ) { + if( settings.logging.net.relay.rawMessage ) { + console.log( "Relay \"" + self.strRelayName + "\" relay-client socket \"" + + eventData.strSavedRemoteAddress + "\" raw message", eventData ); + } + const joMessage = eventData.message; + if( settings.logging.net.relay.message ) { + console.log( "Relay \"" + self.strRelayName + "\" relay-client socket \"" + + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage ); + } + if( ! pipeOutgoing ) { + throw new Error( "Relay \"" + self.strRelayName + + "\" is not completely initialized and cannot transfer messages" ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "message", { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": false, + "message": joMessage + } ) ); + pipeOutgoing.send( joMessage ); + if( self.isAutoFlushOutgoing ) + pipeOutgoing.flush(); + }; + _offAllPipeEventListeners = function() { + if( _onExternalPipeClose ) { + pipeIncoming.off( "close", _onExternalPipeClose ); + _onExternalPipeClose = null; + } + if( _onExternalPipeError ) { + pipeIncoming.off( "error", _onExternalPipeError ); + _onExternalPipeError = null; + } + if( _onExternalPipeMessage ) { + pipeIncoming.off( "message", _onExternalPipeMessage ); + _onExternalPipeMessage = null; + } + if( pipeOutgoing.relayClientSocket ) { + if( _onRelayPipeClose ) { + pipeOutgoing.off( "close", _onRelayPipeClose ); + _onRelayPipeClose = null; + } + if( _onRelayPipeError ) { + pipeOutgoing.off( "error", _onRelayPipeError ); + _onRelayPipeError = null; + } + if( _onRelayPipeMessage ) { + pipeOutgoing.off( "message", _onRelayPipeMessage ); + _onRelayPipeMessage = null; + } + pipeOutgoing.disconnect(); + pipeOutgoing.dispose(); + } + pipeIncoming.disconnect(); + pipeIncoming.dispose(); + }; + pipeIncoming.on( "close", _onExternalPipeClose ); + pipeIncoming.on( "error", _onExternalPipeError ); + pipeIncoming.on( "message", _onExternalPipeMessage ); + // 2) configure outgoing relay client pipe + pipeOutgoing = pipeIncoming.relayClientSocket = self.fnCreateClient(); + if( ! pipeOutgoing ) { + pipeIncoming.dispose(); + throw new Error( "Relay \"" + self.strRelayName + + "\" failed to initialize relay-client socket to target server" ); + } + pipeOutgoing.on( "close", _onRelayPipeClose ); + pipeOutgoing.on( "error", _onRelayPipeError ); + pipeOutgoing.on( "message", _onRelayPipeMessage ); + }; + self.acceptor.on( "connection", self.onConnection_ ); + } + dispose() { + this.isDisposing = true; + if( this.acceptor ) + this.acceptor.off( "connection", this.onConnection_ ); + this.onConnection_ = null; + super.dispose(); + } + flush() { + if( this.acceptor ) + this.acceptor.flush(); + } +}; + +export class OneToOneRelay extends EventDispatcher { + // eslint-disable-next-line max-lines-per-function + constructor( + strRelayName, pipeIncoming, pipeOutgoing, isAutoFlushIncoming, isAutoFlushOutgoing + ) { + super(); + const self = this; + self.strRelayName = + ( strRelayName != null && strRelayName != undefined && + typeof strRelayName == "string" && strRelayName.length > 0 ) + ? ( "" + strRelayName ) : "unnamed"; + self.isAutoFlushIncoming = + ( isAutoFlushIncoming == null || isAutoFlushIncoming == undefined ) + ? true : ( isAutoFlushIncoming ? true : false ); + self.isAutoFlushOutgoing = + ( isAutoFlushOutgoing == null || isAutoFlushOutgoing == undefined ) + ? true : ( isAutoFlushOutgoing ? true : false ); + self.pipeIncoming = pipeIncoming; + self.pipeOutgoing = pipeOutgoing; + if( ( !( "strSavedRemoteAddress" in pipeIncoming ) ) || + pipeIncoming.strSavedRemoteAddress == null || + pipeIncoming.strSavedRemoteAddress == undefined ) + pipeIncoming.strSavedRemoteAddress = "" + pipeIncoming.constructor.name; + if( ( !( "strSavedRemoteAddress" in pipeOutgoing ) ) || + pipeOutgoing.strSavedRemoteAddress == null || + pipeOutgoing.strSavedRemoteAddress == undefined ) + pipeOutgoing.strSavedRemoteAddress = "" + pipeOutgoing.constructor.name; + + // 1) configure incoming pipe + let _offAllPipeEventListeners = null; + let _onIncomingPipeClose = function() { + if( settings.logging.net.relay.disconnect ) { + console.warn( + "Relay \"" + self.strRelayName + "\" incoming-client socket closed \"" + + pipeIncoming.strSavedRemoteAddress + "\"" + ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "close", + { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": true + } ) + ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onOutgoingPipeClose = function() { + if( settings.logging.net.relay.disconnect ) { + console.warn( + "Relay \"" + self.strRelayName + "\" outgoing-client socket closed \"" + + pipeIncoming.strSavedRemoteAddress + "\"" + ); + } + self.dispatchEvent( new UniversalDispatcherEvent( + "close", + { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": false + } ) + ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onIncomingPipeError = function( eventData ) { + if( settings.logging.net.relay.error ) { + console.warn( + "Relay client \"" + self.strRelayName + + "\" incoming-client socket error \"" + + pipeIncoming.strSavedRemoteAddress + "\"" + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": true + } ) + ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onOutgoingPipeError = function( eventData ) { + if( settings.logging.net.relay.error ) { + console.warn( + "Relay client \"" + self.strRelayName + + "\" outgoing-client socket error \"" + + pipeIncoming.strSavedRemoteAddress + "\"" + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": false + } ) + ); + if( _offAllPipeEventListeners ) { + _offAllPipeEventListeners(); + _offAllPipeEventListeners = null; + } + }; + let _onIncomingPipeMessage = function( eventData ) { + if( settings.logging.net.relay.rawMessage ) { + console.log( + "Relay \"" + self.strRelayName + "\" incoming-client socket \"" + + eventData.strSavedRemoteAddress + "\" raw message", eventData + ); + } + const joMessage = eventData.message; + if( settings.logging.net.relay.message ) { + console.log( + "Relay \"" + self.strRelayName + "\" incoming-client socket \"" + + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage + ); + } + if( ! pipeOutgoing ) { + throw new Error( + "Relay \"" + self.strRelayName + + "\" is not completely initialized and cannot transfer messages" + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "message", + { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": true, + "message": joMessage + } ) + ); + pipeOutgoing.send( joMessage ); + if( self.isAutoFlushIncoming ) + pipeOutgoing.flush(); + }; + let _onOutgoingPipeMessage = function( eventData ) { + if( settings.logging.net.relay.rawMessage ) { + console.log( + "Relay \"" + self.strRelayName + "\" outgoing-client socket \"" + + eventData.strSavedRemoteAddress + "\" raw message", eventData + ); + } + const joMessage = eventData.message; + if( settings.logging.net.relay.message ) { + console.log( + "Relay \"" + self.strRelayName + "\" outgoing-client socket \"" + + pipeIncoming.strSavedRemoteAddress + "\" message ", joMessage + ); + } + if( ! pipeOutgoing ) { + throw new Error( + "Relay \"" + self.strRelayName + + "\" is not completely initialized and cannot transfer messages" + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "message", + { + "relay": self, + "socket": pipeIncoming, + "remoteAddress": "" + pipeIncoming.strSavedRemoteAddress, + "isExternalSocket": false, + "message": joMessage + } ) + ); + pipeIncoming.send( joMessage ); + if( self.isAutoFlushOutgoing ) + pipeIncoming.flush(); + }; + _offAllPipeEventListeners = function() { + if( _onIncomingPipeClose ) { + pipeIncoming.off( "close", _onIncomingPipeClose ); + _onIncomingPipeClose = null; + } + if( _onIncomingPipeError ) { + pipeIncoming.off( "error", _onIncomingPipeError ); + _onIncomingPipeError = null; + } + if( _onIncomingPipeMessage ) { + pipeIncoming.off( "message", _onIncomingPipeMessage ); + _onIncomingPipeMessage = null; + } + if( pipeOutgoing.relayClientSocket ) { + if( _onOutgoingPipeClose ) { + pipeOutgoing.off( "close", _onOutgoingPipeClose ); + _onOutgoingPipeClose = null; + } + if( _onOutgoingPipeError ) { + pipeOutgoing.off( "error", _onOutgoingPipeError ); + _onOutgoingPipeError = null; + } + if( _onOutgoingPipeMessage ) { + pipeOutgoing.off( "message", _onOutgoingPipeMessage ); + _onOutgoingPipeMessage = null; + } + pipeOutgoing.disconnect(); + pipeOutgoing.dispose(); + } + pipeIncoming.disconnect(); + pipeIncoming.dispose(); + }; + pipeIncoming.on( "close", _onIncomingPipeClose ); + pipeIncoming.on( "error", _onIncomingPipeError ); + pipeIncoming.on( "message", _onIncomingPipeMessage ); + + // 2) configure outgoing relay client pipe + pipeOutgoing.on( "close", _onOutgoingPipeClose ); + pipeOutgoing.on( "error", _onOutgoingPipeError ); + pipeOutgoing.on( "message", _onOutgoingPipeMessage ); + } + dispose() { + this.isDisposing = true; + super.dispose(); + } + flush() { + if( this.pipeIncoming ) + this.pipeIncoming.flush(); + if( this.pipeOutgoing ) + this.pipeOutgoing.flush(); + } +}; + +export class DirectPipe extends BasicSocketPipe { + constructor( counterPipe, isBroadcastOpenEvents ) { + super(); + isBroadcastOpenEvents = isBroadcastOpenEvents ? true : false; + this.socketType = "Direct"; + this.socketSubtype = "direct.not.initialized.yet"; + this.isConnected = false; + this.acceptor = null; + this.counterPipe = ( counterPipe != null && counterPipe != undefined ) + ? counterPipe : null; // set outside after this constructor call + this.strEndPoint = this.counterPipe + ? ( "2-" + this.counterPipe.strEndPoint ) : ( "1-" + utils.randomDirectPipeID() ); + this.clientPort = this.counterPipe ? 2 : 1; + this.socketSubtype = "direct." + this.clientPort; + this.url = "direct_pipe://" + this.strEndPoint + ":" + this.clientPort; + if( this.counterPipe ) { + this.counterPipe.counterPipe = this; + this.isConnected = true; + this.counterPipe.isConnected = true; + if( isBroadcastOpenEvents ) { + const self = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( new UniversalDispatcherEvent( + "open", { "socket": self } ) ); + self.counterPipe.dispatchEvent( + new UniversalDispatcherEvent( + "open", { "socket": self.counterPipe } ) ); + }, 0 ); + } + } + } + dispose() { + this.performDisconnect(); + super.dispose(); + } + handleServerDisposed() { // this method is for using in local client/server pipe pairs + this.performDisconnect(); + this.isConnected = false; + this.dispatchEvent( new UniversalDispatcherEvent( "close", { "socket": this } ) ); + this.acceptor = null; + this.counterPipe = null; + this.clientPort = 0; + this.url = ""; + this.dispose(); + } + performDisconnect() { + if( ! this.isConnected ) + return; + this.isConnected = false; + if( this.acceptor ) + this.acceptor.unregisterClientByKey( this.clientPort ); + this.dispatchEvent( new UniversalDispatcherEvent( "close", { "socket": this } ) ); + this.counterPipe.performDisconnect(); + this.acceptor = null; + this.counterPipe = null; + this.clientPort = 0; + this.url = ""; + } + implSend( data ) { + if( ( !this.isConnected ) || ( !this.counterPipe ) || ( !this.counterPipe.isConnected ) ) { + const s = "Cannot send messages to disconnected local server pipe"; + this.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + const s = socketSentDataMarshall( data ); + const jo = socketReceivedDataReverseMarshall( s ); + this.counterPipe.receive( jo ); + } + disconnect() { + this.performDisconnect(); + super.disconnect(); + } +}; + +export class LocalSocketServerPipe extends DirectPipe { + constructor( counterPipe, acceptor, clientPort ) { + super( counterPipe, false ); + this.socketType = "Local"; + this.socketSubtype = "server"; + this.isConnected = true; + this.acceptor = acceptor; + this.clientPort = 0 + parseInt( clientPort, 10 ); + this.url = "local_server_pipe://" + acceptor.strEndPoint + ":" + clientPort; + this.acceptor.mapClients["" + clientPort] = this; + const self = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": self } ) ); + }, 0 ); + } + dispose() { + super.dispose(); + } +}; + +export class LocalSocketServerAcceptor extends BasicServerAcceptor { + constructor( strEndPoint ) { + super(); + this.socketType = "Local"; + this.nextClientPort = 1; + this.strEndPoint = + ( strEndPoint && typeof strEndPoint == "string" && strEndPoint.length > 0 ) + ? strEndPoint : "default_local_endpoint"; + if( this.strEndPoint in gMapLocalServers ) { + const s = + "Cannot start local socket server on already listening \"" + + this.strEndPoint + "\" endpoint"; + this.dispatchEvent( new UniversalDispatcherEvent( + "error", { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + gMapLocalServers[this.strEndPoint] = this; + this.isListening = true; + const self = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( + new UniversalDispatcherEvent( "open", { "socket": self } ) ); + }, 0 ); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.disposeNotifyClients(); + if( this.strEndPoint && + typeof this.strEndPoint == "string" && + this.strEndPoint.length > 0 + ) { + if( this.strEndPoint in gMapLocalServers ) + delete gMapLocalServers[this.strEndPoint]; + } + super.dispose(); + } +}; + +export class LocalSocketClientPipe extends DirectPipe { + constructor( strEndPoint ) { + super( null, false ); + this.socketType = "Local"; + this.socketSubtype = "client"; + this.isConnected = false; + this.clientPort = 0; + this.acceptor = null; + this.counterPipe = null; + this.strEndPoint = + ( strEndPoint && typeof strEndPoint == "string" && strEndPoint.length > 0 ) + ? strEndPoint : "default_local_endpoint"; + if( !( this.strEndPoint in gMapLocalServers ) ) { + const s = + "Cannot connect to local socket server \"" + this.strEndPoint + + "\" endpoint, no such server"; + this.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + this.acceptor = gMapLocalServers[this.strEndPoint]; + this.clientPort = 0 + this.acceptor.nextClientPort; + ++ this.acceptor.nextClientPort; + this.url = "local_client_pipe://" + this.strEndPoint + ":" + this.clientPort; + this.isConnected = true; + const serverPipe = new LocalSocketServerPipe( this, this.acceptor, 0 + this.clientPort ); + serverPipe.counterPipe = this; + this.counterPipe = serverPipe; + this.acceptor.mapClients[0 + this.clientPort] = { + serverPipe: serverPipe, + clientPipe: this + }; + const self = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": self } ) ); + self.acceptor.dispatchEvent( + new UniversalDispatcherEvent( + "connection", + { "socket": serverPipe, "remoteAddress": "" + self.url } ) + ); + }, 0 ); + } + dispose() { + super.dispose(); + } +}; + +export class WebSocketServerPipe extends BasicSocketPipe { + constructor( acceptor, wsConnection, remoteAddress ) { + super(); + this.socketType = "WS"; + this.socketSubtype = "server"; + const self = this; + this.isConnected = true; + this.acceptor = acceptor; + this.clientNumber = 0 + acceptor.nextClientNumber; + this.clientPort = 0 + this.clientNumber; + ++ acceptor.nextClientNumber; + this.wsConnection = wsConnection; + this.remoteAddress = "" + remoteAddress; + this.url = "ws_server_pipe(" + this.clientNumber + ")://" + remoteAddress; + this._onWsClose = function() { + self.dispatchEvent( + new UniversalDispatcherEvent( "close", { "socket": self } ) ); + }; + this._onWsError = function( event ) { + self.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": self, "message": event } ) ); + }; + this._onWsMessage = function( event ) { + self.receive( event.data ); + }; + this._removeWsEventListeners = function() { + if( self._onWsClose ) { + wsConnection.removeEventListener( "close", self._onWsClose ); + self._onWsClose = null; + } + if( self._onWsError ) { + wsConnection.removeEventListener( "error", self._onWsError ); + self._onWsError = null; + } + if( self._onWsMessage ) { + wsConnection.removeEventListener( "message", self._onWsMessage ); + self._onWsMessage = null; + } + }; + wsConnection.addEventListener( "close", this._onWsClose ); + wsConnection.addEventListener( "error", this._onWsError ); + wsConnection.addEventListener( "message", this._onWsMessage ); + this.acceptor.mapClients["" + this.clientPort] = this; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": self } ) ); + self.acceptor.dispatchEvent( + new UniversalDispatcherEvent( + "connection", + { "socket": self, "remoteAddress": "" + remoteAddress } ) + ); + }, 0 ); + } + dispose() { + this.performDisconnect(); + super.dispose(); + } + handleServerDisposed() { + this.isConnected = false; + this.clientNumber = 0; + this.acceptor = null; + this.wsConnection = null; + this.url = ""; + this.remoteAddress = ""; + this.dispose(); + } + performDisconnect() { + if( ! this.isConnected ) + return; + this.isConnected = false; + if( this._removeWsEventListeners ) { + this._removeWsEventListeners(); + this._removeWsEventListeners = null; + } + if( this.wsConnection ) { + try { + this.wsConnection.terminate(); + } catch ( err ) { + console.warn( "Web socket server pipe termination error", err ); + } + this.wsConnection = null; + } + if( this.acceptor ) + this.acceptor.unregisterClientByKey( this.clientPort ); + this.clientNumber = 0; + this.acceptor = null; + this.url = ""; + this.remoteAddress = ""; + } + implSend( data ) { + if( ( !this.isConnected ) || ( !this.wsConnection ) ) { + const s = "Cannot send messages to disconnected web socket server pipe"; + this.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + const s = socketSentDataMarshall( data ); + this.wsConnection.send( s ); + } + disconnect() { + this.performDisconnect(); + super.disconnect(); + } + implReceive( data ) { + const jo = socketReceivedDataReverseMarshall( data ); + this.dispatchEvent( + new UniversalDispatcherEvent( "message", { "socket": this, "message": jo } ) ); + } +}; + +export class WebSocketServerAcceptor extends BasicServerAcceptor { + constructor( nTcpPort, key, cert ) { + super(); + this.socketType = "WS"; + this.wsServer = null; + if( key != null && key != undefined && typeof key == "string" && key.length > 0 && + cert != null && cert != undefined && typeof cert == "string" && cert.length > 0 + ) { + const server = httpsModule.createServer( { + key: "" + key, + cert: "" + cert + // , ca: ... + } ); + server.listen( nTcpPort ); + this.wsServer = new wsModule.WebSocketServer( { server } ); + } else + this.wsServer = new wsModule.WebSocketServer( { port: nTcpPort } ); + + const self = this; + self.wsServer.on( "connection", function( wsConnection, req ) { + wsConnection.strSavedRemoteAddress = "" + req.connection.remoteAddress; + wsConnection.serverPipe = + new WebSocketServerPipe( self, wsConnection, req.connection.remoteAddress ); + } ); + this.isListening = true; + const iv = setTimeout( function() { + clearTimeout( iv ); + self.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": self } ) ); + }, 0 ); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.disposeNotifyClients(); + super.dispose(); + } +}; + +export class WebSocketClientPipe extends BasicSocketPipe { + constructor( url ) { + super(); + this.socketType = "WS"; + this.socketSubtype = "client"; + this.isConnected = false; + this.wsConnection = null; + this._onWsOpen = null; + this._onWsClose = null; + this._onWsError = null; + this._onWsMessage = null; + this.urlWS = + "" + ( ( url != null && url != undefined && typeof url == "string" ) ? url : "" ); + this.url = "ws_client_pipe-" + this.urlWS; + this.reconnect(); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.performDisconnect(); + this.urlWS = null; + super.dispose(); + } + implSend( data ) { + if( ( !this.isConnected ) || ( !this.wsConnection ) ) { + const s = "Cannot send messages to disconnected web socket client pipe"; + this.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + const s = socketSentDataMarshall( data ); + this.wsConnection.send( s ); + } + reconnect() { + this.performDisconnect(); + this.wsConnect( "" + this.urlWS ); + } + disconnect() { + this.performDisconnect(); + super.disconnect(); + } + performDisconnect() { + if( ! this.isConnected ) + return; + this.wsDisconnect(); + } + wsConnectAttempt( url, reconnectAfterMilliseconds, iv ) { + const self = this; + try { + if( this.isConnected || this.wsConnection ) + this.wsDisconnect(); + this.wsConnection = wsModule + ? new wsModule.WebSocket( + url, + { tlsOptions: { rejectUnauthorized: false } } + ) // server side + : new WebSocket( url ); // client side + this.url = "" + url; + this._onWsOpen = function() { + self.isConnected = true; + self.dispatchEvent( + new UniversalDispatcherEvent( + "open", { "socket": self } ) ); + }; + this._onWsClose = function( event ) { + // alert( JSON.stringify( event ) ); + self.isConnected = false; + self.dispatchEvent( + new UniversalDispatcherEvent( + "close", { "socket": self, "message": event } ) ); + }; + this._onWsError = function( event ) { + // alert( JSON.stringify( event ) ); + self.isConnected = false; + self.dispatchEvent( + new UniversalDispatcherEvent( + "error", { "socket": self, "message": event } ) ); + }; + this._onWsMessage = function( event ) { + self.receive( event.data ); + }; + this._removeWsEventListeners = function() { + if( self._onWsOpen ) { + self.wsConnection.removeEventListener( "open", self._onWsOpen ); + self._onWsOpen = null; + } + if( self._onWsClose ) { + self.wsConnection.removeEventListener( "close", self._onWsClose ); + self._onWsClose = null; + } + if( self._onWsError ) { + self.wsConnection.removeEventListener( "error", self._onWsError ); + self._onWsError = null; + } + if( self._onWsMessage ) { + self.wsConnection.removeEventListener( "message", self._onWsMessage ); + self._onWsMessage = null; + } + }; + this.wsConnection.addEventListener( "open", this._onWsOpen ); + this.wsConnection.addEventListener( "close", this._onWsClose ); + this.wsConnection.addEventListener( "error", this._onWsError ); + this.wsConnection.addEventListener( "message", this._onWsMessage ); + if( iv ) + clearTimeout( iv ); + return true; + } catch ( err ) { + console.warn( "WS client connect error:", err ); + } + if( reconnectAfterMilliseconds != null && reconnectAfterMilliseconds != undefined ) { + reconnectAfterMilliseconds = parseInt( reconnectAfterMilliseconds, 10 ); + if( reconnectAfterMilliseconds > 0 && ( !iv ) ) { + const iv = setTimeout( function() { + try { + if( self.wsConnectAttempt( url, reconnectAfterMilliseconds, iv ) ) + clearTimeout( iv ); + } catch ( err ) { + } + }, reconnectAfterMilliseconds ); + } + } + return false; + } + wsConnect( url ) { + if( url.length == 0 ) { + const s = "Cannot connect web socket server \"" + url + "\", bad url"; + this.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": this, "message": "" + s } ) ); + throw new Error( s ); + } + this.wsConnectAttempt( url, settings.net.ws.client.reconnectAfterMilliseconds, null ); + } + wsDisconnect() { + if( this._removeWsEventListeners ) { + this._removeWsEventListeners(); + this._removeWsEventListeners = null; + } + if( this.wsConnection ) { + let bPass = false, anyError = null; + try { + this.wsConnection.close(); + bPass = true; + } catch ( err ) { + anyError = err; + } + if( ! bPass ) { + try { + this.wsConnection.terminate(); + bPass = true; + } catch ( err ) { + anyError = err; + } + } + if( ! bPass ) + console.warn( "Web socket client pipe termination error", anyError ); + this.wsConnection = null; + } + this.isConnected = false; + this.url = ""; + } + implReceive( data ) { + const jo = socketReceivedDataReverseMarshall( data ); + this.dispatchEvent( + new UniversalDispatcherEvent( "message", { "socket": this, "message": jo } ) ); + } +}; + +export class RTCConnection extends EventDispatcher { + constructor( strSignalingServerURL, idRtcParticipant ) { + super(); + this.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); + this.idRtcParticipant = "" + + ( ( idRtcParticipant != null && idRtcParticipant != undefined && + typeof idRtcParticipant == "string" && idRtcParticipant.length > 0 ) + ? idRtcParticipant : utils.UUIDv4() ); + this.wasIdentified = false; + this.iceComplete = false; + this.pc = null; + this.dc = null; + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.closeDataChannel(); + this.closePeer(); + this.dc = null; + this.wasIdentified = false; + this.iceComplete = false; + this.idRtcParticipant = null; + super.dispose(); + } + describe( strInstanceType, arrAdditionalProps ) { + let strInstanceDescription = + ( strInstanceType == null || strInstanceType == undefined || + ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) + ? "participant" + : ( "" + strInstanceType ); + if( typeof this.idRtcParticipant == "string" && this.idRtcParticipant.length > 0 ) + strInstanceDescription += " " + this.idRtcParticipant; + const arrProps = []; + if( this.isDisposed ) + arrProps.push( "disposed" ); + if( this.wasIdentified ) + arrProps.push( "identified" ); + if( this.pc ) + arrProps.push( "pc" ); + if( this.dc ) + arrProps.push( "dc" ); + if( arrAdditionalProps != null && + arrAdditionalProps != undefined && + arrAdditionalProps.length > 0 + ) { + for( let i = 0; i < arrAdditionalProps.length; ++ i ) + arrProps.push( arrAdditionalProps[i] ); + } + if( arrProps.length > 0 ) + strInstanceDescription += "(" + arrProps.join( ", " ) + ")"; + return strInstanceDescription; + } + closeDataChannel() { + if( this.dc ) { + try { + this.dc.ondatachannel = null; + this.dc.close(); + if( settings.logging.net.rtc.closeDataChannel ) + console.warn( this.describe() + " did closed RTC data channel" ); + } catch ( err ) { + if( settings.logging.net.rtc.error ) + console.warn( this.describe() + " error closing RTC data channel:", err ); + } + this.dc = null; + this.dispatchEvent( + new UniversalDispatcherEvent( + "dataChannelClose", { "detail": { "actor": this } } ) ); + } + } + closePeer() { + if( this.pc ) { + try { + this.pc.onicecandidate = null; + this.pc.oniceconnectionstatechange = null; + this.pc.close(); + if( settings.logging.net.rtc.closePeer ) + console.warn( this.describe() + " did closed RTC peer" ); + } catch ( err ) { + if( settings.logging.net.rtc.error ) + console.warn( this.describe() + " error closing RTC peer:", err ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "peerClose", { "detail": { "actor": this } } ) ); + this.pc = null; + } + } + onError( err ) { + this.dispatchEvent( + new UniversalDispatcherEvent( + "rtcParticipantError", { "detail": { "actor": this, "error": err } } ) ); + if( settings.logging.net.rtc.error ) + console.warn( " !!! " + this.describe() + " error:", err ); + this.closeDataChannel(); + this.closePeer(); + } + send( data ) { + const s = socketSentDataMarshall( data ); + if( ! this.dc ) { + this.onError( "Attempt to send message to uninitialized RTC data channel: " + s ); + return; + } + try { + this.dc.send( s ); + } catch ( err ) { + this.onError( "Failed to send message to RTC data channel: " + err.toString() ); + } + } + onDataChannelOpen( event ) { + this.dispatchEvent( + new UniversalDispatcherEvent( + "dataChannelOpen", { "detail": { "actor": this } } ) ); + } + onDataChannelClose( event ) { + this.dispatchEvent( + new UniversalDispatcherEvent( + "dataChannelClose", { "detail": { "actor": this } } ) ); + } + onDataChannelError( event ) { + this.dispatchEvent( + new UniversalDispatcherEvent( + "dataChannelError", { "detail": { "actor": this } } ) ); + this.onError( "Data channel error " + event.toString() ); + } + onDataChannelMessage( event ) { + if( event.data.size ) { + if( settings.logging.net.rtc.error ) { + console.warn( + this.describe() + " will ignore file transfer message of size", event.data.size + ); + } + } else { + if( event.data.charCodeAt( 0 ) == 2 ) + return; + const data = JSON.parse( event.data ); + if( data.type === "file" ) { + if( settings.logging.net.rtc.error ) + console.warn( this.describe() + " will ignore file transfer message" ); + } else { + this.dispatchEvent( + new UniversalDispatcherEvent( + "dataChannelMessage", { "detail": { "actor": this, "data": data } } ) ); + } + } + } + onIceComplete( event ) { + } + onIceConnectionStateChange( event ) { + // handler for self.pc.oniceconnectionstatechange, + // see https://developer.mozilla.org/en-US/docs/ + // Web/API/RTCPeerConnection/oniceconnectionstatechange + if( settings.logging.net.rtc.iceConnectionStateChange ) { + console.log( + "Participant \"" + this.idRtcParticipant + + "\" ICE connection state changed to \"" + + this.pc.iceConnectionState + "\", event is:", event + ); + } else if( settings.logging.net.rtc.iceConnectionStateName ) { + // similar to previous but prints only connection state name + console.log( + "Participant \"" + this.idRtcParticipant + + "\" ICE connection state changed to \"" + this.pc.iceConnectionState + "\"" + ); + } + if( this.pc.iceConnectionState === "failed" || + this.pc.iceConnectionState === "closed" || + this.pc.iceConnectionState === "disconnected" + ) { + this.onError( + "ICE connection state(oniceconnectionstatechange) changed to " + + this.pc.iceConnectionState + ); + } + } + onIceGatheringStateChange( event ) { + // handler for self.pc.onicegatheringstatechange - this is recommended to handle + // in a same way as oniceconnectionstatechange, + // see https://developer.mozilla.org/en-US/docs/ + // Web/API/RTCPeerConnection/onicegatheringstatechange + if( ! this.pc ) { + console.log( + "WARNING: Participant \"" + this.idRtcParticipant + + "\" ICE gathering state changed event with no pc\", event is:", event + ); + return; + } + if( settings.logging.net.rtc.iceGatheringStateChange ) { + console.log( + "Participant \"" + this.idRtcParticipant + + "\" ICE gathering state changed to \"" + this.pc.iceGatheringState + + "\", event is:", event + ); + } else if( settings.logging.net.rtc.iceGatheringStateName ) { + // similar to previous but prints only gathering state name + console.log( + "Participant \"" + this.idRtcParticipant + + "\" ICE gathering state changed to \"" + + this.pc.iceGatheringState + "\"" + ); + } + if( this.pc.iceConnectionState === "failed" || + this.pc.iceConnectionState === "closed" || + this.pc.iceConnectionState === "disconnected" + ) { + this.onError( + "ICE connection state(onicegatheringstatechange) changed to " + + this.pc.iceConnectionState + ); + } + } + onIceIdentifyResult( event ) { + // handler for self.pc.onidentityresult, + // see https://developer.mozilla.org/en-US/docs/Web/API/RTCIdentityEvent + if( settings.logging.net.rtc.iceIceIdentifyResult ) { + if( "assertion" in event ) { + console.warn( + "Participant \"" + this.idRtcParticipant + + "\" ICE identify result event with new identity assertion (blob: '" + + event.assertion + "') has been generated." + ); + } else { + console.warn( + "Participant \"" + this.idRtcParticipant + + "\" ICE identify result event is:", event + ); + } + } + } + onIceSignalingStateChange( event ) { + // handler for self.pc.onsignalingstatechange, see + // https://developer.mozilla.org/en-US/docs/ + // Web/API/RTCPeerConnection/onsignalingstatechange + if( settings.logging.net.rtc.iceSignalingStateChange ) { + console.log( + "Participant \"" + this.idRtcParticipant + + "\" ICE signaling state changed to \"" + + ( ( this.pc && "signalingState" in this.pc ) ? this.pc.signalingState : "N/A" ) + + "\", event is:", event ); + } + } + onIceNegotiationNeeded( event ) { + // handler for self.pc.onnegotiationneeded, + // see https://developer.mozilla.org/en-US/docs/ + // Web/API/RTCPeerConnection/onnegotiationneeded + // TO-DO: improve this + if( settings.logging.net.rtc.iceNegotiationNeeded ) { + console.log( + "Participant \"" + this.idRtcParticipant + + "\" ICE negotiation needed event is:", event + ); + } + } +}; + +export class RTCActor extends RTCConnection { + constructor( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions ) { + super( strSignalingServerURL, idRtcParticipant ); + this.isDisposed = false; + this.idSomebodyCreator = null; + this.bWasImpersonated = false; + this.isCreator = false; + this.isJoiner = false; + + this.offerOptions = { + optional: [], + // offer to the remote peer the opportunity to try to send audio + offerToReceiveAudio: false, + // offer to the remote peer the opportunity to try to send video + offerToReceiveVideo: false, + voiceActivityDetection: false, + iceRestart: false + }; + if( offerOptions ) { + this.offerOptions.offerToReceiveAudio = + ( "offerToReceiveAudio" in offerOptions && offerOptions.offerToReceiveAudio ) + ? true : false; + this.offerOptions.offerToReceiveVideo = + ( "offerToReceiveVideo" in offerOptions && offerOptions.offerToReceiveVideo ) + ? true : false; + this.offerOptions.voiceActivityDetection = + ( "voiceActivityDetection" in offerOptions && offerOptions.voiceActivityDetection ) + ? true : false; + this.offerOptions.iceRestart = + ( "iceRestart" in offerOptions && offerOptions.iceRestart ) + ? true : false; + } + + this.signalingOptions = { + idCategory: "" + settings.rtcSpace.defaultSpaceCategory, + idSpace: "" + settings.rtcSpace.defaultSpaceName + }; + if( signalingOptions ) { + if( "idCategory" in signalingOptions && + typeof signalingOptions.idCategory == "string" && + signalingOptions.idCategory.length > 0 + ) + this.signalingOptions.idCategory = "" + signalingOptions.idCategory; + if( "idSpace" in signalingOptions && + typeof signalingOptions.idSpace == "string" && + signalingOptions.idSpace.length > 0 + ) + this.signalingOptions.idSpace = "" + signalingOptions.idSpace; + } + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.signalingPipeClose(); + this.idSomebodyCreator = null; + this.strSignalingServerURL = null; + this.bWasImpersonated = false; + super.dispose(); + } + describe( strInstanceType, arrAdditionalProps ) { + strInstanceType = + ( strInstanceType == null || + strInstanceType == undefined || + ( typeof strInstanceType != "string" ) || + strInstanceType.length == 0 ) + ? ( this.isCreator ? "creator" : ( this.isJoiner ? "joiner" : "actor" ) ) + : strInstanceType; + return super.describe( strInstanceType, arrAdditionalProps ); + } + onError( err ) { + super.onError( err ); + } + signalingPipeOpen() { + try { + const self = this; + self.signalingPipeClose(); + self.dispatchEvent( + new UniversalDispatcherEvent( + "signalingWillStart", { "detail": { "actor": this } } ) ); + self.signalingPipe = new WebSocketClientPipe( self.strSignalingServerURL ); + self.signalingPipe.on( + "open", function( eventData ) { self.signalingPipeOnOpen( eventData ); } ); + self.signalingPipe.on( + "close", function( eventData ) { self.signalingPipeOnClose( eventData ); } ); + self.signalingPipe.on( + "error", function( eventData ) { self.signalingPipeOnError( eventData ); } ); + self.signalingPipe.on( + "message", function( eventData ) { self.signalingPipeOnRawMessage( eventData ); } ); + self.dispatchEvent( + new UniversalDispatcherEvent( + "signalingDidStarted", { "detail": { "actor": this } } ) ); + } catch ( err ) { + if( settings.logging.net.signaling.error ) + console.warn( this.describe() + " error starting signaling pipe:", err ); + this.onError( err ); + } + } + signalingPipeClose() { + if( this.signalingPipe ) { + try { + if( settings.logging.net.signaling.disconnect ) + console.warn( this.describe() + " will close signaling pipe" ); + this.signalingPipe.offAll(); + this.signalingPipe.disconnect(); + if( settings.logging.net.signaling.disconnect ) + console.warn( this.describe() + " did closed signaling pipe" ); + } catch ( err ) { + if( settings.logging.net.signaling.error ) + console.warn( this.describe() + " error closing signaling pipe:", err ); + } + this.signalingPipe = null; + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingClosed", { "detail": { "actor": this } } ) ); + } + } + signalingPipeOnOpen( eventData ) { + try { + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingOpened", { "detail": { "actor": this } } ) ); + if( settings.logging.net.signaling.connect ) { + console.log( + "+++ " + this.describe() + " did connected to " + this.strSignalingServerURL + ); + } + const joImpersonateMessage = { + "id": utils.randomCallID(), + "method": "signalingImpersonate", + "idCategory": "" + this.signalingOptions.idCategory, + "idSpace": "" + this.signalingOptions.idSpace, + "idRtcParticipant": "" + this.idRtcParticipant, + "role": this.isCreator ? "creator" : "joiner" + }; + if( settings.logging.net.signaling.message ) + console.log( " <<< " + this.describe() + " message out", joImpersonateMessage ); + this.signalingPipe.send( joImpersonateMessage ); + } catch ( err ) { + if( settings.logging.net.signaling.error ) { + console.warn( + this.describe() + " error sending impersonation to signaling pipe:", err + ); + } + this.onError( err ); + } + } + signalingPipeOnClose( eventData ) { + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingPipeClose", { "detail": { "actor": this } } ) ); + if( settings.logging.net.signaling.disconnect ) { + console.warn( + " !!! " + this.describe() + " signaling pipe closed for " + + this.strSignalingServerURL + ); + } + this.signalingPipeClose(); + } + signalingPipeOnError( eventData ) { + // alert( JSON.stringify( eventData ) ); + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingPipeError", { "detail": { "actor": this, "error": eventData } } ) ); + if( settings.logging.net.signaling.error ) { + console.warn( + " !!! " + this.describe() + " signaling pipe error for " + + this.strSignalingServerURL + ", error is:", eventData + ); + } + this.onError( eventData ); + this.signalingPipeClose(); + } + signalingPipeOnRawMessage( eventData ) { + try { + if( settings.logging.net.signaling.rawMessage ) { + console.log( + " >>> " + this.describe() + " raw signaling message received", eventData ); + } + const joMessage = eventData.message; + if( settings.logging.net.signaling.message ) { + console.log( + " >>> " + this.describe() + " signaling message received", joMessage ); + } + this.signalingPipeOnMessage( joMessage ); + } catch ( err ) { + if( settings.logging.net.signaling.error ) + console.warn( "Error handling raw message in " + this.describe() + ":", err ); + this.onError( err ); + } + } + signalingPipeOnMessage( joMessage ) { + switch ( joMessage.method ) { + case "signalingImpersonate": { + if( joMessage.error == null ) { + // OKay, impersonated + this.bWasImpersonated = true; + if( settings.logging.net.signaling.generic ) { + console.log( + "Success, " + this.describe() + " impersonated on signaling server" + ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingPassedImpersonation", { "detail": { "actor": this } } ) ); + this.onImpersonationComplete(); + } else { + if( settings.logging.net.signaling.error ) { + console.warn( + " >>> " + this.describe() + " signaling impersonation error", + joMessage.error + ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingFailedImpersonation", + { "detail": { "actor": this, "error": joMessage.error } } ) + ); + this.onError( joMessage.error ); + } + } break; + default: + if( settings.logging.net.signaling.error ) { + console.warn( + " >>> " + this.describe() + " unhandled signaling message", + joMessage + ); + } + break; + } // switch( joMessage.method ) + } + onImpersonationComplete() { } + // generic implementation should never be called + onOtherSideIdentified( idSomebodyOtherSide, idOffer ) { } +}; + +export class RTCServerPeer extends RTCConnection { + constructor( + rtcCreator, timeToPublishMilliseconds, timeToSignalingNegotiationMilliseconds, + peerConfiguration, peerAdditionalOptions, localMediaStream + ) { + super(); + this.rtcCreator = rtcCreator; + this.idSomebodyOtherSide = null; + this.idOffer = this.rtcCreator.idOfferNext ++; + this.tsOfferCreated = null; + if( settings.logging.net.signaling.offerRegister ) + console.log( "Register offer", this.idOffer, "(RTCServerPeer constructor)" ); + this.rtcCreator.mapServerOffers[0 + this.idOffer] = this; + this.isPublishing = false; + this.isSignalingNegotiation = false; + this.isPublishTimeout = false; + this.isSignalingNegotiationTimeout = false; + this.timerPublishing = null; + this.timerSignalingNegotiation = null; + this.timeToPublishMilliseconds = timeToPublishMilliseconds + ? parseInt( timeToPublishMilliseconds, 10 ) + : settings.net.rtc.timeToPublishMilliseconds; + this.timeToSignalingNegotiationMilliseconds = timeToSignalingNegotiationMilliseconds + ? parseInt( timeToSignalingNegotiationMilliseconds, 10 ) + : settings.net.rtc.timeToSignalingNegotiationMilliseconds; + this.peerConfiguration = + ( peerConfiguration && typeof peerConfiguration == "object" ) + ? peerConfiguration : settings.net.rtc.peerConfiguration; + this.peerAdditionalOptions = + ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) + ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; + this.localMediaStream = + ( localMediaStream != null && localMediaStream != undefined && + typeof localMediaStream == "object" ) + ? localMediaStream : null; + this.isOfferPublishedOnSignalingServer = false; + this.initPeer(); + this.publish(); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.publishCancel(); + this.signalingNegotiationCancel(); + if( this.rtcCreator ) { + if( this.idOffer in this.rtcCreator.mapServerOffers ) { + if( settings.logging.net.signaling.offerUnregister ) + console.log( "Unregister offer", this.idOffer, "(RTCServerPeer dispose)" ); + delete this.rtcCreator.mapServerOffers[this.idOffer]; + } + this.idOffer = 0; + } + this.idOffer = 0; + if( this.idSomebodyOtherSide != null ) { + if( this.idSomebodyOtherSide in this.rtcCreator.mapServerPeers ) + delete this.rtcCreator.mapServerPeers[this.idSomebodyOtherSide]; + + this.idSomebodyOtherSide = null; + } + this.rtcCreator = null; + this.tsOfferCreated = null; + super.dispose(); + } + describe( strInstanceType, arrAdditionalProps ) { + strInstanceType = + ( strInstanceType == null || strInstanceType == undefined || + ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) + ? "server-peer" + : strInstanceType; + return super.describe( strInstanceType, arrAdditionalProps ); + } + initPeer() { + if( this.isDisposed ) + return; + const self = this; + if( self.pc ) + return; + self.pc = + new webRtcModule.RTCPeerConnection( + self.peerConfiguration, self.peerAdditionalOptions ); + if( self.localMediaStream ) { + for( const track of self.localMediaStream.getTracks() ) + self.pc.addTrack( track, self.localMediaStream ); + } else { + self.dc = + self.pc.createDataChannel( + settings.net.rtc.dataChannel.label, settings.net.rtc.dataChannel.opts ); + self.dc.addEventListener( + "open", function( event ) { self.onDataChannelOpen( event ); } ); + self.dc.addEventListener( + "close", function( event ) { self.onDataChannelClose( event ); } ); + self.dc.addEventListener( + "error", function( event ) { self.onDataChannelError( event ); } ); + self.dc.addEventListener( + "message", function( event ) { self.onDataChannelMessage( event ); } ); + } + } + publishCancel() { + if( ! this.isPublishing ) + return; + this.isOfferPublishedOnSignalingServer = false; + this.isPublishing = false; + if( this.timerPublishing ) { + clearTimeout( this.timerPublishing ); + this.timerPublishing = null; + } + this.signalingNegotiationCancel(); // mutual cancel + } + signalingNegotiationCancel() { + if( ! this.isSignalingNegotiation ) + return; + this.isSignalingNegotiation = false; + if( this.timerSignalingNegotiation ) { + clearTimeout( this.timerSignalingNegotiation ); + this.timerSignalingNegotiation = null; + } + this.publishCancel(); // mutual cancel + } + publish() { + if( this.isDisposed || this.isPublishing || this.isSignalingNegotiation || + ( !this.rtcCreator ) || ( !this.rtcCreator.signalingPipe ) ) + return; + const self = this; + self.isPublishing = true; + if( self.timeToPublishMilliseconds > 0 ) { + self.isSignalingNegotiation = false; + self.timerPublishing = setTimeout( function() { + self.publishCancel(); + self.signalingNegotiationCancel(); + self.isPublishTimeout = true; + if( settings.logging.net.signaling.publishTimeout ) { + console.warn( + " !!! " + self.describe() + " offer publish timeout " + + self.timeToPublishMilliseconds + " milliseconds reached" + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "publishTimeout", + { "detail": { "participant": self } } ) + ); + if( self.rtcCreator ) { + self.rtcCreator.dispatchEvent( + new UniversalDispatcherEvent( "publishTimeout", + { "detail": { "participant": self } } ) + ); + } + }, self.timeToPublishMilliseconds ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "publishStart", { "detail": { "participant": self } } ) ); + self.pc.oniceconnectionstatechange = + function( event ) { self.onIceConnectionStateChange( event ); }; + self.pc.onicegatheringstatechange = + function( event ) { self.onIceGatheringStateChange( event ); }; + self.pc.onidentityresult = + function( event ) { self.onIceIdentifyResult( event ); }; + self.pc.onsignalingstatechange = + function( event ) { self.onIceSignalingStateChange( event ); }; + self.pc.onnegotiationneeded = + function( event ) { self.onIceNegotiationNeeded( event ); }; + self.pc.createOffer( self.offerOptions ).then( + function( offerDescription ) { + // success + self.tsOfferCreated = new Date(); + if( settings.logging.net.signaling.offer ) { + console.log( + " <<< " + self.describe() + " offer created at " + + utils.formatDateTime( self.tsOfferCreated ) + + " with description:", offerDescription + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "offerCreated", { "detail": { "participant": self } } ) ); + self.pc.setLocalDescription( offerDescription ).then( + function() { + // success + if( settings.logging.net.signaling.localDescription ) { + console.log( + " <<< " + self.describe() + " local description set:", + offerDescription + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "localDescriptionSet", + { "detail": { "participant": self } } ) + ); + self.pc.onicecandidate = function( event ) { + self.iceComplete = true; + self.onIceComplete( event ); + }; // onicecandidate + }, function( err ) { + // error of setLocalDescription + self.publishCancel(); + self.signalingNegotiationCancel(); + self.onError( "Failed to set local description: " + err.toString() ); + } ); + }, function() { + self.publishCancel(); + self.signalingNegotiationCancel(); + // error of createOffer + self.onError( "Failed to create offer:" + err.toString() ); + } ); + } + onOtherSideIdentified( idSomebodyOtherSide ) { + this.publishCancel(); + this.signalingNegotiationCancel(); + this.idSomebodyOtherSide = "" + idSomebodyOtherSide; + this.wasIdentified = true; + this.dispatchEvent( + new UniversalDispatcherEvent( + "identified", + { + "detail": { + "participant": this, + "idSomebodyOtherSide": "" + idSomebodyOtherSide + } + } ) + ); + } + onError( err ) { + if( this.rtcCreator ) { + this.rtcCreator.onRtcPeerError( this, err ); + if( this.idOffer in this.rtcCreator.mapServerOffers ) { + if( settings.logging.net.signaling.offerUnregister ) { + console.log( + "Unregister offer", this.idOffer, + "due to RTCServerPeer error:".err + ); + } + delete this.rtcCreator.mapServerOffers[this.idOffer]; + } + this.idOffer = 0; + } + if( this.idSomebodyOtherSide != null ) { + if( this.idSomebodyOtherSide in this.rtcCreator.mapServerPeers ) + delete this.rtcCreator.mapServerPeers[this.idSomebodyOtherSide]; + this.idSomebodyOtherSide = null; + } + super.onError( err ); + } + onImpersonationCompleteForCreator() { // specific for server peer + if( settings.logging.net.signaling.creatorImpersonationComplete ) + console.log( "Creator impersonation complete" ); + } + publishOfferOnSignalingServer() { + const self = this; + try { + if( settings.logging.net.signaling.candidate ) + console.log( " <<< " + self.describe() + " got candidate", event ); + if( settings.logging.net.signaling.candidate ) + console.log( " <<< " + self.describe() + " got candidate", event ); + if( ! self.rtcCreator.signalingPipe ) + throw new Error( "no connection to signaling server" ); + const joPublishOfferMessage = { + "id": utils.randomCallID(), + "method": "signalingPublishOffer", + "offer": self.pc.localDescription, + "idSomebodyCreator": "" + self.rtcCreator.idRtcParticipant, + "idOffer": 0 + self.idOffer + }; + if( settings.logging.net.signaling.message ) { + console.log( + " <<< " + self.describe() + " signaling message out", + joPublishOfferMessage + ); + } + self.rtcCreator.signalingPipe.send( joPublishOfferMessage ); + self.publishCancel(); + self.dispatchEvent( + new UniversalDispatcherEvent( + "signalingNegotiationStart", { "detail": { "participant": self } } ) ); + if( self.timeToSignalingNegotiationMilliseconds > 0 ) { + self.isSignalingNegotiation = true; + self.timerSignalingNegotiation = setTimeout( function() { + self.publishCancel(); + self.signalingNegotiationCancel(); + self.isSignalingNegotiationTimeout = true; + if( settings.logging.net.signaling.signalingNegotiationTimeout ) { + console.warn( + " !!! " + self.describe() + " signaling negotiation timeout " + + self.timeToSignalingNegotiationMilliseconds + " milliseconds reached" + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "signalingNegotiationTimeout", + { "detail": { "participant": self } } ) + ); + if( self.rtcCreator ) { + self.rtcCreator.dispatchEvent( + new UniversalDispatcherEvent( + "signalingNegotiationTimeout", + { "detail": { "participant": self } } ) + ); + } + }, self.timeToSignalingNegotiationMilliseconds ); + } + } catch ( err ) { + throw err; + } + } + onIceComplete( event ) { + super.onIceComplete( event ); + const self = this; + try { + if( event.candidate == null || + settings.net.rtc.fastPublishMode.serverPeer + ) { + if( ! self.isOfferPublishedOnSignalingServer ) { + self.isOfferPublishedOnSignalingServer = true; + self.publishOfferOnSignalingServer(); + } + } + if( event.candidate != null ) { + if( settings.logging.net.signaling.candidateWalk ) { + console.log( + " <<< " + self.describe() + " got candidate", event + ); + } + } + } catch ( err ) { + self.publishCancel(); + self.signalingNegotiationCancel(); + self.onError( "Failed to process ICE candidate: " + err.toString() ); + } + } +}; + +export class RTCCreator extends RTCActor { + constructor( + strSignalingServerURL, + idRtcParticipant, + offerOptions, + signalingOptions + ) { + super( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions ); + const self = this; + self.idOfferNext = 1; + self.isCreator = true; + self.mapServerOffers = { }; // idOffer -> RTCServerPeer + self.mapServerPeers = { }; // idSomebodyOtherSide -> RTCServerPeer + self.signalingPipeOpen(); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + for( const [ idOffer, rtcPeer ] of Object.entries( this.mapServerOffers ) ) { + if( settings.logging.net.signaling.offerUnregister ) + console.log( "Unregister offer", idOffer, "(one of all, RTCCreator dispose)" ); + rtcPeer.dispose(); + } + for( const [ /*idSomebodyOtherSide*/, rtcPeer ] of + Object.entries( this.mapServerPeers ) ) + rtcPeer.dispose(); + this.mapServerOffers = { }; + super.dispose(); + } + describe( strInstanceType, arrAdditionalProps ) { + strInstanceType = + ( strInstanceType == null || strInstanceType == undefined || + ( typeof strInstanceType != "string" ) || strInstanceType.length == 0 ) + ? "rtc-creator" + : strInstanceType; + return super.describe( strInstanceType, arrAdditionalProps ); + } + onOtherSideIdentified( idSomebodyOtherSide, idOffer ) { // server peer got result + if( settings.logging.net.signaling.impersonate ) { + console.log( + this.describe() + " did identified other side RTC joiner \"" + + idSomebodyOtherSide + "\" via offer ID " + idOffer.toString() + ); + } + if( ! ( idOffer in this.mapServerOffers ) ) { + const strError = "not a registered pending offer(onOtherSideIdentified)"; + if( settings.logging.net.signaling.error ) { + console.warn( + " >>> " + this.describe() + + " came across with incorrect other side identification for *somebody*", + idSomebodyOtherSide, "and offer ID", idOffer, ":".strError + ); + } + this.onError( strError ); + return; + } + const rtcPeer = this.mapServerOffers[idOffer]; + if( settings.logging.net.signaling.offerUnregister ) { + console.log( + "Unregister offer", idOffer, "(onOtherSideIdentified in RTCCreator)" + ); + } + delete this.mapServerOffers[idOffer]; + this.mapServerPeers["" + idSomebodyOtherSide] = rtcPeer; + rtcPeer.onOtherSideIdentified( "" + idSomebodyOtherSide ); + } + onRtcPeerError( rtcPeer, err ) { + if( settings.logging.net.rtc.error ) + console.warn( " !!! " + this.describe() + " rtc peer error", err ); + this.dispatchEvent( + new UniversalDispatcherEvent( + "rtcPeerError", + { "detail": { "actor": this, "peer": rtcPeer, "error": err } } ) + ); + } + signalingPipeOnMessage( joMessage ) { + const self = this; + switch ( joMessage.method ) { + case "signalingPublishOffer": { + if( joMessage.error == null ) { + // OKay, creator offer published + if( settings.logging.net.signaling.offer ) + console.log( "Success, " + this.describe() + " offer published (step 1)" ); + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingPassedOfferPublish", { "detail": { "actor": this } } ) ); + } else { + if( settings.logging.net.signaling.error ) { + console.warn( + " !!! " + this.describe() + " signaling offer publishing (step 1) error", + joMessage.error ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingFailedOfferPublish", + { "detail": { "actor": this, "error": joMessage.error } } ) + ); + this.onError( joMessage.error ); + } + } break; + case "signalingPublishAnswer": { // server peer got result + if( joMessage.error == null ) { + const idSomebodyOtherSide = "" + joMessage.idSomebody_joiner; + const idOffer = 0 + joMessage.idOffer; + if( ! ( idOffer in this.mapServerOffers ) ) { + const strError = "not a registered pending offer(signalingPublishAnswer)"; + if( settings.logging.net.signaling.error ) { + console.warn( + " !!! " + this.describe() + + " came across with incorrect " + + "signalingPublishAnswer message for *somebody*", + idSomebodyOtherSide, "and offer ID", idOffer, ":", strError + ); + } + this.onError( strError ); + return; + } + const rtcPeer = this.mapServerOffers[idOffer]; + // OKay, finally got answer from candida + if( settings.logging.net.signaling.generic ) { + console.log( + "Success, " + this.describe() + " got answer from candidate (step 3)" + ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingPassedPublishAnswer", + { + "detail": { + "actor": this, + "idSomebodyOtherSide": "" + idSomebodyOtherSide, + idOffer: 0 + idOffer + } + } ) + ); + const answer = joMessage.answer; + if( settings.logging.net.signaling.offer ) + console.log( " >>> " + self.describe() + " got answer:", answer ); + const answerDescription = new webRtcModule.RTCSessionDescription( answer ); + if( settings.logging.net.signaling.offer ) { + console.log( + " >>> " + self.describe() + " got answer description:", + answerDescription + ); + } + if( rtcPeer.pc.signalingState != "have-local-offer" ) { + if( settings.logging.net.signaling.offerSkipPublishedAnswer ) { + console.warn( + " >>> " + self.describe() + " in \"" + rtcPeer.pc.signalingState + + "\" state will skip setting remote description from answer", + answerDescription + ); + } + return; + } + rtcPeer.pc.setRemoteDescription( answerDescription ).then( + function() { + // success + if( settings.logging.net.signaling.remoteDescription ) { + console.log( + " >>> " + self.describe() + "did set remote description:", + answerDescription + ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "remoteDescriptionSet", + { "detail": { "participant": self } } ) + ); + self.onOtherSideIdentified( + idSomebodyOtherSide, idOffer ); // server peer got result + }, function( err ) { + // error + self.onError( "Failed to set remote description: " + err.toString() ); + } ); + } else { + if( settings.logging.net.signaling.error ) { + console.warn( + " !!! " + this.describe() + + " error getting candidate answer (step 1) error", + joMessage.error ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingFailedPublishAnswer", + { "detail": { "actor": this, "error": joMessage.error } } ) + ); + this.onError( joMessage.error ); + } + } break; + default: + super.signalingPipeOnMessage( joMessage ); + break; + } // switch( joMessage.method ) + } + send( data ) { // implementation in RTCCreator does send to all + try { + const s = socketSentDataMarshall( data ); + for( const [ /*idSomebodyOtherSide*/, rtcPeer ] + of Object.entries( this.mapServerPeers ) ) { + try { + rtcPeer.send( s ); + } catch ( err ) { + this.onRtcPeerError( rtcPeer, err ); + } + } + } catch ( err ) { + this.onError( err ); + } + } + onImpersonationComplete() { + super.onImpersonationComplete(); + for( const [ /*idOffer*/, rtcPeer ] + of Object.entries( this.mapServerOffers ) ) + rtcPeer.onImpersonationCompleteForCreator(); + for( const [ /*idSomebodyOtherSide*/, rtcPeer ] + of Object.entries( this.mapServerPeers ) ) + rtcPeer.onImpersonationCompleteForCreator(); + } +}; + +export class RTCJoiner extends RTCActor { + constructor( + strSignalingServerURL, + idRtcParticipant, + offerOptions, + signalingOptions, + peerConfiguration, + peerAdditionalOptions + ) { + super( strSignalingServerURL, idRtcParticipant, offerOptions, signalingOptions ); + this.idSomebodyOtherSide = null; + this.idOffer = 0; + this.isJoiner = true; + this.tsAnswerCreated = null; + this.isAnswerPublishedOnSignalingServer = false; + this.signalingPipeOpen(); + this.peerConfiguration = + ( peerConfiguration && typeof peerConfiguration == "object" ) + ? peerConfiguration : settings.net.rtc.peerConfiguration; + this.peerAdditionalOptions = + ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) + ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.idSomebodyOtherSide = null; + this.idOffer = 0; + this.tsAnswerCreated = null; + this.isAnswerPublishedOnSignalingServer = false; + super.dispose(); + } + describe( strInstanceType, arrAdditionalProps ) { + strInstanceType = + ( strInstanceType == null || + strInstanceType == undefined || + ( typeof strInstanceType != "string" ) || + strInstanceType.length == 0 ) + ? "rtc-joiner" + : strInstanceType; + return super.describe( strInstanceType, arrAdditionalProps ); + } + initPeer() { + if( this.isDisposed ) + return; + const self = this; + if( self.pc ) + return; + self.pc = + new webRtcModule.RTCPeerConnection( + self.peerConfiguration, self.peerAdditionalOptions ); + self.pc.addEventListener( "track", function( event ) { + self.dispatchEvent( + new UniversalDispatcherEvent( + "trackAvailable", + { "detail": { "participant": self, "event": event } } ) ); + } ); + self.pc.oniceconnectionstatechange = + function( event ) { self.onIceConnectionStateChange( event ); }; + self.pc.onicegatheringstatechange = + function( event ) { self.onIceGatheringStateChange( event ); }; + self.pc.onidentityresult = + function( event ) { self.onIceIdentifyResult( event ); }; + self.pc.onsignalingstatechange = + function( event ) { self.onIceSignalingStateChange( event ); }; + self.pc.onnegotiationneeded = + function( event ) { self.onIceNegotiationNeeded( event ); }; + self.pc.ondatachannel = function( event ) { + self.dispatchEvent( + new UniversalDispatcherEvent( + "dataChannelAvailable", + { "detail": { "participant": self, "event": event } } ) + ); + const dataChannel = event.channel || event; + self.dc = dataChannel; + self.dc.addEventListener( + "open", + function( event ) { self.onDataChannelOpen( event ); } ); + self.dc.addEventListener( + "close", + function( event ) { self.onDataChannelClose( event ); } ); + self.dc.addEventListener( + "error", + function( event ) { self.onDataChannelError( event ); } ); + self.dc.addEventListener( + "message", + function( event ) { self.onDataChannelMessage( event ); } ); + }; + self.pc.onicecandidate = function( event ) { + self.iceComplete = true; + self.onIceComplete( event ); + try { + if( ! self.signalingPipe ) { + if( self.dc ) + return; // already connected, ignore (Firefox fix) + throw new Error( "no connection to signaling server" ); + } + if( ! self.isAnswerPublishedOnSignalingServer ) { + self.publishSignalingAnswer( event ); + self.iAnswerPublishedOnSignalingServer = true; + } + if( event.candidate != null ) { + if( settings.logging.net.signaling.candidateWalk ) { + console.log( + " <<< " + self.describe() + " got candidate", + event + ); + } + } + } catch ( err ) { + self.onError( + "Failed to process ICE candidate: " + err.toString() + ); + } + }; // onicecandidate + } + publishSignalingAnswer( event ) { + const self = this; + try { + if( event.candidate == null || + settings.net.rtc.fastPublishMode.joiner + ) { + if( settings.logging.net.signaling.candidate ) { + console.log( + " <<< " + self.describe() + " got candidate", + event + ); + } + if( ! self.signalingPipe ) + throw new Error( "no connection to signaling server" ); + const joPublishAnswerMessage = { + "id": utils.randomCallID(), + "method": "signalingPublishAnswer", + "answer": self.pc.localDescription, + "idRtcParticipant": "" + self.idRtcParticipant, + "idSomebodyCreator": "" + self.idSomebodyCreator, + "idOffer": 0 + self.idOffer + }; + if( settings.logging.net.signaling.message ) { + console.log( + " <<< " + self.describe() + + " signaling client message out", + joPublishAnswerMessage + ); + } + self.signalingPipe.send( joPublishAnswerMessage ); + } + } catch ( err ) { + throw err; + } + } + delayedInitPeer() { + if( this.bWasImpersonated ) + this.initPeer(); + } + onImpersonationComplete() { + super.onImpersonationComplete(); + const joFetchOfferMessage = { + "id": utils.randomCallID(), + "method": "signalingFetchOffer" + }; + if( settings.logging.net.signaling.message ) { + console.log( + " <<< " + this.describe() + " signaling client message out", + joFetchOfferMessage + ); + } + this.signalingPipe.send( joFetchOfferMessage ); + } + onIceComplete( event ) { + super.onIceComplete( event ); + } + onOtherSideIdentified( idSomebodyOtherSide, idOffer ) { // client peer got result + if( settings.logging.net.signaling.impersonate ) { + console.log( + this.describe() + " did identified other side RTC creator \"" + + idSomebodyOtherSide + "\" via offer ID " + idOffer.toString() + ); + } + this.idSomebodyOtherSide = "" + idSomebodyOtherSide; + this.idOffer = 0 + idOffer; + this.wasIdentified = true; + this.dispatchEvent( + new UniversalDispatcherEvent( + "identified", + { + "detail": { + "participant": this, + "idSomebodyOtherSide": "" + idSomebodyOtherSide + } + } ) ); + } + signalingPipeOnMessage( joMessage ) { + const self = this; + switch ( joMessage.method ) { + case "signalingFetchOffer": { + if( joMessage.error == null ) { + // OKay, fetched offer from creator + this.delayedInitPeer(); + this.idSomebodyCreator = "" + joMessage.idSomebodyCreator; + const idSomebodyOtherSide = "" + joMessage.idSomebodyCreator; + const idOffer = 0 + joMessage.idOffer; + if( settings.logging.net.signaling.generic ) { + console.log( + "Success, " + this.describe() + " fetched offer from creator (step 2)" + ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingPassedFetchOffer", + { + "detail": { + "actor": this, + "idSomebodyOtherSide": "" + idSomebodyOtherSide, + idOffer: 0 + idOffer + } + } ) ); + const offer = joMessage.offer; + if( settings.logging.net.signaling.offer ) + console.log( " <<< " + self.describe() + " got offer:", offer ); + const offerDescription = new webRtcModule.RTCSessionDescription( offer ); + if( settings.logging.net.signaling.offer ) { + console.log( + " <<< " + self.describe() + " got offer description:", offerDescription + ); + } + this.pc.setRemoteDescription( offerDescription ).then( + function() { + // success + if( settings.logging.net.signaling.remoteDescription ) { + console.log( + " <<< " + self.describe() + "did set remote description:", + offerDescription ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "remoteDescriptionSet", + { "detail": { "participant": self } } ) ); + self.pc.createAnswer( self.offerOptions ).then( + function( answerDescription ) { + // success + self.tsAnswerCreated = new Date(); + if( settings.logging.net.signaling.answer ) { + console.log( + " <<< " + self.describe() + "did created answer at " + + utils.formatDateTime( self.tsAnswerCreated ) + + " with description:", answerDescription ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "answerCreated", + { "detail": { "participant": self } } ) ); + self.pc.setLocalDescription( answerDescription ).then( + function() { + // success + if( settings.logging.net.signaling.localDescription ) { + console.log( + " <<< " + self.describe() + + " local description set:", answerDescription ); + } + self.dispatchEvent( + new UniversalDispatcherEvent( + "localDescriptionSet", + { "detail": { "participant": self } } ) ); + self.onOtherSideIdentified( + idSomebodyOtherSide, + idOffer ); // client peer got result + }, function( err ) { + // error of setLocalDescription + self.onError( + "Failed to set local description " + + "(while fetching offer for \"" + + idSomebodyOtherSide + "\"): " + + err.toString() ); + } ); + }, function( err ) { + // error of createAnswer + self.onError( + "Failed to create answer (while fetching offer for \"" + + idSomebodyOtherSide + "\"): " + err.toString() ); + } ); + }, function( err ) { + // error of setLocalDescription + self.onError( + "Failed to set remote description: (while fetching offer for \"" + + idSomebodyOtherSide + "\"): " + err.toString() ); + } ); + } else { + if( settings.logging.net.signaling.error ) { + console.warn( + " !!! " + this.describe() + + " signaling offer publishing (step 1) error", joMessage.error ); + } + this.dispatchEvent( + new UniversalDispatcherEvent( + "signalingFailedFetchOffer", + { "detail": { "actor": this, "error": joMessage.error } } ) ); + this.onError( joMessage.error ); + } + } break; + default: + super.signalingPipeOnMessage( joMessage ); + break; + } // switch( joMessage.method ) + } +}; + +export class WebRTCServerPipe extends BasicSocketPipe { + constructor( acceptor, rtcPeer, strSignalingServerURL ) { + super(); + const self = this; + self.socketType = "WebRTC"; + self.socketSubtype = "server"; + self.isConnected = true; + self.acceptor = acceptor; + self.clientNumber = 0 + acceptor.nextClientNumber; + self.clientPort = 0 + self.clientNumber; + ++ acceptor.nextClientNumber; + self.rtcPeer = rtcPeer; + self.strSignalingServerURL = + utils.makeValidSignalingServerURL( strSignalingServerURL ); + self.url = "rtc_server_pipe(" + self.clientNumber + ")://" + strSignalingServerURL; + self.rtcPeer.on( "dataChannelOpen", function( jo ) { + self.isConnected = true; + self.acceptor.mapClients["" + self.clientPort] = self; + self.dispatchEvent( new UniversalDispatcherEvent( "open", { "socket": self } ) ); + self.acceptor.dispatchEvent( + new UniversalDispatcherEvent( + "connection", + { "socket": self, strSignalingServerURL: "" + strSignalingServerURL } ) ); + } ); + self.rtcPeer.on( "dataChannelMessage", function( jo ) { + self.receive( jo.detail.data ); + } ); + self.rtcPeer.on( "rtcParticipantError", function( jo ) { + self.isConnected = false; + self.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": self, "message": jo } ) ); + } ); + self.rtcPeer.on( "dataChannelError", function( jo ) { + self.isConnected = false; + self.dispatchEvent( + new UniversalDispatcherEvent( "error", { "socket": self, "message": jo } ) ); + } ); + self.rtcPeer.on( "dataChannelClose", function( jo ) { + self.isConnected = false; + self.dispatchEvent( + new UniversalDispatcherEvent( "close", { "socket": self, "message": jo } ) ); + } ); + self.rtcPeer.on( "peerClose", function( jo ) { + self.isConnected = false; + self.dispatchEvent( + new UniversalDispatcherEvent( "close", { "socket": self, "message": jo } ) ); + } ); + } + dispose() { + this.performDisconnect(); + super.dispose(); + } + handleServerDisposed() { + this.performDisconnect(); + this.isConnected = false; + this.clientNumber = 0; + this.acceptor = null; + this.rtcPeer = null; + this.url = ""; + this.strSignalingServerURL = ""; + super.handleServerDisposed(); + this.dispose(); + } + performDisconnect() { + if( ! this.isConnected ) + return; + this.isConnected = false; + if( this.acceptor ) + this.acceptor.unregisterClientByKey( this.clientPort ); + if( this.rtcPeer ) { + this.rtcPeer.offAll(); + this.rtcPeer = null; + } + this.clientNumber = 0; + this.acceptor = null; + this.url = ""; + this.strSignalingServerURL = ""; + } + implSend( data ) { + if( ( !this.isConnected ) || ( !this.rtcPeer ) ) { + const err = "Cannot send messages to disconnected WebRTC socket server pipe"; + this.onError( err ); + throw err; + } + const s = socketSentDataMarshall( data ); + this.rtcPeer.send( s ); + } + disconnect() { + this.performDisconnect(); + super.disconnect(); + } + implReceive( data ) { + const jo = socketReceivedDataReverseMarshall( data ); + this.dispatchEvent( + new UniversalDispatcherEvent( "message", { "socket": this, "message": jo } ) ); + } +}; + +export class WebRTCServerAcceptor extends BasicServerAcceptor { + constructor( + strSignalingServerURL, idRtcParticipant, offerOptions, + signalingOptions, maxActiveOfferCount, timeToPublishMilliseconds, + timeToSignalingNegotiationMilliseconds, peerConfiguration, peerAdditionalOptions + ) { + super(); + this.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); + this.idRtcParticipant = "" + + ( ( idRtcParticipant != null && idRtcParticipant != undefined && + typeof idRtcParticipant == "string" && idRtcParticipant.length > 0 ) + ? idRtcParticipant : utils.UUIDv4() ); + this.offerOptions = offerOptions ? offerOptions : null; + this.signalingOptions = signalingOptions ? signalingOptions : null; + this.peerConfiguration = + ( peerConfiguration && typeof peerConfiguration == "object" ) + ? peerConfiguration : settings.net.rtc.peerConfiguration; + this.peerAdditionalOptions = + ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) + ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; + this.socketType = "WebRTC"; + this.maxActiveOfferCount = + ( maxActiveOfferCount != null && maxActiveOfferCount != undefined ) + ? parseInt( maxActiveOfferCount, 10 ) : settings.net.rtc.maxActiveOfferCount; + if( this.maxActiveOfferCount < 1 ) + this.maxActiveOfferCount = 1; + this.mapPendingOffers = { }; // idOffer -> RTCServerPeer + this.timeToPublishMilliseconds = timeToPublishMilliseconds + ? parseInt( timeToPublishMilliseconds, 10 ) + : settings.net.rtc.timeToPublishMilliseconds; + this.timeToSignalingNegotiationMilliseconds = timeToSignalingNegotiationMilliseconds + ? parseInt( timeToSignalingNegotiationMilliseconds, 10 ) + : settings.net.rtc.timeToSignalingNegotiationMilliseconds; + this.rtcCreator = + new RTCCreator( + "" + this.strSignalingServerURL, + "" + this.idRtcParticipant, + this.offerOptions, + this.signalingOptions ); + this.isListening = true; + const self = this; + this.rtcCreator.on( "signalingPassedImpersonation", function( eventData ) { + self.updateAllPendingOffers(); + self.dispatchEvent( + new UniversalDispatcherEvent( + "signalingPassedImpersonation", + { "detail": { "acceptor": self } } ) ); + } ); + this.rtcCreator.on( "signalingFailedImpersonation", function( eventData ) { + self.dispatchEvent( + new UniversalDispatcherEvent( + "signalingFailedImpersonation", + { "detail": { "acceptor": self } } ) ); + } ); + this.rtcCreator.on( "error", function( eventData ) { + self.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { + "detail": { + "acceptor": self, + "eventData": eventData, + "errorType": "rtcCreatorError" + } + } ) ); + } ); + this.rtcCreator.on( "close", function( eventData ) { + self.dispatchEvent( + new UniversalDispatcherEvent( + "close", + { "detail": { "acceptor": self, "eventData": eventData } } ) ); + } ); + self.rtcCreator.on( "signalingPipeError", function( jo ) { + self.isConnected = false; + self.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { "socket": self, "message": jo, "errorType": "signalingPipeError" } ) ); + } ); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.removeAllPendingOffers(); + if( this.rtcCreator ) { + this.rtcCreator.dispose(); + this.rtcCreator = null; + } + this.disposeNotifyClients(); + super.dispose(); + } + addPendingOffer() { + if( this.isDisposed ) + return; + const rtcPeer = + new RTCServerPeer( + this.rtcCreator, this.timeToPublishMilliseconds, + this.timeToSignalingNegotiationMilliseconds, + this.peerConfiguration, this.peerAdditionalOptions ); + const self = this; + rtcPeer.on( "identified", function( event ) { + if( rtcPeer.isDisposing || rtcPeer.isDisposed ) + return; + if( settings.logging.net.signaling.generic ) { + console.log( + self.rtcCreator.describe() + " is now identified peer", + event.detail.idSomebodyOtherSide ); + } + rtcPeer.serverPipe = + new WebRTCServerPipe( self, rtcPeer, self.strSignalingServerURL ); + self.detachPendingOffer( rtcPeer.idOffer ); + self.dispatchEvent( + new UniversalDispatcherEvent( "identified", { "detail": { "peer": rtcPeer } } ) ); + self.updateAllPendingOffers(); + } ); + rtcPeer.on( "localDescriptionSet", function( event ) { + self.dispatchEvent( + new UniversalDispatcherEvent( + "peerLocalDescriptionSet", + { "detail": { "acceptor": self, "peerEvent": event } } ) ); + } ); + const onTimeoutHandler = function() { + self.disposePendingOffer( rtcPeer.idOffer ); + self.updateAllPendingOffers(); + }; + rtcPeer.on( "publishTimeout", onTimeoutHandler ); + rtcPeer.on( "signalingNegotiationTimeout", onTimeoutHandler ); + rtcPeer.on( "signalingNegotiationStart", function() { + self.updateAllPendingOffers(); + } ); + + const retranslateError = function( eventData ) { + self.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { + "detail": { + "acceptor": self, + "rtcPeer": rtcPeer, + "eventData": eventData, + "errorType": "rtcPeerError" + } + } ) ); + }; + rtcPeer.on( "error", retranslateError ); + rtcPeer.on( "rtcPeerError", retranslateError ); + + this.mapPendingOffers[rtcPeer.idOffer] = rtcPeer; + } + detachPendingOffer( idOffer ) { + if( idOffer in this.mapPendingOffers ) + delete this.mapPendingOffers[idOffer]; + } + disposePendingOffer( idOffer ) { + if( idOffer in this.mapPendingOffers ) { + const rtcPeer = this.mapPendingOffers[idOffer]; + rtcPeer.dispose(); + delete this.mapPendingOffers[idOffer]; + } + } + removeAllPendingOffers() { + for( const [ /*idOffer*/, rtcPeer ] + of Object.entries( this.rtcCreator.mapServerPeers ) ) { + const serverPipe = rtcPeer.serverPipe; + serverPipe.dispose(); + } + this.rtcCreator.mapServerPeers = { }; + for( const [ /*idOffer*/, rtcPeer ] + of Object.entries( this.rtcCreator.mapPendingOffers ) ) + rtcPeer.dispose(); + + this.mapPendingOffers = { }; + } + updateAllPendingOffers() { + if( this.isDisposed ) + return; + for( let n = Object.keys( this.mapPendingOffers ); n < this.maxActiveOfferCount; ++ n ) + this.addPendingOffer(); + } +}; + +export class WebRTCClientPipe extends BasicSocketPipe { + constructor( + strSignalingServerURL, idRtcParticipant, offerOptions, + signalingOptions, peerConfiguration, peerAdditionalOptions + ) { + super(); + this.strSignalingServerURL = utils.makeValidSignalingServerURL( strSignalingServerURL ); + this.idRtcParticipant = "" + + ( ( idRtcParticipant != null && idRtcParticipant != undefined && + typeof idRtcParticipant == "string" && idRtcParticipant.length > 0 ) + ? idRtcParticipant : utils.UUIDv4() ); + this.offerOptions = offerOptions ? offerOptions : null; + this.signalingOptions = signalingOptions ? signalingOptions : null; + this.peerConfiguration = + ( peerConfiguration && typeof peerConfiguration == "object" ) + ? peerConfiguration : settings.net.rtc.peerConfiguration; + this.peerAdditionalOptions = + ( peerAdditionalOptions && typeof peerAdditionalOptions == "object" ) + ? peerAdditionalOptions : settings.net.rtc.peerAdditionalOptions; + this.socketType = "WebRTC"; + this.socketSubtype = "client"; + this.isConnected = false; + this.rtcPeer = null; + this.isAutoCloseSignalingPipeOnDataChannelOpen = + settings.net.rtc.isAutoCloseSignalingPipeOnDataChannelOpen ? true : false; + this.url = "rtc_client_pipe-" + this.strSignalingServerURL; + this.reconnect(); + } + dispose() { + if( this.isDisposed ) + return; + this.isDisposing = true; + this.performDisconnect(); + this.strSignalingServerURL = null; + super.dispose(); + } + implSend( data ) { + if( ( !this.isConnected ) || ( !this.rtcPeer ) ) { + const s = "Cannot send messages to disconnected WebRTC socket client pipe"; + this.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { "socket": this, "message": "" + s, "errorType": "dataSendError" } ) ); + throw new Error( s ); + } + const s = socketSentDataMarshall( data ); + this.rtcPeer.send( s ); + } + reconnect() { + this.performDisconnect(); + this.rtcConnect( "" + this.strSignalingServerURL ); + } + disconnect() { + this.performDisconnect(); + super.disconnect(); + } + performDisconnect() { + if( ! this.isConnected ) + return; + this.rtcDisconnect(); + } + rtcConnect( strSignalingServerURL ) { + if( strSignalingServerURL.length == 0 ) { + const s = "Cannot connect signaling server \"" + strSignalingServerURL + "\", bad url"; + this.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { "socket": this, "message": "" + s, "errorType": "badSignalingServerURL" } ) ); + throw new Error( s ); + } + const self = this; + while( true ) { + try { + if( self.isConnected || self.rtcPeer ) + self.rtcDisconnect(); + self.rtcPeer = + new RTCJoiner( + "" + strSignalingServerURL, "" + self.idRtcParticipant, + self.offerOptions, self.signalingOptions, + self.peerConfiguration, self.peerAdditionalOptions + ); // client side + self.strSignalingServerURL = + utils.makeValidSignalingServerURL( strSignalingServerURL ); + self.rtcPeer.on( "identified", function( event ) { + if( settings.logging.net.signaling.generic ) { + console.log( + self.rtcPeer.describe() + " is now identified peer", + event.detail.idSomebodyOtherSide + ); + } + } ); + self.rtcPeer.on( "dataChannelOpen", function( jo ) { + self.isConnected = true; + self.dispatchEvent( + new UniversalDispatcherEvent( "open", { "socket": self } ) + ); + if( self.isAutoCloseSignalingPipeOnDataChannelOpen ) { + if( settings.logging.net.signaling.disconnect ) { + console.warn( + self.rtcPeer.describe() + + " will auto-close signaling pipe" + + "(inside socket \"dataChannelOpen\" handler)" + ); + } + self.rtcPeer.signalingPipeClose(); + } + } ); + self.rtcPeer.on( "dataChannelMessage", function( jo ) { + self.receive( jo.detail.data ); + } ); + self.rtcPeer.on( "rtcParticipantError", function( jo ) { + self.isConnected = false; + self.dispatchEvent( new UniversalDispatcherEvent( + "error", + { + "socket": self, + "message": jo, + "errorType": "rtcParticipantError" + } ) + ); + } ); + self.rtcPeer.on( "dataChannelError", function( jo ) { + self.isConnected = false; + self.dispatchEvent( new UniversalDispatcherEvent( + "error", + { + "socket": self, + "message": jo, + "errorType": "dataChannelError" + } ) + ); + } ); + self.rtcPeer.on( "dataChannelClose", function( jo ) { + self.isConnected = false; + self.dispatchEvent( new UniversalDispatcherEvent( + "close", + { "socket": self, "message": jo } ) ); + } ); + self.rtcPeer.on( "signalingPipeError", function( jo ) { + self.isConnected = false; + self.dispatchEvent( new UniversalDispatcherEvent( + "error", + { + "socket": self, + "message": jo, + "errorType": "signalingPipeError" + } ) + ); + } ); + return; + } catch ( err ) { + console.warn( "WebRTC client connect error:", err ); + continue; + } + } + } + rtcDisconnect() { + if( this.rtcPeer ) { + this.rtcPeer.offAll(); + this.rtcPeer.dispose(); + this.rtcPeer = null; + } + this.isConnected = false; + this.url = ""; + } + implReceive( data ) { + const jo = socketReceivedDataReverseMarshall( data ); + this.dispatchEvent( + new UniversalDispatcherEvent( + "message", + { "socket": this, "message": jo } ) ); + } +}; diff --git a/npms/skale-cool-socket/server.js b/npms/skale-cool-socket/socketServer.mjs similarity index 69% rename from npms/skale-cool-socket/server.js rename to npms/skale-cool-socket/socketServer.mjs index d4335a472..b6949c603 100644 --- a/npms/skale-cool-socket/server.js +++ b/npms/skale-cool-socket/socketServer.mjs @@ -19,14 +19,14 @@ */ /** - * @file server.js + * @file socketServer.mjs * @copyright SKALE Labs 2019-Present */ -const { EventDispatcher, UniversalDispatcherEvent } = require( "./event_dispatcher.js" ); -const utils = require( "./utils.js" ); +import { EventDispatcher, UniversalDispatcherEvent } from "./eventDispatcher.mjs"; +import * as utils from "./socketUtils.mjs"; -class Server extends EventDispatcher { +export class SocketServer extends EventDispatcher { constructor( acceptor ) { super(); if( acceptor == null || acceptor == undefined || typeof acceptor != "object" ) @@ -42,7 +42,9 @@ class Server extends EventDispatcher { self.isLogSocketTrafficRaw = false; acceptor.on( "connection", function( eventData ) { const socket = eventData.socket; - if( ( ! ( "remoteAddress" in eventData ) ) || eventData.remoteAddress == null || eventData.remoteAddress == undefined ) + if( ( ! ( "remoteAddress" in eventData ) ) || + eventData.remoteAddress == null || + eventData.remoteAddress == undefined ) socket.strSavedRemoteAddress = socket.constructor.name; else socket.strSavedRemoteAddress = "" + eventData.remoteAddress; @@ -69,42 +71,60 @@ class Server extends EventDispatcher { delete self.mapAcceptedPipes[socket]; }; let _onPipeMessage = function( eventData ) { - if( self.isLogSocketTrafficRaw ) - self.log( "Accepted socket \"" + socket.strSavedRemoteAddress + "\" raw message", eventData ); + if( self.isLogSocketTrafficRaw ) { + self.log( + "Accepted socket \"" + socket.strSavedRemoteAddress + + "\" raw message", eventData ); + } const joMessage = eventData.message; - if( self.isLogAcceptedSocket ) - self.log( "Accepted socket \"" + socket.strSavedRemoteAddress + "\" message", joMessage ); + if( self.isLogAcceptedSocket ) { + self.log( + "Accepted socket \"" + socket.strSavedRemoteAddress + + "\" message", joMessage ); + } let joAnswer = null; let isFlush = false; try { if( joMessage.method in self.mapApiHandlers ) { joAnswer = utils.prepareAnswerJSON( joMessage ); - joAnswer = self.mapApiHandlers[joMessage.method]( joMessage, joAnswer, eventData, socket ); + joAnswer = self.mapApiHandlers[joMessage.method]( + joMessage, joAnswer, eventData, socket ); if( joAnswer ) isFlush = true; } else { joAnswer = utils.prepareAnswerJSON( joMessage ); joAnswer.error = "Unhandled message"; joAnswer.joMessage = joMessage; // send it back )) - if( self.isLogSocketTraffic ) - self.log( "Accepted socket \"" + socket.strSavedRemoteAddress + "\" unhandled message", joMessage ); + if( self.isLogSocketTraffic ) { + self.log( + "Accepted socket \"" + socket.strSavedRemoteAddress + + "\" unhandled message", joMessage ); + } isFlush = true; } } catch ( err ) { - if( self.isLogSocketErrors ) - self.log( "Server method", joMessage.method, "RPC exception:", err ); + if( self.isLogSocketErrors ) { + self.log( + "Server method", joMessage.method, + "RPC exception:", err, ", stack is:", err.stack ); + } joAnswer = utils.prepareAnswerJSON( joMessage ); joAnswer.error = "" + err.toString(); } - // - // + if( joAnswer != null && joAnswer != undefined ) { if( typeof joAnswer.error == "string" && joAnswer.error.length > 0 ) { - if( self.isLogSocketErrors ) - self.log( "Accepted socket \"" + socket.strSavedRemoteAddress + "\" error answer", joAnswer ); + if( self.isLogSocketErrors ) { + self.log( + "Accepted socket \"" + socket.strSavedRemoteAddress + + "\" error answer", joAnswer ); + } } else { - if( self.isLogSocketTraffic ) - self.log( "Accepted socket \"" + socket.strSavedRemoteAddress + " answer", joAnswer ); + if( self.isLogSocketTraffic ) { + self.log( + "Accepted socket \"" + socket.strSavedRemoteAddress + + " answer", joAnswer ); + } } socket.send( joAnswer, isFlush ); } @@ -128,14 +148,11 @@ class Server extends EventDispatcher { socket.on( "error", _onPipeError ); socket.on( "message", _onPipeMessage ); } ); - this.dispatchEvent( new UniversalDispatcherEvent( "initialized", { detail: { ref: this } } ) ); + this.dispatchEvent( + new UniversalDispatcherEvent( "initialized", { "detail": { "ref": this } } ) ); } dispose() { this.isDisposing = true; super.dispose(); } }; - -module.exports = { - Server: Server -}; diff --git a/npms/skale-cool-socket/settings.js b/npms/skale-cool-socket/socketSettings.mjs similarity index 82% rename from npms/skale-cool-socket/settings.js rename to npms/skale-cool-socket/socketSettings.mjs index ca1e6215c..fc366ae9d 100644 --- a/npms/skale-cool-socket/settings.js +++ b/npms/skale-cool-socket/socketSettings.mjs @@ -19,7 +19,7 @@ */ /** - * @file settings.js + * @file socketSettings.mjs * @copyright SKALE Labs 2019-Present */ @@ -46,10 +46,14 @@ const settings = { }, rtc: { arrKnownIceServers: [ - // see: https://gist.github.com/mondain/b0ec1cf5f60ae726202e and https://gist.github.com/zziuni/3741933 - // see: https://stackoverflow.com/questions/20068944/webrtc-stun-stun-l-google-com19302 + // see: https://gist.github.com/mondain/b0ec1cf5f60ae726202e + // and https://gist.github.com/zziuni/3741933 + // see: https://stackoverflow.com/questions + // /20068944/webrtc-stun-stun-l-google-com19302 // see: https://gist.github.com/yetithefoot/7592580 - // even more to see: https://gist.github.com/sagivo/3a4b2f2c7ac6e1b5267c2f1f59ac6c6b + // even more to see: + // https://gist.github.com/sagivo + // /3a4b2f2c7ac6e1b5267c2f1f59ac6c6b "stun:stun.1.google.com:19302", "stun:stun.2.google.com:19302", "stun:stun.3.google.com:19302", @@ -80,14 +84,11 @@ const settings = { "stun:stun.voxgratia.org" ] , peerConfiguration: { - iceServers: [ - // { urls: "stun:192.168.88.220:3478", username: "webrtc", credential: "qwerty" } - // { urls: "turn:192.168.88.220:3478", username: "webrtc", credential: "qwerty" } - { urls: "stun:127.0.0.1:3478", username: "webrtc", credential: "qwerty" } - // { urls: "turn:127.0.0.1:3478", username: "webrtc", credential: "qwerty" } - ] - // , iceTransportPolicy: "all" - // , iceCandidatePoolSize: "0" // efault value is 0 (meaning no candidate pre-fetching will occur). + iceServers: [ { + urls: "stun:some.ip.address.here:3478", + username: "some.user.name", + credential: "some.password" + } ] }, peerAdditionalOptions: { optional: [ { DtlsSrtpKeyAgreement: true } ] @@ -97,9 +98,12 @@ const settings = { opts: { reliable: true, ordered: true } }, maxActiveOfferCount: 10, - isAutoCloseSignalingPipeOnDataChannelOpen: true, // network_layer.WebRTCClientPipe only - timeToPublishMilliseconds: 0, // 0 - no timeout, 300000 = 5 minutes, 60000 = 1 minute - timeToSignalingNegotiationMilliseconds: 0, // 0 - no timeout, 10000 = 10 seconds to identify by WebRTC + // networkLayer.WebRTCClientPipe only + isAutoCloseSignalingPipeOnDataChannelOpen: true, + // 0 - no timeout, 300000 = 5 minutes, 60000 = 1 minute + timeToPublishMilliseconds: 0, + // 0 - no timeout, 10000 = 10 seconds to identify by WebRTC + timeToSignalingNegotiationMilliseconds: 0, offerDiscovery: { periodMilliseconds: 1000, stepCount: 20 @@ -192,6 +196,4 @@ const settings = { } }; -module.exports = { - settings: settings -}; +export { settings }; diff --git a/npms/skale-cool-socket/utils.js b/npms/skale-cool-socket/socketUtils.mjs similarity index 54% rename from npms/skale-cool-socket/utils.js rename to npms/skale-cool-socket/socketUtils.mjs index 270b57c68..9173bcdb4 100644 --- a/npms/skale-cool-socket/utils.js +++ b/npms/skale-cool-socket/socketUtils.mjs @@ -19,28 +19,30 @@ */ /** - * @file utils.js + * @file socketUtils.mjs * @copyright SKALE Labs 2019-Present */ -const { settings } = require( "./settings.js" ); +import { settings } from "./socketSettings.mjs"; -const uuid_v4 = function() { +export const UUIDv4 = function() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace( /[xy]/g, function( c ) { const r = Math.random() * 16 | 0, v = c == "x" ? r : ( r & 0x3 | 0x8 ); return v.toString( 16 ); } ); }; -const getRandomInt = function( nMax ) { +export const getRandomInt = function( nMax ) { return parseInt( Math.floor( Math.random() * Math.floor( nMax ) ), 10 ); }; -const randomFixedInteger = function( length ) { - return Math.floor( Math.pow( 10, length - 1 ) + Math.random() * ( Math.pow( 10, length ) - Math.pow( 10, length - 1 ) - 1 ) ); +export const randomFixedInteger = function( length ) { + return Math.floor( + Math.pow( 10, length - 1 ) + + Math.random() * ( Math.pow( 10, length ) - Math.pow( 10, length - 1 ) - 1 ) ); }; -const randomStringABC = function( length, arrCharacters ) { +export const randomStringABC = function( length, arrCharacters ) { length = parseInt( length, 10 ); if( length <= 0 || arrCharacters.length == 0 ) return ""; @@ -50,14 +52,20 @@ const randomStringABC = function( length, arrCharacters ) { return s; }; -const randomString = function( length, isABC, isDigits, isSpecChr, isPunctuation ) { // by default only isABC=true +export const randomString = function( + length, isABC, isDigits, isSpecChr, isPunctuation +) { // by default only isABC=true length = parseInt( length, 10 ); if( length <= 0 ) return ""; - isABC = ( isABC == null || isABC == undefined ) ? true : ( isABC ? true : false ); - isDigits = ( isDigits == null || isDigits == undefined ) ? false : ( isDigits ? true : false ); - isSpecChr = ( isSpecChr == null || isSpecChr == undefined ) ? false : ( isSpecChr ? true : false ); - isPunctuation = ( isPunctuation == null || isPunctuation == undefined ) ? false : ( isPunctuation ? true : false ); + isABC = ( isABC == null || isABC == undefined ) + ? true : ( isABC ? true : false ); + isDigits = ( isDigits == null || isDigits == undefined ) + ? false : ( isDigits ? true : false ); + isSpecChr = ( isSpecChr == null || isSpecChr == undefined ) + ? false : ( isSpecChr ? true : false ); + isPunctuation = ( isPunctuation == null || isPunctuation == undefined ) + ? false : ( isPunctuation ? true : false ); let arrCharacters = ""; if( isABC ) arrCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; @@ -72,16 +80,17 @@ const randomString = function( length, isABC, isDigits, isSpecChr, isPunctuation return randomStringABC( length, arrCharacters ); }; -const randomHexString = function( length ) { // length in characters, not bytes, each byte is 2 characters +export const randomHexString = function( length ) { + // length in characters, not bytes, each byte is 2 characters const arrCharacters = "0123456789abcdef"; return randomStringABC( length, arrCharacters ); }; -const replaceAll = function( str, find, replace ) { +export const replaceAll = function( str, find, replace ) { return str.replace( new RegExp( find, "g" ), replace ); }; -const simpleEscapeString = function( s ) { +export const simpleEscapeString = function( s ) { if( s == null || s == undefined || typeof s != "string" ) return s; s = replaceAll( s, "&", "&" ); @@ -91,54 +100,66 @@ const simpleEscapeString = function( s ) { return s; }; -const abstractUniqueID = function() { - const id = replaceAll( uuid_v4(), "-", "" ).toLowerCase(); +export const abstractUniqueID = function() { + const id = replaceAll( UUIDv4(), "-", "" ).toLowerCase(); return id; }; -const isEven = function( n ) { +export const isEven = function( n ) { return n % 2 == 0; }; -const isOdd = function( n ) { +export const isOdd = function( n ) { return Math.abs( n % 2 ) == 1; }; -const g_nCallIdDigits = 10; -const randomCallID = function() { - const id = randomHexString( g_nCallIdDigits ); +const gCountOfCallIdDigits = 10; +export const randomCallID = function() { + const id = randomHexString( gCountOfCallIdDigits ); return id; }; -const g_nDirectPipeIdDigits = 10; -const randomDirectPipeID = function() { - const id = randomHexString( g_nDirectPipeIdDigits ); +const gCountOfDirectPipeIdDigits = 10; +export const randomDirectPipeID = function() { + const id = randomHexString( gCountOfDirectPipeIdDigits ); return id; }; -const bind_scope_to_function = function( scope, fn ) { +export const bindScopeToFunction = function( scope, fn ) { return function() { fn.apply( scope, arguments ); }; }; -const prepareAnswerJSON = function( joMessage ) { +export const prepareAnswerJSON = function( joMessage ) { const joAnswer = { - id: "" + ( ( joMessage != null && joMessage != undefined && typeof joMessage.id == "string" ) ? joMessage.id : randomCallID() ), - method: "" + ( ( joMessage != null && joMessage != undefined && typeof joMessage.method == "string" ) ? joMessage.method : "" ), - error: null + "id": "" + + ( ( joMessage != null && + joMessage != undefined && + typeof joMessage.id == "string" ) + ? joMessage.id : randomCallID() ), + "method": "" + + ( ( joMessage != null && + joMessage != undefined && + typeof joMessage.method == "string" ) + ? joMessage.method : "" ), + "error": null }; return joAnswer; }; -const makeValidSignalingServerURL = function( strSignalingServerURL ) { +export const makeValidSignalingServerURL = function( strSignalingServerURL ) { const proto = settings.net.secure ? "wss" : "ws"; - return "" + ( ( strSignalingServerURL != null && strSignalingServerURL != undefined && typeof strSignalingServerURL == "string" && strSignalingServerURL.length > 0 ) - ? "" + strSignalingServerURL - : "" + proto + "://" + settings.net.hostname + ":" + settings.net.ports.signaling - ); + return "" + + ( ( strSignalingServerURL != null && + strSignalingServerURL != undefined && + typeof strSignalingServerURL == "string" && + strSignalingServerURL.length > 0 ) + ? "" + strSignalingServerURL + : "" + proto + "://" + settings.net.hostname + ":" + settings.net.ports.signaling + ); }; -const zero_padding_left = function( val, cntCharsNeeded ) { +export const zeroPaddingLeft = function( val, cntCharsNeeded ) { if( val == null || val == undefined ) return val; let s = "" + val; @@ -146,7 +167,7 @@ const zero_padding_left = function( val, cntCharsNeeded ) { s = "0" + s; return s; }; -const zero_padding_right = function( val, cntCharsNeeded ) { +export const zeroPaddingRight = function( val, cntCharsNeeded ) { if( val == null || val == undefined ) return val; let s = "" + val; @@ -155,7 +176,7 @@ const zero_padding_right = function( val, cntCharsNeeded ) { return s; }; -const parse_date_time = function( ts ) { +export const parseDateTime = function( ts ) { if( ts === null || ts === undefined ) return ts; if( typeof ts != "string" ) @@ -183,7 +204,9 @@ const parse_date_time = function( ts ) { d.setMilliseconds( millisecond ); return d; }; -const format_date_time = function( dt, isDate, isTime, isMilliseconds, sepDate, sepTime, sepBetween, sepMilliseconds ) { +export const formatDateTime = function( + dt, isDate, isTime, isMilliseconds, sepDate, sepTime, sepBetween, sepMilliseconds +) { if( dt === null ) return "null-date-time"; if( dt === undefined ) @@ -196,58 +219,44 @@ const format_date_time = function( dt, isDate, isTime, isMilliseconds, sepDate, return ""; let s = ""; if( isDate ) { - sepDate = ( sepDate == null || sepDate == undefined || ( typeof sepDate != "string" ) ) ? "/" : sepDate; + sepDate = ( sepDate == null || sepDate == undefined || ( typeof sepDate != "string" ) ) + ? "/" : sepDate; const strDate = "" + - zero_padding_left( dt.getFullYear(), 4 ) + + zeroPaddingLeft( dt.getFullYear(), 4 ) + sepDate + - zero_padding_left( dt.getMonth() + 1, 2 ) + + zeroPaddingLeft( dt.getMonth() + 1, 2 ) + sepDate + - zero_padding_left( dt.getDate(), 2 ); + zeroPaddingLeft( dt.getDate(), 2 ); s += strDate; } if( isTime ) { - sepTime = ( sepTime == null || sepTime == undefined || ( typeof sepTime != "string" ) ) ? ":" : sepTime; + sepTime = ( sepTime == null || sepTime == undefined || ( typeof sepTime != "string" ) ) + ? ":" : sepTime; if( isDate ) { - sepBetween = ( sepBetween == null || sepBetween == undefined || ( typeof sepBetween != "string" ) ) ? "-" : sepBetween; + sepBetween = + ( sepBetween == null || + sepBetween == undefined || + ( typeof sepBetween != "string" ) ) + ? "-" : sepBetween; s += sepBetween; } let strTime = "" + - zero_padding_left( dt.getHours(), 2 ) + + zeroPaddingLeft( dt.getHours(), 2 ) + sepDate + - zero_padding_left( dt.getMinutes(), 2 ) + + zeroPaddingLeft( dt.getMinutes(), 2 ) + sepDate + - zero_padding_left( dt.getSeconds(), 2 ); - isMilliseconds = ( isMilliseconds == null || isMilliseconds == undefined ) ? true : ( isMilliseconds ? true : false ); + zeroPaddingLeft( dt.getSeconds(), 2 ); + isMilliseconds = ( isMilliseconds == null || isMilliseconds == undefined ) + ? true : ( isMilliseconds ? true : false ); if( isMilliseconds ) { - sepMilliseconds = ( sepMilliseconds == null || sepMilliseconds == undefined || ( typeof sepMilliseconds != "string" ) ) ? "." : sepMilliseconds; - strTime += sepMilliseconds + zero_padding_right( dt.getMilliseconds(), 3 ); + sepMilliseconds = + ( sepMilliseconds == null || + sepMilliseconds == undefined || + ( typeof sepMilliseconds != "string" ) ) + ? "." : sepMilliseconds; + strTime += sepMilliseconds + zeroPaddingRight( dt.getMilliseconds(), 3 ); } s += strTime; } return s; }; - -module.exports = { - uuid_v4: uuid_v4, - getRandomInt: getRandomInt, - randomFixedInteger: randomFixedInteger, - randomStringABC: randomStringABC, - randomString: randomString, - randomHexString: randomHexString, - replaceAll: replaceAll, - simpleEscapeString: simpleEscapeString, - abstractUniqueID: abstractUniqueID, - isEven: isEven, - isOdd: isOdd, - g_nCallIdDigits: g_nCallIdDigits, - randomCallID: randomCallID, - g_nDirectPipeIdDigits: g_nDirectPipeIdDigits, - randomDirectPipeID: randomDirectPipeID, - bind_scope_to_function: bind_scope_to_function, - prepareAnswerJSON: prepareAnswerJSON, - makeValidSignalingServerURL: makeValidSignalingServerURL, - zero_padding_left: zero_padding_left, - zero_padding_right: zero_padding_right, - parse_date_time: parse_date_time, - format_date_time: format_date_time -}; diff --git a/npms/skale-cool-socket/test.js b/npms/skale-cool-socket/test.js deleted file mode 100644 index dd9183dd2..000000000 --- a/npms/skale-cool-socket/test.js +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE COOL SOCKET - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file test.js - * @copyright SKALE Labs 2019-Present - */ - -const network_layer = require( "./socket.js" ); -const { TestServer } = require( "./test_server.js" ); -const { Worker } = require( "worker_threads" ); -const { settings } = require( "./settings.js" ); -const ws = require( "ws" ); -// const wrtc = require( "wrtc" ); - -const joTestMessage = { "method": "echo", "message": "Please echo this message!" }; - -const sleep = ( milliseconds ) => { return new Promise( resolve => setTimeout( resolve, milliseconds ) ); }; - -async function test_local() { - console.log( "Local test" ); - const strEndPoint = "local_endpoint"; - const acceptor = new network_layer.LocalSocketServerAcceptor( strEndPoint ); - const server = new TestServer( acceptor ); - const client = new network_layer.LocalSocketClientPipe( strEndPoint ); - client.on( "message", function( eventData ) { - const joMessage = eventData.message; - console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); - client.disconnect(); - console.log( " " ); - } ); - await sleep( 1 ); - console.log( "CLIENT >>>", JSON.stringify( joTestMessage ) ); - client.send( joTestMessage ); - await sleep( 100 ); - const joReturnValue = { - server: server, - client: client - }; - return joReturnValue; -} - -async function test_worker() { - console.log( "Worker test" ); - const url = "local_worker_server"; - const worker = new Worker( "./test_worker.js" ); - console.log( "Will connect to " + url ); - worker.on( "message", jo => { - if( network_layer.out_of_worker_apis.on_message( worker, jo ) ) - return; - } ); - const client = new network_layer.OutOfWorkerSocketClientPipe( url, worker ); - client.on( "message", function( eventData ) { - const joMessage = eventData.message; - console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); - client.disconnect(); - worker.terminate(); - console.log( " " ); - } ); - await sleep( 100 ); - console.log( "CLIENT >>>", JSON.stringify( joTestMessage ) ); - client.send( joTestMessage ); - await sleep( 100 ); - const joReturnValue = { - worker: worker, - client: client - }; - return joReturnValue; -} - -async function test_web_socket() { - console.log( "Web socket test" ); - network_layer.set_ws_mod( ws ); - const nPort = 33123; - const url = ( settings.net.secure ? "wss" : "ws" ) + "://127.0.0.1:" + nPort; - const key = settings.net.secure ? fs.readFileSync( "./self-signed/self-signed-key.pem", "utf8" ) : null; - const cert = settings.net.secure ? fs.readFileSync( "./self-signed/self-signed-cert.pem", "utf8" ) : null; - const acceptor = new network_layer.WebSocketServerAcceptor( nPort, key, cert ); - const server = new TestServer( acceptor ); - const client = new network_layer.WebSocketClientPipe( url ); - client.on( "message", function( eventData ) { - const joMessage = eventData.message; - console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); - client.disconnect(); - console.log( " " ); - } ); - await sleep( 100 ); - console.log( "CLIENT >>>", JSON.stringify( joTestMessage ) ); - client.send( joTestMessage ); - await sleep( 100 ); - const joReturnValue = { - server: server, - client: client - }; - return joReturnValue; -} - -// async function test_wrtc() { -// // -// // Needed in package.json: "wrtc": "^0.4.6", -// // -// // ## Coturn - own STUN and/or TURN server -// // -// // See and see -// // Explanation for Mac OSX is -// // -// // Install via **sudo apt-get install coturn** or **brew install coturn**. -// // Run **sudo nano /etc/turnserver.conf** and specify described in , -// // realm **realm=origin/realm**, **no-tls** and **no-dtls**. Also set **listening-ip** to **0.0.0.0** -// // -// // **STUN** config entry is **{ urls: "stun:127.0.0.1:3478", username: "webrtc", credential: "qwerty" }**. -// // **TURN** config entry is **{ urls: "turn:127.0.0.1:3478", username: "webrtc", credential: "qwerty" }**. -// // -// console.log( "Web RTC test" ); -// network_layer.set_ws_mod( ws ); -// network_layer.set_wrtc_mod( wrtc ); -// const url = null; // null here means url will be got from settings -// const acceptor = new network_layer.WebRTCServerAcceptor( url ); -// const server = new TestServer( acceptor ); -// server.on( "dispose", function() { console.log( "disposed", url ); } ); -// console.log( "Will connect to " + url ); -// const client = new network_layer.WebRTCClientPipe( url ); -// client.on( "message", function( eventData ) { -// const joMessage = eventData.message; -// console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); -// client.disconnect(); -// console.log( " " ); -// } ); -// await sleep( 1000 ); -// console.log( "CLIENT >>>", JSON.stringify( joTestMessage ) ); -// client.send( joTestMessage ); -// await sleep( 1000 ); -// const joReturnValue = { -// server: server, -// client: client -// }; -// return joReturnValue; -// } - -async function test() { - await test_local(); - await test_worker(); - await test_web_socket(); - // await test_wrtc(); - process.exit( 0 ); -} -test(); diff --git a/npms/skale-cool-socket/test_server.js b/npms/skale-cool-socket/testSocketServer.mjs similarity index 89% rename from npms/skale-cool-socket/test_server.js rename to npms/skale-cool-socket/testSocketServer.mjs index 32283918d..dfae57bd6 100644 --- a/npms/skale-cool-socket/test_server.js +++ b/npms/skale-cool-socket/testSocketServer.mjs @@ -19,13 +19,13 @@ */ /** - * @file test_server.js + * @file testSocketServer.mjs * @copyright SKALE Labs 2019-Present */ -const { Server } = require( "./server.js" ); +import { SocketServer } from "./socketServer.mjs"; -class TestServer extends Server { +export class TestSocketServer extends SocketServer { constructor( acceptor ) { super( acceptor ); const self = this; @@ -41,7 +41,3 @@ class TestServer extends Server { super.dispose(); } }; - -module.exports = { - TestServer: TestServer -}; diff --git a/npms/skale-cool-socket/test_signaling_server.js b/npms/skale-cool-socket/testSocketSignalingServer.mjs similarity index 54% rename from npms/skale-cool-socket/test_signaling_server.js rename to npms/skale-cool-socket/testSocketSignalingServer.mjs index 736839c19..a13990014 100644 --- a/npms/skale-cool-socket/test_signaling_server.js +++ b/npms/skale-cool-socket/testSocketSignalingServer.mjs @@ -19,42 +19,41 @@ */ /** - * @file test_signaling_server.js + * @file testSocketSignalingServer.mjs.mjs * @copyright SKALE Labs 2019-Present */ -const fs = require( "fs" ); +import * as fs from "fs"; -const https_loaded_mod = require( "https" ); -const ws_loaded_mod = require( "ws" ); -const wrtc_loaded_mod = require( "wrtc" ); +import * as httpsModuleLoaded from "https"; +import * as wsModuleLoaded from "ws"; +import * as webRtcModuleLoaded from "wrtc"; -const network_layer = require( "./socket.js" ); -const { settings } = require( "./settings.js" ); -const { UniversalDispatcherEvent, EventDispatcher } = require( "./event_dispatcher.js" ); -const utils = require( "./utils.js" ); +import * as networkLayer from "./socket.mjs"; +import { settings } from "./socketSettings.mjs"; +import { UniversalDispatcherEvent, EventDispatcher } from "./eventDispatcher.mjs"; +import * as utils from "./socketUtils.mjs"; -// const connect = connect_loaded_mod; // .default; -// const serveStatic = serveStatic_loaded_mod; // .default; -const https_mod = https_loaded_mod; // .default; -const ws_mod = ws_loaded_mod; // .default; -const wrtc_mod = wrtc_loaded_mod; // .default; +const httpsModule = httpsModuleLoaded; // .default; +const wsModule = wsModuleLoaded; // .default; +const webRtcModule = webRtcModuleLoaded; // .default; -network_layer.set_https_mod( https_mod ); -network_layer.set_ws_mod( ws_mod ); -network_layer.set_wrtc_mod( wrtc_mod ); +networkLayer.setHttpsModule( httpsModule ); +networkLayer.setWsModule( wsModule ); +networkLayer.setWebRtcModule( webRtcModule ); console.log( "Test signaling server application..." ); process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - class SignalingClient extends EventDispatcher { constructor( idRtcParticipant, strRole, signalingSpace, socket ) { super(); this.isDisposed = false; - this.idRtcParticipant = "" + ( ( idRtcParticipant && typeof idRtcParticipant == "string" && idRtcParticipant.length > 0 ) ? idRtcParticipant : "" ); + this.idRtcParticipant = "" + + ( ( idRtcParticipant && + typeof idRtcParticipant == "string" && + idRtcParticipant.length > 0 ) + ? idRtcParticipant : "" ); this.isCreator = ( strRole == "creator" ) ? true : false; this.isJoiner = ( strRole == "joiner" ) ? true : false; this.signalingSpace = signalingSpace; @@ -62,27 +61,41 @@ class SignalingClient extends EventDispatcher { socket.signalingClient = this; if( this.isCreator ) this.signalingSpace.idSomebodyCreator = "" + this.idRtcParticipant; - this.signalingSpace.map_clients[this.idRtcParticipant] = this; + this.signalingSpace.mapClients[this.idRtcParticipant] = this; this.idSpace = "" + this.signalingSpace.idSpace; this.idCategory = "" + this.signalingSpace.signalingCategory.idCategory; this.isFetchingOffer = false; this.timerFetchingOffer = null; this.fetchingOfferStepNumber = 0; - if( settings.logging.net.signaling.objectLifetime ) - console.log( "New signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\" using socket " + this.socket.strSavedRemoteAddress ); - this.signalingSpace.dispatchEvent( new UniversalDispatcherEvent( "clientAdded", { detail: { signalingClient: this } } ) ); + if( settings.logging.net.signaling.objectLifetime ) { + console.log( + "New signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + + this.idSpace + "\" in signaling category \"" + this.idCategory + + "\" using socket " + this.socket.strSavedRemoteAddress ); + } + this.signalingSpace.dispatchEvent( + new UniversalDispatcherEvent( + "clientAdded", + { "detail": { "signalingClient": this } } ) ); } dispose() { if( this.isDisposed ) return; this.isDisposing = true; - if( settings.logging.net.signaling.objectLifetime ) - console.log( "Disposing signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\"" ); + if( settings.logging.net.signaling.objectLifetime ) { + console.log( + "Disposing signaling client \"" + this.idRtcParticipant + + "\" in signaling space \"" + this.idSpace + + "\" in signaling category \"" + this.idCategory + "\"" ); + } this.disconnect(); if( this.idRtcParticipant ) { if( this.signalingSpace ) { - this.signalingSpace.dispatchEvent( new UniversalDispatcherEvent( "clientRemoved", { detail: { signalingClient: this } } ) ); - delete this.signalingSpace.map_clients[this.idRtcParticipant]; + this.signalingSpace.dispatchEvent( + new UniversalDispatcherEvent( + "clientRemoved", + { "detail": { "signalingClient": this } } ) ); + delete this.signalingSpace.mapClients[this.idRtcParticipant]; } this.idRtcParticipant = null; } @@ -110,28 +123,44 @@ class SignalingClient extends EventDispatcher { anyError = err; } if( ! bPass ) { - if( settings.logging.net.signaling.error ) - console.warn( "Signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\" - web socket signaling pipe termination error", anyError ); + if( settings.logging.net.signaling.error ) { + console.warn( + "Signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + + his.idSpace + "\" in signaling category \"" + this.idCategory + + "\" - web socket signaling pipe termination error", anyError ); + } } - // + this.socket.signalingClient = null; this.socket = null; - if( settings.logging.net.signaling.disconnect ) - console.warn( "Disconnected/force signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\"" ); + if( settings.logging.net.signaling.disconnect ) { + console.warn( + "Disconnected/force signaling client \"" + this.idRtcParticipant + + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + + this.idCategory + "\"" ); + } } onPipeClose( socket ) { if( this.isDisposed ) return; - if( settings.logging.net.signaling.disconnect ) - console.warn( "Disconnected/pipe signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\"" ); + if( settings.logging.net.signaling.disconnect ) { + console.warn( + "Disconnected/pipe signaling client \"" + this.idRtcParticipant + + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + + this.idCategory + "\"" ); + } this.offerDiscoveryStop(); this.dispose(); } onPipeError( socket ) { if( this.isDisposed ) return; - if( settings.logging.net.signaling.error ) - console.warn( "Disconnected/error signaling client \"" + this.idRtcParticipant + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\"" ); + if( settings.logging.net.signaling.error ) { + console.warn( + "Disconnected/error signaling client \"" + this.idRtcParticipant + + "\" in signaling space \"" + this.idSpace + "\" in signaling category \"" + + this.idCategory + "\"" ); + } this.offerDiscoveryStop(); this.dispose(); } @@ -157,14 +186,15 @@ class SignalingClient extends EventDispatcher { let joAnswer = null; ++ this.fetchingOfferStepNumber; try { - // let signalingCategory = null; const signalingSpace = this.signalingSpace; - // if( signalingSpace ) - // signalingCategory = signalingSpace.signalingCategory; const joOfferInfo = signalingSpace.fetchPublishedOffer(); if( ! joOfferInfo ) { - if( settings.logging.net.signaling.offerDiscoveryStepFail ) - console.warn( "Signaling client socket \"" + this.socket.strSavedRemoteAddress + "\" did not found offer at step", this.fetchingOfferStepNumber, "of", settings.net.rtc.offerDiscovery.stepCount ); + if( settings.logging.net.signaling.offerDiscoveryStepFail ) { + console.warn( + "Signaling client socket \"" + this.socket.strSavedRemoteAddress + + "\" did not found offer at step", this.fetchingOfferStepNumber, "of", + settings.net.rtc.offerDiscovery.stepCount ); + } if( this.fetchingOfferStepNumber >= settings.net.rtc.offerDiscovery.stepCount ) { this.offerDiscoveryStop(); throw new Error( "no offer found" ); @@ -178,8 +208,11 @@ class SignalingClient extends EventDispatcher { return; } if( settings.logging.net.signaling.impersonate ) { - console.log( "Signaling client socket \"" + this.socket.strSavedRemoteAddress + "\" impersonated as \"" + this.idRtcParticipant + - "\" in signaling space \"" + signalingSpace.idSpace + "\" did fetched published offer:", joOfferInfo ); + console.log( + "Signaling client socket \"" + this.socket.strSavedRemoteAddress + + "\" impersonated as \"" + this.idRtcParticipant + + "\" in signaling space \"" + signalingSpace.idSpace + + "\" did fetched published offer:", joOfferInfo ); } joAnswer = utils.prepareAnswerJSON( joMessage ); // successful answer joAnswer.offer = joOfferInfo.offer; @@ -192,52 +225,69 @@ class SignalingClient extends EventDispatcher { joAnswer.error = "" + err.toString(); } if( typeof joAnswer.error == "string" && joAnswer.error.length > 0 ) { - if( settings.logging.net.signaling.error ) - console.warn( "Signaling client socket \"" + this.socket.strSavedRemoteAddress + "\" error answer", joAnswer ); - } else if( settings.logging.net.signaling.message ) - console.log( "Signaling client socket \"" + this.socket.strSavedRemoteAddress + " answer", joAnswer ); + if( settings.logging.net.signaling.error ) { + console.warn( + "Signaling client socket \"" + this.socket.strSavedRemoteAddress + + "\" error answer", joAnswer ); + } + } else if( settings.logging.net.signaling.message ) { + console.log( + "Signaling client socket \"" + this.socket.strSavedRemoteAddress + + " answer", joAnswer ); + } this.socket.send( joAnswer, true ); // isFlush=true always in signaling server this.offerDiscoveryStop(); } }; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - class SignalingSpace extends EventDispatcher { constructor( idSpace, signalingCategory ) { super(); this.isDisposed = false; - this.idSpace = "" + ( ( idSpace && typeof idSpace == "string" && idSpace.length > 0 ) ? idSpace : "" ); + this.idSpace = "" + + ( ( idSpace && typeof idSpace == "string" && idSpace.length > 0 ) + ? idSpace : "" ); this.idSomebodyCreator = ""; - this.arr_published_offers = []; + this.arrPublishedOffers = []; this.signalingCategory = signalingCategory; - this.map_clients = {}; - this.signalingCategory.map_spaces[this.idSpace] = this; + this.mapClients = {}; + this.signalingCategory.mapSpaces[this.idSpace] = this; this.idCategory = "" + this.signalingCategory.idCategory; - if( settings.logging.net.signaling.objectLifetime ) - console.log( "New signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\"" ); - this.signalingCategory.dispatchEvent( new UniversalDispatcherEvent( "spaceAdded", { detail: { signalingSpace: this } } ) ); + if( settings.logging.net.signaling.objectLifetime ) { + console.log( + "New signaling space \"" + this.idSpace + "\" in signaling category \"" + + this.idCategory + "\"" ); + } + this.signalingCategory.dispatchEvent( + new UniversalDispatcherEvent( + "spaceAdded", + { "detail": { "signalingSpace": this } } ) ); } dispose() { if( this.isDisposed ) return; this.isDisposing = true; - if( settings.logging.net.signaling.objectLifetime ) - console.log( "Disposing signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\"" ); - for( const [ /*idRtcParticipant*/, signalingClient ] of Object.entries( this.map_clients ) ) + if( settings.logging.net.signaling.objectLifetime ) { + console.log( + "Disposing signaling space \"" + this.idSpace + "\" in signaling category \"" + + this.idCategory + "\"" ); + } + for( const [ /*idRtcParticipant*/, signalingClient ] of Object.entries( this.mapClients ) ) signalingClient.dispose(); if( this.idSpace ) { if( this.signalingCategory ) { - this.signalingCategory.dispatchEvent( new UniversalDispatcherEvent( "spaceRemoved", { detail: { signalingSpace: this } } ) ); - delete this.signalingCategory.map_spaces[this.idSpace]; + this.signalingCategory.dispatchEvent( + new UniversalDispatcherEvent( + "spaceRemoved", + { "detail": { "signalingSpace": this } } ) ); + delete this.signalingCategory.mapSpaces[this.idSpace]; } this.idSpace = null; } this.idCategory = null; this.signalingCategory.autoDispose(); this.signalingCategory = null; - this.arr_published_offers = []; + this.arrPublishedOffers = []; super.dispose(); } autoDispose() { @@ -245,27 +295,30 @@ class SignalingSpace extends EventDispatcher { return; if( this.allSomebodyIDs().length > 0 ) return; - if( settings.logging.net.signaling.objectLifetime ) - console.log( "Auto-dispose signaling space \"" + this.idSpace + "\" in signaling category \"" + this.idCategory + "\"" ); + if( settings.logging.net.signaling.objectLifetime ) { + console.log( + "Auto-dispose signaling space \"" + this.idSpace + "\" in signaling category \"" + + this.idCategory + "\"" ); + } this.dispose(); } allSomebodyIDs() { if( this.isDisposed ) return []; - return Object.keys( this.map_clients ); + return Object.keys( this.mapClients ); } clientGet( idRtcParticipant ) { if( this.isDisposed ) return null; - const signalingClient = this.map_clients[idRtcParticipant]; + const signalingClient = this.mapClients[idRtcParticipant]; return signalingClient ? signalingClient : null; } clientRemove( idRtcParticipant ) { if( this.isDisposed ) return false; idRtcParticipant = "" + ( idRtcParticipant ? idRtcParticipant.toString() : "" ); - if( idRtcParticipant in this.map_clients ) { - const signalingClient = this.map_clients[idRtcParticipant]; + if( idRtcParticipant in this.mapClients ) { + const signalingClient = this.mapClients[idRtcParticipant]; signalingClient.dispose(); this.autoDispose(); return true; @@ -278,37 +331,42 @@ class SignalingSpace extends EventDispatcher { console.warn( "Attempt to fetch offer in destroyed signaling space" ); return null; } - if( this.idSomebodyCreator == undefined || this.idSomebodyCreator == null || this.idSomebodyCreator == "" ) { + if( this.idSomebodyCreator == undefined || + this.idSomebodyCreator == null || + this.idSomebodyCreator == "" + ) { if( settings.logging.net.signaling.offerDiscoveryStepFail ) console.warn( "Attempt to fetch offer in malformed signaling space" ); return null; } - if( this.arr_published_offers.length == 0 ) { + if( this.arrPublishedOffers.length == 0 ) { if( settings.logging.net.signaling.offerDiscoveryStepFail ) console.warn( "Attempt to fetch offer in signaling space with no offers" ); return null; } - const joOfferInfo = this.arr_published_offers[0]; - this.arr_published_offers.splice( 0, 1 ); + const joOfferInfo = this.arrPublishedOffers[0]; + this.arrPublishedOffers.splice( 0, 1 ); joOfferInfo.idSomebodyCreator = "" + this.idSomebodyCreator; return joOfferInfo; } }; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - class SignalingCategory extends EventDispatcher { constructor( idCategory, signalingManager ) { super(); this.isDisposed = false; - this.idCategory = "" + ( ( idCategory && typeof idCategory == "string" && idCategory.length > 0 ) ? idCategory : "" ); + this.idCategory = "" + + ( ( idCategory && typeof idCategory == "string" && idCategory.length > 0 ) + ? idCategory : "" ); this.signalingManager = signalingManager; - this.map_spaces = {}; - this.signalingManager.map_categories[this.idCategory] = this; + this.mapSpaces = {}; + this.signalingManager.mapCategories[this.idCategory] = this; if( settings.logging.net.signaling.objectLifetime ) console.log( "New signaling category \"" + this.idCategory + "\"" ); - this.signalingManager.dispatchEvent( new UniversalDispatcherEvent( "categoryAdded", { detail: { signalingCategory: this } } ) ); + this.signalingManager.dispatchEvent( + new UniversalDispatcherEvent( + "categoryAdded", + { "detail": { "signalingCategory": this } } ) ); } dispose() { if( this.isDisposed ) @@ -316,14 +374,17 @@ class SignalingCategory extends EventDispatcher { this.isDisposing = true; if( settings.logging.net.signaling.objectLifetime ) console.log( "Disposing signaling category \"" + this.idCategory + "\"" ); - for( const [ /*idSpace*/, signalingSpace ] of Object.entries( this.map_spaces ) ) + for( const [ /*idSpace*/, signalingSpace ] of Object.entries( this.mapSpaces ) ) signalingSpace.dispose(); if( this.signalingManager ) { - delete this.signalingManager.map_categories[this.idCategory]; - this.signalingManager.dispatchEvent( new UniversalDispatcherEvent( "categoryRemoved", { detail: { signalingCategory: this } } ) ); + delete this.signalingManager.mapCategories[this.idCategory]; + this.signalingManager.dispatchEvent( + new UniversalDispatcherEvent( + "categoryRemoved", + { "detail": { "signalingCategory": this } } ) ); this.signalingManager = null; } - this.map_spaces = {}; + this.mapSpaces = {}; this.idCategory = null; super.dispose(); } @@ -339,19 +400,24 @@ class SignalingCategory extends EventDispatcher { allCSpaceIDs() { if( this.isDisposed ) return []; - return Object.keys( this.map_spaces ); + return Object.keys( this.mapSpaces ); } spaceGet( idSpace, isAutoAlloc ) { if( this.isDisposed ) return null; try { idSpace = "" + ( idSpace ? idSpace.toString() : settings.rtcSpace.defaultSpaceName ); - isAutoAlloc = ( isAutoAlloc == null || isAutoAlloc == undefined ) ? true : ( isAutoAlloc ? true : false ); + isAutoAlloc = + ( isAutoAlloc == null || isAutoAlloc == undefined ) ? true : ( isAutoAlloc + ? true : false ); let signalingSpace = null; - if( idSpace in this.map_spaces ) - signalingSpace = this.map_spaces[idSpace]; - else if( isAutoAlloc ) - this.map_spaces["" + idSpace] = signalingSpace = new SignalingSpace( "" + idSpace, this ); + if( idSpace in this.mapSpaces ) + signalingSpace = this.mapSpaces[idSpace]; + else if( isAutoAlloc ) { + this.mapSpaces["" + idSpace] = + signalingSpace = + new SignalingSpace( "" + idSpace, this ); + } return signalingSpace; } catch ( err ) { if( settings.logging.net.signaling.error ) @@ -363,8 +429,8 @@ class SignalingCategory extends EventDispatcher { if( this.isDisposed ) return false; idSpace = "" + ( idSpace ? idSpace.toString() : idSpace.rtcSpace.defaultSpaceName ); - if( idSpace in this.map_spaces ) { - const signalingSpace = this.map_spaces[idSpace]; + if( idSpace in this.mapSpaces ) { + const signalingSpace = this.mapSpaces[idSpace]; signalingSpace.dispose(); this.autoDispose(); return true; @@ -374,7 +440,7 @@ class SignalingCategory extends EventDispatcher { fetchPublishedOffer() { if( this.isDisposed ) return null; - for( const [ /*idSpace*/, signalingSpace ] of Object.entries( this.map_spaces ) ) { + for( const [ /*idSpace*/, signalingSpace ] of Object.entries( this.mapSpaces ) ) { const joOfferInfo = signalingSpace.fetchPublishedOffer(); if( joOfferInfo ) return joOfferInfo; @@ -383,14 +449,11 @@ class SignalingCategory extends EventDispatcher { } }; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - class SignalingManager extends EventDispatcher { constructor() { super(); this.isDisposed = false; - this.map_categories = {}; + this.mapCategories = {}; if( settings.logging.net.signaling.objectLifetime ) console.log( "New signaling manager" ); } @@ -400,23 +463,29 @@ class SignalingManager extends EventDispatcher { this.isDisposing = true; if( settings.logging.net.signaling.objectLifetime ) console.log( "Disposing signaling manager" ); - for( const [ /*idCategory*/, signalingCategory ] of Object.entries( this.map_categories ) ) + for( const [ /*idCategory*/, signalingCategory ] + of Object.entries( this.mapCategories ) ) signalingCategory.dispose(); - this.map_categories = {}; + this.mapCategories = {}; super.dispose(); } allCategoryIDs() { - return Object.keys( this.map_categories ); + return Object.keys( this.mapCategories ); } categoryGet( idCategory, isAutoAlloc ) { try { - idCategory = "" + ( idCategory ? idCategory.toString() : settings.rtcSpace.defaultSpaceCategory ); - isAutoAlloc = ( isAutoAlloc == null || isAutoAlloc == undefined ) ? true : ( isAutoAlloc ? true : false ); + idCategory = "" + ( idCategory + ? idCategory.toString() : settings.rtcSpace.defaultSpaceCategory ); + isAutoAlloc = ( isAutoAlloc == null || isAutoAlloc == undefined ) + ? true : ( isAutoAlloc ? true : false ); let signalingCategory = null; - if( idCategory in this.map_categories ) - signalingCategory = this.map_categories[idCategory]; - else if( isAutoAlloc ) - this.map_categories["" + idCategory] = signalingCategory = new SignalingCategory( "" + idCategory, this ); + if( idCategory in this.mapCategories ) + signalingCategory = this.mapCategories[idCategory]; + else if( isAutoAlloc ) { + this.mapCategories["" + idCategory] = + signalingCategory = + new SignalingCategory( "" + idCategory, this ); + } return signalingCategory; } catch ( err ) { if( settings.logging.net.signaling.error ) @@ -425,9 +494,10 @@ class SignalingManager extends EventDispatcher { } } categoryRemove( idCategory ) { - idCategory = "" + ( idCategory ? idCategory.toString() : settings.rtcSpace.defaultSpaceName ); - if( idCategory in this.map_categories ) { - const signalingCategory = this.map_categories[idCategory]; + idCategory = "" + ( idCategory + ? idCategory.toString() : settings.rtcSpace.defaultSpaceName ); + if( idCategory in this.mapCategories ) { + const signalingCategory = this.mapCategories[idCategory]; signalingCategory.dispose(); return true; } @@ -435,28 +505,35 @@ class SignalingManager extends EventDispatcher { } }; -const g_default_signaling_manager = new SignalingManager(); - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const gDefaultSignalingManager = new SignalingManager(); class SignalingServer extends EventDispatcher { + // eslint-disable-next-line max-lines-per-function constructor( acceptor, signalingManager ) { super(); - if( acceptor == null || acceptor == undefined || typeof acceptor != "object" ) + if( acceptor == null || + acceptor == undefined || + typeof acceptor != "object" ) throw new Error( "Cannot create test server on bad acceptor" ); this.acceptor = acceptor; - this.signalingManager = signalingManager || g_default_signaling_manager; + this.signalingManager = signalingManager || gDefaultSignalingManager; const self = this; + // eslint-disable-next-line max-lines-per-function acceptor.on( "connection", function( eventData ) { const socket = eventData.socket; - if( ( ! ( "remoteAddress" in eventData ) ) || eventData.remoteAddress == null || eventData.remoteAddress == undefined ) + if( ( ! ( "remoteAddress" in eventData ) ) || + eventData.remoteAddress == null || + eventData.remoteAddress == undefined ) socket.strSavedRemoteAddress = socket.constructor.name; else socket.strSavedRemoteAddress = "" + eventData.remoteAddress; socket.signalingClient = null; // not impersonated yet - if( settings.logging.net.signaling.connect ) - console.log( "New signaling server connection \"" + socket.strSavedRemoteAddress + "\"" ); + if( settings.logging.net.signaling.connect ) { + console.log( + "New signaling server connection \"" + + socket.strSavedRemoteAddress + "\"" + ); + } socket.signalingAuthInfo = { isAuthorized: false, idCategory: null, @@ -465,8 +542,12 @@ class SignalingServer extends EventDispatcher { }; let _offAllPipeEventListeners = null; let _onPipeClose = function() { - if( settings.logging.net.signaling.disconnect ) - console.warn( "Signaling client socket closed \"" + socket.strSavedRemoteAddress + "\"" ); + if( settings.logging.net.signaling.disconnect ) { + console.warn( + "Signaling client socket closed \"" + + socket.strSavedRemoteAddress + "\"" + ); + } if( _offAllPipeEventListeners ) { _offAllPipeEventListeners(); _offAllPipeEventListeners = null; @@ -477,8 +558,11 @@ class SignalingServer extends EventDispatcher { } }; let _onPipeError = function( eventData ) { - if( settings.logging.net.signaling.error ) - console.warn( "Socket error \"" + socket.strSavedRemoteAddress + "\"" ); + if( settings.logging.net.signaling.error ) { + console.warn( + "Socket error \"" + socket.strSavedRemoteAddress + "\"" + ); + } if( _offAllPipeEventListeners ) { _offAllPipeEventListeners(); _offAllPipeEventListeners = null; @@ -488,12 +572,19 @@ class SignalingServer extends EventDispatcher { socket.signalingClient = null; } }; + // eslint-disable-next-line max-lines-per-function let _onPipeMessage = function( eventData ) { - if( settings.logging.net.signaling.rawMessage ) - console.log( "Signaling client socket \"" + eventData.strSavedRemoteAddress + "\" raw message", eventData ); + if( settings.logging.net.signaling.rawMessage ) { + console.log( + "Signaling client socket \"" + eventData.strSavedRemoteAddress + + "\" raw message", eventData ); + } const joMessage = eventData.message; - if( settings.logging.net.signaling.message ) - console.log( "Signaling client socket \"" + socket.strSavedRemoteAddress + "\" message ", joMessage ); + if( settings.logging.net.signaling.message ) { + console.log( + "Signaling client socket \"" + socket.strSavedRemoteAddress + + "\" message ", joMessage ); + } let signalingCategory = null; let signalingSpace = null; let signalingClient = socket.signalingClient; @@ -512,107 +603,171 @@ class SignalingServer extends EventDispatcher { } break; case "signalingImpersonate": { const idRtcParticipant = joMessage.idRtcParticipant; - if( ( !idRtcParticipant ) || typeof idRtcParticipant != "string" || idRtcParticipant.length <= 0 ) { + if( ( !idRtcParticipant ) || + typeof idRtcParticipant != "string" || + idRtcParticipant.length <= 0 + ) { isForceDisconnect = true; - throw new Error( "Bad impersonate call data, no valid signaling *somebody* ID provided" ); + throw new Error( + "Bad impersonate call data, " + + "no valid signaling *somebody* ID provided" + ); } - // + const strRole = joMessage.role; - if( ( !strRole ) || typeof strRole != "string" || strRole.length <= 0 || ( ! ( strRole == "creator" || strRole == "joiner" ) ) ) { + if( ( !strRole ) || + typeof strRole != "string" || + strRole.length <= 0 || + ( ! ( strRole == "creator" || strRole == "joiner" ) ) + ) { isForceDisconnect = true; - throw new Error( "Bad impersonate call data, no valid signaling *somebody* role provided" ); + throw new Error( + "Bad impersonate call data, " + + "no valid signaling *somebody* role provided" + ); } - // + const idCategory = joMessage.idCategory; - if( ( !idCategory ) || typeof idCategory != "string" || idCategory.length <= 0 ) { + if( ( !idCategory ) || + typeof idCategory != "string" || + idCategory.length <= 0 + ) { isForceDisconnect = true; - throw new Error( "Bad impersonate call data, no valid signaling space category provided" ); + throw new Error( + "Bad impersonate call data, " + + "no valid signaling space category provided" + ); } signalingCategory = self.signalingManager.categoryGet( idCategory, true ); if( ! signalingCategory ) { isForceDisconnect = true; - throw new Error( "Bad impersonate call data, cannot get/alloc signaling category with \"" + idCategory + "\" name" ); + throw new Error( + "Bad impersonate call data, " + + "cannot get/alloc signaling category with \"" + + idCategory + "\" name" + ); } - // + const idSpace = joMessage.idSpace; if( ( !idSpace ) || typeof idSpace != "string" || idSpace.length <= 0 ) { isForceDisconnect = true; - throw new Error( "Bad impersonate call data, no valid signaling space name provided" ); + throw new Error( + "Bad impersonate call data, " + + "no valid signaling space name provided" + ); } signalingSpace = signalingCategory.spaceGet( idSpace, true ); if( ! signalingSpace ) { isForceDisconnect = true; - throw new Error( "Bad impersonate call data, cannot get/alloc signaling space with \"" + idSpace + "\" name" ); + throw new Error( + "Bad impersonate call data, " + + "cannot get/alloc signaling space with \"" + + idSpace + "\" name" + ); } - // + if( signalingSpace.clientGet( idRtcParticipant ) != null ) { isForceDisconnect = true; - throw new Error( "*Somebody* \"" + idRtcParticipant + "\" is already in \"" + idSpace + "\" signaling space" ); + throw new Error( + "*Somebody* \"" + idRtcParticipant + "\" is already in \"" + + idSpace + "\" signaling space" + ); + } + + if( strRole == "creator" && + signalingSpace.idSomebodyCreator != "" && + signalingSpace.idSomebodyCreator != idRtcParticipant + ) { + throw new Error( + "*Somebody* \"" + idRtcParticipant + + "\" is already in \"" + idSpace + + "\" attempted to impersonate as creator " + + "while other creator already exist" + ); } - // - if( strRole == "creator" && signalingSpace.idSomebodyCreator != "" && signalingSpace.idSomebodyCreator != idRtcParticipant ) - throw new Error( "*Somebody* \"" + idRtcParticipant + "\" is already in \"" + idSpace + "\" attempted to impersonate as creator while other creator already exist" ); - // - signalingClient = new SignalingClient( "" + idRtcParticipant, "" + strRole, signalingSpace, socket ); + + signalingClient = + new SignalingClient( + "" + idRtcParticipant, + "" + strRole, + signalingSpace, + socket + ); if( settings.logging.net.signaling.impersonate ) { isForceDisconnect = true; - console.log( "Signaling client socket \"" + socket.strSavedRemoteAddress + "\" was impersonated as \"" + idRtcParticipant + - "\" in signaling space \"" + signalingSpace.idSpace + "\"" ); + console.log( + "Signaling client socket \"" + socket.strSavedRemoteAddress + + "\" was impersonated as \"" + idRtcParticipant + + "\" in signaling space \"" + signalingSpace.idSpace + "\"" + ); } - // if( (!( "fnFlushNetwork" in signalingSpace )) || (!signalingSpace.fnFlushNetwork) ) - // //console.log( "Setting up network data flushing in acceptor" ); - // signalingSpace.fnFlushNetwork = function() { - // // TO-DO: improve this - // //console.log( "Flushing data to network via acceptor" ); - // acceptor.flush(); // network - // }; socket.signalingClient = signalingClient; socket.signalingAuthInfo.isAuthorized = true; socket.signalingAuthInfo.idCategory = "" + idCategory; socket.signalingAuthInfo.idSpaceSpace = "" + idSpace; socket.signalingAuthInfo.idRtcParticipant = "" + idRtcParticipant; joAnswer = utils.prepareAnswerJSON( joMessage ); // successful answer - joAnswer.signalingAuthInfo = JSON.parse( JSON.stringify( socket.signalingAuthInfo ) ); + joAnswer.signalingAuthInfo = + JSON.parse( JSON.stringify( socket.signalingAuthInfo ) ); } break; case "signalingPublishOffer": { - if( ! ( signalingClient && signalingSpace && signalingCategory ) ) - throw new Error( "only connected signaling clients can publish offers" ); + if( ! ( signalingClient && signalingSpace && signalingCategory ) ) { + throw new Error( + "only connected signaling clients can publish offers" ); + } if( ! ( signalingClient.isCreator ) ) throw new Error( "only creator can publish offers" ); const joOfferInfo = { - // ts: some time stamp - offer: joMessage.offer, - idOffer: 0 + joMessage.idOffer + // "ts": some time stamp + "offer": joMessage.offer, + "idOffer": 0 + joMessage.idOffer }; - signalingSpace.arr_published_offers.push( joOfferInfo ); + signalingSpace.arrPublishedOffers.push( joOfferInfo ); if( settings.logging.net.signaling.publishOffer ) { - console.log( "Signaling client socket \"" + socket.strSavedRemoteAddress + "\" impersonated as \"" + signalingClient.idRtcParticipant + - "\" in signaling space \"" + signalingSpace.idSpace + "\" did published creator offer:", joOfferInfo ); + console.log( + "Signaling client socket \"" + socket.strSavedRemoteAddress + + "\" impersonated as \"" + signalingClient.idRtcParticipant + + "\" in signaling space \"" + signalingSpace.idSpace + + "\" did published creator offer:", joOfferInfo + ); } joAnswer = utils.prepareAnswerJSON( joMessage ); // successful answer } break; case "signalingFetchOffer": { - if( ! ( signalingClient && signalingSpace && signalingCategory ) ) - throw new Error( "only connected signaling clients can fetch published offers" ); + if( ! ( signalingClient && signalingSpace && signalingCategory ) ) { + throw new Error( + "only connected signaling clients can fetch published offers" ); + } signalingClient.offerDiscoveryStart( joMessage ); } break; case "signalingPublishAnswer": { - if( ! ( signalingClient && signalingSpace && signalingCategory ) ) - throw new Error( "only connected signaling clients can publish offer answers" ); - const connectedServerCreator = signalingSpace.clientGet( joMessage.idSomebodyCreator ); - if( ! connectedServerCreator ) - throw new Error( "answer published with invalid server holder reference: " + joMessage.idSomebodyCreator ); + if( ! ( signalingClient && signalingSpace && signalingCategory ) ) { + throw new Error( + "only connected signaling clients can publish offer answers" ); + } + const connectedServerCreator = + signalingSpace.clientGet( joMessage.idSomebodyCreator ); + if( ! connectedServerCreator ) { + throw new Error( + "answer published with invalid server holder reference: " + + joMessage.idSomebodyCreator ); + } const joForwardMessage = JSON.parse( JSON.stringify( joMessage ) ); joForwardMessage.idSomebody_joiner = "" + signalingClient.idRtcParticipant; - connectedServerCreator.socket.send( joForwardMessage ); // re-send it to server holder, joiner *somebody* ID is added + // re-send it to server holder, joiner *somebody* ID is added + connectedServerCreator.socket.send( joForwardMessage ); // no answer so far(( } break; default: { joAnswer = utils.prepareAnswerJSON( joMessage ); joAnswer.error = "Unhandled message"; joAnswer.joMessage = joMessage; // send it back )) - if( settings.logging.net.signaling.error ) - console.warn( "Signaling client socket \"" + socket.strSavedRemoteAddress + "\" unhandled message", joMessage ); + if( settings.logging.net.signaling.error ) { + console.warn( + "Signaling client socket \"" + socket.strSavedRemoteAddress + + "\" unhandled message", joMessage + ); + } } break; } // switch( joMessage.method ) } catch ( err ) { @@ -623,10 +778,18 @@ class SignalingServer extends EventDispatcher { } if( joAnswer != null && joAnswer != undefined ) { if( typeof joAnswer.error == "string" && joAnswer.error.length > 0 ) { - if( settings.logging.net.signaling.error ) - console.warn( "Signaling client socket \"" + socket.strSavedRemoteAddress + "\" error answer", joAnswer ); - } else if( settings.logging.net.signaling.message ) - console.log( "Signaling client socket \"" + socket.strSavedRemoteAddress + " answer", joAnswer ); + if( settings.logging.net.signaling.error ) { + console.warn( + "Signaling client socket \"" + socket.strSavedRemoteAddress + + "\" error answer", joAnswer + ); + } + } else if( settings.logging.net.signaling.message ) { + console.log( + "Signaling client socket \"" + socket.strSavedRemoteAddress + + " answer", joAnswer + ); + } socket.send( joAnswer, true ); // isFlush=true always in signaling server if( isForceDisconnect ) socket.disconnect(); @@ -653,8 +816,12 @@ class SignalingServer extends EventDispatcher { const signalingClient = socket.signalingClient; if( signalingClient ) { signalingSpace = signalingClient.signalingSpace; - if( settings.logging.net.signaling.disconnect ) - console.log( "Handling connection close for signaling client \"" + signalingClient.idRtcParticipant + "\"" ); + if( settings.logging.net.signaling.disconnect ) { + console.log( + "Handling connection close for signaling client \"" + + signalingClient.idRtcParticipant + "\"" + ); + } if( signalingSpace ) signalingSpace.clientRemove( signalingClient.idRtcParticipant ); @@ -666,7 +833,10 @@ class SignalingServer extends EventDispatcher { socket.on( "error", _onPipeError ); socket.on( "message", _onPipeMessage ); } ); - this.dispatchEvent( new UniversalDispatcherEvent( "initialized", { detail: { ref: this } } ) ); + this.dispatchEvent( + new UniversalDispatcherEvent( + "initialized", + { "detail": { "ref": this } } ) ); } dispose() { this.isDisposing = true; @@ -674,16 +844,19 @@ class SignalingServer extends EventDispatcher { } }; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - const protoName = settings.net.secure ? "WSS" : "WS"; if( settings.logging.net.signaling.generic ) console.log( protoName + " signaling server will start" ); - -const key = settings.net.secure ? fs.readFileSync( "./self-signed/self-signed-key.pem", "utf8" ) : null; -const cert = settings.net.secure ? fs.readFileSync( "./self-signed/self-signed-cert.pem", "utf8" ) : null; -let acceptor = new network_layer.WebSocketServerAcceptor( settings.net.ports.signaling, key, cert ); +const key = settings.net.secure + ? fs.readFileSync( "./self-signed/self-signed-key.pem", "utf8" ) : null; +const cert = settings.net.secure + ? fs.readFileSync( "./self-signed/self-signed-cert.pem", "utf8" ) : null; +let acceptor = + new networkLayer.WebSocketServerAcceptor( + settings.net.ports.signaling, + key, + cert + ); let signalingServer = new SignalingServer( acceptor ); signalingServer.on( "initialized", function() { if( settings.logging.net.signaling.generic ) @@ -694,17 +867,14 @@ signalingServer.on( "dispose", function() { console.log( protoName + " signaling server did stopped" ); } ); -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -let g_bShouldExit = false, g_bProcessExitRequested = false; -function exit_if_needed() { - if( ! g_bShouldExit ) +let gFlagShouldExit = false, gFlagProcessExitWasRequested = false; +function exitIfNeeded() { + if( ! gFlagShouldExit ) return; - if( g_bProcessExitRequested ) + if( gFlagProcessExitWasRequested ) return; // ensure components stopped here, if needed - g_bProcessExitRequested = true; + gFlagProcessExitWasRequested = true; console.log( "App will exit" ); process.exit( 0 ); } @@ -724,11 +894,8 @@ process.on( "SIGINT", function() { acceptor = null; console.log( "Did stopped signaling acceptor" ); } - g_bShouldExit = true; - // - exit_if_needed(); - g_bShouldExit = true; -} ); + gFlagShouldExit = true; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + exitIfNeeded(); + gFlagShouldExit = true; +} ); diff --git a/npms/skale-cool-socket/testSocketTypes.mjs b/npms/skale-cool-socket/testSocketTypes.mjs new file mode 100644 index 000000000..44a117862 --- /dev/null +++ b/npms/skale-cool-socket/testSocketTypes.mjs @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE COOL SOCKET + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file testSocketTypes.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as path from "path"; +import * as url from "url"; +import * as networkLayer from "./socket.mjs"; +import { TestSocketServer } from "./testSocketServer.mjs"; +import { Worker } from "worker_threads"; +import { settings } from "./socketSettings.mjs"; +import * as ws from "ws"; + +const __dirname = path.dirname( url.fileURLToPath( import.meta.url ) ); + +const joTestMessage = { "method": "echo", "message": "Please echo this message!" }; + +const sleep = ( milliseconds ) => { + return new Promise( resolve => setTimeout( resolve, milliseconds ) ); +}; + +async function testLocal() { + console.log( "Local test" ); + const strEndPoint = "local_endpoint"; + const acceptor = new networkLayer.LocalSocketServerAcceptor( strEndPoint ); + const server = new TestSocketServer( acceptor ); + const client = new networkLayer.LocalSocketClientPipe( strEndPoint ); + client.on( "message", function( eventData ) { + const joMessage = eventData.message; + console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); + client.disconnect(); + console.log( " " ); + } ); + await sleep( 1 ); + console.log( "CLIENT >>>", JSON.stringify( joTestMessage ) ); + client.send( joTestMessage ); + await sleep( 100 ); + const joReturnValue = { + server: server, + client: client + }; + return joReturnValue; +} + +async function testWorker() { + console.log( "Worker test" ); + const url = "local_worker_server"; + const worker = + new Worker( + path.join( __dirname, "testSocketWorker.mjs" ), + { "type": "module" } + ); + console.log( "Will connect to " + url ); + worker.on( "message", jo => { + if( networkLayer.outOfWorkerAPIs.onMessage( worker, jo ) ) + return; + } ); + const client = new networkLayer.OutOfWorkerSocketClientPipe( url, worker ); + client.on( "message", function( eventData ) { + const joMessage = eventData.message; + console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); + client.disconnect(); + worker.terminate(); + console.log( " " ); + } ); + await sleep( 100 ); + console.log( "CLIENT >>>", JSON.stringify( joTestMessage ) ); + client.send( joTestMessage ); + await sleep( 100 ); + const joReturnValue = { + worker: worker, + client: client + }; + return joReturnValue; +} + +async function testWS() { + console.log( "Web socket test" ); + networkLayer.setWsModule( ws ); + const nPort = 33123; + const url = + ( settings.net.secure ? "wss" : "ws" ) + + "://127.0.0.1:" + nPort; + const key = settings.net.secure + ? fs.readFileSync( "./self-signed/self-signed-key.pem", "utf8" ) : null; + const cert = settings.net.secure + ? fs.readFileSync( "./self-signed/self-signed-cert.pem", "utf8" ) : null; + const acceptor = new networkLayer.WebSocketServerAcceptor( nPort, key, cert ); + const server = new TestSocketServer( acceptor ); + const client = new networkLayer.WebSocketClientPipe( url ); + client.on( "message", function( eventData ) { + const joMessage = eventData.message; + console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); + client.disconnect(); + console.log( " " ); + } ); + await sleep( 100 ); + console.log( "CLIENT >>>", JSON.stringify( joTestMessage ) ); + client.send( joTestMessage ); + await sleep( 100 ); + const joReturnValue = { + server: server, + client: client + }; + return joReturnValue; +} + +async function test() { + await testLocal(); + await testWorker(); + await testWS(); + process.exit( 0 ); +} +test(); diff --git a/npms/skale-cool-socket/test_worker.js b/npms/skale-cool-socket/testSocketWorker.mjs similarity index 56% rename from npms/skale-cool-socket/test_worker.js rename to npms/skale-cool-socket/testSocketWorker.mjs index a315cf581..a89ac440d 100644 --- a/npms/skale-cool-socket/test_worker.js +++ b/npms/skale-cool-socket/testSocketWorker.mjs @@ -19,34 +19,36 @@ */ /** - * @file test_worker.js + * @file testSocketWorker.mjs * @copyright SKALE Labs 2019-Present */ -const network_layer = require( "./socket.js" ); -const { TestServer } = require( "./test_server.js" ); -const { +import * as networkLayer from "./socket.mjs"; +import { TestSocketServer } from "./testSocketServer.mjs"; +import { parentPort //, workerData -} = require( "worker_threads" ); +} from "worker_threads"; parentPort.on( "message", jo => { - if( network_layer.in_worker_apis.on_message( jo ) ) + if( networkLayer.inWorkerAPIs.onMessage( jo ) ) return; } ); -function doSendMessage( type, endpoint, worker_uuid, data ) { - const jo = network_layer.socket_received_data_reverse_marshall( data ); +function doSendMessage( type, endpoint, workerUUID, data ) { + const jo = networkLayer.socketReceivedDataReverseMarshall( data ); const joSend = { - worker_message_type: ( type && typeof type == "string" && type.length > 0 ) ? type : "in_worker_message", - worker_endpoint: endpoint, - worker_uuid: worker_uuid, - data: jo + "workerMessageType": + ( type && typeof type == "string" && type.length > 0 ) + ? type : "inWorkerMessage", + "workerEndPoint": endpoint, + "workerUUID": workerUUID, + "data": jo }; - parentPort.postMessage( network_layer.socket_sent_data_marshall( joSend ) ); + parentPort.postMessage( networkLayer.socketSentDataMarshall( joSend ) ); } const url = "local_worker_server"; -const acceptor = new network_layer.InWorkerSocketServerAcceptor( url, doSendMessage ); -const server = new TestServer( acceptor ); +const acceptor = new networkLayer.InWorkerSocketServerAcceptor( url, doSendMessage ); +const server = new TestSocketServer( acceptor ); server.on( "dispose", function() { console.log( "disposed in-worker server" ); } ); diff --git a/npms/skale-cool-socket/yarn.lock b/npms/skale-cool-socket/yarn.lock index 71b02d8b2..4146a51a8 100644 --- a/npms/skale-cool-socket/yarn.lock +++ b/npms/skale-cool-socket/yarn.lock @@ -3,30 +3,30 @@ "@babel/code-frame@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: - "@babel/highlight" "^7.16.7" + "@babel/highlight" "^7.18.6" -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== +"@babel/helper-validator-identifier@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== -"@babel/highlight@^7.16.7": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3" - integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg== +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/helper-validator-identifier" "^7.18.6" chalk "^2.0.0" js-tokens "^4.0.0" "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== acorn-jsx@^5.2.0: version "5.3.2" @@ -86,31 +86,47 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -array-includes@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" - integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== +array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" is-string "^1.0.7" -array.prototype.flat@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" - integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== +array.prototype.flat@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" + integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -188,7 +204,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" @@ -198,7 +214,7 @@ color-name@~1.1.4: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== connect@^3.7.0: version "3.7.0" @@ -221,7 +237,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -debug@2.6.9, debug@^2.6.9: +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== @@ -247,12 +263,13 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" depd@2.0.0: version "2.0.0" @@ -281,7 +298,7 @@ doctrine@^3.0.0: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== emoji-regex@^7.0.1: version "7.0.3" @@ -296,33 +313,62 @@ emoji-regex@^8.0.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -es-abstract@^1.19.0, es-abstract@^1.19.1: - version "1.19.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.2.tgz#8f7b696d8f15b167ae3640b4060670f3d054143f" - integrity sha512-gfSBJoZdlL2xRiOCy0g8gLMryhoe1TlimjzU99L/31Z8QEGIhVQI+EWwt5lT+AuU9SnorVupXFqqOGqGfsyO6w== +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" + integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== dependencies: + available-typed-arrays "^1.0.5" call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" function-bind "^1.1.1" - get-intrinsic "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" 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.3" - is-callable "^1.2.4" + internal-slot "^1.0.4" + is-array-buffer "^3.0.1" + is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" + 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.0" + object-inspect "^1.12.2" object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" es-to-primitive@^1.2.1: version "1.2.1" @@ -336,33 +382,33 @@ es-to-primitive@^1.2.1: escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== eslint-config-standard@^14.1.1: version "14.1.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg== -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== +eslint-import-resolver-node@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" + integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== dependencies: debug "^3.2.7" - resolve "^1.20.0" + is-core-module "^2.11.0" + resolve "^1.22.1" -eslint-module-utils@^2.7.3: - version "2.7.3" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" - integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== +eslint-module-utils@^2.7.4: + version "2.7.4" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" + integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== dependencies: debug "^3.2.7" - find-up "^2.1.0" eslint-plugin-es@^3.0.0: version "3.0.1" @@ -373,22 +419,24 @@ eslint-plugin-es@^3.0.0: regexpp "^3.0.0" eslint-plugin-import@^2.20.2: - version "2.26.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" - integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== + version "2.27.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" + integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.3" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.7.4" has "^1.0.3" - is-core-module "^2.8.1" + is-core-module "^2.11.0" is-glob "^4.0.3" minimatch "^3.1.2" - object.values "^1.1.5" - resolve "^1.22.0" + object.values "^1.1.6" + resolve "^1.22.1" + semver "^6.3.0" tsconfig-paths "^3.14.1" eslint-plugin-node@^11.1.0: @@ -529,7 +577,7 @@ esutils@^2.0.2: etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== external-editor@^3.0.3: version "3.1.0" @@ -553,7 +601,7 @@ fast-json-stable-stringify@^2.0.0: fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== figures@^3.0.0: version "3.2.0" @@ -582,13 +630,6 @@ finalhandler@1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -603,34 +644,56 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 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== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + 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.1" + has-symbols "^1.0.3" get-symbol-description@^1.0.0: version "1.0.0" @@ -648,14 +711,14 @@ glob-parent@^5.0.0: is-glob "^4.0.1" glob@^7.1.3: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + 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.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" @@ -666,22 +729,48 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -has-bigints@^1.0.1: +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +gopd@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, 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== @@ -724,9 +813,9 @@ ignore@^4.0.6: integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.1.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== import-fresh@^3.0.0: version "3.3.0" @@ -739,12 +828,12 @@ import-fresh@^3.0.0: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -773,15 +862,24 @@ inquirer@^7.0.0: strip-ansi "^6.0.0" through "^2.3.6" -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +internal-slot@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" + integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== dependencies: - get-intrinsic "^1.1.0" + get-intrinsic "^1.1.3" has "^1.0.3" side-channel "^1.0.4" +is-array-buffer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" + integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-typed-array "^1.1.10" + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -797,15 +895,15 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== +is-core-module@^2.11.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" @@ -819,12 +917,12 @@ is-date-object@^1.0.1: is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -858,7 +956,7 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-shared-array-buffer@^1.0.1: +is-shared-array-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== @@ -879,6 +977,17 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + 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" + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -889,7 +998,7 @@ is-weakref@^1.0.2: isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== js-tokens@^4.0.0: version "4.0.0" @@ -912,31 +1021,23 @@ json-schema-traverse@^0.4.1: json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - lodash@^4.17.14, lodash@^4.17.19: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -952,7 +1053,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -960,9 +1061,9 @@ minimatch@^3.0.4, minimatch@^3.1.2: brace-expansion "^1.1.7" minimist@^1.2.0, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== mkdirp@^0.5.1: version "0.5.6" @@ -974,7 +1075,7 @@ mkdirp@^0.5.1: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2: version "2.1.2" @@ -994,41 +1095,41 @@ mute-stream@0.0.8: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -object-inspect@^1.12.0, object-inspect@^1.9.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== +object-inspect@^1.12.2, 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== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" object-keys "^1.1.1" -object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.20.4" on-finished@2.4.1: version "2.4.1" @@ -1040,14 +1141,14 @@ on-finished@2.4.1: on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -1073,26 +1174,7 @@ optionator@^0.8.3: os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^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" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== parent-module@^1.0.0: version "1.0.1" @@ -1106,20 +1188,15 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - 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 sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== path-parse@^1.0.7: version "1.0.7" @@ -1129,7 +1206,7 @@ path-parse@^1.0.7: prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== progress@^2.0.0: version "2.0.3" @@ -1137,15 +1214,24 @@ progress@^2.0.0: integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== 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== +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -1161,12 +1247,12 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.10.1, resolve@^1.20.0, resolve@^1.22.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== +resolve@^1.10.1, resolve@^1.22.1: + 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.8.1" + is-core-module "^2.9.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -1197,6 +1283,15 @@ rxjs@^6.6.0: dependencies: tslib "^1.9.0" +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -1207,7 +1302,7 @@ semver@^5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.1.0, semver@^6.1.2: +semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -1231,7 +1326,7 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serve-static@^1.14.1: +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== @@ -1249,14 +1344,14 @@ setprototypeof@1.2.0: shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== side-channel@^1.0.4: version "1.0.4" @@ -1284,7 +1379,7 @@ slice-ansi@^2.1.0: sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== statuses@2.0.1: version "2.0.1" @@ -1294,7 +1389,7 @@ statuses@2.0.1: statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== string-width@^3.0.0: version "3.1.0" @@ -1314,21 +1409,23 @@ string-width@^4.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.20.4" strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" @@ -1347,7 +1444,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-json-comments@^3.0.1: version "3.1.1" @@ -1386,12 +1483,12 @@ table@^5.2.3: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== tmp@^0.0.33: version "0.0.33" @@ -1423,7 +1520,7 @@ tslib@^1.9.0: type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" @@ -1437,20 +1534,29 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== uri-js@^4.2.2: version "4.4.1" @@ -1462,7 +1568,7 @@ uri-js@^4.2.2: utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== v8-compile-cache@^2.0.3: version "2.3.0" @@ -1480,6 +1586,18 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + 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" + is-typed-array "^1.1.10" + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -1495,7 +1613,7 @@ word-wrap@~1.2.3: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write@1.0.3: version "1.0.3" @@ -1504,7 +1622,7 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -ws@^8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.6.0.tgz#e5e9f1d9e7ff88083d0c0dd8281ea662a42c9c23" - integrity sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw== +ws@^8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" + integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== diff --git a/npms/skale-ima/imaEthOperations.mjs b/npms/skale-ima/imaEthOperations.mjs new file mode 100644 index 000000000..2384d5ec0 --- /dev/null +++ b/npms/skale-ima/imaEthOperations.mjs @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaEthOperations.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as imaHelperAPIs from "./imaHelperAPIs.mjs"; +import * as imaTx from "./imaTx.mjs"; +import * as imaGasUsage from "./imaGasUsageOperations.mjs"; +import * as imaEventLogScan from "./imaEventLogScan.mjs"; + +export async function getBalanceEth( + isMainNet, + ethersProvider, + chainId, + joAccount, + contractERC20 +) { + const strLogPrefix = cc.info( "getBalanceEth() call" ) + " "; + try { + if( ! ( ethersProvider && joAccount ) ) + return ""; + const strAddress = joAccount.address(); + if( ( !isMainNet ) && contractERC20 ) { + const balance = + await contractERC20.callStatic.balanceOf( strAddress, { from: strAddress } ); + return balance; + } + const balance = await ethersProvider.getBalance( strAddress ); + return balance; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + } + return ""; +} + +// transfer money from main-net to S-chain +// main-net.DepositBox call: function deposit(string schainName, address to) public payable +// Where: +// schainName...obvious +// to.........address in S-chain +// Notice: +// this function is available for everyone in main-net +// money is sent from caller +// "value" JSON arg is used to specify amount of money to sent +export async function doEthPaymentFromMainNet( + ethersProviderMainNet, + chainIdMainNet, + joAccountSrc, + joAccountDst, + joDepositBox, + joMessageProxyMainNet, // for checking logs + chainIdSChain, + weiHowMuch, // how much WEI money to send + transactionCustomizerMainNet +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "M2S ETH Payment:" ) + " "; + try { + details.write( strLogPrefix + cc.debug( "Doing payment from mainnet with " ) + + cc.notice( "chainIdSChain" ) + cc.debug( "=" ) + cc.notice( chainIdSChain ) + + cc.debug( "..." ) + "\n" ); + strActionName = "ETH payment from Main Net, deposit"; + const arrArguments = [ + chainIdSChain + ]; + const gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGas = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "DepositBox", joDepositBox, "deposit", arrArguments, + joAccountSrc, strActionName, + gasPrice, 3000000, weiHowMuch, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); + } + const isIgnore = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "DepositBox", joDepositBox, "deposit", arrArguments, + joAccountSrc, strActionName, isIgnore, + gasPrice, estimatedGas, weiHowMuch, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const joReceipt = + await imaTx.payedCall( + details, ethersProviderMainNet, + "DepositBox", joDepositBox, "deposit", arrArguments, + joAccountSrc, strActionName, + gasPrice, estimatedGas, weiHowMuch, null ); + if( joReceipt && typeof joReceipt == "object" ) { + jarrReceipts.push( { + "description": "doEthPaymentFromMainNet", + "receipt": joReceipt + } ); + } + + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxyMainNet ) { + details.write( strLogPrefix + + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxyMainNet.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderMainNet, joMessageProxyMainNet, strEventName, + joReceipt.blockNumber, joReceipt.transactionHash, + joMessageProxyMainNet.filters[strEventName]() + ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + + cc.success( "Success, verified the " ) + cc.info( strEventName ) + + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + + cc.success( "/" ) + cc.notice( joMessageProxyMainNet.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" " + + "event of the \"MessageProxy\"/" + + joMessageProxyMainNet.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doEthPaymentFromMainNet", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "ETH PAYMENT FROM MAIN NET", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doEthPaymentFromMainNet", true ); + details.close(); + return true; +} + +// transfer money from S-chain to main-net +// S-chain.TokenManager call: function exitToMain(address to) public payable +// Where: +// to.........address in main-net +// Notice: +// this function is available for everyone in S-chain +// money is sent from caller +// "value" JSON arg is used to specify amount of money to sent +export async function doEthPaymentFromSChain( + ethersProviderSChain, + chainIdSChain, + joAccountSrc, + joAccountDst, + joTokenManagerETH, + joMessageProxySChain, // for checking logs + weiHowMuch, // how much WEI money to send + transactionCustomizerSChain +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "S2M ETH Payment:" ) + " "; + try { + strActionName = "ETH payment from S-Chain, exitToMain"; + const arrArguments = [ + owaspUtils.toBN( weiHowMuch ) + ]; + const gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGas = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "TokenManagerETH", joTokenManagerETH, "exitToMain", arrArguments, + joAccountSrc, strActionName, + gasPrice, 6000000, 0, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); + } + const isIgnore = true; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "TokenManagerETH", joTokenManagerETH, "exitToMain", arrArguments, + joAccountSrc, strActionName, isIgnore, + gasPrice, estimatedGas, 0, null + ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + isCheckTransactionToSchain: true + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProviderSChain, + "TokenManagerETH", joTokenManagerETH, "exitToMain", arrArguments, + joAccountSrc, strActionName, + gasPrice, estimatedGas, 0, opts ); + if( joReceipt && typeof joReceipt == "object" ) { + jarrReceipts.push( { + "description": "doEthPaymentFromSChain", + "receipt": joReceipt + } ); + } + + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxySChain ) { + details.write( strLogPrefix + + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxySChain.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderSChain, joMessageProxySChain, strEventName, + joReceipt.blockNumber, joReceipt.transactionHash, + joMessageProxySChain.filters[strEventName]() + ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + + cc.success( "Success, verified the " ) + cc.info( strEventName ) + + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + + cc.success( "/" ) + cc.notice( joMessageProxySChain.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" " + + "event of the \"MessageProxy\"/" + + joMessageProxySChain.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doEthPaymentFromSChain", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "ETH PAYMENT FROM S-CHAIN", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doEthPaymentFromSChain", true ); + details.close(); + return true; +} + +export async function receiveEthPaymentFromSchainOnMainNet( + ethersProviderMainNet, + chainIdMainNet, + joAccountMN, + joDepositBoxETH, + transactionCustomizerMainNet +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "M2S ETH Receive:" ) + " "; + try { + strActionName = "Receive ETH payment from S-Chain on Main Met, getMyEth"; + const arrArguments = []; + const weiHowMuch = undefined; + const gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGas = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "DepositBoxETH", joDepositBoxETH, "getMyEth", arrArguments, + joAccountMN, strActionName, + gasPrice, 3000000, weiHowMuch, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); + } + const isIgnore = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "DepositBoxETH", joDepositBoxETH, + "getMyEth", arrArguments, + joAccountMN, strActionName, isIgnore, + gasPrice, estimatedGas, weiHowMuch, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const joReceipt = + await imaTx.payedCall( + details, ethersProviderMainNet, + "DepositBoxETH", joDepositBoxETH, + "getMyEth", arrArguments, + joAccountMN, strActionName, + gasPrice, estimatedGas, weiHowMuch, null ); + if( joReceipt && typeof joReceipt == "object" ) { + jarrReceipts.push( { + "description": "receiveEthPaymentFromSchainOnMainNet", + "receipt": joReceipt + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Receive payment error in " + strActionName + ": " ) + + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "receiveEthPaymentFromSchainOnMainNet", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "RECEIVE ETH ON MAIN NET", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "receiveEthPaymentFromSchainOnMainNet", true ); + details.close(); + return true; +} + +export async function viewEthPaymentFromSchainOnMainNet( + ethersProviderMainNet, + joAccountMN, + joDepositBoxETH +) { + const details = log.createMemoryStream(); + const strActionName = ""; + const strLogPrefix = cc.info( "S ETH View:" ) + " "; + try { + if( ! ( ethersProviderMainNet && joAccountMN && joDepositBoxETH ) ) + return null; + const addressFrom = joAccountMN.address(); + const xWei = + await joDepositBoxETH.callStatic.approveTransfers( + addressFrom, + { from: addressFrom } ); + details.write( strLogPrefix + + cc.success( "You can receive(wei): " ) + cc.attention( xWei ) + "\n" ); + const xEth = owaspUtils.ethersMod.ethers.utils.formatEther( owaspUtils.toBN( xWei ) ); + const s = strLogPrefix + + cc.success( "You can receive(eth): " ) + cc.attention( xEth ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "viewEthPaymentFromSchainOnMainNet", true ); + details.close(); + return xWei; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " View payment error in " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "viewEthPaymentFromSchainOnMainNet", false ); + details.close(); + return null; + } +} diff --git a/npms/skale-ima/imaEventLogScan.mjs b/npms/skale-ima/imaEventLogScan.mjs new file mode 100644 index 000000000..14c069d0a --- /dev/null +++ b/npms/skale-ima/imaEventLogScan.mjs @@ -0,0 +1,641 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaEventLogScan.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as rpcCall from "../../agent/rpcCall.mjs"; +import * as imaHelperAPIs from "./imaHelperAPIs.mjs"; +import * as imaTransferErrorHandling from "./imaTransferErrorHandling.mjs"; + +export function createProgressiveEventsScanPlan( details, nLatestBlockNumber ) { + // assume Main Net mines 6 blocks per minute + const blocksInOneMinute = 6; + const blocksInOneHour = blocksInOneMinute * 60; + const blocksInOneDay = blocksInOneHour * 24; + const blocksInOneWeek = blocksInOneDay * 7; + const blocksInOneMonth = blocksInOneDay * 31; + const blocksInOneYear = blocksInOneDay * 366; + const blocksInThreeYears = blocksInOneYear * 3; + const arrProgressiveEventsScanPlanA = [ { + "nBlockFrom": + nLatestBlockNumber - blocksInOneDay, + "nBlockTo": "latest", + "type": "1 day" + }, { + "nBlockFrom": + nLatestBlockNumber - blocksInOneWeek, + "nBlockTo": "latest", + "type": "1 week" + }, { + "nBlockFrom": + nLatestBlockNumber - blocksInOneMonth, + "nBlockTo": "latest", + "type": "1 month" + }, { + "nBlockFrom": + nLatestBlockNumber - blocksInOneYear, + "nBlockTo": "latest", + "type": "1 year" + }, { + "nBlockFrom": + nLatestBlockNumber - blocksInThreeYears, + "nBlockTo": "latest", + "type": "3 years" + } ]; + const arrProgressiveEventsScanPlan = []; + for( let idxPlan = 0; idxPlan < arrProgressiveEventsScanPlanA.length; ++idxPlan ) { + const joPlan = arrProgressiveEventsScanPlanA[idxPlan]; + if( joPlan.nBlockFrom >= 0 ) + arrProgressiveEventsScanPlan.push( joPlan ); + } + if( arrProgressiveEventsScanPlan.length > 0 ) { + const joLastPlan = + arrProgressiveEventsScanPlan[arrProgressiveEventsScanPlan.length - 1]; + if( ! ( joLastPlan.nBlockFrom == 0 && joLastPlan.nBlockTo == "latest" ) ) { + arrProgressiveEventsScanPlan.push( + { "nBlockFrom": 0, "nBlockTo": "latest", "type": "entire block range" } ); + } + } else { + arrProgressiveEventsScanPlan.push( + { "nBlockFrom": 0, "nBlockTo": "latest", "type": "entire block range" } ); + } + return arrProgressiveEventsScanPlan; +} + +export async function safeGetPastEventsProgressive( + details, strLogPrefix, + ethersProvider, attempts, joContract, strEventName, + nBlockFrom, nBlockTo, joFilter +) { + if( ! imaTransferErrorHandling.getEnabledProgressiveEventsScan() ) { + details.write( strLogPrefix + + cc.fatal( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Will skip " ) + cc.attention( "progressive" ) + + cc.warning( " events scan in block range from " ) + + cc.j( nBlockFrom ) + cc.warning( " to " ) + cc.j( nBlockTo ) + + cc.warning( " because it's " ) + cc.error( "DISABLED" ) + "\n" ); + return await safeGetPastEvents( + details, strLogPrefix, + ethersProvider, attempts, joContract, strEventName, + nBlockFrom, nBlockTo, joFilter + ); + } + const nLatestBlockNumber = + owaspUtils.toBN( await imaHelperAPIs.safeGetBlockNumber( details, 10, ethersProvider ) ); + let isLastLatest = false; + if( nBlockTo == "latest" ) { + isLastLatest = true; + nBlockTo = nLatestBlockNumber; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Iterative scan up to latest block " ) + + cc.attention( "#" ) + cc.info( nBlockTo.toHexString() ) + + cc.debug( " assumed instead of " ) + cc.attention( "latest" ) + "\n" ); + } + } else { + nBlockTo = owaspUtils.toBN( nBlockTo ); + if( nBlockTo.eq( nLatestBlockNumber ) ) + isLastLatest = true; + } + nBlockFrom = owaspUtils.toBN( nBlockFrom ); + const nBlockZero = owaspUtils.toBN( 0 ); + const isFirstZero = ( nBlockFrom.eq( nBlockZero ) ) ? true : false; + if( ! ( isFirstZero && isLastLatest ) ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will skip " ) + cc.attention( "progressive" ) + + cc.debug( " scan and use scan in block range from " ) + + cc.info( nBlockFrom.toHexString() ) + cc.debug( " to " ) + + cc.info( nBlockTo.toHexString() ) + "\n" ); + } + return await safeGetPastEvents( + details, strLogPrefix, + ethersProvider, attempts, joContract, strEventName, + nBlockFrom, nBlockTo, joFilter + ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will run " ) + + cc.attention( "progressive" ) + cc.debug( " scan..." ) + "\n" ); + details.write( strLogPrefix + cc.debug( "Current latest block number is " ) + + cc.info( nLatestBlockNumber.toHexString() ) + "\n" ); + } + const arrProgressiveEventsScanPlan = + createProgressiveEventsScanPlan( details, nLatestBlockNumber ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( "Composed " ) + cc.attention( "progressive" ) + + cc.debug( " scan plan is: " ) + cc.j( arrProgressiveEventsScanPlan ) + "\n" ); + } + let joLastPlan = { "nBlockFrom": 0, "nBlockTo": "latest", "type": "entire block range" }; + for( let idxPlan = 0; idxPlan < arrProgressiveEventsScanPlan.length; ++idxPlan ) { + const joPlan = arrProgressiveEventsScanPlan[idxPlan]; + if( joPlan.nBlockFrom < 0 ) + continue; + joLastPlan = joPlan; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Progressive scan of " ) + + cc.attention( "getPastEvents" ) + cc.debug( "/" ) + cc.info( strEventName ) + + cc.debug( ", from block " ) + cc.info( joPlan.nBlockFrom ) + + cc.debug( ", to block " ) + cc.info( joPlan.nBlockTo ) + + cc.debug( ", block range is " ) + cc.info( joPlan.type ) + + cc.debug( "..." ) + "\n" ); + } + try { + const joAllEventsInBlock = + await safeGetPastEventsIterative( + details, strLogPrefix, + ethersProvider, attempts, joContract, strEventName, + joPlan.nBlockFrom, joPlan.nBlockTo, joFilter + ); + if( joAllEventsInBlock && joAllEventsInBlock.length > 0 ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.success( "Progressive scan of " ) + + cc.attention( "getPastEvents" ) + cc.debug( "/" ) + + cc.info( strEventName ) + cc.success( ", from block " ) + + cc.info( joPlan.nBlockFrom ) + cc.success( ", to block " ) + + cc.info( joPlan.nBlockTo ) + cc.success( ", block range is " ) + + cc.info( joPlan.type ) + cc.success( ", found " ) + + cc.info( joAllEventsInBlock.length ) + cc.success( " event(s)" ) + "\n" ); + } + return joAllEventsInBlock; + } + } catch ( err ) {} + } + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.error( "Could not not get Event \"" ) + + cc.info( strEventName ) + cc.error( "\", from block " ) + + cc.info( joLastPlan.nBlockFrom ) + cc.error( ", to block " ) + + cc.info( joLastPlan.nBlockTo ) + cc.debug( ", block range is " ) + + cc.info( joLastPlan.type ) + cc.error( ", using " ) + cc.attention( "progressive" ) + + cc.error( " event scan" ) + "\n" ); + } + return []; +} + +export async function getContractCallEvents( + details, strLogPrefix, + ethersProvider, joContract, strEventName, + nBlockNumber, strTxHash, joFilter +) { + joFilter = joFilter || {}; + nBlockNumber = owaspUtils.toBN( nBlockNumber ); + const n10 = owaspUtils.toBN( 10 ); + let nBlockFrom = nBlockNumber.sub( n10 ), nBlockTo = nBlockNumber.add( n10 ); + const nBlockZero = owaspUtils.toBN( 0 ); + const nLatestBlockNumber = + owaspUtils.toBN( await imaHelperAPIs.safeGetBlockNumber( details, 10, ethersProvider ) ); + if( nBlockFrom.lt( nBlockZero ) ) + nBlockFrom = nBlockZero; + if( nBlockTo.gt( nLatestBlockNumber ) ) + nBlockTo = nLatestBlockNumber; + const joAllEventsInBlock = + await safeGetPastEventsIterative( + details, strLogPrefix, ethersProvider, 10, joContract, strEventName, + nBlockFrom, nBlockTo, joFilter ); + const joAllTransactionEvents = []; let i; + for( i = 0; i < joAllEventsInBlock.length; ++i ) { + const joEvent = joAllEventsInBlock[i]; + if( "transactionHash" in joEvent && joEvent.transactionHash == strTxHash ) + joAllTransactionEvents.push( joEvent ); + } + return joAllTransactionEvents; +} + +export async function safeGetTransactionCount( + details, cntAttempts, ethersProvider, address, param, retValOnFail, throwIfServerOffline +) { + const strFnName = "getTransactionCount"; + const u = owaspUtils.ethersProviderToUrl( ethersProvider ); + const nWaitStepMilliseconds = 10 * 1000; + if( throwIfServerOffline == null || throwIfServerOffline == undefined ) + throwIfServerOffline = true; + cntAttempts = + owaspUtils.parseIntOrHex( cntAttempts ) < 1 + ? 1 + : owaspUtils.parseIntOrHex( cntAttempts ); + if( retValOnFail == null || retValOnFail == undefined ) + retValOnFail = ""; + let ret = retValOnFail; + let idxAttempt = 1; + try { + ret = await ethersProvider[strFnName]( address, param ); + return ret; + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + + cc.error( " to " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + + cc.u( u ) + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + ++ idxAttempt; + while( ret === "" && idxAttempt <= cntAttempts ) { + const isOnLine = rpcCall.checkUrl( u, nWaitStepMilliseconds ); + if( ! isOnLine ) { + ret = retValOnFail; + if( ! throwIfServerOffline ) + return ret; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Cannot call " ) + cc.note( strFnName + "()" ) + + cc.error( " via " ) + cc.u( u ) + + cc.warning( " because server is off-line" ) + "\n" ); + } + throw new Error( + "Cannot " + strFnName + "() via " + u.toString() + + " because server is off-line" ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.warning( "Repeat call to " ) + cc.note( strFnName + "()" ) + + cc.error( " via " ) + cc.u( u ) + cc.warning( ", attempt " ) + + cc.info( idxAttempt ) + "\n" ); + } + try { + ret = await ethersProvider[strFnName]( address, param ); + return ret; + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + + cc.error( " to " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + + cc.u( u ) + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + ++ idxAttempt; + } + if( ( idxAttempt + 1 ) > cntAttempts && ret === "" ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.fatal( "ERROR:" ) + cc.error( " Failed call to " ) + + cc.note( strFnName + "()" ) + + cc.error( " via " ) + cc.u( u ) + + cc.error( " after " ) + cc.info( cntAttempts ) + cc.error( " attempts " ) + "\n" ); + } + throw new Error( + "Failed call to " + strFnName + "() via " + u.toString() + + " after " + cntAttempts + " attempts" ); + } + return ret; +} + +export async function safeGetTransactionReceipt( + details, cntAttempts, ethersProvider, txHash, retValOnFail, throwIfServerOffline +) { + const strFnName = "getTransactionReceipt"; + const u = owaspUtils.ethersProviderToUrl( ethersProvider ); + const nWaitStepMilliseconds = 10 * 1000; + if( throwIfServerOffline == null || throwIfServerOffline == undefined ) + throwIfServerOffline = true; + cntAttempts = + owaspUtils.parseIntOrHex( cntAttempts ) < 1 + ? 1 + : owaspUtils.parseIntOrHex( cntAttempts ); + if( retValOnFail == null || retValOnFail == undefined ) + retValOnFail = ""; + let ret = retValOnFail; + let idxAttempt = 1; + try { + ret = await ethersProvider[strFnName]( txHash ); + return ret; + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + + cc.error( " to " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + cc.u( u ) + + cc.error( ", error is: " ) + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + ++ idxAttempt; + while( txReceipt === "" && idxAttempt <= cntAttempts ) { + const isOnLine = rpcCall.checkUrl( u, nWaitStepMilliseconds ); + if( ! isOnLine ) { + ret = retValOnFail; + if( ! throwIfServerOffline ) + return ret; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Cannot call " ) + cc.note( strFnName + "()" ) + + cc.error( " via " ) + cc.u( u ) + cc.warning( " because server is off-line" ) + + "\n" ); + } + throw new Error( + "Cannot " + strFnName + "() via " + u.toString() + + " because server is off-line" ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.warning( "Repeat call to " ) + cc.note( strFnName + "()" ) + + cc.error( " via " ) + cc.u( u ) + cc.warning( ", attempt " ) + + cc.info( idxAttempt ) + "\n" ); + } + try { + ret = await ethersProvider[strFnName]( txHash ); + return ret; + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + + cc.error( " to " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + + cc.u( u ) + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + ++ idxAttempt; + } + if( ( idxAttempt + 1 ) > cntAttempts && ( txReceipt === "" || txReceipt === undefined ) ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.fatal( "ERROR:" ) + cc.error( " Failed call to " ) + + cc.note( strFnName + "()" ) + cc.error( " via " ) + cc.u( u ) + + cc.error( " after " ) + cc.info( cntAttempts ) + cc.error( " attempts " ) + "\n" ); + } + throw new Error( + "Failed call to " + strFnName + "() via " + u.toString() + + " after " + cntAttempts + " attempts" ); + } + return ret; +} + +export async function safeGetPastEvents( + details, strLogPrefix, + ethersProvider, cntAttempts, joContract, strEventName, + nBlockFrom, nBlockTo, joFilter, retValOnFail, throwIfServerOffline +) { + const u = owaspUtils.ethersProviderToUrl( ethersProvider ); + const nWaitStepMilliseconds = 10 * 1000; + if( throwIfServerOffline == null || throwIfServerOffline == undefined ) + throwIfServerOffline = true; + cntAttempts = + owaspUtils.parseIntOrHex( cntAttempts ) < 1 + ? 1 + : owaspUtils.parseIntOrHex( cntAttempts ); + if( retValOnFail == null || retValOnFail == undefined ) + retValOnFail = ""; + let ret = retValOnFail; + let idxAttempt = 1; + const strErrorTextAboutNotExistingEvent = + "Event \"" + strEventName + "\" doesn't exist in this contract"; + if( nBlockTo == "latest" ) { + const nLatestBlockNumber = owaspUtils.toBN( + await imaHelperAPIs.safeGetBlockNumber( details, 10, ethersProvider ) ); + nBlockTo = nLatestBlockNumber; + } else + nBlockTo = owaspUtils.toBN( nBlockTo ); + nBlockFrom = owaspUtils.toBN( nBlockFrom ); + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "First time, will query filter " ) + + cc.j( joFilter ) + cc.debug( " on contract " ) + cc.info( joContract.address ) + + cc.debug( " from block " ) + cc.info( nBlockFrom.toHexString() ) + + cc.debug( " to block " ) + cc.info( nBlockTo.toHexString() ) + "\n" ); + } + ret = + await joContract.queryFilter( + joFilter, + nBlockFrom.toHexString(), + nBlockTo.toHexString() + ); + return ret; + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.error( "Failed filtering attempt " ) + + cc.info( idxAttempt ) + cc.error( " for event " ) + cc.note( strEventName ) + + cc.error( " via " ) + cc.u( u ) + cc.error( ", from block " ) + + cc.warning( nBlockFrom.toHexString() ) + + cc.error( ", to block " ) + cc.warning( nBlockTo.toHexString() ) + + cc.error( ", error is: " ) + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + if( owaspUtils.extractErrorMessage( err ) + .indexOf( strErrorTextAboutNotExistingEvent ) >= 0 + ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.error( "Did stopped filtering of " ) + + cc.note( strEventName ) + cc.error( " event because no such event " + + "exist in smart contract " ) + "\n" ); + } + return ret; + } + } + ++ idxAttempt; + while( ret === "" && idxAttempt <= cntAttempts ) { + const isOnLine = rpcCall.checkUrl( u, nWaitStepMilliseconds ); + if( ! isOnLine ) { + ret = retValOnFail; + if( ! throwIfServerOffline ) + return ret; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.error( "Cannot do " ) + cc.note( strEventName ) + + cc.error( " event filtering via " ) + cc.u( u ) + + cc.warning( " because server is off-line" ) + "\n" ); + } + throw new Error( + "Cannot do " + strEventName + " event filtering, from block " + + nBlockFrom.toHexString() + ", to block " + nBlockTo.toHexString() + + " via " + u.toString() + " because server is off-line" + ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.warning( "Repeat " ) + cc.note( strEventName ) + + cc.error( " event filtering via " ) + cc.u( u ) + + cc.warning( ", attempt " ) + cc.info( idxAttempt ) + "\n" ); + } + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Attempt " ) + cc.info( idxAttempt ) + + cc.debug( ", will query filter " ) + cc.j( joFilter ) + + cc.debug( " on contract " ) + cc.info( joContract.address ) + + cc.debug( " from block " ) + cc.info( nBlockFrom.toHexString() ) + + cc.debug( " to block " ) + cc.info( nBlockTo.toHexString() ) + "\n" ); + } + ret = + await joContract.queryFilter( + joFilter, + nBlockFrom.toHexString(), + nBlockTo.toHexString() + ); + return ret; + + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.error( "Failed filtering attempt " ) + + cc.info( idxAttempt ) + cc.error( " for event " ) + cc.note( strEventName ) + + cc.error( " via " ) + cc.u( u ) + cc.error( ", from block " ) + + cc.info( nBlockFrom.toHexString() ) + cc.error( ", to block " ) + + cc.info( nBlockTo.toHexString() ) + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + if( owaspUtils.extractErrorMessage( err ) + .indexOf( strErrorTextAboutNotExistingEvent ) >= 0 + ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.error( "Did stopped " ) + + cc.note( strEventName ) + cc.error( " event filtering because " + + "no such event exist in smart contract " ) + "\n" ); + } + return ret; + } + } + ++ idxAttempt; + } + if( ( idxAttempt + 1 ) === cntAttempts && ret === "" ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.fatal( "ERROR:" ) + + cc.error( " Failed filtering attempt for " ) + cc.note( strEventName ) + + + cc.error( " event via " ) + cc.u( u ) + cc.error( ", from block " ) + + cc.info( nBlockFrom.toHexString() ) + cc.error( ", to block " ) + + cc.info( nBlockTo.toHexString() ) + cc.error( " after " ) + cc.info( cntAttempts ) + + cc.error( " attempts " ) + "\n" ); + } + throw new Error( + "Failed filtering attempt for " + strEventName + " event, from block " + + nBlockFrom.toHexString() + ", to block " + nBlockTo.toHexString() + + " via " + u.toString() + " after " + cntAttempts + " attempts" + ); + } + return ret; +} + +export async function safeGetPastEventsIterative( + details, strLogPrefix, + ethersProvider, attempts, joContract, strEventName, + nBlockFrom, nBlockTo, joFilter +) { + if( imaHelperAPIs.getBlocksCountInInIterativeStepOfEventsScan() <= 0 || + imaHelperAPIs.getMaxIterationsInAllRangeEventsScan() <= 0 ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + details.write( strLogPrefix + cc.fatal( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Will skip " ) + cc.attention( "iterative" ) + + cc.warning( " events scan in block range from " ) + + cc.j( nBlockFrom ) + cc.warning( " to " ) + cc.j( nBlockTo ) + + cc.warning( " because it's " ) + cc.error( "DISABLED" ) + "\n" ); + } + return await safeGetPastEvents( + details, strLogPrefix, + ethersProvider, attempts, joContract, + strEventName, nBlockFrom, nBlockTo, joFilter + ); + } + const nLatestBlockNumber = + owaspUtils.toBN( await imaHelperAPIs.safeGetBlockNumber( details, 10, ethersProvider ) ); + let isLastLatest = false; + if( nBlockTo == "latest" ) { + isLastLatest = true; + nBlockTo = nLatestBlockNumber; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Iterative scan up to latest block " ) + + cc.info( "#" ) + cc.info( nBlockTo.toHexString() ) + + cc.debug( " assumed instead of " ) + cc.attention( "latest" ) + "\n" ); + } + } else { + nBlockTo = owaspUtils.toBN( nBlockTo ); + if( nBlockTo.eq( nLatestBlockNumber ) ) + isLastLatest = true; + } + nBlockFrom = owaspUtils.toBN( nBlockFrom ); + const nBlockZero = owaspUtils.toBN( 0 ); + const isFirstZero = ( nBlockFrom.eq( nBlockZero ) ) ? true : false; + if( isFirstZero && isLastLatest ) { + if( nLatestBlockNumber.div( + owaspUtils.toBN( imaHelperAPIs.getBlocksCountInInIterativeStepOfEventsScan() ) + ).gt( owaspUtils.toBN( imaHelperAPIs.getMaxIterationsInAllRangeEventsScan() ) ) + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + details.write( strLogPrefix + cc.fatal( "IMPORTANT NOTICE:" ) + " " + + cc.warning( "Will skip " ) + cc.attention( "iterative" ) + + cc.warning( " scan and use scan in block range from " ) + + cc.info( nBlockFrom.toHexString() ) + cc.warning( " to " ) + + cc.info( nBlockTo.toHexString() ) + "\n" ); + } + return await safeGetPastEvents( + details, strLogPrefix, + ethersProvider, attempts, joContract, strEventName, + nBlockFrom, nBlockTo, joFilter + ); + } + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Iterative scan in " ) + + cc.info( nBlockFrom.toHexString() ) + cc.debug( "/" ) + + cc.info( nBlockTo.toHexString() ) + cc.debug( " block range..." ) + "\n" ); + } + let idxBlockSubRangeFrom = nBlockFrom; + for( ; true; ) { + let idxBlockSubRangeTo = idxBlockSubRangeFrom.add( + owaspUtils.toBN( imaHelperAPIs.getBlocksCountInInIterativeStepOfEventsScan() ) ); + if( idxBlockSubRangeTo.gt( nBlockTo ) ) + idxBlockSubRangeTo = nBlockTo; + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Iterative scan of " ) + + cc.info( idxBlockSubRangeFrom.toHexString() ) + cc.debug( "/" ) + + cc.info( idxBlockSubRangeTo.toHexString() ) + + cc.debug( " block sub-range in " ) + + cc.info( nBlockFrom.toHexString() ) + cc.debug( "/" ) + + cc.info( nBlockTo.toHexString() ) + cc.debug( " block range..." ) + "\n" ); + } + const joAllEventsInBlock = await safeGetPastEvents( + details, strLogPrefix, + ethersProvider, attempts, joContract, strEventName, + idxBlockSubRangeFrom, idxBlockSubRangeTo, joFilter + ); + if( joAllEventsInBlock && joAllEventsInBlock != "" && joAllEventsInBlock.length > 0 ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.success( "Result of " ) + + cc.attention( "iterative" ) + cc.success( " scan in " ) + + cc.info( nBlockFrom.toHexString() ) + cc.success( "/" ) + + cc.info( nBlockTo.toHexString() ) + cc.success( " block range is " ) + + cc.j( joAllEventsInBlock ) + "\n" ); + } + return joAllEventsInBlock; + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + details.write( strLogPrefix + + cc.error( "Got scan error during interactive scan of " ) + + cc.info( idxBlockSubRangeFrom.toHexString() ) + cc.error( "/" ) + + cc.info( idxBlockSubRangeTo.toHexString() ) + + cc.error( " block sub-range in " ) + cc.info( nBlockFrom.toHexString() ) + + cc.error( "/" ) + cc.info( nBlockTo.toHexString() ) + + cc.error( " block range, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + idxBlockSubRangeFrom = idxBlockSubRangeTo; + if( idxBlockSubRangeFrom.eq( nBlockTo ) ) + break; + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "Result of " ) + cc.attention( "iterative" ) + + cc.debug( " scan in " ) + cc.info( nBlockFrom.toHexString() ) + cc.debug( "/" ) + + cc.info( nBlockTo.toHexString() ) + cc.debug( " block range is " ) + + cc.warning( "empty" ) + "\n" ); + } + return ""; +} diff --git a/npms/skale-ima/imaGasUsageOperations.mjs b/npms/skale-ima/imaGasUsageOperations.mjs new file mode 100644 index 000000000..793c7a1be --- /dev/null +++ b/npms/skale-ima/imaGasUsageOperations.mjs @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaGasUsageOperations.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; + +export function composeGasUsageReportFromArray( strName, jarrReceipts ) { + if( ! ( strName && typeof strName == "string" && jarrReceipts ) ) + return ""; + let i, sumGasUsed = owaspUtils.toBN( "0" ), + s = "\n" + cc.info( "Gas usage report for " ) + cc.attention( strName ) + "\n"; + for( i = 0; i < jarrReceipts.length; ++ i ) { + try { + sumGasUsed = sumGasUsed.add( owaspUtils.toBN( jarrReceipts[i].receipt.gasUsed ) ); + s += " " + cc.notice( jarrReceipts[i].description ) + cc.debug( "....." ) + + cc.info( jarrReceipts[i].receipt.gasUsed.toString() ) + "\n"; + } catch ( err ) { } + } + s += " " + cc.attention( "SUM" ) + cc.debug( "....." ) + + cc.info( sumGasUsed.toString() ) + "\n"; + return { "sumGasUsed": sumGasUsed, "strReport": s }; +} + +export function printGasUsageReportFromArray( strName, jarrReceipts, details ) { + if( log.verboseGet() >= log.verboseReversed().notice ) { + details = details || log; + const jo = composeGasUsageReportFromArray( strName, jarrReceipts ); + if( jo.strReport && + typeof jo.strReport == "string" && + jo.strReport.length > 0 && + jo.sumGasUsed && + jo.sumGasUsed.gt( owaspUtils.toBN( "0" ) ) + ) + log.write( jo.strReport ); + } +} diff --git a/npms/skale-ima/imaHelperAPIs.mjs b/npms/skale-ima/imaHelperAPIs.mjs new file mode 100644 index 000000000..f2facc866 --- /dev/null +++ b/npms/skale-ima/imaHelperAPIs.mjs @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaHelperAPIs.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as rpcCall from "../../agent/rpcCall.mjs"; + +export const longSeparator = + "============================================================" + + "==========================================================="; + +let gMillisecondsSleepBeforeFetchOutgoingMessageEvent = 5000; +let gMillisecondsSleepBetweenTransactionsOnSChain = 0; // example - 5000 +let gFlagWaitForNextBlockOnSChain = false; + +export function getMillisecondsSleepBeforeFetchOutgoingMessageEvent() { + return gMillisecondsSleepBeforeFetchOutgoingMessageEvent; +} +export function setMillisecondsSleepBeforeFetchOutgoingMessageEvent( val ) { + gMillisecondsSleepBeforeFetchOutgoingMessageEvent = val ? val : 0; +} + +export function getSleepBetweenTransactionsOnSChainMilliseconds() { + return gMillisecondsSleepBetweenTransactionsOnSChain; +} +export function setSleepBetweenTransactionsOnSChainMilliseconds( val ) { + gMillisecondsSleepBetweenTransactionsOnSChain = val ? val : 0; +} + +export function getWaitForNextBlockOnSChain() { + return gFlagWaitForNextBlockOnSChain ? true : false; +} +export function setWaitForNextBlockOnSChain( val ) { + gFlagWaitForNextBlockOnSChain = val ? true : false; +} + +export const sleep = ( milliseconds ) => { + return new Promise( resolve => setTimeout( resolve, milliseconds ) ); +}; +export const currentTimestamp = () => { + return parseInt( parseInt( Date.now().valueOf() ) / 1000 ); +}; + +export async function safeWaitForNextBlockToAppear( details, ethersProvider ) { + const nBlockNumber = + owaspUtils.toBN( await safeGetBlockNumber( details, 10, ethersProvider ) ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( "Waiting for next block to appear..." ) + "\n" ); + details.write( cc.debug( " ...have block " ) + + cc.info( nBlockNumber.toHexString() ) + "\n" ); + } + for( ; true; ) { + await sleep( 1000 ); + const nBlockNumber2 = + owaspUtils.toBN( await safeGetBlockNumber( details, 10, ethersProvider ) ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( " ...have block " ) + + cc.info( nBlockNumber2.toHexString() ) + "\n" ); + } + if( nBlockNumber2.gt( nBlockNumber ) ) + break; + } +} + +export async function safeGetBlockNumber( + details, cntAttempts, ethersProvider, retValOnFail, throwIfServerOffline +) { + const strFnName = "getBlockNumber"; + const u = owaspUtils.ethersProviderToUrl( ethersProvider ); + const nWaitStepMilliseconds = 10 * 1000; + if( throwIfServerOffline == null || throwIfServerOffline == undefined ) + throwIfServerOffline = true; + cntAttempts = + owaspUtils.parseIntOrHex( cntAttempts ) < 1 + ? 1 : owaspUtils.parseIntOrHex( cntAttempts ); + if( retValOnFail == null || retValOnFail == undefined ) + retValOnFail = ""; + let idxAttempt = 1; + let ret = retValOnFail; + try { + ret = await ethersProvider[strFnName](); + return ret; + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + + cc.error( " to " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + + cc.u( u ) + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + ++ idxAttempt; + while( ret === "" && idxAttempt <= cntAttempts ) { + const isOnLine = rpcCall.checkUrl( u, nWaitStepMilliseconds ); + if( ! isOnLine ) { + ret = retValOnFail; + if( ! throwIfServerOffline ) + return ret; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Cannot call " ) + cc.note( strFnName + "()" ) + + cc.error( " via " ) + cc.u( u ) + cc.warning( " because server is off-line" ) + + "\n" ); + } + throw new Error( "Cannot " + strFnName + "() via " + u.toString() + + " because server is off-line" ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.warning( "Repeat call to " ) + cc.note( strFnName + "()" ) + + cc.error( " via " ) + cc.u( u ) + cc.warning( ", attempt " ) + + cc.info( idxAttempt ) + "\n" ); + } + try { + ret = await ethersProvider[strFnName](); + return ret; + } catch ( err ) { + ret = retValOnFail; + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + + cc.error( " to " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + + cc.u( u ) + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + ++ idxAttempt; + } + if( ( idxAttempt + 1 ) > cntAttempts && ret === "" ) { + details.write( cc.fatal( "ERROR:" ) + + cc.error( " Failed call to " ) + cc.note( strFnName + "()" ) + + + cc.error( " via " ) + cc.u( u ) + cc.error( " after " ) + + cc.info( cntAttempts ) + cc.error( " attempts " ) + + "\n" ); + throw new Error( "Failed call to " + strFnName + "() via " + + u.toString() + " after " + cntAttempts + " attempts" ); + } + return ret; +} + +let gCountOfBlocksInIterativeStep = 1000; +let gMaxBlockScanIterationsInAllRange = 5000; + +export function getBlocksCountInInIterativeStepOfEventsScan() { + return gCountOfBlocksInIterativeStep; +} +export function setBlocksCountInInIterativeStepOfEventsScan( n ) { + if( ! n ) + gCountOfBlocksInIterativeStep = 0; + else { + gCountOfBlocksInIterativeStep = owaspUtils.parseIntOrHex( n ); + if( gCountOfBlocksInIterativeStep < 0 ) + gCountOfBlocksInIterativeStep = 0; + } +} + +export function getMaxIterationsInAllRangeEventsScan() { + return gCountOfBlocksInIterativeStep; +} +export function setMaxIterationsInAllRangeEventsScan( n ) { + if( ! n ) + gMaxBlockScanIterationsInAllRange = 0; + else { + gMaxBlockScanIterationsInAllRange = owaspUtils.parseIntOrHex( n ); + if( gMaxBlockScanIterationsInAllRange < 0 ) + gMaxBlockScanIterationsInAllRange = 0; + } +} + +// default S<->S transfer mode for "--s2s-transfer" is "forward" +let gFlagIsForwardS2S = true; + +export function getS2STransferModeDescription() { + return gFlagIsForwardS2S ? "forward" : "reverse"; +} + +export function getS2STransferModeDescriptionColorized() { + return gFlagIsForwardS2S ? cc.success( "forward" ) : cc.error( "reverse" ); +} + +export function isForwardS2S() { + return gFlagIsForwardS2S ? true : false; +} + +export function isReverseS2S() { + return gFlagIsForwardS2S ? false : true; +} + +export function setForwardS2S( b ) { + if( b == null || b == undefined ) + b = true; + gFlagIsForwardS2S = b ? true : false; +} + +export function setReverseS2S( b ) { + if( b == null || b == undefined ) + b = true; + gFlagIsForwardS2S = b ? false : true; +} diff --git a/npms/skale-ima/imaOracleOperations.mjs b/npms/skale-ima/imaOracleOperations.mjs new file mode 100644 index 000000000..1e774863f --- /dev/null +++ b/npms/skale-ima/imaOracleOperations.mjs @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaOracleOperations.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as imaOracle from "../../agent/oracle.mjs"; +import * as imaTx from "./imaTx.mjs"; +import * as imaGasUsage from "./imaGasUsageOperations.mjs"; +import * as imaTransferErrorHandling from "./imaTransferErrorHandling.mjs"; + +let gFlagIsEnabledOracle = false; + +export function getEnabledOracle( isEnabled ) { + return gFlagIsEnabledOracle ? true : false; +} +export function setEnabledOracle( isEnabled ) { + gFlagIsEnabledOracle = isEnabled ? true : false; +} + +async function prepareOracleGasPriceSetup( optsGasPriseSetup ) { + optsGasPriseSetup.strActionName = + "prepareOracleGasPriceSetup.optsGasPriseSetup.latestBlockNumber()"; + optsGasPriseSetup.latestBlockNumber = + await optsGasPriseSetup.ethersProviderMainNet.getBlockNumber(); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "Latest block on Main Net is " ) + + cc.info( optsGasPriseSetup.latestBlockNumber ) + "\n" ); + } + optsGasPriseSetup.strActionName = + "prepareOracleGasPriceSetup.optsGasPriseSetup.bnTimestampOfBlock()"; + optsGasPriseSetup.latestBlock = + await optsGasPriseSetup.ethersProviderMainNet + .getBlock( optsGasPriseSetup.latestBlockNumber ); + optsGasPriseSetup.bnTimestampOfBlock = + owaspUtils.toBN( optsGasPriseSetup.latestBlock.timestamp ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "Local timestamp on Main Net is " ) + + cc.info( optsGasPriseSetup.bnTimestampOfBlock.toString() ) + cc.debug( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( + optsGasPriseSetup.bnTimestampOfBlock.toHexString() ) ) + + cc.debug( " (original)" ) + "\n" ); + } + optsGasPriseSetup.bnTimeZoneOffset = owaspUtils.toBN( parseInt( new Date( parseInt( + optsGasPriseSetup.bnTimestampOfBlock.toString(), 10 ) ).getTimezoneOffset(), 10 ) ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "Local time zone offset is " ) + + cc.info( optsGasPriseSetup.bnTimeZoneOffset.toString() ) + cc.debug( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( + optsGasPriseSetup.bnTimeZoneOffset.toHexString() ) ) + + cc.debug( " (original)" ) + "\n" ); + } + optsGasPriseSetup.bnTimestampOfBlock = + optsGasPriseSetup.bnTimestampOfBlock.add( optsGasPriseSetup.bnTimeZoneOffset ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "UTC timestamp on Main Net is " ) + + cc.info( optsGasPriseSetup.bnTimestampOfBlock.toString() ) + cc.debug( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( + optsGasPriseSetup.bnTimestampOfBlock.toHexString() ) ) + + cc.debug( " (original)" ) + "\n" ); + } + const bnValueToSubtractFromTimestamp = owaspUtils.toBN( 60 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "Value to subtract from timestamp is " ) + + cc.info( bnValueToSubtractFromTimestamp ) + cc.debug( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( + bnValueToSubtractFromTimestamp.toHexString() ) ) + + cc.debug( " (to adjust it to past a bit)" ) + "\n" ); + } + optsGasPriseSetup.bnTimestampOfBlock = + optsGasPriseSetup.bnTimestampOfBlock.sub( bnValueToSubtractFromTimestamp ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "Timestamp on Main Net is " ) + + cc.info( optsGasPriseSetup.bnTimestampOfBlock.toHexString() ) + cc.debug( "=" ) + + cc.info( owaspUtils.ensureStartsWith0x( + optsGasPriseSetup.bnTimestampOfBlock.toHexString() ) ) + + cc.debug( " (adjusted to past a bit)" ) + "\n" ); + } + optsGasPriseSetup.strActionName = "prepareOracleGasPriceSetup.getGasPrice()"; + optsGasPriseSetup.gasPriceOnMainNet = null; + if( getEnabledOracle() ) { + const oracleOpts = { + url: owaspUtils.ethersProviderToUrl( optsGasPriseSetup.ethersProviderSChain ), + callOpts: { }, + nMillisecondsSleepBefore: 1000, + nMillisecondsSleepPeriod: 3000, + cntAttempts: 40, + isVerbose: ( log.verboseGet() >= log.verboseReversed().information ) ? true : false, + isVerboseTraceDetails: + ( log.verboseGet() >= log.verboseReversed().debug ) ? true : false + }; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsGasPriseSetup.details.write( cc.debug( "Will fetch " ) + + cc.info( "Main Net gas price" ) + cc.debug( " via call to " ) + + cc.info( "Oracle" ) + cc.debug( " with options " ) + + cc.j( oracleOpts ) + cc.debug( "..." ) + "\n" ); + } + try { + optsGasPriseSetup.gasPriceOnMainNet = owaspUtils.ensureStartsWith0x( + ( await imaOracle.oracleGetGasPrice( + oracleOpts, optsGasPriseSetup.details ) ).toString( 16 ) ); + } catch ( err ) { + optsGasPriseSetup.gasPriceOnMainNet = null; + if( log.verboseGet() >= log.verboseReversed().error ) { + optsGasPriseSetup.details.write( cc.error( "Failed to fetch " ) + + cc.info( "Main Net gas price" ) + cc.error( " via call to " ) + + cc.info( "Oracle" ) + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + } + if( optsGasPriseSetup.gasPriceOnMainNet === null ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsGasPriseSetup.details.write( cc.debug( "Will fetch " ) + + cc.info( "Main Net gas price" ) + cc.debug( " directly..." ) + "\n" ); + } + optsGasPriseSetup.gasPriceOnMainNet = owaspUtils.ensureStartsWith0x( + owaspUtils.toBN( + await optsGasPriseSetup.ethersProviderMainNet.getGasPrice() ).toHexString() ); + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsGasPriseSetup.details.write( cc.success( "Done, " ) + cc.info( "Oracle" ) + + cc.success( " did computed new " ) + cc.info( "Main Net gas price" ) + + cc.success( "=" ) + + cc.bright( owaspUtils.toBN( optsGasPriseSetup.gasPriceOnMainNet ).toString() ) + + cc.success( "=" ) + cc.bright( optsGasPriseSetup.gasPriceOnMainNet ) + "\n" ); + } + const joGasPriceOnMainNetOld = + await optsGasPriseSetup.joCommunityLocker.callStatic.mainnetGasPrice( + { from: optsGasPriseSetup.joAccountSC.address() } ); + const bnGasPriceOnMainNetOld = owaspUtils.toBN( joGasPriceOnMainNetOld ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "Previous " ) + cc.info( "Main Net gas price" ) + + cc.debug( " saved and kept in " ) + cc.info( "CommunityLocker" ) + cc.debug( "=" ) + + cc.bright( bnGasPriceOnMainNetOld.toString() ) + cc.debug( "=" ) + + cc.bright( bnGasPriceOnMainNetOld.toHexString() ) + "\n" ); + } + if( bnGasPriceOnMainNetOld.eq( owaspUtils.toBN( optsGasPriseSetup.gasPriceOnMainNet ) ) ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( cc.debug( "Previous " ) + + cc.info( "Main Net gas price" ) + + cc.debug( " is equal to new one, will skip setting it in " ) + + cc.info( "CommunityLocker" ) + "\n" ); + } + if( log.exposeDetailsGet() ) + optsGasPriseSetup.details.exposeDetailsTo( log, "doOracleGasPriceSetup", true ); + optsGasPriseSetup.details.close(); + return; + } +} + +export async function doOracleGasPriceSetup( + ethersProviderMainNet, + ethersProviderSChain, + transactionCustomizerSChain, + joCommunityLocker, + joAccountSC, + chainIdMainNet, + chainIdSChain, + fnSignMsgOracle +) { + if( ! getEnabledOracle() ) + return; + const optsGasPriseSetup = { + ethersProviderMainNet: ethersProviderMainNet, + ethersProviderSChain: ethersProviderSChain, + transactionCustomizerSChain: transactionCustomizerSChain, + joCommunityLocker: joCommunityLocker, + joAccountSC: joAccountSC, + chainIdMainNet: chainIdMainNet, + chainIdSChain: chainIdSChain, + fnSignMsgOracle: fnSignMsgOracle, + details: log.createMemoryStream(), + jarrReceipts: [], + strLogPrefix: cc.info( "Oracle gas price setup:" ) + " ", + strActionName: "", + latestBlockNumber: null, + latestBlock: null, + bnTimestampOfBlock: null, + bnTimeZoneOffset: null, + gasPriceOnMainNet: null + }; + + if( optsGasPriseSetup.fnSignMsgOracle == null || + optsGasPriseSetup.fnSignMsgOracle == undefined ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( optsGasPriseSetup.strLogPrefix + + cc.debug( "Using internal u256 signing stub function" ) + "\n" ); + } + optsGasPriseSetup.fnSignMsgOracle = async function( u256, details, fnAfter ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( optsGasPriseSetup.strLogPrefix + + cc.debug( "u256 signing callback was " ) + cc.error( "not provided" ) + "\n" ); + } + await fnAfter( null, u256, null ); // null - no error, null - no signatures + }; + } else { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( optsGasPriseSetup.strLogPrefix + + cc.debug( "Using externally provided u256 signing function" ) + "\n" ); + } + } + try { + await prepareOracleGasPriceSetup( optsGasPriseSetup ); + optsGasPriseSetup.strActionName = + "doOracleGasPriceSetup.optsGasPriseSetup.fnSignMsgOracle()"; + await optsGasPriseSetup.fnSignMsgOracle( + optsGasPriseSetup.gasPriceOnMainNet, optsGasPriseSetup.details, + async function( strError, u256, joGlueResult ) { + if( strError ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( log.id != optsGasPriseSetup.details.id ) { + log.write( optsGasPriseSetup.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in doOracleGasPriceSetup() during " + + optsGasPriseSetup.strActionName + ": " ) + + cc.error( strError ) + "\n" ); + } + } + optsGasPriseSetup.details.write( optsGasPriseSetup.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in doOracleGasPriceSetup() during " + + optsGasPriseSetup.strActionName + ": " ) + cc.error( strError ) + "\n" ); + optsGasPriseSetup.details.exposeDetailsTo( + log, "doOracleGasPriceSetup", false ); + imaTransferErrorHandling.saveTransferError( + "oracle", optsGasPriseSetup.details.toString() ); + optsGasPriseSetup.details.close(); + return; + } + optsGasPriseSetup.strActionName = "doOracleGasPriceSetup.formatSignature"; + let signature = joGlueResult ? joGlueResult.signature : null; + if( ! signature ) + signature = { X: "0", Y: "0" }; + let hashPoint = joGlueResult ? joGlueResult.hashPoint : null; + if( ! hashPoint ) + hashPoint = { X: "0", Y: "0" }; + let hint = joGlueResult ? joGlueResult.hint : null; + if( ! hint ) + hint = "0"; + const sign = { + blsSignature: [ signature.X, signature.Y ], // BLS glue of signatures + hashA: hashPoint.X, // G1.X from joGlueResult.hashSrc + hashB: hashPoint.Y, // G1.Y from joGlueResult.hashSrc + counter: hint + }; + optsGasPriseSetup.strActionName = + "Oracle gas price setup via CommunityLocker.setGasPrice()"; + const arrArgumentsSetGasPrice = [ + u256, + owaspUtils.ensureStartsWith0x( + optsGasPriseSetup.bnTimestampOfBlock.toHexString() ), + sign // bls signature components + ]; + if( log.verboseGet() >= log.verboseReversed().debug ) { + const joDebugArgs = [ + [ signature.X, signature.Y ], // BLS glue of signatures + hashPoint.X, // G1.X from joGlueResult.hashSrc + hashPoint.Y, // G1.Y from joGlueResult.hashSrc + hint + ]; + optsGasPriseSetup.details.write( optsGasPriseSetup.strLogPrefix + + cc.debug( "....debug args for " ) + cc.debug( ": " ) + + cc.j( joDebugArgs ) + "\n" ); + } + const weiHowMuch = undefined; + const gasPrice = + await optsGasPriseSetup.transactionCustomizerSChain.computeGasPrice( + optsGasPriseSetup.ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( optsGasPriseSetup.strLogPrefix + + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasSetGasPrice = + await optsGasPriseSetup.transactionCustomizerSChain.computeGas( + optsGasPriseSetup.details, optsGasPriseSetup.ethersProviderSChain, + "CommunityLocker", optsGasPriseSetup.joCommunityLocker, + "setGasPrice", arrArgumentsSetGasPrice, optsGasPriseSetup.joAccountSC, + optsGasPriseSetup.strActionName, gasPrice, 10000000, weiHowMuch, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsGasPriseSetup.details.write( optsGasPriseSetup.strLogPrefix + + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGasSetGasPrice ) + "\n" ); + } + const isIgnoreSetGasPrice = false; + const strErrorOfDryRun = await imaTx.dryRunCall( optsGasPriseSetup.details, + optsGasPriseSetup.ethersProviderSChain, + "CommunityLocker", optsGasPriseSetup.joCommunityLocker, + "setGasPrice", arrArgumentsSetGasPrice, + optsGasPriseSetup.joAccountSC, optsGasPriseSetup.strActionName, + isIgnoreSetGasPrice, gasPrice, + estimatedGasSetGasPrice, weiHowMuch, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + const opts = { + isCheckTransactionToSchain: + ( optsGasPriseSetup.chainIdSChain !== "Mainnet" ) ? true : false + }; + const joReceipt = await imaTx.payedCall( optsGasPriseSetup.details, + optsGasPriseSetup.ethersProviderSChain, + "CommunityLocker", optsGasPriseSetup.joCommunityLocker, + "setGasPrice", arrArgumentsSetGasPrice, + optsGasPriseSetup.joAccountSC, optsGasPriseSetup.strActionName, + gasPrice, estimatedGasSetGasPrice, weiHowMuch, + opts ); + if( joReceipt && typeof joReceipt == "object" ) { + optsGasPriseSetup.jarrReceipts.push( { + "description": "doOracleGasPriceSetup/setGasPrice", + "receipt": joReceipt + } ); + imaGasUsage.printGasUsageReportFromArray( + "(intermediate result) ORACLE GAS PRICE SETUP ", + optsGasPriseSetup.jarrReceipts, optsGasPriseSetup.details ); + } + imaTransferErrorHandling.saveTransferSuccess( "oracle" ); + } ); + } catch ( err ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.verboseGet() >= log.verboseReversed().critical ) { + if( log.id != optsGasPriseSetup.details.id ) { + log.write( optsGasPriseSetup.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in doOracleGasPriceSetup() during " + + optsGasPriseSetup.strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + optsGasPriseSetup.details.write( optsGasPriseSetup.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in doOracleGasPriceSetup() during " + + optsGasPriseSetup.strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + optsGasPriseSetup.details.exposeDetailsTo( log, "doOracleGasPriceSetup", false ); + imaTransferErrorHandling.saveTransferError( + "oracle", optsGasPriseSetup.details.toString() ); + optsGasPriseSetup.details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "ORACLE GAS PRICE SETUP ", + optsGasPriseSetup.jarrReceipts, optsGasPriseSetup.details ); + if( log.exposeDetailsGet() ) + optsGasPriseSetup.details.exposeDetailsTo( log, "doOracleGasPriceSetup", true ); + optsGasPriseSetup.details.close(); + return true; +} diff --git a/npms/skale-ima/imaRegistrationOperations.mjs b/npms/skale-ima/imaRegistrationOperations.mjs new file mode 100644 index 000000000..6392b9ae7 --- /dev/null +++ b/npms/skale-ima/imaRegistrationOperations.mjs @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaRegistrationOperations.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as imaHelperAPIs from "./imaHelperAPIs.mjs"; +import * as imaTx from "./imaTx.mjs"; + +export async function invokeHasChain( + details, + ethersProvider, // Main-Net or S-Chin + joLinker, // Main-Net or S-Chin + joAccount, // Main-Net or S-Chin + chainIdSChain +) { + const strLogPrefix = cc.sunny( "Wait for added chain status:" ) + " "; + const strActionName = "invokeHasChain(hasSchain): joLinker.hasSchain"; + try { + details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + + cc.debug( "..." ) + "\n" ); + const addressFrom = joAccount.address(); + const bHasSchain = + await joLinker.callStatic.hasSchain( chainIdSChain, { from: addressFrom } ); + details.write( strLogPrefix + + cc.success( "Got joLinker.hasSchain() status is: " ) + cc.attention( bHasSchain ) + + "\n" ); + return bHasSchain; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( "Error in invokeHasChain() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + } + return false; +} + +export async function waitForHasChain( + details, + ethersProvider, // Main-Net or S-Chin + joLinker, // Main-Net or S-Chin + joAccount, // Main-Net or S-Chin + chainIdSChain, + cntWaitAttempts, + nSleepMilliseconds +) { + if( cntWaitAttempts == null || cntWaitAttempts == undefined ) + cntWaitAttempts = 100; + if( nSleepMilliseconds == null || nSleepMilliseconds == undefined ) + nSleepMilliseconds = 5; + for( let idxWaitAttempts = 0; idxWaitAttempts < cntWaitAttempts; ++ idxWaitAttempts ) { + if( await invokeHasChain( + details, ethersProvider, joLinker, joAccount, chainIdSChain + ) ) + return true; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.normal( "Sleeping " ) + cc.info( nSleepMilliseconds ) + + cc.normal( " milliseconds..." ) + "\n" ); + } + await imaHelperAPIs.sleep( nSleepMilliseconds ); + } + return false; +} + +// +// register direction for money transfer +// main-net.DepositBox call: function addSchain(string schainName, address tokenManagerAddress) +// +export async function checkIsRegisteredSChainInDepositBoxes( // step 1 + ethersProviderMainNet, + joLinker, + joAccountMN, + chainIdSChain +) { + const details = log.createMemoryStream(); + details.write( cc.info( "Main-net " ) + cc.sunny( "Linker" ) + + cc.info( " address is....." ) + cc.bright( joLinker.address ) + "\n" ); + details.write( cc.info( "S-Chain " ) + cc.sunny( "ID" ) + + cc.info( " is......................." ) + cc.bright( chainIdSChain ) + "\n" ); + const strLogPrefix = cc.note( "RegChk S in depositBox:" ) + " "; + details.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + details.write( strLogPrefix + + cc.bright( "checkIsRegisteredSChainInDepositBoxes(reg-step1)" ) + "\n" ); + details.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + let strActionName = ""; + try { + strActionName = "checkIsRegisteredSChainInDepositBoxes(reg-step1)"; + const addressFrom = joAccountMN.address(); + const bIsRegistered = + await joLinker.callStatic.hasSchain( chainIdSChain, { from: addressFrom } ); + details.write( strLogPrefix + + cc.success( "checkIsRegisteredSChainInDepositBoxes(reg-step1) status is: " ) + + cc.attention( bIsRegistered ) + + "\n" ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "checkIsRegisteredSChainInDepositBoxes", true ); + details.close(); + return bIsRegistered; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( + " Error in checkIsRegisteredSChainInDepositBoxes(reg-step1)() during " + + strActionName + ": " ) + cc.error( strError ) + cc.error( ", stack is: " ) + + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "checkIsRegisteredSChainInDepositBoxes", false ); + details.close(); + } + return false; +} + +export async function registerSChainInDepositBoxes( // step 1 + ethersProviderMainNet, + joLinker, + joAccountMN, + joTokenManagerETH, // only s-chain + joTokenManagerERC20, // only s-chain + joTokenManagerERC721, // only s-chain + joTokenManagerERC1155, // only s-chain + joTokenManagerERC721WithMetadata, // only s-chain + joCommunityLocker, // only s-chain + joTokenManagerLinker, + chainNameSChain, + chainNameMainNet, + transactionCustomizerMainNet, + cntWaitAttempts, + nSleepMilliseconds +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + details.write( cc.info( "Main-net " ) + cc.sunny( "Linker" ) + + cc.info( " address is......." ) + cc.bright( joLinker.address ) + "\n" ); + details.write( cc.info( "S-Chain " ) + cc.sunny( "ID" ) + + cc.info( " is......................." ) + cc.bright( chainNameSChain ) + "\n" ); + const strLogPrefix = cc.sunny( "Reg S in depositBoxes:" ) + " "; + details.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + details.write( strLogPrefix + + cc.bright( "reg-step1:registerSChainInDepositBoxes" ) + "\n" ); + details.write( strLogPrefix + cc.debug( imaHelperAPIs.longSeparator ) + "\n" ); + let strActionName = ""; + try { + strActionName = "Register S-chain in deposit boxes, step 1, connectSchain"; + details.write( strLogPrefix + + cc.debug( "Will register S-Chain in lock_and_data on Main-net" ) + "\n" ); + const arrArguments = [ + chainNameSChain, + [ + joTokenManagerLinker.address, // call params + joCommunityLocker.address, // call params + joTokenManagerETH.address, // call params + joTokenManagerERC20.address, // call params + joTokenManagerERC721.address, // call params + joTokenManagerERC1155.address, // call params + joTokenManagerERC721WithMetadata.address // call params + ] + ]; + const weiHowMuch = undefined; + const gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGas = + await transactionCustomizerMainNet.computeGas( + details, + ethersProviderMainNet, + "Linker", joLinker, "connectSchain", arrArguments, + joAccountMN, strActionName, + gasPrice, 3000000, weiHowMuch, + null + ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); + } + const isIgnore = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "Linker", joLinker, "connectSchain", arrArguments, + joAccountMN, strActionName, isIgnore, + gasPrice, estimatedGas, weiHowMuch, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const joReceipt = + await imaTx.payedCall( + details, ethersProviderMainNet, + "Linker", joLinker, "connectSchain", arrArguments, + joAccountMN, strActionName, + gasPrice, estimatedGas, weiHowMuch, null ); + if( joReceipt && typeof joReceipt == "object" ) { + jarrReceipts.push( { + "description": "registerSChainInDepositBoxes", + "receipt": joReceipt + } ); + } + const isSChainStatusOKay = await waitForHasChain( + details, ethersProviderMainNet, + joLinker, joAccountMN, chainNameSChain, + cntWaitAttempts, nSleepMilliseconds ); + if( ! isSChainStatusOKay ) + throw new Error( "S-Chain ownership status check timeout" ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in registerSChainInDepositBoxes() during " + + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "registerSChainInDepositBoxes", false ); + details.close(); + return null; + } + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "registerSChainInDepositBoxes", true ); + details.close(); + return jarrReceipts; +} diff --git a/npms/skale-ima/imaReimbursementOperations.mjs b/npms/skale-ima/imaReimbursementOperations.mjs new file mode 100644 index 000000000..87897d47d --- /dev/null +++ b/npms/skale-ima/imaReimbursementOperations.mjs @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaReimbursementOperations.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as imaTx from "./imaTx.mjs"; +import * as imaGasUsage from "./imaGasUsageOperations.mjs"; + +export async function reimbursementShowBalance( + ethersProviderMainNet, + joCommunityPool, + joReceiverMainNet, + strChainNameMainNet, + chainIdMainNet, + transactionCustomizerMainNet, + strReimbursementChain, + isForcePrintOut +) { + const details = log.createMemoryStream(); + let s = ""; + const strLogPrefix = cc.info( "Gas Reimbursement - Show Balance" ) + " "; + try { + const addressFrom = joReceiverMainNet; + details.write( strLogPrefix + cc.debug( "Querying wallet " ) + + cc.notice( strReimbursementChain ) + cc.debug( "/" ) + cc.info( addressFrom ) + + cc.debug( " balance..." ) + "\n" ); + const xWei = + await joCommunityPool.callStatic.getBalance( + addressFrom, strReimbursementChain, { from: addressFrom } ); + s = strLogPrefix + cc.success( "Balance(wei): " ) + cc.attention( xWei ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + const xEth = owaspUtils.ethersMod.ethers.utils.formatEther( owaspUtils.toBN( xWei ) ); + s = strLogPrefix + cc.success( "Balance(eth): " ) + cc.attention( xEth ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "reimbursementShowBalance", true ); + details.close(); + return xWei; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in reimbursementShowBalance(): " ) + + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "reimbursementShowBalance", false ); + details.close(); + return 0; + } +} + +export async function reimbursementEstimateAmount( + ethersProviderMainNet, + joCommunityPool, + joReceiverMainNet, + strChainNameMainNet, + chainIdMainNet, + transactionCustomizerMainNet, + strReimbursementChain, + isForcePrintOut +) { + const details = log.createMemoryStream(); + let s = ""; + const strLogPrefix = cc.info( "Gas Reimbursement - Estimate Amount To Recharge" ) + " "; + try { + details.write( strLogPrefix + cc.debug( "Querying wallet " ) + + cc.notice( strReimbursementChain ) + cc.debug( " balance..." ) + "\n" ); + const addressReceiver = joReceiverMainNet; + const xWei = + await joCommunityPool.callStatic.getBalance( + addressReceiver, strReimbursementChain, { from: addressReceiver } ); + s = strLogPrefix + cc.success( "Balance(wei): " ) + cc.attention( xWei ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + const xEth = owaspUtils.ethersMod.ethers.utils.formatEther( owaspUtils.toBN( xWei ) ); + s = strLogPrefix + cc.success( "Balance(eth): " ) + cc.attention( xEth ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + + const minTransactionGas = + owaspUtils.parseIntOrHex( + await joCommunityPool.callStatic.minTransactionGas( + { from: addressReceiver } ) ); + s = strLogPrefix + cc.success( "MinTransactionGas: " ) + + cc.attention( minTransactionGas ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + + const gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + s = strLogPrefix + cc.success( "Multiplied Gas Price: " ) + cc.attention( gasPrice ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + + const minAmount = minTransactionGas * gasPrice; + s = strLogPrefix + cc.success( "Minimum recharge balance: " ) + + cc.attention( minAmount ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + + let amountToRecharge = 0; + if( xWei >= minAmount ) + amountToRecharge = 1; + else + amountToRecharge = minAmount - xWei; + + s = strLogPrefix + cc.success( "Estimated amount to recharge(wei): " ) + + cc.attention( amountToRecharge ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + + const amountToRechargeEth = + owaspUtils.ethersMod.ethers.utils.formatEther( + owaspUtils.toBN( amountToRecharge.toString() ) ); + s = strLogPrefix + cc.success( "Estimated amount to recharge(eth): " ) + + cc.attention( amountToRechargeEth ) + "\n"; + if( isForcePrintOut || log.verboseGet() >= log.verboseReversed().information ) + log.write( s ); + details.write( s ); + + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "reimbursementEstimateAmount", true ); + details.close(); + return amountToRecharge; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in reimbursementEstimateAmount(): " ) + + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "reimbursementEstimateAmount", false ); + details.close(); + return 0; + } +} + +export async function reimbursementWalletRecharge( + ethersProviderMainNet, + joCommunityPool, + joAccountMN, + strChainNameMainNet, + chainIdMainNet, + transactionCustomizerMainNet, + strReimbursementChain, + nReimbursementRecharge +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "Gas Reimbursement - Wallet Recharge" ) + " "; + try { + details.write( strLogPrefix + cc.debug( "Recharging wallet " ) + + cc.notice( strReimbursementChain ) + cc.debug( "..." ) + "\n" ); + strActionName = "Recharge reimbursement wallet on Main Net"; + const addressReceiver = joAccountMN.address(); + const arrArguments = [ + strReimbursementChain, + addressReceiver + ]; + const gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGas = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "CommunityPool", joCommunityPool, "rechargeUserWallet", arrArguments, + joAccountMN, strActionName, + gasPrice, 3000000, nReimbursementRecharge, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); + } + const isIgnore = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "CommunityPool", joCommunityPool, "rechargeUserWallet", arrArguments, + joAccountMN, strActionName, isIgnore, + gasPrice, estimatedGas, nReimbursementRecharge, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const joReceipt = + await imaTx.payedCall( + details, ethersProviderMainNet, + "CommunityPool", joCommunityPool, "rechargeUserWallet", arrArguments, + joAccountMN, strActionName, + gasPrice, estimatedGas, nReimbursementRecharge, null ); + if( joReceipt && typeof joReceipt == "object" ) { + jarrReceipts.push( { + "description": "reimbursementWalletRecharge", + "receipt": joReceipt + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "reimbursementWalletRecharge", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "REIMBURSEMENT_WALLET_RECHARGE", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "reimbursementWalletRecharge", true ); + details.close(); + return true; +} + +export async function reimbursementWalletWithdraw( + ethersProviderMainNet, + joCommunityPool, + joAccountMN, + strChainNameMainNet, + chainIdMainNet, + transactionCustomizerMainNet, + strReimbursementChain, + nReimbursementWithdraw +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "Gas Reimbursement - Wallet Withdraw" ) + " "; + try { + details.write( strLogPrefix + cc.debug( "Withdrawing wallet " ) + + cc.notice( strReimbursementChain ) + cc.debug( "..." ) + "\n" ); + strActionName = "Withdraw reimbursement wallet"; + const arrArguments = [ + strReimbursementChain, + owaspUtils.ensureStartsWith0x( + owaspUtils.toBN( nReimbursementWithdraw ).toHexString() ) + ]; + const weiHowMuch = undefined; + const gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + + "\n" ); + } + const estimatedGas = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "CommunityPool", joCommunityPool, "withdrawFunds", arrArguments, + joAccountMN, strActionName, + gasPrice, 3000000, weiHowMuch, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); + } + const isIgnore = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "CommunityPool", joCommunityPool, "withdrawFunds", arrArguments, + joAccountMN, strActionName, isIgnore, + gasPrice, estimatedGas, weiHowMuch, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const joReceipt = + await imaTx.payedCall( + details, ethersProviderMainNet, + "CommunityPool", joCommunityPool, "withdrawFunds", arrArguments, + joAccountMN, strActionName, + gasPrice, estimatedGas, weiHowMuch, null ); + if( joReceipt && typeof joReceipt == "object" ) { + jarrReceipts.push( { + "description": "reimbursementWalletWithdraw", + "receipt": joReceipt + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "reimbursementWalletWithdraw", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "REIMBURSEMENT_WALLET_WITHDRAW", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "reimbursementWalletWithdraw", true ); + details.close(); + return true; +} + +export async function reimbursementSetRange( + ethersProviderSChain, + joCommunityLocker, + joAccountSC, + strChainNameSChain, + chainIdSChain, + transactionCustomizerSChain, + strChainNameOriginChain, + nReimbursementRange +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = + cc.info( "Gas Reimbursement - Set Minimal time interval from S2M transfers" ) + " "; + try { + details.write( strLogPrefix + cc.debug( "Setting minimal S2M interval to " ) + + cc.notice( nReimbursementRange ) + cc.debug( "..." ) + "\n" ); + strActionName = "Set reimbursement range"; + const arrArguments = [ + strChainNameOriginChain, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nReimbursementRange ).toHexString() ) + ]; + const weiHowMuch = undefined; + const gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGas = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "CommunityLocker", joCommunityLocker, + "setTimeLimitPerMessage", arrArguments, + joAccountSC, strActionName, + gasPrice, 3000000, weiHowMuch, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); + } + const isIgnore = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "CommunityLocker", joCommunityLocker, + "setTimeLimitPerMessage", arrArguments, + joAccountSC, strActionName, isIgnore, + gasPrice, estimatedGas, weiHowMuch, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + isCheckTransactionToSchain: true + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProviderSChain, + "CommunityLocker", joCommunityLocker, + "setTimeLimitPerMessage", arrArguments, + joAccountSC, strActionName, + gasPrice, estimatedGas, weiHowMuch, opts ); + if( joReceipt && typeof joReceipt == "object" ) { + jarrReceipts.push( { + "description": "reimbursementSetRange", + "receipt": joReceipt + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "reimbursementSetRange", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "REIMBURSEMENT_SET_RANGE", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "reimbursementSetRange", true ); + details.close(); + return true; +} diff --git a/npms/skale-ima/imaTokenOperations.mjs b/npms/skale-ima/imaTokenOperations.mjs new file mode 100644 index 000000000..21bd4510d --- /dev/null +++ b/npms/skale-ima/imaTokenOperations.mjs @@ -0,0 +1,2895 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaTokenOperations.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as imaHelperAPIs from "./imaHelperAPIs.mjs"; +import * as imaTx from "./imaTx.mjs"; +import * as imaGasUsage from "./imaGasUsageOperations.mjs"; +import * as imaEventLogScan from "./imaEventLogScan.mjs"; + +export async function getBalanceErc20( + isMainNet, + ethersProvider, + chainId, + joAccount, + strCoinName, + joABI +) { + const strLogPrefix = cc.info( "getBalanceErc20() call" ) + " "; + try { + if( ! ( ethersProvider && joAccount && strCoinName && joABI && ( strCoinName + "_abi" ) in + joABI && + ( strCoinName + "_address" ) in joABI ) + ) + return ""; + const strAddress = joAccount.address(); + const contractERC20 = new owaspUtils.ethersMod.ethers.Contract( + joABI[strCoinName + "_address"], + joABI[strCoinName + "_abi"], + ethersProvider + ); + const balance = + await contractERC20.callStatic.balanceOf( strAddress, { from: strAddress } ); + return balance; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + } + return ""; +} + +export async function getOwnerOfErc721( + isMainNet, + ethersProvider, + chainId, + joAccount, + strCoinName, + joABI, + idToken +) { + const strLogPrefix = cc.info( "getOwnerOfErc721() call" ) + " "; + try { + if( ! ( ethersProvider && joAccount && strCoinName && joABI && ( strCoinName + "_abi" ) in + joABI && + ( strCoinName + "_address" ) in joABI ) + ) + return ""; + const strAddress = joAccount.address(); + const contractERC721 = owaspUtils.ethersMod.ethers.Contract( + joABI[strCoinName + "_address"], + joABI[strCoinName + "_abi"], + ethersProvider + ); + const owner = + await contractERC721.callStatic.ownerOf( idToken, { from: strAddress } ); + return owner; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return ""; +} + +export async function getBalanceErc1155( + isMainNet, + ethersProvider, + chainId, + joAccount, + strCoinName, + joABI, + idToken +) { + const strLogPrefix = cc.info( "getBalanceErc1155() call" ) + " "; + try { + if( ! ( ethersProvider && joAccount && strCoinName && joABI && ( strCoinName + "_abi" ) in + joABI && + ( strCoinName + "_address" ) in joABI ) + ) + return ""; + const strAddress = joAccount.address(); + const contractERC1155 = new owaspUtils.ethersMod.ethers.Contract( + joABI[strCoinName + "_address"], + joABI[strCoinName + "_abi"], + ethersProvider + ); + const balance = + await contractERC1155.callStatic.balanceOf( + strAddress, idToken, { from: strAddress } ); + return balance; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return ""; +} + +export async function doErc721PaymentFromMainNet( + ethersProviderMainNet, + ethersProviderSChain, + chainIdMainNet, + chainIdSChain, + joAccountSrc, + joAccountDst, + joDepositBoxERC721, + joMessageProxyMainNet, // for checking logs + chainNameSChain, + tokenId, // which ERC721 token id to send + weiHowMuch, // how much ETH + joTokenManagerERC721, // only s-chain + strCoinNameErc721MainNet, + erc721PrivateTestnetJsonMainNet, + strCoinNameErc721SChain, + erc721PrivateTestnetJsonSChain, + transactionCustomizerMainNet +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "M2S ERC721 Payment:" ) + " "; + try { + strActionName = "ERC721 payment from Main Net, approve"; + const erc721ABI = erc721PrivateTestnetJsonMainNet[strCoinNameErc721MainNet + "_abi"]; + const erc721AddressMainNet = + erc721PrivateTestnetJsonMainNet[strCoinNameErc721MainNet + "_address"]; + const contractERC721 = + new owaspUtils.ethersMod.ethers.Contract( + erc721AddressMainNet, + erc721ABI, + ethersProviderMainNet + ); + const depositBoxAddress = joDepositBoxERC721.address; + const arrArgumentsApprove = [ + depositBoxAddress, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ) + ]; + const arrArgumentsDepositERC721 = [ + chainNameSChain, + erc721AddressMainNet, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderMainNet, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": "doErc721PaymentFromMainNet/approve", + "receipt": joReceiptApprove + } ); + } + + strActionName = "ERC721 payment from Main Net, depositERC721"; + const weiHowMuchDepositERC721 = undefined; + gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasDeposit = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "DepositBoxERC721", joDepositBoxERC721, + "depositERC721", arrArgumentsDepositERC721, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchDepositERC721, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasDeposit ) + "\n" ); + } + const isIgnoreDepositERC721 = true; + const strErrorOfDryRunDepositERC721 = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "DepositBoxERC721", joDepositBoxERC721, + "depositERC721", arrArgumentsDepositERC721, + joAccountSrc, strActionName, isIgnoreDepositERC721, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC721, null ); + if( strErrorOfDryRunDepositERC721 ) + throw new Error( strErrorOfDryRunDepositERC721 ); + + const joReceiptDeposit = + await imaTx.payedCall( + details, ethersProviderMainNet, + "DepositBoxERC721", joDepositBoxERC721, + "depositERC721", arrArgumentsDepositERC721, + joAccountSrc, strActionName, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC721, null ); + if( joReceiptDeposit && typeof joReceiptDeposit == "object" ) { + jarrReceipts.push( { + "description": "doErc721PaymentFromMainNet/deposit", + "receipt": joReceiptDeposit + } ); + } + + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxyMainNet ) { + details.write( strLogPrefix + + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxyMainNet.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderMainNet, joMessageProxyMainNet, strEventName, + joReceiptDeposit.blockNumber, joReceiptDeposit.transactionHash, + joMessageProxyMainNet.filters[strEventName]() + ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + + cc.success( "Success, verified the " ) + cc.info( strEventName ) + + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + + cc.success( "/" ) + cc.notice( joMessageProxyMainNet.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" " + + "event of the \"MessageProxy\"/" + + joMessageProxyMainNet.address + " contract, no events found" + ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc721PaymentFromMainNet", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-721 PAYMENT FROM MAIN NET", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc721PaymentFromMainNet", true ); + details.close(); + return true; +} + +export async function doErc20PaymentFromMainNet( + ethersProviderMainNet, + ethersProviderSChain, + chainIdMainNet, + chainIdSChain, + joAccountSrc, + joAccountDst, + joDepositBoxERC20, + joMessageProxyMainNet, // for checking logs + chainNameSChain, + tokenAmount, // how much ERC20 tokens to send + weiHowMuch, // how much ETH + joTokenManagerERC20, // only s-chain + strCoinNameErc20MainNet, + erc20MainNet, + strCoinNameErc20SChain, + erc20SChain, + transactionCustomizerMainNet +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "M2S ERC20 Payment:" ) + " "; + try { + strActionName = "ERC20 payment from Main Net, approve"; + const erc20ABI = erc20MainNet[strCoinNameErc20MainNet + "_abi"]; + const erc20AddressMainNet = + erc20MainNet[strCoinNameErc20MainNet + "_address"]; + const contractERC20 = + new owaspUtils.ethersMod.ethers.Contract( + erc20AddressMainNet, + erc20ABI, + ethersProviderMainNet + ); + const depositBoxAddress = joDepositBoxERC20.address; + const arrArgumentsApprove = [ + depositBoxAddress, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenAmount ).toHexString() ) + ]; + const arrArgumentsDepositERC20 = [ + chainNameSChain, + erc20AddressMainNet, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenAmount ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderMainNet, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": "doErc20PaymentFromMainNet/approve", + "receipt": joReceiptApprove + } ); + } + + strActionName = "ERC20 payment from Main Net, depositERC20"; + const weiHowMuchDepositERC20 = undefined; + gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasDeposit = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "DepositBoxERC20", joDepositBoxERC20, + "depositERC20", arrArgumentsDepositERC20, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchDepositERC20, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasDeposit ) + "\n" ); + } + const isIgnoreDepositERC20 = true; + const strErrorOfDryRunDepositERC20 = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "DepositBoxERC20", joDepositBoxERC20, + "depositERC20", arrArgumentsDepositERC20, + joAccountSrc, strActionName, isIgnoreDepositERC20, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC20, null ); + if( strErrorOfDryRunDepositERC20 ) + throw new Error( strErrorOfDryRunDepositERC20 ); + + const joReceiptDeposit = + await imaTx.payedCall( + details, ethersProviderMainNet, + "DepositBoxERC20", joDepositBoxERC20, + "depositERC20", arrArgumentsDepositERC20, + joAccountSrc, strActionName, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC20, null ); + if( joReceiptDeposit && typeof joReceiptDeposit == "object" ) { + jarrReceipts.push( { + "description": "doErc20PaymentFromMainNet/deposit", + "receipt": joReceiptDeposit + } ); + } + + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxyMainNet ) { + details.write( strLogPrefix + + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxyMainNet.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderMainNet, joMessageProxyMainNet, strEventName, + joReceiptDeposit.blockNumber, joReceiptDeposit.transactionHash, + joMessageProxyMainNet.filters[strEventName]() + ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + + cc.success( "Success, verified the " ) + cc.info( strEventName ) + + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + + cc.success( "/" ) + cc.notice( joMessageProxyMainNet.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + + "\n" ); + } else { + throw new Error( + "Verification failed for th\"OutgoingMessage\" event " + + "of the \"MessageProxy\"/" + + joMessageProxyMainNet.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc20PaymentFromMainNet", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-20 PAYMENT FROM MAIN NET", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc20PaymentFromMainNet", true ); + details.close(); + return true; +} + +export async function doErc1155PaymentFromMainNet( + ethersProviderMainNet, + ethersProviderSChain, + chainIdMainNet, + chainIdSChain, + joAccountSrc, + joAccountDst, + joDepositBoxERC1155, + joMessageProxyMainNet, // for checking logs + chainNameSChain, + tokenId, // which ERC1155 token id to send + tokenAmount, // which ERC1155 token id to send + weiHowMuch, // how much ETH + joTokenManagerERC1155, // only s-chain + strCoinNameErc1155SMainNet, + erc1155PrivateTestnetJsonMainNet, + strCoinNameErc1155SChain, + erc1155PrivateTestnetJsonSChain, + transactionCustomizerMainNet +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "M2S ERC1155 Payment:" ) + " "; + try { + strActionName = "ERC1155 payment from Main Net, approve"; + const erc1155ABI = + erc1155PrivateTestnetJsonMainNet[strCoinNameErc1155SMainNet + "_abi"]; + const erc1155AddressMainNet = + erc1155PrivateTestnetJsonMainNet[strCoinNameErc1155SMainNet + "_address"]; + const contractERC1155 = new owaspUtils.ethersMod.ethers.Contract( + erc1155AddressMainNet, erc1155ABI, ethersProviderMainNet ); + const depositBoxAddress = joDepositBoxERC1155.address; + const arrArgumentsApprove = [ + depositBoxAddress, + true + ]; + const arrArgumentsDepositERC1155 = [ + chainNameSChain, + erc1155AddressMainNet, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ), + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenAmount ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderMainNet, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, estimatedGasApprove, weiHowMuchApprove, + null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": "doErc1155PaymentFromMainNet/approve", + "receipt": joReceiptApprove + } ); + } + strActionName = "ERC1155 payment from Main Net, depositERC1155"; + const weiHowMuchDepositERC1155 = undefined; + gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasDeposit = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "DepositBoxERC1155", joDepositBoxERC1155, + "depositERC1155", arrArgumentsDepositERC1155, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchDepositERC1155, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasDeposit ) + "\n" ); + } + const isIgnoreDepositERC1155 = true; + const strErrorOfDryRunDepositERC1155 = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "DepositBoxERC1155", joDepositBoxERC1155, + "depositERC1155", arrArgumentsDepositERC1155, + joAccountSrc, strActionName, isIgnoreDepositERC1155, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC1155, null ); + if( strErrorOfDryRunDepositERC1155 ) + throw new Error( strErrorOfDryRunDepositERC1155 ); + const joReceiptDeposit = + await imaTx.payedCall( + details, ethersProviderMainNet, + "DepositBoxERC1155", joDepositBoxERC1155, + "depositERC1155", arrArgumentsDepositERC1155, + joAccountSrc, strActionName, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC1155, null ); + if( joReceiptDeposit && typeof joReceiptDeposit == "object" ) { + jarrReceipts.push( { + "description": "doErc1155PaymentFromMainNet/deposit", + "receipt": joReceiptDeposit + } ); + } + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxyMainNet ) { + details.write( strLogPrefix + + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxyMainNet.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderMainNet, joMessageProxyMainNet, strEventName, + joReceiptDeposit.blockNumber, joReceiptDeposit.transactionHash, + joMessageProxyMainNet.filters[strEventName]() + ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + + cc.success( "Success, verified the " ) + cc.info( strEventName ) + + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + + cc.success( "/" ) + cc.notice( joMessageProxyMainNet.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" event " + + "of the \"MessageProxy\"/" + + joMessageProxyMainNet.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc1155PaymentFromMainNet", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-1155 PAYMENT FROM MAIN NET", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc1155PaymentFromMainNet", true ); + details.close(); + return true; +} + +export async function doErc1155BatchPaymentFromMainNet( + ethersProviderMainNet, ethersProviderSChain, + chainIdMainNet, chainIdSChain, + joAccountSrc, joAccountDst, + joDepositBoxERC1155, + joMessageProxyMainNet, // for checking logs + chainNameSChain, + arrTokenIds, // which ERC1155 token id to send + arrTokenAmounts, // which ERC1155 token id to send + weiHowMuch, // how much ETH + joTokenManagerERC1155, // only s-chain + strCoinNameErc1155SMainNet, + erc1155PrivateTestnetJsonMainNet, strCoinNameErc1155SChain, + erc1155PrivateTestnetJsonSChain, transactionCustomizerMainNet +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "M2S ERC1155 Batch Payment:" ) + " "; + try { + strActionName = "ERC1155 batch-payment from Main Net, approve"; + const erc1155ABI = + erc1155PrivateTestnetJsonMainNet[strCoinNameErc1155SMainNet + "_abi"]; + const erc1155AddressMainNet = + erc1155PrivateTestnetJsonMainNet[strCoinNameErc1155SMainNet + "_address"]; + const contractERC1155 = + new owaspUtils.ethersMod.ethers.Contract( + erc1155AddressMainNet, + erc1155ABI, + ethersProviderMainNet + ); + const depositBoxAddress = joDepositBoxERC1155.address; + const arrArgumentsApprove = [ + // joAccountSrc.address(), + depositBoxAddress, + true + ]; + const arrArgumentsDepositERC1155Batch = [ + chainNameSChain, erc1155AddressMainNet, arrTokenIds, arrTokenAmounts ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderMainNet, "ERC1155", contractERC1155, + "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderMainNet, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": "doErc1155BatchPaymentFromMainNet/approve", + "receipt": joReceiptApprove + } ); + } + strActionName = "ERC1155 batch-payment from Main Net, depositERC1155Batch"; + const weiHowMuchDepositERC1155Batch = undefined; + gasPrice = await transactionCustomizerMainNet.computeGasPrice( + ethersProviderMainNet, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasDeposit = + await transactionCustomizerMainNet.computeGas( + details, ethersProviderMainNet, + "DepositBoxERC1155", joDepositBoxERC1155, + "depositERC1155Batch", arrArgumentsDepositERC1155Batch, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchDepositERC1155Batch, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasDeposit ) + "\n" ); + } + const isIgnoreDepositERC1155Batch = true; + const strErrorOfDryRunDepositERC1155Batch = + await imaTx.dryRunCall( + details, ethersProviderMainNet, + "DepositBoxERC1155", joDepositBoxERC1155, + "depositERC1155Batch", arrArgumentsDepositERC1155Batch, + joAccountSrc, strActionName, isIgnoreDepositERC1155Batch, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC1155Batch, null ); + if( strErrorOfDryRunDepositERC1155Batch ) + throw new Error( strErrorOfDryRunDepositERC1155Batch ); + const joReceiptDeposit = + await imaTx.payedCall( + details, ethersProviderMainNet, + "DepositBoxERC1155", joDepositBoxERC1155, + "depositERC1155Batch", arrArgumentsDepositERC1155Batch, + joAccountSrc, strActionName, + gasPrice, estimatedGasDeposit, weiHowMuchDepositERC1155Batch, null ); + if( joReceiptDeposit && typeof joReceiptDeposit == "object" ) { + jarrReceipts.push( { + "description": "doErc1155BatchPaymentFromMainNet/deposit", + "receipt": joReceiptDeposit + } ); + } + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxyMainNet ) { + details.write( strLogPrefix + + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxyMainNet.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderMainNet, joMessageProxyMainNet, strEventName, + joReceiptDeposit.blockNumber, joReceiptDeposit.transactionHash, + joMessageProxyMainNet.filters[strEventName]() + ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + + cc.success( "Success, verified the " ) + cc.info( strEventName ) + + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + + cc.success( "/" ) + cc.notice( joMessageProxyMainNet.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" event " + + "of the \"MessageProxy\"/" + + joMessageProxyMainNet.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc1155BatchPaymentFromMainNet", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-1155 PAYMENT FROM MAIN NET", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc1155BatchPaymentFromMainNet", true ); + details.close(); + return true; +} + +export async function doErc20PaymentFromSChain( + ethersProviderMainNet, + ethersProviderSChain, + chainIdMainNet, + chainIdSChain, + joAccountSrc, + joAccountDst, + joTokenManagerERC20, // only s-chain + joMessageProxySChain, // for checking logs + joDepositBox, // only main net + tokenAmount, // how much ERC20 tokens to send + weiHowMuch, // how much ETH + strCoinNameErc20MainNet, + joErc20MainNet, + strCoinNameErc20SChain, + joErc20SChain, + transactionCustomizerSChain +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "S2M ERC20 Payment:" ) + " "; + try { + strActionName = "ERC20 payment from S-Chain, approve"; + const erc20ABI = joErc20SChain[strCoinNameErc20SChain + "_abi"]; + const erc20AddressSChain = joErc20SChain[strCoinNameErc20SChain + "_address"]; + const tokenManagerAddress = joTokenManagerERC20.address; + const contractERC20 = + new owaspUtils.ethersMod.ethers.Contract( + erc20AddressSChain, erc20ABI, ethersProviderSChain ); + const arrArgumentsApprove = [ + tokenManagerAddress, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenAmount ).toHexString() ) ]; + const erc20AddressMainNet = joErc20MainNet[strCoinNameErc20MainNet + "_address"]; + const arrArgumentsExitToMainERC20 = [ + erc20AddressMainNet, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenAmount ).toHexString() ) + // owaspUtils.ensureStartsWith0x( owaspUtils.toBN( weiHowMuch ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const opts = { isCheckTransactionToSchain: true }; + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSChain, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, estimatedGasApprove, weiHowMuchApprove, opts ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": "doErc20PaymentFromSChain/approve", + "receipt": joReceiptApprove + } ); + } + if( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() > 0 ) { + details.write( cc.normal( "Sleeping " ) + + cc.info( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ) + + cc.normal( " milliseconds between transactions..." ) + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ); + } + if( imaHelperAPIs.getWaitForNextBlockOnSChain() ) + await imaHelperAPIs.safeWaitForNextBlockToAppear( details, ethersProviderSChain ); + strActionName = "ERC20 payment from S-Chain, exitToMainERC20"; + const weiHowMuchExitToMainERC20 = undefined; + const estimatedGasExitToMainERC20 = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "TokenManagerERC20", joTokenManagerERC20, + "exitToMainERC20", arrArgumentsExitToMainERC20, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchExitToMainERC20, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasExitToMainERC20 ) + + "\n" ); + } + gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const isIgnoreExitToMainERC20 = true; + const strErrorOfDryRunExitToMainERC20 = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "TokenManagerERC20", joTokenManagerERC20, + "exitToMainERC20", arrArgumentsExitToMainERC20, + joAccountSrc, strActionName, isIgnoreExitToMainERC20, + gasPrice, estimatedGasExitToMainERC20, weiHowMuchExitToMainERC20, null ); + if( strErrorOfDryRunExitToMainERC20 ) + throw new Error( strErrorOfDryRunExitToMainERC20 ); + opts.isCheckTransactionToSchain = true; + const joReceiptExitToMainERC20 = + await imaTx.payedCall( + details, ethersProviderSChain, + "TokenManagerERC20", joTokenManagerERC20, + "exitToMainERC20", arrArgumentsExitToMainERC20, + joAccountSrc, strActionName, gasPrice, + estimatedGasExitToMainERC20, weiHowMuchExitToMainERC20, opts ); + if( joReceiptExitToMainERC20 && typeof joReceiptExitToMainERC20 == "object" ) { + jarrReceipts.push( { + "description": "doErc20PaymentFromSChain/exit-to-main", + "receipt": joReceiptExitToMainERC20 + } ); + } + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxySChain ) { + details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxySChain.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderSChain, joMessageProxySChain, strEventName, + joReceiptExitToMainERC20.blockNumber, joReceiptExitToMainERC20.transactionHash, + joMessageProxySChain.filters[strEventName]() ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + cc.success( "Success, verified the " ) + + cc.info( strEventName ) + cc.success( " event of the " ) + + cc.info( "MessageProxy" ) + cc.success( "/" ) + + cc.notice( joMessageProxySChain.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" event " + + "of the \"MessageProxy\"/" + + joMessageProxySChain.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc20PaymentFromSChain", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-20 PAYMENT FROM S-CHAIN", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc20PaymentFromSChain", true ); + details.close(); + return true; +} + +export async function doErc721PaymentFromSChain( + ethersProviderMainNet, + ethersProviderSChain, + chainIdMainNet, + chainIdSChain, + joAccountSrc, + joAccountDst, + joTokenManagerERC721, // only s-chain + joMessageProxySChain, // for checking logs + joDepositBox, // only main net + tokenId, // which ERC721 token id to send + weiHowMuch, // how much ETH + strCoinNameErc721MainNet, + joErc721MainNet, + strCoinNameErc721SChain, + joErc721SChain, + transactionCustomizerSChain +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "S2M ERC721 Payment:" ) + " "; + try { + strActionName = "ERC721 payment from S-Chain, approve"; + const erc721ABI = joErc721SChain[strCoinNameErc721SChain + "_abi"]; + const erc721AddressSChain = joErc721SChain[strCoinNameErc721SChain + "_address"]; + const tokenManagerAddress = joTokenManagerERC721.address; + const contractERC721 = + new owaspUtils.ethersMod.ethers.Contract( + erc721AddressSChain, erc721ABI, ethersProviderSChain ); + const arrArgumentsApprove = [ + tokenManagerAddress, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ) + ]; + const erc721AddressMainNet = + joErc721MainNet[strCoinNameErc721MainNet + "_address"]; + const arrArgumentsExitToMainERC721 = [ + erc721AddressMainNet, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(transfer from) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const opts = { isCheckTransactionToSchain: true }; + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSChain, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, + estimatedGasApprove, weiHowMuchApprove, opts ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": "doErc721PaymentFromSChain/transfer-from", + "receipt": joReceiptApprove + } ); + } + if( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() > 0 ) { + details.write( cc.normal( "Sleeping " ) + + cc.info( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ) + + cc.normal( " milliseconds between transactions..." ) + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ); + } + if( imaHelperAPIs.getWaitForNextBlockOnSChain() ) + await imaHelperAPIs.safeWaitForNextBlockToAppear( details, ethersProviderSChain ); + strActionName = "ERC721 payment from S-Chain, exitToMainERC721"; + const weiHowMuchExitToMainERC721 = undefined; + gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasExitToMainERC721 = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "TokenManagerERC721", joTokenManagerERC721, + "exitToMainERC721", arrArgumentsExitToMainERC721, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchExitToMainERC721, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(exit to main) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasExitToMainERC721 ) + + "\n" ); + } + const isIgnoreExitToMainERC721 = true; + const strErrorOfDryRunExitToMainERC721 = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "TokenManagerERC721", joTokenManagerERC721, + "exitToMainERC721", arrArgumentsExitToMainERC721, + joAccountSrc, strActionName, isIgnoreExitToMainERC721, gasPrice, + estimatedGasExitToMainERC721, weiHowMuchExitToMainERC721, null ); + if( strErrorOfDryRunExitToMainERC721 ) + throw new Error( strErrorOfDryRunExitToMainERC721 ); + opts.isCheckTransactionToSchain = true; + const joReceiptExitToMainERC721 = + await imaTx.payedCall( + details, ethersProviderSChain, + "TokenManagerERC721", joTokenManagerERC721, + "exitToMainERC721", arrArgumentsExitToMainERC721, + joAccountSrc, strActionName, gasPrice, + estimatedGasExitToMainERC721, weiHowMuchExitToMainERC721, opts ); + if( joReceiptExitToMainERC721 && typeof joReceiptExitToMainERC721 == "object" ) { + jarrReceipts.push( { + "description": "doErc721PaymentFromSChain/exit-to-main", + "receipt": joReceiptExitToMainERC721 + } ); + } + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxySChain ) { + details.write( strLogPrefix + cc.debug( "Verifying the " ) + + cc.info( strEventName ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + + cc.debug( "/" ) + cc.notice( joMessageProxySChain.address ) + + cc.debug( " contract ..." ) + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderSChain, joMessageProxySChain, strEventName, + joReceiptExitToMainERC721.blockNumber, + joReceiptExitToMainERC721.transactionHash, + joMessageProxySChain.filters[strEventName]() ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + cc.success( "Success, verified the " ) + + cc.info( strEventName ) + cc.success( " event of the " ) + + cc.info( "MessageProxy" ) + cc.success( "/" ) + + cc.notice( joMessageProxySChain.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" event " + + "of the \"MessageProxy\"/" + + joMessageProxySChain.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc721PaymentFromSChain", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-721 PAYMENT FROM S-CHAIN", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc721PaymentFromSChain", true ); + details.close(); + return true; +} + +export async function doErc1155PaymentFromSChain( + ethersProviderMainNet, + ethersProviderSChain, + chainIdMainNet, + chainIdSChain, + joAccountSrc, + joAccountDst, + joTokenManagerERC1155, // only s-chain + joMessageProxySChain, // for checking logs + joDepositBox, // only main net + tokenId, // which ERC1155 token id to send + tokenAmount, // which ERC1155 token id to send + weiHowMuch, // how much ETH + strCoinNameErc1155SMainNet, + joErc1155MainNet, + strCoinNameErc1155SChain, + joErc1155Chain, + transactionCustomizerSChain +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "S2M ERC1155 Payment:" ) + " "; + try { + strActionName = "ERC1155 payment from S-Chain, approve"; + const erc1155ABI = joErc1155Chain[strCoinNameErc1155SChain + "_abi"]; + const erc1155AddressSChain = joErc1155Chain[strCoinNameErc1155SChain + "_address"]; + const tokenManagerAddress = joTokenManagerERC1155.address; + const contractERC1155 = + new owaspUtils.ethersMod.ethers.Contract( + erc1155AddressSChain, erc1155ABI, ethersProviderSChain ); + const arrArgumentsApprove = [ + tokenManagerAddress, + true + ]; + const erc1155AddressMainNet = + joErc1155MainNet[strCoinNameErc1155SMainNet + "_address"]; + const arrArgumentsExitToMainERC1155 = [ + erc1155AddressMainNet, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ), + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenAmount ).toHexString() ) + // owaspUtils.ensureStartsWith0x( owaspUtils.toBN( weiHowMuch ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(transfer from) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const opts = { isCheckTransactionToSchain: true }; + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSChain, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, estimatedGasApprove, weiHowMuchApprove, + opts ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": "doErc1155PaymentFromSChain/transfer-from", + "receipt": joReceiptApprove + } ); + } + if( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() > 0 ) { + details.write( cc.normal( "Sleeping " ) + + cc.info( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ) + + cc.normal( " milliseconds between transactions..." ) + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ); + } + if( imaHelperAPIs.getWaitForNextBlockOnSChain() ) + await imaHelperAPIs.safeWaitForNextBlockToAppear( details, ethersProviderSChain ); + strActionName = "ERC1155 payment from S-Chain, exitToMainERC1155"; + const weiHowMuchExitToMainERC1155 = undefined; + gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasExitToMainERC1155 = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "TokenManagerERC1155", joTokenManagerERC1155, + "exitToMainERC1155", arrArgumentsExitToMainERC1155, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchExitToMainERC1155, + null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(exit to main) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasExitToMainERC1155 ) + + "\n" ); + } + const isIgnoreExitToMainERC1155 = true; + const strErrorOfDryRunExitToMainERC1155 = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "TokenManagerERC1155", joTokenManagerERC1155, + "exitToMainERC1155", arrArgumentsExitToMainERC1155, + joAccountSrc, strActionName, isIgnoreExitToMainERC1155, + gasPrice, estimatedGasExitToMainERC1155, weiHowMuchExitToMainERC1155, + null ); + if( strErrorOfDryRunExitToMainERC1155 ) + throw new Error( strErrorOfDryRunExitToMainERC1155 ); + opts.isCheckTransactionToSchain = true; + const joReceiptExitToMainERC1155 = + await imaTx.payedCall( + details, ethersProviderSChain, + "TokenManagerERC1155", joTokenManagerERC1155, + "exitToMainERC1155", arrArgumentsExitToMainERC1155, + joAccountSrc, strActionName, gasPrice, + estimatedGasExitToMainERC1155, weiHowMuchExitToMainERC1155, opts ); + if( joReceiptExitToMainERC1155 && typeof joReceiptExitToMainERC1155 == "object" ) { + jarrReceipts.push( { + "description": "doErc1155PaymentFromSChain/exit-to-main", + "receipt": joReceiptExitToMainERC1155 + } ); + } + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxySChain ) { + details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxySChain.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderSChain, joMessageProxySChain, strEventName, + joReceiptExitToMainERC1155.blockNumber, + joReceiptExitToMainERC1155.transactionHash, + joMessageProxySChain.filters[strEventName]() ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + cc.success( "Success, verified the " ) + + cc.info( strEventName ) + cc.success( " event of the " ) + + cc.info( "MessageProxy" ) + cc.success( "/" ) + + cc.notice( joMessageProxySChain.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" event " + + "of the \"MessageProxy\"/" + + joMessageProxySChain.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc1155PaymentFromSChain", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-1155 PAYMENT FROM S-CHAIN", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc1155PaymentFromSChain", true ); + details.close(); + return true; +} + +export async function doErc1155BatchPaymentFromSChain( + ethersProviderMainNet, + ethersProviderSChain, + chainIdMainNet, + chainIdSChain, + joAccountSrc, + joAccountDst, + joTokenManagerERC1155, // only s-chain + joMessageProxySChain, // for checking logs + joDepositBox, // only main net + arrTokenIds, // which ERC1155 token ids to send + arrTokenAmounts, // which ERC1155 token amounts to send + weiHowMuch, // how much ETH + strCoinNameErc1155SMainNet, + joErc1155MainNet, + strCoinNameErc1155SChain, + joErc1155Chain, + transactionCustomizerSChain +) { + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = cc.info( "S2M ERC1155 Batch Payment:" ) + " "; + try { + strActionName = "ERC1155 payment from S-Chain, approve"; + const erc1155ABI = joErc1155Chain[strCoinNameErc1155SChain + "_abi"]; + const erc1155AddressSChain = joErc1155Chain[strCoinNameErc1155SChain + "_address"]; + const tokenManagerAddress = joTokenManagerERC1155.address; + const contractERC1155 = + new owaspUtils.ethersMod.ethers.Contract( + erc1155AddressSChain, erc1155ABI, ethersProviderSChain ); + const arrArgumentsApprove = [ + tokenManagerAddress, + true + ]; + const erc1155AddressMainNet = + joErc1155MainNet[strCoinNameErc1155SMainNet + "_address"]; + const arrArgumentsExitToMainERC1155Batch = [ + erc1155AddressMainNet, + arrTokenIds, + arrTokenAmounts + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(transfer from) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const opts = { isCheckTransactionToSchain: true }; + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSChain, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, estimatedGasApprove, weiHowMuchApprove, + opts ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": + "doErc1155BatchPaymentFromSChain/transfer-from", + "receipt": joReceiptApprove + } ); + } + if( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() > 0 ) { + details.write( cc.normal( "Sleeping " ) + + cc.info( imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ) + + cc.normal( " milliseconds between transactions..." ) + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getSleepBetweenTransactionsOnSChainMilliseconds() ); + } + if( imaHelperAPIs.getWaitForNextBlockOnSChain() ) + await imaHelperAPIs.safeWaitForNextBlockToAppear( details, ethersProviderSChain ); + strActionName = "ERC1155 batch-payment from S-Chain, exitToMainERC1155Batch"; + const weiHowMuchExitToMainERC1155Batch = undefined; + gasPrice = await transactionCustomizerSChain.computeGasPrice( + ethersProviderSChain, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasExitToMainERC1155Batch = + await transactionCustomizerSChain.computeGas( + details, ethersProviderSChain, + "TokenManagerERC1155", joTokenManagerERC1155, + "exitToMainERC1155Batch", arrArgumentsExitToMainERC1155Batch, + joAccountSrc, strActionName, gasPrice, 8000000, + weiHowMuchExitToMainERC1155Batch, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(exit to main) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + + cc.notice( estimatedGasExitToMainERC1155Batch ) + "\n" ); + } + const isIgnoreExitToMainERC1155Batch = true; + const strErrorOfDryRunExitToMainERC1155Batch = + await imaTx.dryRunCall( + details, ethersProviderSChain, + "TokenManagerERC1155", joTokenManagerERC1155, + "exitToMainERC1155Batch", arrArgumentsExitToMainERC1155Batch, + joAccountSrc, strActionName, isIgnoreExitToMainERC1155Batch, gasPrice, + estimatedGasExitToMainERC1155Batch, weiHowMuchExitToMainERC1155Batch, null ); + if( strErrorOfDryRunExitToMainERC1155Batch ) + throw new Error( strErrorOfDryRunExitToMainERC1155Batch ); + opts.isCheckTransactionToSchain = true; + const joReceiptExitToMainERC1155Batch = + await imaTx.payedCall( + details, ethersProviderSChain, + "TokenManagerERC1155", joTokenManagerERC1155, + "exitToMainERC1155Batch", arrArgumentsExitToMainERC1155Batch, + joAccountSrc, strActionName, gasPrice, + estimatedGasExitToMainERC1155Batch, weiHowMuchExitToMainERC1155Batch, opts ); + if( joReceiptExitToMainERC1155Batch && + typeof joReceiptExitToMainERC1155Batch == "object" + ) { + jarrReceipts.push( { + "description": "doErc1155BatchPaymentFromSChain/exit-to-main", + "receipt": joReceiptExitToMainERC1155Batch + } ); + } + // Must-have event(s) analysis as indicator(s) of success + const strEventName = "OutgoingMessage"; + if( joMessageProxySChain ) { + details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + + cc.notice( joMessageProxySChain.address ) + cc.debug( " contract ..." ) + + "\n" ); + await imaHelperAPIs.sleep( + imaHelperAPIs.getMillisecondsSleepBeforeFetchOutgoingMessageEvent() ); + const joEvents = await imaEventLogScan.getContractCallEvents( + details, strLogPrefix, + ethersProviderSChain, joMessageProxySChain, strEventName, + joReceiptExitToMainERC1155Batch.blockNumber, + joReceiptExitToMainERC1155Batch.transactionHash, + joMessageProxySChain.filters[strEventName]() ); + if( joEvents.length > 0 ) { + details.write( strLogPrefix + cc.success( "Success, verified the " ) + + cc.info( strEventName ) + cc.success( " event of the " ) + + cc.info( "MessageProxy" ) + cc.success( "/" ) + + cc.notice( joMessageProxySChain.address ) + + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); + } else { + throw new Error( + "Verification failed for the \"OutgoingMessage\" event " + + "of the \"MessageProxy\"/" + + joMessageProxySChain.address + " contract, no events found" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( log, "doErc1155BatchPaymentFromSChain", false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "ERC-1155 PAYMENT FROM S-CHAIN", jarrReceipts, details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "doErc1155BatchPaymentFromSChain", true ); + details.close(); + return true; +} + +export async function doErc20PaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC20Src, + nAmountOfToken, // how much ERC20 tokens to send + nAmountOfWei, // how much to send + strCoinNameErc20Src, + joSrcErc20, + ercDstAddress20, // only reverse payment needs it + tc +) { + const isReverse = isForward ? false : true; + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = + cc.info( "S2S ERC20 Payment(" + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; + try { + strActionName = + "validateArgs/doErc20PaymentS2S/" + ( isForward ? "forward" : "reverse" ); + if( ! ethersProviderSrc ) + throw new Error( "No ethers provider specified for source of transfer" ); + if( ! strChainNameDst ) + throw new Error( "No destination chain name provided" ); + if( ! joAccountSrc ) + throw new Error( "No account or sign TX way provided" ); + if( ! strCoinNameErc20Src ) + throw new Error( "Need full source ERC20 information, like ABI" ); + if( ! joSrcErc20 ) + throw new Error( "No source ERC20 ABI provided" ); + if( isReverse ) { + if( ! ercDstAddress20 ) + throw new Error( "No destination ERC20 address provided" ); + } + if( ! tc ) + throw new Error( "No transaction customizer provided" ); + const ercSrcAbi20 = joSrcErc20[strCoinNameErc20Src + "_abi"]; + const ercSrcAddress20 = joSrcErc20[strCoinNameErc20Src + "_address"]; + details.write( strLogPrefix + cc.attention( "Token Manager ERC20" ) + + cc.debug( " address on source chain...." ) + + cc.note( joTokenManagerERC20Src.address ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC20" ) + + cc.debug( " coin name........................." ) + + cc.note( strCoinNameErc20Src ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC20" ) + + cc.debug( " token address....................." ) + + cc.note( ercSrcAddress20 ) + "\n" ); + if( isReverse || ercDstAddress20 ) { + details.write( strLogPrefix + cc.attention( "Destination ERC20" ) + + cc.debug( " token address................" ) + + cc.note( ercDstAddress20 ) + "\n" ); + } + details.write( strLogPrefix + cc.attention( "Destination chain name" ) + + cc.debug( "........................." ) + + cc.note( strChainNameDst ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Amount of tokens" ) + + cc.debug( " to transfer..................." ) + + cc.note( nAmountOfToken ) + "\n" ); + strActionName = "ERC20 payment S2S, approve, " + ( isForward ? "forward" : "reverse" ); + const contractERC20 = + new owaspUtils.ethersMod.ethers.Contract( + ercSrcAddress20, ercSrcAbi20, ethersProviderSrc ); + const arrArgumentsApprove = [ + joTokenManagerERC20Src.address, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nAmountOfToken ).toHexString() ) + ]; + const arrArgumentsTransfer = [ + strChainNameDst, + isReverse ? ercDstAddress20 : ercSrcAddress20, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nAmountOfToken ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await tc.computeGas( + details, ethersProviderSrc, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSrc, + "ERC20", contractERC20, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, + estimatedGasApprove, weiHowMuchApprove, null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": + "doErc20PaymentS2S/approve/" + ( isForward ? "forward" : "reverse" ), + "receipt": joReceiptApprove + } ); + } + strActionName = + "ERC20 payment S2S, transferERC20 " + ( isForward ? "forward" : "reverse" ); + const weiHowMuchTransferERC20 = undefined; + gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasTransfer = + await tc.computeGas( + details, ethersProviderSrc, + "TokenManagerERC20", joTokenManagerERC20Src, + "transferToSchainERC20", arrArgumentsTransfer, + joAccountSrc, strActionName, gasPrice, + 8000000, weiHowMuchTransferERC20, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasTransfer ) + "\n" ); + } + const isIgnoreTransferERC20 = true; + const strErrorOfDryRunTransferERC20 = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "TokenManagerERC20", joTokenManagerERC20Src, + "transferToSchainERC20", arrArgumentsTransfer, + joAccountSrc, strActionName, isIgnoreTransferERC20, + gasPrice, estimatedGasTransfer, weiHowMuchTransferERC20, null ); + if( strErrorOfDryRunTransferERC20 ) + throw new Error( strErrorOfDryRunTransferERC20 ); + const joReceiptTransfer = + await imaTx.payedCall( + details, ethersProviderSrc, + "TokenManagerERC20", joTokenManagerERC20Src, + "transferToSchainERC20", arrArgumentsTransfer, + joAccountSrc, strActionName, gasPrice, + estimatedGasTransfer, weiHowMuchTransferERC20, null ); + if( joReceiptTransfer && typeof joReceiptTransfer == "object" ) { + jarrReceipts.push( { + "description": "doErc20PaymentS2S/transfer", + "receipt": joReceiptTransfer + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( + log, "doErc20PaymentS2S/" + ( isForward ? "forward" : "reverse" ), false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "ERC-20 PAYMENT FROM S2S/" + + ( isForward ? "forward" : "reverse" ), jarrReceipts, details ); + if( log.exposeDetailsGet() ) { + details.exposeDetailsTo( + log, "doErc20PaymentS2S/" + ( isForward ? "forward" : "reverse" ), true ); + } + details.close(); + return true; +} + +export async function doErc721PaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC721Src, + tokenId, // which ERC721 token id to send + nAmountOfWei, // how much to send + strCoinNameErc721Src, + joSrcErc721, + ercDstAddress721, // only reverse payment needs it + tc +) { + const isReverse = isForward ? false : true; + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = + cc.info( "S2S ERC721 Payment(" + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; + try { + strActionName = + "validateArgs/doErc721PaymentS2S/" + ( isForward ? "forward" : "reverse" ); + if( ! ethersProviderSrc ) + throw new Error( "No provider for source of transfer" ); + if( ! strChainNameDst ) + throw new Error( "No destination chain name provided" ); + if( ! joAccountSrc ) + throw new Error( "No account or sign TX way provided" ); + if( ! strCoinNameErc721Src ) + throw new Error( "Need full source ERC721 information, like ABI" ); + if( ! joSrcErc721 ) + throw new Error( "No source ERC721 ABI provided" ); + if( isReverse ) { + if( ! ercDstAddress721 ) + throw new Error( "No destination ERC721 address provided" ); + } + if( ! tc ) + throw new Error( "No transaction customizer provided" ); + const ercSrcAbi721 = joSrcErc721[strCoinNameErc721Src + "_abi"]; + const ercSrcAddress721 = joSrcErc721[strCoinNameErc721Src + "_address"]; + details.write( strLogPrefix + cc.attention( "Token Manager ERC721" ) + + cc.debug( " address on source chain...." ) + + cc.note( joTokenManagerERC721Src.address ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC721" ) + + cc.debug( " coin name........................." ) + + cc.note( strCoinNameErc721Src ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC721" ) + + cc.debug( " token address....................." ) + + cc.note( ercSrcAddress721 ) + "\n" ); + if( isReverse || ercDstAddress721 ) { + details.write( strLogPrefix + cc.attention( "Destination ERC721" ) + + cc.debug( " token address................" ) + + cc.note( ercDstAddress721 ) + "\n" ); + } + details.write( strLogPrefix + cc.attention( "Destination chain name" ) + + cc.debug( "........................." ) + cc.note( strChainNameDst ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Token ID" ) + + cc.debug( " to transfer..........................." ) + cc.note( tokenId ) + "\n" ); + strActionName = "ERC721 payment S2S, approve, " + ( isForward ? "forward" : "reverse" ); + const contractERC721 = + new owaspUtils.ethersMod.ethers.Contract( + ercSrcAddress721, ercSrcAbi721, ethersProviderSrc ); + const arrArgumentsApprove = [ + joTokenManagerERC721Src.address, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ) + ]; + const arrArgumentsTransfer = [ + strChainNameDst, + isReverse ? ercDstAddress721 : ercSrcAddress721, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await tc.computeGas( + details, ethersProviderSrc, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSrc, + "ERC721", contractERC721, "approve", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": + "doErc721PaymentS2S/approve/" + ( isForward ? "forward" : "reverse" ), + "receipt": joReceiptApprove + } ); + } + const isIgnoreTransferERC721 = true; + strActionName = + "ERC721 payment S2S, transferERC721 " + ( isForward ? "forward" : "reverse" ); + const weiHowMuchTransferERC721 = undefined; + gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasTransfer = + await tc.computeGas( + details, ethersProviderSrc, + "TokenManagerERC721", joTokenManagerERC721Src, + "transferToSchainERC721", arrArgumentsTransfer, + joAccountSrc, strActionName, isIgnoreTransferERC721, + gasPrice, 8000000, weiHowMuchTransferERC721, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasTransfer ) + "\n" ); + } + const strErrorOfDryRunTransferERC721 = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "TokenManagerERC721", joTokenManagerERC721Src, + "transferToSchainERC721", arrArgumentsTransfer, + joAccountSrc, strActionName, isIgnoreTransferERC721, + gasPrice, estimatedGasTransfer, weiHowMuchTransferERC721, null ); + if( strErrorOfDryRunTransferERC721 ) + throw new Error( strErrorOfDryRunTransferERC721 ); + const joReceiptTransfer = + await imaTx.payedCall( + details, ethersProviderSrc, + "TokenManagerERC721", joTokenManagerERC721Src, + "transferToSchainERC721", arrArgumentsTransfer, + joAccountSrc, strActionName, + gasPrice, estimatedGasTransfer, weiHowMuchTransferERC721, null ); + if( joReceiptTransfer && typeof joReceiptTransfer == "object" ) { + jarrReceipts.push( { + "description": "doErc721PaymentS2S/transfer", + "receipt": joReceiptTransfer + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( + log, + "doErc721PaymentS2S/" + ( isForward ? "forward" : "reverse" ), false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "ERC-721 PAYMENT FROM S2S/" + + ( isForward ? "forward" : "reverse" ), jarrReceipts, details ); + if( log.exposeDetailsGet() ) { + details.exposeDetailsTo( + log, + "doErc721PaymentS2S/" + ( isForward ? "forward" : "reverse" ), + true ); + } + details.close(); + return true; +} + +export async function doErc1155PaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC1155Src, + tokenId, // which ERC721 token id to send + nAmountOfToken, // how much ERC1155 tokens to send + nAmountOfWei, // how much to send + strCoinNameErc1155Src, + joSrcErc1155, + ercDstAddress1155, // only reverse payment needs it + tc +) { + const isReverse = isForward ? false : true; + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = + cc.info( "S2S ERC1155 Payment(" + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; + try { + strActionName = + "validateArgs/doErc1155PaymentS2S/" + ( isForward ? "forward" : "reverse" ); + if( ! ethersProviderSrc ) + throw new Error( "No provider for source of transfer" ); + if( ! strChainNameDst ) + throw new Error( "No destination chain name provided" ); + if( ! joAccountSrc ) + throw new Error( "No account or sign TX way provided" ); + if( ! strCoinNameErc1155Src ) + throw new Error( "Need full source ERC1155 information, like ABI" ); + if( ! joSrcErc1155 ) + throw new Error( "No source ERC1155 ABI provided" ); + if( isReverse ) { + if( ! ercDstAddress1155 ) + throw new Error( "No destination ERC1155 address provided" ); + } + if( ! tc ) + throw new Error( "No transaction customizer provided" ); + const ercSrcAbi1155 = joSrcErc1155[strCoinNameErc1155Src + "_abi"]; + const ercSrcAddress1155 = joSrcErc1155[strCoinNameErc1155Src + "_address"]; + details.write( strLogPrefix + cc.attention( "Token Manager ERC1155" ) + + cc.debug( " address on source chain...." ) + + cc.note( joTokenManagerERC1155Src.address ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + + cc.debug( " coin name........................." ) + + cc.note( strCoinNameErc1155Src ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + + cc.debug( " token address....................." ) + + cc.note( ercSrcAddress1155 ) + "\n" ); + if( isReverse || ercDstAddress1155 ) { + details.write( strLogPrefix + cc.attention( "Destination ERC1155" ) + + cc.debug( " token address................" ) + + cc.note( ercDstAddress1155 ) + "\n" ); + } + details.write( strLogPrefix + cc.attention( "Destination chain name" ) + + cc.debug( "........................." ) + cc.note( strChainNameDst ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Token ID" ) + + cc.debug( " to transfer..........................." ) + cc.note( tokenId ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Amount of tokens" ) + + cc.debug( " to transfer..................." ) + cc.note( nAmountOfToken ) + "\n" ); + strActionName = "ERC1155 payment S2S, approve, " + ( isForward ? "forward" : "reverse" ); + const contractERC1155 = + new owaspUtils.ethersMod.ethers.Contract( + ercSrcAddress1155, ercSrcAbi1155, ethersProviderSrc ); + const arrArgumentsApprove = [ + joTokenManagerERC1155Src.address, + true + ]; + const arrArgumentsTransfer = [ + strChainNameDst, + isReverse ? ercDstAddress1155 : ercSrcAddress1155, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( tokenId ).toHexString() ), + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nAmountOfToken ).toHexString() ) + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await tc.computeGas( + details, ethersProviderSrc, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSrc, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, + estimatedGasApprove, weiHowMuchApprove, null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": + "doErc1155PaymentS2S/approve/" + ( isForward ? "forward" : "reverse" ), + "receipt": joReceiptApprove + } ); + } + strActionName = + "ERC1155 payment S2S, transferERC1155 " + ( isForward ? "forward" : "reverse" ); + const weiHowMuchTransferERC1155 = undefined; + gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasTransfer = + await tc.computeGas( + details, ethersProviderSrc, + "TokenManagerERC1155", joTokenManagerERC1155Src, + "transferToSchainERC1155", arrArgumentsTransfer, + joAccountSrc, strActionName, gasPrice, + 8000000, weiHowMuchTransferERC1155, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasTransfer ) + "\n" ); + } + const isIgnoreTransferERC1155 = true; + const strErrorOfDryRunTransferERC1155 = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "TokenManagerERC1155", joTokenManagerERC1155Src, + "transferToSchainERC1155", arrArgumentsTransfer, + joAccountSrc, strActionName, isIgnoreTransferERC1155, gasPrice, + estimatedGasTransfer, weiHowMuchTransferERC1155, null ); + if( strErrorOfDryRunTransferERC1155 ) + throw new Error( strErrorOfDryRunTransferERC1155 ); + const joReceiptTransfer = + await imaTx.payedCall( + details, ethersProviderSrc, + "TokenManagerERC1155", joTokenManagerERC1155Src, + "transferToSchainERC1155", arrArgumentsTransfer, + joAccountSrc, strActionName, gasPrice, estimatedGasTransfer, + weiHowMuchTransferERC1155, null ); + if( joReceiptTransfer && typeof joReceiptTransfer == "object" ) { + jarrReceipts.push( { + "description": "doErc1155PaymentS2S/transfer", + "receipt": joReceiptTransfer + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( + log, "doErc1155PaymentS2S/" + ( isForward ? "forward" : "reverse" ), false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "ERC-1155 PAYMENT FROM S2S/" + + ( isForward ? "forward" : "reverse" ), jarrReceipts, details ); + if( log.exposeDetailsGet() ) { + details.exposeDetailsTo( + log, "doErc1155PaymentS2S/" + ( isForward ? "forward" : "reverse" ), true ); + } + details.close(); + return true; +} + +export async function doErc1155BatchPaymentS2S( + isForward, + ethersProviderSrc, + chainIdSrc, + strChainNameDst, + joAccountSrc, + joTokenManagerERC1155Src, + arrTokenIds, // which ERC1155 token id to send + arrTokenAmounts, // which ERC1155 token id to send + nAmountOfWei, // how much to send + strCoinNameErc1155Src, + joSrcErc1155, + ercDstAddress1155, // only reverse payment needs it + tc +) { + const isReverse = isForward ? false : true; + const details = log.createMemoryStream(); + const jarrReceipts = []; + let strActionName = ""; + const strLogPrefix = + cc.info( "S2S Batch ERC1155 Payment(" + + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; + try { + strActionName = + "validateArgs/doErc1155BatchPaymentS2S/" + + ( isForward ? "forward" : "reverse" ); + if( ! ethersProviderSrc ) + throw new Error( "No provider for source of transfer" ); + if( ! strChainNameDst ) + throw new Error( "No destination chain name provided" ); + if( ! joAccountSrc ) + throw new Error( "No account or sign TX way provided" ); + if( ! strCoinNameErc1155Src ) + throw new Error( "Need full source ERC1155 information, like ABI" ); + if( ! joSrcErc1155 ) + throw new Error( "No source ERC1155 ABI provided" ); + if( isReverse ) { + if( ! ercDstAddress1155 ) + throw new Error( "No destination ERC1155 address provided" ); + } + if( ! tc ) + throw new Error( "No transaction customizer provided" ); + const ercSrcAbi1155 = joSrcErc1155[strCoinNameErc1155Src + "_abi"]; + const ercSrcAddress1155 = joSrcErc1155[strCoinNameErc1155Src + "_address"]; + details.write( strLogPrefix + cc.attention( "Token Manager ERC1155" ) + + cc.debug( " address on source chain...." ) + + cc.note( joTokenManagerERC1155Src.address ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + + cc.debug( " coin name........................." ) + + cc.note( strCoinNameErc1155Src ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + + cc.debug( " token address....................." ) + + cc.note( ercSrcAddress1155 ) + "\n" ); + if( isReverse || ercDstAddress1155 ) { + details.write( strLogPrefix + cc.attention( "Destination ERC1155" ) + + cc.debug( " token address................" ) + + cc.note( ercDstAddress1155 ) + "\n" ); + } + details.write( strLogPrefix + cc.attention( "Destination chain name" ) + + cc.debug( "........................." ) + cc.note( strChainNameDst ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Token IDs" ) + + cc.debug( " to transfer.........................." ) + cc.j( arrTokenIds ) + "\n" ); + details.write( strLogPrefix + cc.attention( "Amounts of tokens" ) + + cc.debug( " to transfer.................." ) + cc.j( arrTokenAmounts ) + "\n" ); + strActionName = + "ERC1155 batch-payment S2S, approve, " + ( isForward ? "forward" : "reverse" ); + const contractERC1155 = + new owaspUtils.ethersMod.ethers.Contract( + ercSrcAddress1155, ercSrcAbi1155, ethersProviderSrc ); + const arrArgumentsApprove = [ + joTokenManagerERC1155Src.address, + true + ]; + const arrArgumentsTransfer = [ + strChainNameDst, + isReverse ? ercDstAddress1155 : ercSrcAddress1155, + arrTokenIds, + arrTokenAmounts + ]; + const weiHowMuchApprove = undefined; + let gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasApprove = + await tc.computeGas( + details, ethersProviderSrc, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, gasPrice, 8000000, weiHowMuchApprove, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasApprove ) + "\n" ); + } + const isIgnoreApprove = false; + const strErrorOfDryRunApprove = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, isIgnoreApprove, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( strErrorOfDryRunApprove ) + throw new Error( strErrorOfDryRunApprove ); + const joReceiptApprove = + await imaTx.payedCall( + details, ethersProviderSrc, + "ERC1155", contractERC1155, "setApprovalForAll", arrArgumentsApprove, + joAccountSrc, strActionName, + gasPrice, estimatedGasApprove, weiHowMuchApprove, null ); + if( joReceiptApprove && typeof joReceiptApprove == "object" ) { + jarrReceipts.push( { + "description": + "doErc1155BatchPaymentS2S/approve/" + + ( isForward ? "forward" : "reverse" ), + "receipt": joReceiptApprove + } ); + } + strActionName = + "ERC1155 batch-payment S2S, transferERC1155 " + ( isForward ? "forward" : "reverse" ); + const weiHowMuchTransferERC1155 = undefined; + gasPrice = await tc.computeGasPrice( ethersProviderSrc, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasTransfer = + await tc.computeGas( + details, ethersProviderSrc, + "TokenManagerERC1155", joTokenManagerERC1155Src, + "transferToSchainERC1155Batch", arrArgumentsTransfer, + joAccountSrc, strActionName, + gasPrice, 8000000, weiHowMuchTransferERC1155, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGasTransfer ) + "\n" ); + } + const isIgnoreTransferERC1155 = true; + const strErrorOfDryRunTransferERC1155 = + await imaTx.dryRunCall( + details, ethersProviderSrc, + "TokenManagerERC1155", joTokenManagerERC1155Src, + "transferToSchainERC1155Batch", arrArgumentsTransfer, + joAccountSrc, strActionName, isIgnoreTransferERC1155, + gasPrice, estimatedGasTransfer, weiHowMuchTransferERC1155, null ); + if( strErrorOfDryRunTransferERC1155 ) + throw new Error( strErrorOfDryRunTransferERC1155 ); + const joReceiptTransfer = + await imaTx.payedCall( + details, ethersProviderSrc, + "TokenManagerERC1155", joTokenManagerERC1155Src, + "transferToSchainERC1155Batch", arrArgumentsTransfer, + joAccountSrc, strActionName, + gasPrice, estimatedGasTransfer, weiHowMuchTransferERC1155, null ); + if( joReceiptTransfer && typeof joReceiptTransfer == "object" ) { + jarrReceipts.push( { + "description": "doErc1155PaymentS2S/transfer", + "receipt": joReceiptTransfer + } ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.id != details.id ) + log.write( s ); + details.write( s ); + } + details.exposeDetailsTo( + log, "doErc1155BatchPaymentS2S/" + ( isForward ? "forward" : "reverse" ), false ); + details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( "ERC-1155-batch PAYMENT FROM S2S/" + + ( isForward ? "forward" : "reverse" ), jarrReceipts, details ); + if( log.exposeDetailsGet() ) { + details.exposeDetailsTo( + log, "doErc1155BatchPaymentS2S/" + ( isForward ? "forward" : "reverse" ), true ); + } + details.close(); + return true; +} + +export async function mintErc20( + ethersProvider, + chainId, + chainName, + joAccount, + strAddressMintTo, + nAmount, + strTokenContractAddress, + joTokenContractABI, + tc +) { + let strActionName = "mintErc20() init"; + const strLogPrefix = cc.info( "mintErc20() call" ) + " "; + const details = log.createMemoryStream(); + try { + details.write( strLogPrefix + + cc.debug( "Mint " ) + cc.info( "ERC20" ) + cc.debug( " token amount " ) + + cc.notice( nAmount ) + "\n" ); + if( ! ( ethersProvider && joAccount && strAddressMintTo && + typeof strAddressMintTo == "string" && strAddressMintTo.length > 0 && + strTokenContractAddress && typeof strTokenContractAddress == "string" && + strTokenContractAddress.length > 0 && joTokenContractABI + ) ) + throw new Error( "Missing valid arguments" ); + strActionName = "mintErc20() instantiate token contract"; + const contract = new owaspUtils.ethersMod.ethers.Contract( + strTokenContractAddress, + joTokenContractABI, + ethersProvider + ); + const arrArgumentsMint = [ + strAddressMintTo, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nAmount ).toHexString() ) + ]; + const weiHowMuchMint = undefined; + const gasPrice = await tc.computeGasPrice( ethersProvider, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasMint = + await tc.computeGas( + details, ethersProvider, + "ERC20", contract, "mint", arrArgumentsMint, + joAccount, strActionName, + gasPrice, 10000000, weiHowMuchMint, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGasMint ) + "\n" ); + } + strActionName = "Mint ERC20"; + const isIgnoreMint = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProvider, + "ERC20", contract, "mint", arrArgumentsMint, + joAccount, strActionName, isIgnoreMint, + gasPrice, estimatedGasMint, weiHowMuchMint, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + isCheckTransactionToSchain: ( chainNameDst !== "Mainnet" ) ? true : false + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProvider, + "ERC20", contract, "mint", arrArgumentsMint, + joAccount, strActionName, + gasPrice, estimatedGasMint, weiHowMuchMint, opts ); + imaGasUsage.printGasUsageReportFromArray( "MINT ERC20 ", [ { + "description": "mintErc20()/mint", + "receipt": joReceipt + } ], details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "mintErc20", true ); + details.close(); + return joReceipt; // can be used as "true" boolean value + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.id != details.id ) { + log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in mintErc20() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in mintErc20() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.exposeDetailsTo( log, "mintErc20()", false ); + details.close(); + return false; + } +} + +export async function mintErc721( + ethersProvider, + chainId, + chainName, + joAccount, + strAddressMintTo, + idToken, + strTokenContractAddress, + joTokenContractABI, + tc +) { + let strActionName = "mintErc721() init"; + const strLogPrefix = cc.info( "mintErc721() call" ) + " "; + const details = log.createMemoryStream(); + try { + details.write( strLogPrefix + cc.debug( "Mint " ) + cc.info( "ERC721" ) + + cc.debug( " token ID " ) + cc.notice( idToken ) + "\n" ); + if( ! ( ethersProvider && joAccount && strAddressMintTo && + typeof strAddressMintTo == "string" && strAddressMintTo.length > 0 && + strTokenContractAddress && typeof strTokenContractAddress == "string" && + strTokenContractAddress.length > 0 && joTokenContractABI + ) ) + throw new Error( "Missing valid arguments" ); + strActionName = "mintErc721() instantiate token contract"; + const contract = + new owaspUtils.ethersMod.ethers.Contract( + strTokenContractAddress, + joTokenContractABI, + ethersProvider + ); + const arrArgumentsMint = [ + strAddressMintTo, + owaspUtils.ensureStartsWith0x( + owaspUtils.toBN( idToken ).toHexString() ) + ]; + const weiHowMuchMint = undefined; + const gasPrice = await tc.computeGasPrice( ethersProvider, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasMint = + await tc.computeGas( + details, ethersProvider, + "ERC721", contract, "mint", arrArgumentsMint, + joAccount, strActionName, + gasPrice, 10000000, weiHowMuchMint, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGasMint ) + "\n" ); + } + strActionName = "Mint ERC721"; + const isIgnoreMint = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProvider, + "ERC721", contract, "mint", arrArgumentsMint, + joAccount, strActionName, isIgnoreMint, + gasPrice, estimatedGasMint, weiHowMuchMint, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + isCheckTransactionToSchain: ( chainNameDst !== "Mainnet" ) ? true : false + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProvider, + "ERC721", contract, "mint", arrArgumentsMint, + joAccount, strActionName, + gasPrice, estimatedGasMint, weiHowMuchMint, opts ); + imaGasUsage.printGasUsageReportFromArray( "MINT ERC721 ", [ { + "description": "mintErc721()/mint", + "receipt": joReceipt + } ], details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "mintErc721", true ); + details.close(); + return joReceipt; // can be used as "true" boolean value + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.id != details.id ) { + log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in mintErc721() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in mintErc721() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.exposeDetailsTo( log, "mintErc721()", false ); + details.close(); + return false; + } +} + +export async function mintErc1155( + ethersProvider, + chainId, + chainName, + joAccount, + strAddressMintTo, + idToken, + nAmount, + strTokenContractAddress, + joTokenContractABI, + tc +) { + let strActionName = "mintErc1155() init"; + const strLogPrefix = cc.info( "mintErc1155() call" ) + " "; + const details = log.createMemoryStream(); + try { + details.write( strLogPrefix + + cc.debug( "Mint " ) + cc.info( "ERC1155" ) + cc.debug( " token ID " ) + + cc.notice( idToken ) + cc.debug( " token amount " ) + cc.notice( nAmount ) + + "\n" ); + if( ! ( ethersProvider && joAccount && strAddressMintTo && + typeof strAddressMintTo == "string" && strAddressMintTo.length > 0 && + strTokenContractAddress && typeof strTokenContractAddress == "string" && + strTokenContractAddress.length > 0 && joTokenContractABI + ) ) + throw new Error( "Missing valid arguments" ); + strActionName = "mintErc1155() instantiate token contract"; + const contract = + new owaspUtils.ethersMod.ethers.Contract( + strTokenContractAddress, + joTokenContractABI, + ethersProvider + ); + const arrArgumentsMint = [ + strAddressMintTo, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( idToken ).toHexString() ), + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nAmount ).toHexString() ), + [] // data + ]; + const weiHowMuchMint = undefined; + const gasPrice = await tc.computeGasPrice( ethersProvider, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasMint = + await tc.computeGas( + details, ethersProvider, + "ERC1155", contract, "mint", arrArgumentsMint, + joAccount, strActionName, + gasPrice, 10000000, weiHowMuchMint, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGasMint ) + "\n" ); + } + strActionName = "Mint ERC1155"; + const isIgnoreMint = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProvider, + "ERC1155", contract, "mint", arrArgumentsMint, + joAccount, strActionName, isIgnoreMint, + gasPrice, estimatedGasMint, weiHowMuchMint, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + isCheckTransactionToSchain: ( chainNameDst !== "Mainnet" ) ? true : false + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProvider, + "ERC1155", contract, "mint", arrArgumentsMint, + joAccount, strActionName, + gasPrice, estimatedGasMint, weiHowMuchMint, opts ); + imaGasUsage.printGasUsageReportFromArray( "MINT ERC1155 ", [ { + "description": "mintErc1155()/mint", + "receipt": joReceipt + } ], details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "mintErc1155", true ); + details.close(); + return joReceipt; // can be used as "true" boolean value + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.id != details.id ) { + log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in mintErc1155() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in mintErc1155() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.exposeDetailsTo( log, "mintErc1155()", false ); + details.close(); + return false; + } +} + +export async function burnErc20( + ethersProvider, + chainId, + chainName, + joAccount, + strAddressBurnFrom, + nAmount, + strTokenContractAddress, + joTokenContractABI, + tc +) { + let strActionName = "burnErc20() init"; + const strLogPrefix = cc.info( "burnErc20() call" ) + " "; + const details = log.createMemoryStream(); + try { + details.write( strLogPrefix + cc.debug( "Burn " ) + cc.info( "ERC20" ) + + cc.debug( " token amount " ) + cc.notice( nAmount ) + "\n" ); + if( ! ( ethersProvider && joAccount && strAddressBurnFrom && + typeof strAddressBurnFrom == "string" && strAddressBurnFrom.length > 0 && + strTokenContractAddress && typeof strTokenContractAddress == "string" && + strTokenContractAddress.length > 0 && joTokenContractABI + ) ) + throw new Error( "Missing valid arguments" ); + strActionName = "burnErc20() instantiate token contract"; + const contract = + new owaspUtils.ethersMod.ethers.Contract( + strTokenContractAddress, + joTokenContractABI, + ethersProvider + ); + const arrArgumentsBurn = [ + strAddressBurnFrom, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nAmount ).toHexString() ) + ]; + const weiHowMuchBurn = undefined; + const gasPrice = await tc.computeGasPrice( ethersProvider, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasBurn = + await tc.computeGas( + details, ethersProvider, + "ERC20", contract, "burnFrom", arrArgumentsBurn, + joAccount, strActionName, + gasPrice, 10000000, weiHowMuchBurn, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGasBurn ) + "\n" ); + } + strActionName = "Burn ERC20"; + const isIgnoreBurn = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProvider, + "ERC20", contract, "burnFrom", arrArgumentsBurn, + joAccount, strActionName, isIgnoreBurn, + gasPrice, estimatedGasBurn, weiHowMuchBurn, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + isCheckTransactionToSchain: ( chainNameDst !== "Mainnet" ) ? true : false + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProvider, + "ERC20", contract, "burnFrom", arrArgumentsBurn, + joAccount, strActionName, + gasPrice, estimatedGasBurn, weiHowMuchBurn, opts ); + imaGasUsage.printGasUsageReportFromArray( "BURN ERC20 ", [ { + "description": "burnErc20()/burn", + "receipt": joReceipt + } ], details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "burnErc20", true ); + details.close(); + return joReceipt; // can be used as "true" boolean value + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.id != details.id ) { + log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in burnErc20() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in burnErc20() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.exposeDetailsTo( log, "burnErc20()", false ); + details.close(); + return false; + } +} + +export async function burnErc721( + ethersProvider, + chainId, + chainName, + joAccount, + idToken, + strTokenContractAddress, + joTokenContractABI, + tc +) { + let strActionName = "burnErc721() init"; + const strLogPrefix = cc.info( "burnErc721() call" ) + " "; + const details = log.createMemoryStream(); + try { + details.write( strLogPrefix + cc.debug( "Burn " ) + cc.info( "ERC721" ) + + cc.debug( " token ID " ) + cc.notice( idToken ) + "\n" ); + if( ! ( ethersProvider && joAccount && + strTokenContractAddress && typeof strTokenContractAddress == "string" && + strTokenContractAddress.length > 0 && joTokenContractABI + ) ) + throw new Error( "Missing valid arguments" ); + strActionName = "burnErc721() instantiate token contract"; + const contract = + new owaspUtils.ethersMod.ethers.Contract( + strTokenContractAddress, + joTokenContractABI, + ethersProvider + ); + const arrArgumentsBurn = [ + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( idToken ).toHexString() ) + ]; + const weiHowMuchBurn = undefined; + const gasPrice = await tc.computeGasPrice( ethersProvider, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasBurn = + await tc.computeGas( + details, ethersProvider, + "ERC721", contract, "burn", arrArgumentsBurn, + joAccount, strActionName, + gasPrice, 10000000, weiHowMuchBurn, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGasBurn ) + "\n" ); + } + strActionName = "Burn ERC721"; + const isIgnoreBurn = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProvider, + "ERC721", contract, "burn", arrArgumentsBurn, + joAccount, strActionName, isIgnoreBurn, + gasPrice, estimatedGasBurn, weiHowMuchBurn, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + isCheckTransactionToSchain: ( chainNameDst !== "Mainnet" ) ? true : false + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProvider, + "ERC721", contract, "burn", arrArgumentsBurn, + joAccount, strActionName, + gasPrice, estimatedGasBurn, weiHowMuchBurn, opts ); + imaGasUsage.printGasUsageReportFromArray( "BURN ERC721 ", [ { + "description": "burnErc721()/burn", + "receipt": joReceipt + } ], details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "burnErc721", true ); + details.close(); + return joReceipt; // can be used as "true" boolean value + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.id != details.id ) { + log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in burnErc721() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + + "\n" + cc.stack( err.stack ) + "\n" ); + } + details.write( strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in burnErc721() during " + + strActionName + ": " ) + cc.error( strError ) + cc.error( ", stack is: " ) + + "\n" + cc.stack( err.stack ) + "\n" ); + } + details.exposeDetailsTo( log, "burnErc721()", false ); + details.close(); + return false; + } +} + +export async function burnErc1155( + ethersProvider, + chainId, + chainName, + joAccount, + strAddressBurnFrom, + idToken, + nAmount, + strTokenContractAddress, + joTokenContractABI, + tc +) { + let strActionName = "burnErc1155() init"; + const strLogPrefix = cc.info( "burnErc1155() call" ) + " "; + const details = log.createMemoryStream(); + try { + details.write( strLogPrefix + + cc.debug( "Burn " ) + cc.info( "ERC1155" ) + cc.debug( " token ID " ) + + cc.notice( idToken ) + cc.debug( " token amount " ) + cc.notice( nAmount ) + + "\n" ); + if( ! ( ethersProvider && joAccount && strAddressBurnFrom && + typeof strAddressBurnFrom == "string" && strAddressBurnFrom.length > 0 && + strTokenContractAddress && typeof strTokenContractAddress == "string" && + strTokenContractAddress.length > 0 && joTokenContractABI + ) ) + throw new Error( "Missing valid arguments" ); + strActionName = "burnErc1155() instantiate token contract"; + const contract = + new owaspUtils.ethersMod.ethers.Contract( + strTokenContractAddress, + joTokenContractABI, + ethersProvider + ); + const arrArgumentsBurn = [ + strAddressBurnFrom, + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( idToken ).toHexString() ), + owaspUtils.ensureStartsWith0x( owaspUtils.toBN( nAmount ).toHexString() ) + ]; + const weiHowMuchBurn = undefined; + const gasPrice = await tc.computeGasPrice( ethersProvider, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + const estimatedGasBurn = + await tc.computeGas( + details, ethersProvider, + "ERC1155", contract, "burn", arrArgumentsBurn, + joAccount, strActionName, + gasPrice, 10000000, weiHowMuchBurn, null ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + + cc.debug( "=" ) + cc.notice( estimatedGasBurn ) + "\n" ); + } + strActionName = "Burn ERC1155"; + const isIgnoreBurn = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + details, ethersProvider, + "ERC1155", contract, "burn", arrArgumentsBurn, + joAccount, strActionName, isIgnoreBurn, + gasPrice, estimatedGasBurn, weiHowMuchBurn, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + + const opts = { + ToSchain: ( chainNameDst !== "Mainnet" ) ? true : false + }; + const joReceipt = + await imaTx.payedCall( + details, ethersProvider, + "ERC1155", contract, "burn", arrArgumentsBurn, + joAccount, strActionName, + gasPrice, estimatedGasBurn, weiHowMuchBurn, opts ); + imaGasUsage.printGasUsageReportFromArray( "BURN ERC1155 ", [ { + "description": "burnErc1155()/burn", + "receipt": joReceipt + } ], details ); + if( log.exposeDetailsGet() ) + details.exposeDetailsTo( log, "burnErc1155", true ); + details.close(); + return joReceipt; // can be used as "true" boolean value + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + if( log.id != details.id ) { + log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in burnErc1155() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in burnErc1155() during " + strActionName + ": " ) + + cc.error( strError ) + cc.error( ", stack is: " ) + "\n" + + cc.stack( err.stack ) + "\n" ); + } + details.exposeDetailsTo( log, "burnErc1155()", false ); + details.close(); + return false; + } +} diff --git a/npms/skale-ima/imaTransferErrorHandling.mjs b/npms/skale-ima/imaTransferErrorHandling.mjs new file mode 100644 index 000000000..f31868c67 --- /dev/null +++ b/npms/skale-ima/imaTransferErrorHandling.mjs @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaTransferErrorHandling.mjs + * @copyright SKALE Labs 2019-Present + */ + +import { UniversalDispatcherEvent, EventDispatcher } + from "../skale-cool-socket/eventDispatcher.mjs"; + +export function verifyTransferErrorCategoryName( strCategory ) { + return "" + ( strCategory ? strCategory : "default" ); +} + +const gMaxLastTransferErrors = 20; +const gArrLastTransferErrors = []; +let gMapTransferErrorCategories = { }; + +export const saveTransferEvents = new EventDispatcher(); + +export function saveTransferError( strCategory, textLog, ts ) { + ts = ts || Math.round( ( new Date() ).getTime() / 1000 ); + const c = verifyTransferErrorCategoryName( strCategory ); + const joTransferEventError = { + "ts": ts, + "category": "" + c, + "textLog": "" + textLog.toString() + }; + gArrLastTransferErrors.push( joTransferEventError ); + while( gArrLastTransferErrors.length > gMaxLastTransferErrors ) + gArrLastTransferErrors.shift(); + gMapTransferErrorCategories["" + c] = true; + saveTransferEvents.dispatchEvent( + new UniversalDispatcherEvent( + "error", + { "detail": joTransferEventError } ) ); +} + +export function saveTransferSuccess( strCategory ) { + const c = verifyTransferErrorCategoryName( strCategory ); + try { delete gMapTransferErrorCategories["" + c]; } catch ( err ) { } + saveTransferEvents.dispatchEvent( + new UniversalDispatcherEvent( + "success", + { "detail": { "category": strCategory } } ) ); +} + +export function saveTransferSuccessAll() { + // clear all transfer error categories, out of time frame + gMapTransferErrorCategories = { }; +} + +export function getLastTransferErrors( isIncludeTextLog ) { + if( typeof isIncludeTextLog == "undefined" ) + isIncludeTextLog = true; + const jarr = JSON.parse( JSON.stringify( gArrLastTransferErrors ) ); + if( ! isIncludeTextLog ) { + for( let i = 0; i < jarr.length; ++ i ) { + const jo = jarr[i]; + if( "textLog" in jo ) + delete jo.textLog; + } + } + return jarr; +} + +export function getLastErrorCategories() { + return Object.keys( gMapTransferErrorCategories ); +} + +let gFlagIsEnabledProgressiveEventsScan = true; + +export function getEnabledProgressiveEventsScan() { + return gFlagIsEnabledProgressiveEventsScan ? true : false; +} +export function setEnabledProgressiveEventsScan( isEnabled ) { + gFlagIsEnabledProgressiveEventsScan = isEnabled ? true : false; +} diff --git a/npms/skale-ima/imaTx.mjs b/npms/skale-ima/imaTx.mjs new file mode 100644 index 000000000..bcca940a3 --- /dev/null +++ b/npms/skale-ima/imaTx.mjs @@ -0,0 +1,1025 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file imaTx.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as fs from "fs"; +import * as path from "path"; +import * as url from "url"; +import * as childProcessModule from "child_process"; + +import Redis from "ioredis"; +import * as ethereumJsUtilModule from "ethereumjs-util"; + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as rpcCall from "../../agent/rpcCall.mjs"; +import * as imaUtils from "../../agent/utils.mjs"; +import * as imaHelperAPIs from "./imaHelperAPIs.mjs"; +import * as imaEventLogScan from "./imaEventLogScan.mjs"; + +const __dirname = path.dirname( url.fileURLToPath( import.meta.url ) ); + +let redis = null; + +let gFlagDryRunIsEnabled = true; + +export function dryRunIsEnabled() { + return gFlagDryRunIsEnabled ? true : false; +} +export function dryRunEnable( isEnable ) { + gFlagDryRunIsEnabled = ( isEnable != null && isEnable != undefined ) + ? ( isEnable ? true : false ) : true; + return gFlagDryRunIsEnabled ? true : false; +} + +let gFlagDryRunIsIgnored = true; + +export function dryRunIsIgnored() { + return gFlagDryRunIsIgnored ? true : false; +} + +export function dryRunIgnore( isIgnored ) { + gFlagDryRunIsIgnored = ( isIgnored != null && isIgnored != undefined ) + ? ( isIgnored ? true : false ) : true; + return gFlagDryRunIsIgnored ? true : false; +} + +export async function dryRunCall( + details, + ethersProvider, + strContractName, joContract, strMethodName, arrArguments, + joAccount, strActionName, isDryRunResultIgnore, + gasPrice, gasValue, weiHowMuch, + opts +) { + if( ! dryRunIsEnabled() ) + return null; // success + isDryRunResultIgnore = ( isDryRunResultIgnore != null && isDryRunResultIgnore != undefined ) + ? ( isDryRunResultIgnore ? true : false ) : false; + const strContractMethodDescription = + cc.notice( strContractName ) + cc.debug( "(" ) + cc.info( joContract.address ) + + cc.debug( ")." ) + cc.notice( strMethodName ); + let strArgumentsDescription = ""; + if( arrArguments.length > 0 ) { + strArgumentsDescription += cc.debug( "( " ); + for( let i = 0; i < arrArguments.length; ++ i ) { + if( i > 0 ) + strArgumentsDescription += cc.debug( ", " ); + strArgumentsDescription += cc.j( arrArguments[i] ); + } + strArgumentsDescription += cc.debug( " )" ); + } else + strArgumentsDescription += cc.debug( "()" ); + const strContractCallDescription = strContractMethodDescription + strArgumentsDescription; + const strLogPrefix = strContractMethodDescription + " "; + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( "Dry-run of action " ) + cc.info( strActionName ) + + cc.debug( "..." ) + "\n" ); + details.write( cc.debug( "Will dry-run " ) + strContractCallDescription + + cc.debug( "..." ) + "\n" ); + } + const strAccountWalletAddress = joAccount.address(); + const callOpts = { + from: strAccountWalletAddress + }; + if( gasPrice ) + callOpts.gasPrice = owaspUtils.toBN( gasPrice ).toHexString(); + if( gasValue ) + callOpts.gasLimit = owaspUtils.toBN( gasValue ).toHexString(); + if( weiHowMuch ) + callOpts.value = owaspUtils.toBN( weiHowMuch ).toHexString(); + const joDryRunResult = + await joContract.callStatic[strMethodName]( ...arrArguments, callOpts ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.success( "dry-run success: " ) + + cc.j( joDryRunResult ) + "\n" ); + } + return null; // success + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + details.write( strLogPrefix + cc.error( "dry-run error: " ) + + cc.warning( strError ) + "\n" ); + } + if( dryRunIsIgnored() ) + return null; + return strError; + } +} + +async function payedCallPrepare( optsPayedCall ) { + optsPayedCall.joACI = getAccountConnectivityInfo( optsPayedCall.joAccount ); + if( optsPayedCall.gasPrice ) { + optsPayedCall.callOpts.gasPrice = + owaspUtils.toBN( optsPayedCall.gasPrice ).toHexString(); + } + if( optsPayedCall.estimatedGas ) { + optsPayedCall.callOpts.gasLimit = + owaspUtils.toBN( optsPayedCall.estimatedGas ).toHexString(); + } + if( optsPayedCall.weiHowMuch ) { + optsPayedCall.callOpts.value = + owaspUtils.toBN( optsPayedCall.weiHowMuch ).toHexString(); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Payed-call of action " ) + cc.info( optsPayedCall.strActionName ) + + cc.debug( " will do payed-call " ) + optsPayedCall.strContractCallDescription + + cc.debug( " with call options " ) + cc.j( optsPayedCall.callOpts ) + + cc.debug( " via " ) + cc.attention( optsPayedCall.joACI.strType ) + + cc.debug( "-sign-and-send..." ) + "\n" ); + } + optsPayedCall.unsignedTx = + await optsPayedCall.joContract.populateTransaction[optsPayedCall.strMethodName]( + ...optsPayedCall.arrArguments, optsPayedCall.callOpts ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "populated transaction: " ) + cc.j( optsPayedCall.unsignedTx ) + "\n" ); + } + optsPayedCall.unsignedTx.nonce = + await optsPayedCall.ethersProvider.getTransactionCount( optsPayedCall.joAccount.address() ); + if( optsPayedCall.opts && optsPayedCall.opts.isCheckTransactionToSchain ) { + optsPayedCall.unsignedTx = await checkTransactionToSchain( + optsPayedCall.unsignedTx, optsPayedCall.details, + optsPayedCall.ethersProvider, optsPayedCall.joAccount ); + } + optsPayedCall.rawTx = + owaspUtils.ethersMod.ethers.utils.serializeTransaction( optsPayedCall.unsignedTx ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Raw transaction: " ) + cc.j( optsPayedCall.rawTx ) + "\n" ); + } + optsPayedCall.txHash = owaspUtils.ethersMod.ethers.utils.keccak256( optsPayedCall.rawTx ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Transaction hash: " ) + cc.j( optsPayedCall.txHash ) + "\n" ); + } +} + +async function payedCallTM( optsPayedCall ) { + const promiseComplete = new Promise( function( resolve, reject ) { + const doTM = async function() { + const txAdjusted = + optsPayedCall.unsignedTx; // JSON.parse( JSON.stringify( optsPayedCall.rawTx ) ); + const arrNamesConvertToHex = [ "gas", "gasLimit", "optsPayedCall.gasPrice", "value" ]; + for( let idxName = 0; idxName < arrNamesConvertToHex.length; ++ idxName ) { + const strName = arrNamesConvertToHex[idxName]; + if( strName in txAdjusted && + typeof txAdjusted[strName] == "object" && + typeof txAdjusted[strName].toHexString == "function" + ) + txAdjusted[strName] = txAdjusted[strName].toHexString(); + } + if( "gasLimit" in txAdjusted ) + delete txAdjusted.gasLimit; + if( "chainId" in txAdjusted ) + delete txAdjusted.chainId; + const { chainId } = await optsPayedCall.ethersProvider.getNetwork(); + txAdjusted.chainId = chainId; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Adjusted transaction: " ) + cc.j( txAdjusted ) + "\n" ); + } + if( redis == null ) + redis = new Redis( optsPayedCall.joAccount.strTransactionManagerURL ); + const priority = optsPayedCall.joAccount.nTmPriority || 5; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "TM priority: " ) + cc.j( priority ) + "\n" ); + } + try { + const [ idTransaction, joReceiptFromTM ] = + await tmEnsureTransaction( + optsPayedCall.details, optsPayedCall.ethersProvider, priority, txAdjusted ); + optsPayedCall.joReceipt = joReceiptFromTM; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "ID of TM-transaction : " ) + cc.j( idTransaction ) + "\n" ); + } + const txHashSent = "" + optsPayedCall.joReceipt.transactionHash; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Hash of sent TM-transaction: " ) + cc.j( txHashSent ) + "\n" ); + } + resolve( optsPayedCall.joReceipt ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = cc.fatal( "BAD ERROR:" ) + " " + + cc.error( "TM-transaction was not sent, underlying error is: " ) + + cc.warning( err.toString() ); + optsPayedCall.details.write( optsPayedCall.strLogPrefix + strError + "\n" ); + if( log.id != optsPayedCall.details.id ) + log.write( optsPayedCall.strLogPrefix + strError + "\n" ); + } + reject( err ); + } + }; + doTM(); + } ); + await Promise.all( [ promiseComplete ] ); +} + +async function payedCallSGX( optsPayedCall ) { + let rpcCallOpts = null; + if( "strPathSslKey" in optsPayedCall.joAccount && + typeof optsPayedCall.joAccount.strPathSslKey == "string" && + optsPayedCall.joAccount.strPathSslKey.length > 0 && + "strPathSslCert" in optsPayedCall.joAccount && + typeof optsPayedCall.joAccount.strPathSslCert == "string" && + optsPayedCall.joAccount.strPathSslCert.length > 0 + ) { + rpcCallOpts = { + "cert": fs.readFileSync( optsPayedCall.joAccount.strPathSslCert, "utf8" ), + "key": fs.readFileSync( optsPayedCall.joAccount.strPathSslKey, "utf8" ) + }; + } + const promiseComplete = new Promise( function( resolve, reject ) { + rpcCall.create( optsPayedCall.joAccount.strSgxURL, rpcCallOpts, + async function( joCall, err ) { + if( err ) { + const strError = + cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + + cc.error( + " JSON RPC call creation to SGX wallet failed with error " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + if( log.verboseGet() >= log.verboseReversed.error ) { + if( log.id != optsPayedCall.details.id ) + log.write( optsPayedCall.strLogPrefix + strError ); + } + optsPayedCall.details.write( optsPayedCall.strLogPrefix + strError ); + reject( + new Error( + "CRITICAL TRANSACTION SIGNING ERROR: " + + owaspUtils.extractErrorMessage( err ) ) ); + } + const joIn = { + "method": "ecdsaSignMessageHash", + "params": { + "keyName": "" + optsPayedCall.joAccount.strSgxKeyName, + "messageHash": owaspUtils.ensureStartsWith0x( optsPayedCall.txHash ), + "base": 16 + } + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Calling SGX to sign using ECDSA key with " ) + + cc.info( joIn.method ) + cc.debug( "..." ) + "\n" ); + } + joCall.call( joIn, async function( joIn, joOut, err ) { + if( err ) { + const strError = cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + + cc.error( " JSON RPC call sending to SGX wallet " + + "failed with error " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + if( log.verboseGet() >= log.verboseReversed.error ) { + if( log.id != optsPayedCall.details.id ) + log.write( optsPayedCall.strLogPrefix + strError ); + optsPayedCall.details.write( optsPayedCall.strLogPrefix + strError ); + } + reject( + new Error( "CRITICAL TRANSACTION SIGNING ERROR: " + + owaspUtils.extractErrorMessage( err ) ) ); + } + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "SGX wallet ECDSA sign result is: " ) + cc.j( joOut ) + + "\n" ); + } + const v = + owaspUtils.parseIntOrHex( + owaspUtils.toBN( joOut.result.signature_v ).toString() ); + const joExpanded = { + "v": v, + "r": joOut.result.signature_r, + "s": joOut.result.signature_s + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Preliminary expanded signature: " ) + + cc.j( joExpanded ) + "\n" ); + } + let { chainId } = await optsPayedCall.ethersProvider.getNetwork(); + if( chainId == "string" ) + chainId = owaspUtils.parseIntOrHex( chainId ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Chain ID is: " ) + cc.info( chainId ) + "\n" ); + } + joExpanded.v += chainId * 2 + 8 + 27; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Final expanded signature: " ) + cc.j( joExpanded ) + + "\n" ); + } + const joSignature = + owaspUtils.ethersMod.ethers.utils.joinSignature( joExpanded ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Final signature: " ) + cc.j( joSignature ) + "\n" ); + } + optsPayedCall.rawTx = + owaspUtils.ethersMod.ethers.utils.serializeTransaction( + optsPayedCall.unsignedTx, joSignature ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Raw transaction with signature: " ) + + cc.j( optsPayedCall.rawTx ) + "\n" ); + } + const { hash } = await optsPayedCall.ethersProvider.sendTransaction( + owaspUtils.ensureStartsWith0x( optsPayedCall.rawTx ) + ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Raw-sent transaction hash: " ) + cc.j( hash ) + "\n" ); + } + optsPayedCall.joReceipt = + await optsPayedCall.ethersProvider.waitForTransaction( hash ); + resolve( optsPayedCall.joReceipt ); + } catch ( err ) { + const strErrorPrefix = + "CRITICAL TRANSACTION SIGN AND SEND ERROR(PROCESSING SGX RESULT):"; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s = optsPayedCall.strLogPrefix + cc.error( strErrorPrefix ) + + " " + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + optsPayedCall.details.write( s ); + if( log.id != optsPayedCall.details.id ) + log.write( s ); + } + reject( new Error( strErrorPrefix + + " Invoking the " + optsPayedCall.strContractCallDescription + + ", error is: " + owaspUtils.extractErrorMessage( err ) ) ); + } + } ); + } ); + } ); + await Promise.all( [ promiseComplete ] ); +} + +async function payedCallDirect( optsPayedCall ) { + const ethersWallet = + new owaspUtils.ethersMod.ethers.Wallet( + owaspUtils.ensureStartsWith0x( + optsPayedCall.joAccount.privateKey ), + optsPayedCall.ethersProvider ); + const joSent = await ethersWallet.sendTransaction( optsPayedCall.unsignedTx ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Sent transaction: " ) + cc.j( joSent ) + "\n" ); + } + optsPayedCall.joReceipt = await joSent.wait(); + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "Transaction receipt:" ) + cc.j( optsPayedCall.joReceipt ) + "\n" ); + } +} + +export async function payedCall( + details, + ethersProvider, + strContractName, joContract, strMethodName, arrArguments, + joAccount, strActionName, + gasPrice, estimatedGas, weiHowMuch, + opts +) { + const optsPayedCall = { + details: details, + ethersProvider: ethersProvider, + strContractName: strContractName, + joContract: joContract, + strMethodName: strMethodName, + arrArguments: arrArguments, + joAccount: joAccount, + strActionName: strActionName, + gasPrice: gasPrice, + estimatedGas: estimatedGas, + weiHowMuch: weiHowMuch, + opts: opts, + strContractCallDescription: "", + strLogPrefix: "", + joACI: null, + unsignedTx: null, + rawTx: null, + txHash: null, + joReceipt: null, + callOpts: { } + }; + const strContractMethodDescription = cc.notice( optsPayedCall.strContractName ) + + cc.debug( "(" ) + cc.info( optsPayedCall.joContract.address ) + + cc.debug( ")." ) + cc.info( optsPayedCall.strMethodName ); + let strArgumentsDescription = ""; + if( optsPayedCall.arrArguments.length > 0 ) { + strArgumentsDescription += cc.debug( "( " ); + for( let i = 0; i < optsPayedCall.arrArguments.length; ++ i ) { + if( i > 0 ) + strArgumentsDescription += cc.debug( ", " ); + strArgumentsDescription += cc.j( optsPayedCall.arrArguments[i] ); + } + strArgumentsDescription += cc.debug( " )" ); + } else + strArgumentsDescription += cc.debug( "()" ); + optsPayedCall.strContractCallDescription = + strContractMethodDescription + strArgumentsDescription; + optsPayedCall.strLogPrefix = strContractMethodDescription + " "; + try { + await payedCallPrepare( optsPayedCall ); + switch ( optsPayedCall.joACI.strType ) { + case "tm": + await payedCallTM( optsPayedCall ); + break; + case "sgx": + await payedCallSGX( optsPayedCall ); + break; + case "direct": + await payedCallDirect( optsPayedCall ); + break; + default: { + const strErrorPrefix = "CRITICAL TRANSACTION SIGN AND SEND ERROR(INNER FLOW):"; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s = cc.fatal( strErrorPrefix ) + " " + + cc.error( "bad credentials information specified, " + + "no explicit SGX and no explicit private key found" ) + "\n"; + optsPayedCall.details.write( s ); + if( log.id != optsPayedCall.details.id ) + log.write( s ); + } + throw new Error( strErrorPrefix + " bad credentials information specified, " + + "no explicit SGX and no explicit private key found" ); + } // NOTICE: "break;" is not needed here because of "throw" above + } // switch( optsPayedCall.joACI.strType ) + } catch ( err ) { + const strErrorPrefix = "CRITICAL TRANSACTION SIGN AND SEND ERROR(OUTER FLOW):"; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s = + optsPayedCall.strLogPrefix + cc.error( strErrorPrefix ) + " " + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + optsPayedCall.details.write( s ); + if( log.id != optsPayedCall.details.id ) + log.write( s ); + } + throw new Error( strErrorPrefix + + " invoking the " + optsPayedCall.strContractCallDescription + + ", error is: " + owaspUtils.extractErrorMessage( err ) ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + cc.success( "Done, TX was " ) + + cc.attention( optsPayedCall.joACI ? optsPayedCall.joACI.strType : "N/A" ) + + cc.success( "-signed-and-sent, receipt is " ) + cc.j( optsPayedCall.joReceipt ) + + "\n" ); + } + try { + const bnGasSpent = owaspUtils.toBN( optsPayedCall.joReceipt.cumulativeGasUsed ); + const gasSpent = bnGasSpent.toString(); + const ethSpent = + owaspUtils.ethersMod.ethers.utils.formatEther( + optsPayedCall.joReceipt.cumulativeGasUsed.mul( + optsPayedCall.unsignedTx.gasPrice ) ); + optsPayedCall.joReceipt.summary = { + bnGasSpent: bnGasSpent, + gasSpent: gasSpent, + ethSpent: ethSpent + }; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "gas spent: " ) + cc.info( gasSpent ) + "\n" ); + optsPayedCall.details.write( optsPayedCall.strLogPrefix + + cc.debug( "ETH spent: " ) + cc.info( ethSpent ) + "\n" ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + optsPayedCall.details.write( + optsPayedCall.strLogPrefix + cc.warning( "WARNING: " ) + " " + + cc.warning( "TX stats computation error " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.warning( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return optsPayedCall.joReceipt; +} + +export async function checkTransactionToSchain( + unsignedTx, + details, + ethersProvider, + joAccount +) { + const strLogPrefix = cc.attention( "PoW-mining:" ) + " "; + try { + const strFromAddress = joAccount.address(); // unsignedTx.from; + const requiredBalance = unsignedTx.gasPrice.mul( unsignedTx.gasLimit ); + const balance = owaspUtils.toBN( await ethersProvider.getBalance( strFromAddress ) ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Will check whether PoW-mining " + + "is needed for sender " ) + cc.notice( strFromAddress ) + + cc.debug( " with balance " ) + cc.info( balance.toHexString() ) + + cc.debug( " using required balance " ) + cc.info( requiredBalance.toHexString() ) + + cc.debug( ", gas limit is " ) + cc.info( unsignedTx.gasLimit.toHexString() ) + + cc.debug( " gas, checked unsigned transaction is " ) + cc.j( unsignedTx ) + "\n" ); + } + if( balance.lt( requiredBalance ) ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.warning( "Insufficient funds for " ) + + cc.notice( strFromAddress ) + cc.warning( ", will run PoW-mining to get " ) + + cc.info( unsignedTx.gasLimit.toHexString() ) + cc.warning( " of gas" ) + "\n" ); + } + let powNumber = + await calculatePowNumber( + strFromAddress, + owaspUtils.toBN( unsignedTx.nonce ).toHexString(), + unsignedTx.gasLimit.toHexString(), + details, + strLogPrefix + ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "Returned PoW-mining number " ) + + cc.sunny( powNumber ) + "\n" ); + } + powNumber = powNumber.toString().trim(); + powNumber = imaUtils.replaceAll( powNumber, "\r", "" ); + powNumber = imaUtils.replaceAll( powNumber, "\n", "" ); + powNumber = imaUtils.replaceAll( powNumber, "\t", "" ); + powNumber = powNumber.trim(); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Trimmed PoW-mining number is " ) + + cc.sunny( powNumber ) + "\n" ); + } + if( ! powNumber ) { + throw new Error( + "Failed to compute gas price with PoW-mining (1), got empty text" ); + } + powNumber = owaspUtils.toBN( owaspUtils.ensureStartsWith0x( powNumber ) ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "BN PoW-mining number is " ) + + cc.j( powNumber ) + "\n" ); + } + if( powNumber.eq( owaspUtils.toBN( "0" ) ) ) { + throw new Error( + "Failed to compute gas price with PoW-mining (2), got zero value" ); + } + unsignedTx.gasPrice = powNumber; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.success( "Success, finally (after PoW-mining) " + + "modified unsigned transaction is " ) + cc.j( unsignedTx ) + "\n" ); + } + } else { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.success( "Have sufficient funds for " ) + + cc.notice( strFromAddress ) + cc.success( ", PoW-mining is not needed " + + "and will be skipped" ) + "\n" ); + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + details.write( strLogPrefix + + cc.fatal( "CRITICAL PoW-mining ERROR(checkTransactionToSchain):" ) + " " + + cc.error( "exception occur before PoW-mining, error is:" ) + " " + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return unsignedTx; +} + +export async function calculatePowNumber( address, nonce, gas, details, strLogPrefix ) { + try { + let _address = owaspUtils.ensureStartsWith0x( address ); + _address = ethereumJsUtilModule.toChecksumAddress( _address ); + _address = owaspUtils.removeStarting0x( _address ); + const _nonce = owaspUtils.parseIntOrHex( nonce ); + const _gas = owaspUtils.parseIntOrHex( gas ); + const powScriptPath = path.join( __dirname, "pow" ); + const cmd = `${powScriptPath} ${_address} ${_nonce} ${_gas}`; + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + + cc.debug( "Will run PoW-mining command: " ) + cc.notice( cmd ) + "\n" ); + } + const res = childProcessModule.execSync( cmd ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + + cc.debug( "Got PoW-mining execution result: " ) + cc.notice( res ) + "\n" ); + } + return res; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + details.write( strLogPrefix + + cc.fatal( "CRITICAL PoW-mining ERROR(calculatePowNumber):" ) + " " + + cc.error( "exception occur during PoW-mining, error is:" ) + " " + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n" ); + } + throw err; + } +} + +export function getAccountConnectivityInfo( joAccount ) { + const joACI = { + "isBad": true, + "strType": "bad", + "isAutoSend": false + }; + if( "strTransactionManagerURL" in joAccount && + typeof joAccount.strTransactionManagerURL == "string" && + joAccount.strTransactionManagerURL.length > 0 + ) { + joACI.isBad = false; + joACI.strType = "tm"; + joACI.isAutoSend = true; + } else if( "strSgxURL" in joAccount && + typeof joAccount.strSgxURL == "string" && + joAccount.strSgxURL.length > 0 && + "strSgxKeyName" in joAccount && + typeof joAccount.strSgxKeyName == "string" && + joAccount.strSgxKeyName.length > 0 + ) { + joACI.isBad = false; + joACI.strType = "sgx"; + } else if( "privateKey" in joAccount && + typeof joAccount.privateKey == "string" && + joAccount.privateKey.length > 0 + ) { + joACI.isBad = false; + joACI.strType = "direct"; + } else { + // bad by default + } + return joACI; +} + +const gTransactionManagerPool = "transactions"; + +const tmGenerateRandomHex = + size => [ ...Array( size ) ] + .map( () => Math.floor( Math.random() * 16 ).toString( 16 ) ).join( "" ); + +function tmMakeId( details ) { + const prefix = "tx-"; + const unique = tmGenerateRandomHex( 16 ); + const id = prefix + unique + "js"; + if( log.verboseGet() >= log.verboseReversed().trace ) + details.write( cc.debug( "TM - Generated id: " ) + cc.debug( id ) + "\n" ); + return id; +} + +function tmMakeRecord( tx = {}, score ) { + const status = "PROPOSED"; + return JSON.stringify( { + "score": score, + "status": status, + ...tx + } ); +} + +function tmMakeScore( priority ) { + const ts = imaHelperAPIs.currentTimestamp(); + return priority * Math.pow( 10, ts.toString().length ) + ts; +} + +async function tmSend( details, tx, priority = 5 ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( "TM - sending tx " ) + cc.j( tx ) + + cc.debug( " ts: " ) + cc.info( imaHelperAPIs.currentTimestamp() ) + "\n" ); + } + const id = tmMakeId( details ); + const score = tmMakeScore( priority ); + const record = tmMakeRecord( tx, score ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( "TM - Sending score: " ) + cc.info( score ) + + cc.debug( ", record: " ) + cc.info( record ) + "\n" ); + } + const expiration = 24 * 60 * 60; // 1 day; + await redis.multi() + .set( id, record, "EX", expiration ) + .zadd( gTransactionManagerPool, score, id ) + .exec(); + return id; +} + +function tmIsFinished( record ) { + if( record == null ) + return null; + return [ "SUCCESS", "FAILED", "DROPPED" ].includes( record.status ); +} + +async function tmGetRecord( txId ) { + const r = await redis.get( txId ); + if( r != null ) + return JSON.parse( r ); + return null; +} + +async function tmWait( details, txId, ethersProvider, nWaitSeconds = 36000 ) { + const strPrefixDetails = cc.debug( "(gathered details)" ) + " "; + const strPrefixLog = cc.debug( "(immediate log)" ) + " "; + if( log.verboseGet() >= log.verboseReversed().debug ) { + const strMsg = + cc.debug( "TM - will wait TX " ) + cc.info( txId ) + + cc.debug( " to complete for " ) + cc.info( nWaitSeconds ) + + cc.debug( " second(s) maximum" ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + const startTs = imaHelperAPIs.currentTimestamp(); + while( ! tmIsFinished( await tmGetRecord( txId ) ) && + ( imaHelperAPIs.currentTimestamp() - startTs ) < nWaitSeconds ) + await imaHelperAPIs.sleep( 500 ); + const r = await tmGetRecord( txId ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + strMsg = cc.debug( "TM - TX " ) + cc.info( txId ) + cc.debug( " record is " ) + + cc.info( JSON.stringify( r ) ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + if( ( !r ) ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + strMsg = cc.error( "TM - TX " ) + cc.info( txId ) + cc.error( " status is " ) + + cc.warning( "NULL RECORD" ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + } else if( r.status == "SUCCESS" ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + strMsg = cc.success( "TM - TX " ) + cc.info( txId ) + cc.success( " success" ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + } else { + if( log.verboseGet() >= log.verboseReversed().error ) { + strMsg = cc.error( "TM - TX " ) + cc.info( txId ) + cc.error( " status is " ) + + cc.warning( r.status ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + } + if( ( !tmIsFinished( r ) ) || r.status == "DROPPED" ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const s = cc.error( "TM - TX " ) + cc.info( txId ) + + cc.error( " was unsuccessful, wait failed" ) + "\n"; + details.write( s ); + if( log.id != details.id ) + log.write( s ); + } + return null; + } + const joReceipt = await imaEventLogScan.safeGetTransactionReceipt( + details, 10, ethersProvider, r.tx_hash ); + if( !joReceipt ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + strMsg = cc.error( "TM - TX " ) + cc.info( txId ) + + cc.error( " was unsuccessful, failed to fetch transaction receipt" ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + return null; + } + return joReceipt; +} + +async function tmEnsureTransaction( + details, ethersProvider, priority, txAdjusted, cntAttempts, sleepMilliseconds +) { + cntAttempts = cntAttempts || 1; + sleepMilliseconds = sleepMilliseconds || ( 30 * 1000 ); + let txId = ""; + let joReceipt = null; + let idxAttempt = 0; + const strPrefixDetails = cc.debug( "(gathered details)" ) + " "; + const strPrefixLog = cc.debug( "(immediate log)" ) + " "; + let strMsg; + for( ; idxAttempt < cntAttempts; ++idxAttempt ) { + txId = await tmSend( details, txAdjusted, priority ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + strMsg = cc.debug( "TM - next TX " ) + cc.info( txId ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + joReceipt = await tmWait( details, txId, ethersProvider ); + if( joReceipt ) + break; + if( log.verboseGet() >= log.verboseReversed().error ) { + strMsg = + cc.warning( "TM - unsuccessful TX " ) + cc.info( txId ) + + cc.warning( " sending attempt " ) + cc.info( idxAttempt ) + + cc.warning( " of " ) + cc.info( cntAttempts ) + + cc.debug( " receipt: " ) + cc.info( joReceipt ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + await imaHelperAPIs.sleep( sleepMilliseconds ); + } + if( !joReceipt ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + strMsg = + cc.fatal( "BAD ERROR:" ) + " " + cc.error( "TM TX " ) + cc.info( txId ) + + cc.error( " transaction has been dropped" ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + throw new Error( "TM unsuccessful transaction " + txId ); + } + if( log.verboseGet() >= log.verboseReversed().information ) { + strMsg = + cc.success( "TM - successful TX " ) + cc.info( txId ) + + cc.success( ", sending attempt " ) + cc.info( idxAttempt ) + + cc.success( " of " ) + cc.info( cntAttempts ); + details.write( strPrefixDetails + strMsg + "\n" ); + if( log.id != details.id ) + log.write( strPrefixLog + strMsg + "\n" ); + } + return [ txId, joReceipt ]; +} + +export class TransactionCustomizer { + constructor( gasPriceMultiplier, gasMultiplier ) { + this.gasPriceMultiplier = gasPriceMultiplier + ? ( 0.0 + gasPriceMultiplier ) + : null; // null means use current gasPrice or recommendedGasPrice + this.gasMultiplier = gasMultiplier ? ( 0.0 + gasMultiplier ) : 1.25; + } + async computeGasPrice( ethersProvider, maxGasPrice ) { + const gasPrice = + owaspUtils.parseIntOrHex( + owaspUtils.toBN( + await ethersProvider.getGasPrice() ).toHexString() ); + if( gasPrice == 0 || + gasPrice == null || + gasPrice == undefined || + gasPrice <= 1000000000 + ) + return owaspUtils.toBN( "1000000000" ).toHexString(); + else if( + this.gasPriceMultiplier != null && + this.gasPriceMultiplier != undefined && + this.gasPriceMultiplier >= 0 && + maxGasPrice != null && + maxGasPrice != undefined + ) { + let gasPriceMultiplied = gasPrice * this.gasPriceMultiplier; + if( gasPriceMultiplied > maxGasPrice ) + gasPriceMultiplied = maxGasPrice; + return owaspUtils.toBN( maxGasPrice ); + } else + return gasPrice; + } + async computeGas( + details, + ethersProvider, + strContractName, joContract, strMethodName, arrArguments, + joAccount, strActionName, + gasPrice, gasValueRecommended, weiHowMuch, + opts + ) { + let estimatedGas = 0; + const strContractMethodDescription = + cc.notice( strContractName ) + cc.debug( "(" ) + cc.info( joContract.address ) + + cc.debug( ")." ) + cc.notice( strMethodName ); + let strArgumentsDescription = ""; + if( arrArguments.length > 0 ) { + strArgumentsDescription += cc.debug( "( " ); + for( let i = 0; i < arrArguments.length; ++ i ) { + if( i > 0 ) + strArgumentsDescription += cc.debug( ", " ); + strArgumentsDescription += cc.j( arrArguments[i] ); + } + strArgumentsDescription += cc.debug( " )" ); + } else + strArgumentsDescription += cc.debug( "()" ); + const strContractCallDescription = + strContractMethodDescription + strArgumentsDescription; + const strLogPrefix = strContractMethodDescription + " "; + try { + const promiseComplete = new Promise( function( resolve, reject ) { + const doEstimation = async function() { + try { + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( "Estimate-gas of action " ) + + cc.info( strActionName ) + cc.debug( "..." ) + "\n" ); + details.write( cc.debug( "Will estimate-gas " ) + + strContractCallDescription + cc.debug( "..." ) + "\n" ); + } + const strAccountWalletAddress = joAccount.address(); + const callOpts = { + from: strAccountWalletAddress + }; + if( gasPrice ) { + callOpts.gasPrice = + owaspUtils.toBN( gasPrice ).toHexString(); + } + if( gasValueRecommended ) { + callOpts.gasLimit = + owaspUtils.toBN( gasValueRecommended ).toHexString(); + } + if( weiHowMuch ) + callOpts.value = owaspUtils.toBN( weiHowMuch ).toHexString(); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( cc.debug( "Call options for estimate-gas " ) + + cc.j( callOpts ) + "\n" ); + } + estimatedGas = + await joContract.estimateGas[strMethodName]( + ...arrArguments, callOpts ); + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.success( "estimate-gas success: " ) + + cc.j( estimatedGas ) + "\n" ); + } + resolve( estimatedGas ); + } catch ( err ) { + reject( err ); + } + }; + doEstimation(); + } ); + await Promise.all( [ promiseComplete ] ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + details.write( strLogPrefix + cc.error( "Estimate-gas error: " ) + + cc.warning( strError ) + + cc.error( ", default recommended gas value " + + "will be used instead of estimated" ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + estimatedGas = owaspUtils.parseIntOrHex( owaspUtils.toBN( estimatedGas ).toString() ); + if( estimatedGas == 0 ) { + estimatedGas = gasValueRecommended; + if( log.verboseGet() >= log.verboseReversed().warning ) { + details.write( strLogPrefix + cc.warning( "Will use recommended gas " ) + + cc.j( estimatedGas ) + cc.warning( " instead of estimated" ) + "\n" ); + } + } + if( this.gasMultiplier > 0.0 ) { + estimatedGas = + owaspUtils.parseIntOrHex( ( estimatedGas * this.gasMultiplier ).toString() ); + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + details.write( strLogPrefix + cc.debug( "Final amount of gas is " ) + + cc.j( estimatedGas ) + "\n" ); + } + return estimatedGas; + } +}; + +let gTransactionCustomizerMainNet = null; +let gTransactionCustomizerSChain = null; +let gTransactionCustomizerSChainTarget = null; + +export function getTransactionCustomizerForMainNet() { + if( gTransactionCustomizerMainNet ) + return gTransactionCustomizerMainNet; + gTransactionCustomizerMainNet = new TransactionCustomizer( 1.25, 1.25 ); + return gTransactionCustomizerMainNet; +} + +export function getTransactionCustomizerForSChain() { + if( gTransactionCustomizerSChain ) + return gTransactionCustomizerSChain; + gTransactionCustomizerSChain = new TransactionCustomizer( null, 1.25 ); + return gTransactionCustomizerSChain; +} + +export function getTransactionCustomizerForSChainTarget() { + if( gTransactionCustomizerSChainTarget ) + return gTransactionCustomizerSChainTarget; + gTransactionCustomizerSChainTarget = new TransactionCustomizer( null, 1.25 ); + return gTransactionCustomizerSChainTarget; +} diff --git a/npms/skale-ima/index.js b/npms/skale-ima/index.js deleted file mode 100644 index d8b3755be..000000000 --- a/npms/skale-ima/index.js +++ /dev/null @@ -1,7048 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * SKALE IMA is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * SKALE IMA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with SKALE IMA. If not, see . - */ - -/** - * @file index.js - * @copyright SKALE Labs 2019-Present - */ - -// init very basics -const fs = require( "fs" ); -// const path = require( "path" ); -// const url = require( "url" ); -// const os = require( "os" ); -const w3mod = require( "web3" ); -const ethereumjs_tx = require( "ethereumjs-tx" ); -const ethereumjs_wallet = require( "ethereumjs-wallet" ); -const ethereumjs_util = require( "ethereumjs-util" ); - -const Redis = require( "ioredis" ); -let redis = null; -let loopTmSendingCnt = 0; - -const log = require( "../skale-log/log.js" ); -const cc = log.cc; -cc.enable( false ); -log.addStdout(); -// log.add( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ); // example: log output to file - -const owaspUtils = require( "../skale-owasp/owasp-util.js" ); -const { getWeb3FromURL } = require( "../../agent/cli.js" ); - -const g_mtaStrLongSeparator = "======================================================================================================================="; - -const perMessageGasForTransfer = 1000000; -const additionalS2MTransferOverhead = 200000; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// logging helpers -// -const VERBOSE = { - 0: "silent", - 2: "fatal", - 3: "error", - 4: "warning", - 5: "attention", - 6: "information", - 7: "notice", - 8: "debug", - 9: "trace" -}; -const RV_VERBOSE = ( function() { - const m = {}; - for( const key in VERBOSE ) { - if( !VERBOSE.hasOwnProperty( key ) ) - continue; // skip loop if the property is from prototype - const name = VERBOSE[key]; - m[name] = key; - } - m.warn = m.warning; // alias - m.info = m.information; // alias - return m; -}() ); - -let g_isExposeDetails = false; -let g_verboseLevel = RV_VERBOSE.error; - -function expose_details_get() { - return g_isExposeDetails; -} -function expose_details_set( x ) { - g_isExposeDetails = x ? true : false; -} - -function verbose_get() { - return g_verboseLevel; -} -function verbose_set( x ) { - g_verboseLevel = x; -} - -function verbose_parse( s ) { - let n = 5; - try { - const isNumbersOnly = /^\d+$/.test( s ); - if( isNumbersOnly ) - n = owaspUtils.toInteger( s ); - else { - const ch0 = s[0].toLowerCase(); - for( const key in VERBOSE ) { - if( !VERBOSE.hasOwnProperty( key ) ) - continue; // skip loop if the property is from prototype - const name = VERBOSE[key]; - const ch1 = name[0].toLowerCase(); - if( ch0 == ch1 ) { - n = key; - break; - } - } - } - } catch ( err ) {} - return n; -} - -function verbose_list() { - for( const key in VERBOSE ) { - if( !VERBOSE.hasOwnProperty( key ) ) - continue; // skip loop if the property is from prototype - const name = VERBOSE[key]; - console.log( " " + cc.info( key ) + cc.sunny( "=" ) + cc.bright( name ) ); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const g_nSleepBeforeFetchOutgoingMessageEvent = 5000; -let g_nSleepBetweenTransactionsOnSChainMilliseconds = 0; // example - 5000 -let g_bWaitForNextBlockOnSChain = false; - -function getSleepBetweenTransactionsOnSChainMilliseconds() { - return g_nSleepBetweenTransactionsOnSChainMilliseconds; -} -function setSleepBetweenTransactionsOnSChainMilliseconds( val ) { - g_nSleepBetweenTransactionsOnSChainMilliseconds = val ? val : 0; -} - -function getWaitForNextBlockOnSChain() { - return g_bWaitForNextBlockOnSChain ? true : false; -} -function setWaitForNextBlockOnSChain( val ) { - g_bWaitForNextBlockOnSChain = val ? true : false; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const sleep = ( milliseconds ) => { return new Promise( resolve => setTimeout( resolve, milliseconds ) ); }; -const current_timestamp = () => { return parseInt( parseInt( Date.now().valueOf() ) / 1000 ); }; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function wait_for_next_block_to_appear( details, w3 ) { - const nBlockNumber = await get_web3_blockNumber( details, 10, w3 ); - details.write( cc.debug( "Waiting for next block to appear..." ) + "\n" ); - details.write( cc.debug( " ...have block " ) + cc.info( parseIntOrHex( nBlockNumber ) ) + "\n" ); - for( ; true; ) { - await sleep( 1000 ); - const nBlockNumber2 = await get_web3_blockNumber( details, 10, w3 ); - details.write( cc.debug( " ...have block " ) + cc.info( parseIntOrHex( nBlockNumber2 ) ) + "\n" ); - if( nBlockNumber2 > nBlockNumber ) - break; - } -} - -async function get_web3_blockNumber( details, cntAttempts, w3, retValOnFail, throwIfServerOffline ) { - const strFnName = "getBlockNumber"; - const u = owaspUtils.w3_2_url( w3 ); - const nWaitStepMilliseconds = 10 * 1000; - if( throwIfServerOffline == null || throwIfServerOffline == undefined ) - throwIfServerOffline = true; - cntAttempts = parseIntOrHex( cntAttempts ) < 1 ? 1 : parseIntOrHex( cntAttempts ); - if( retValOnFail == null || retValOnFail == undefined ) - retValOnFail = ""; - let idxAttempt = 1; - let ret = retValOnFail; - try { - ret = await w3.eth[strFnName](); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - } - ++ idxAttempt; - while( ret === "" && idxAttempt <= cntAttempts ) { - const isOnlone = rpcCall.check_url( u, nWaitStepMilliseconds ); - if( ! isOnlone ) { - ret = retValOnFail; - if( ! throwIfServerOffline ) - return ret; - details.write( - cc.error( "Cannot call " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + cc.u( u ) + - cc.warning( " because server is off-line" ) + "\n" ); - throw new Error( "Cannot " + strFnName + "() via " + u.toString() + " because server is off-line" ); - } - details.write( - cc.warning( "Repeat call to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.warning( ", attempt " ) + cc.info( idxAttempt ) + - "\n" ); - // await sleep( nWaitStepMilliseconds ); - try { - ret = await w3.eth[strFnName](); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - } - ++ idxAttempt; - } - if( ( idxAttempt + 1 ) > cntAttempts && ret === "" ) { - details.write( cc.fatal( "ERROR:" ) + - cc.error( " Failed call to " ) + cc.note( strFnName + "()" ) + - + cc.error( " via " ) + cc.u( u ) + cc.error( " after " ) + cc.info( cntAttempts ) + cc.error( " attempts " ) + - "\n" ); - throw new Error( "Failed call to " + strFnName + "() via " + u.toString() + " after " + cntAttempts + " attempts" ); - } - return ret; -} - -async function get_web3_transactionCount( details, cntAttempts, w3, address, param, retValOnFail, throwIfServerOffline ) { - const strFnName = "getTransactionCount"; - const u = owaspUtils.w3_2_url( w3 ); - const nWaitStepMilliseconds = 10 * 1000; - if( throwIfServerOffline == null || throwIfServerOffline == undefined ) - throwIfServerOffline = true; - cntAttempts = parseIntOrHex( cntAttempts ) < 1 ? 1 : parseIntOrHex( cntAttempts ); - if( retValOnFail == null || retValOnFail == undefined ) - retValOnFail = ""; - let ret = retValOnFail; - let idxAttempt = 1; - try { - ret = await w3.eth[strFnName]( address, param ); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - } - ++ idxAttempt; - while( ret === "" && idxAttempt <= cntAttempts ) { - const isOnlone = rpcCall.check_url( u, nWaitStepMilliseconds ); - if( ! isOnlone ) { - ret = retValOnFail; - if( ! throwIfServerOffline ) - return ret; - details.write( - cc.error( "Cannot call " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + cc.u( u ) + - cc.warning( " because server is off-line" ) + "\n" ); - throw new Error( "Cannot " + strFnName + "() via " + u.toString() + " because server is off-line" ); - } - details.write( - cc.warning( "Repeat call to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.warning( ", attempt " ) + cc.info( idxAttempt ) + - "\n" ); - // await sleep( nWaitStepMilliseconds ); - try { - ret = await w3.eth[strFnName]( address, param ); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - } - ++ idxAttempt; - } - if( ( idxAttempt + 1 ) > cntAttempts && ret === "" ) { - details.write( cc.fatal( "ERROR:" ) + - cc.error( " Failed call to " ) + cc.note( strFnName + "()" ) + - + cc.error( " via " ) + cc.u( u ) + cc.error( " after " ) + cc.info( cntAttempts ) + cc.error( " attempts " ) + - "\n" ); - throw new Error( "Failed call to " + strFnName + "() via " + u.toString() + " after " + cntAttempts + " attempts" ); - } - return ret; -} - -async function get_web3_transactionReceipt( details, cntAttempts, w3, txHash, retValOnFail, throwIfServerOffline ) { - const strFnName = "getTransactionReceipt"; - const u = owaspUtils.w3_2_url( w3 ); - const nWaitStepMilliseconds = 10 * 1000; - if( throwIfServerOffline == null || throwIfServerOffline == undefined ) - throwIfServerOffline = true; - cntAttempts = parseIntOrHex( cntAttempts ) < 1 ? 1 : parseIntOrHex( cntAttempts ); - if( retValOnFail == null || retValOnFail == undefined ) - retValOnFail = ""; - let ret = retValOnFail; - let idxAttempt = 1; - try { - ret = await w3.eth[strFnName]( txHash ); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - } - ++ idxAttempt; - while( txReceipt === "" && idxAttempt <= cntAttempts ) { - const isOnlone = rpcCall.check_url( u, nWaitStepMilliseconds ); - if( ! isOnlone ) { - ret = retValOnFail; - if( ! throwIfServerOffline ) - return ret; - details.write( - cc.error( "Cannot call " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + cc.u( u ) + - cc.warning( " because server is off-line" ) + "\n" ); - throw new Error( "Cannot " + strFnName + "() via " + u.toString() + " because server is off-line" ); - } - details.write( - cc.warning( "Repeat call to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.warning( ", attempt " ) + cc.info( idxAttempt ) + - "\n" ); - // await sleep( nWaitStepMilliseconds ); - try { - ret = await w3.eth[strFnName]( txHash ); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - } - ++ idxAttempt; - } - if( ( idxAttempt + 1 ) > cntAttempts && ( txReceipt === "" || txReceipt === undefined ) ) { - details.write( cc.fatal( "ERROR:" ) + - cc.error( " Failed call to " ) + cc.note( strFnName + "()" ) + - + cc.error( " via " ) + cc.u( u ) + cc.error( " after " ) + cc.info( cntAttempts ) + cc.error( " attempts " ) + - "\n" ); - throw new Error( "Failed call to " + strFnName + "() via " + u.toString() + " after " + cntAttempts + " attempts" ); - } - return ret; -} - -async function get_web3_pastEvents( details, w3, cntAttempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter, retValOnFail, throwIfServerOffline ) { - const strFnName = "getPastEvents"; - const u = owaspUtils.w3_2_url( w3 ); - const nWaitStepMilliseconds = 10 * 1000; - if( throwIfServerOffline == null || throwIfServerOffline == undefined ) - throwIfServerOffline = true; - cntAttempts = parseIntOrHex( cntAttempts ) < 1 ? 1 : parseIntOrHex( cntAttempts ); - if( retValOnFail == null || retValOnFail == undefined ) - retValOnFail = ""; - let ret = retValOnFail; - let idxAttempt = 1; - const strErrorTextAboutNotExistingEvent = "Event \"" + strEventName + "\" doesn't exist in this contract"; - try { - ret = await joContract[strFnName]( "" + strEventName, { - filter: joFilter, - fromBlock: nBlockFrom, - toBlock: nBlockTo - } ); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", from block " ) + cc.warning( nBlockFrom ) + cc.error( ", to block " ) + cc.warning( nBlockTo ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - if( err.toString().indexOf( strErrorTextAboutNotExistingEvent ) >= 0 ) { - details.write( - cc.error( "Did stopped calls to " ) + cc.note( strFnName + "()" ) + - cc.error( " because event " ) + cc.notice( strEventName ) + - cc.error( " does not exist in smart contract " ) + - "\n" ); - return ret; - } - } - ++ idxAttempt; - while( ret === "" && idxAttempt <= cntAttempts ) { - const isOnlone = rpcCall.check_url( u, nWaitStepMilliseconds ); - if( ! isOnlone ) { - ret = retValOnFail; - if( ! throwIfServerOffline ) - return ret; - details.write( - cc.error( "Cannot call " ) + cc.note( strFnName + "()" ) + cc.error( " via " ) + cc.u( u ) + - cc.warning( " because server is off-line" ) + "\n" ); - throw new Error( - "Cannot " + strFnName + "(), from block " + nBlockFrom + ", to block " + nBlockTo + - " via " + u.toString() + " because server is off-line" - ); - } - details.write( - cc.warning( "Repeat call to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.warning( ", attempt " ) + cc.info( idxAttempt ) + - "\n" ); - // await sleep( nWaitStepMilliseconds ); - try { - ret = await joContract[strFnName]( "" + strEventName, { - filter: joFilter, - fromBlock: nBlockFrom, - toBlock: nBlockTo - } ); - return ret; - } catch ( err ) { - ret = retValOnFail; - details.write( - cc.error( "Failed call attempt " ) + cc.info( idxAttempt ) + - cc.error( " to " ) + cc.note( strFnName + "()" ) + - cc.error( " via " ) + cc.u( u ) + - cc.error( ", from block " ) + cc.warning( nBlockFrom ) + cc.error( ", to block " ) + cc.warning( nBlockTo ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - "\n" ); - if( err.toString().indexOf( strErrorTextAboutNotExistingEvent ) >= 0 ) { - details.write( - cc.error( "Did stopped calls to " ) + cc.note( strFnName + "()" ) + - cc.error( " because event " ) + cc.notice( strEventName ) + - cc.error( " does not exist in smart contract " ) + - "\n" ); - return ret; - } - } - ++ idxAttempt; - } - if( ( idxAttempt + 1 ) === cntAttempts && ret === "" ) { - details.write( cc.fatal( "ERROR:" ) + - cc.error( " Failed call to " ) + cc.note( strFnName + "()" ) + - + cc.error( " via " ) + cc.u( u ) + - cc.error( ", from block " ) + cc.warning( nBlockFrom ) + cc.error( ", to block " ) + cc.warning( nBlockTo ) + - cc.error( " after " ) + cc.info( cntAttempts ) + cc.error( " attempts " ) + - "\n" ); - throw new Error( - "Failed call to " + strFnName + "(), from block " + nBlockFrom + ", to block " + nBlockTo + - " via " + u.toString() + " after " + cntAttempts + " attempts" - ); - } - return ret; -} - -let g_nCountOfBlocksInIterativeStep = 1000; -let g_nMaxBlockScanIterationsInAllRange = 5000; - -function getBlocksCountInInIterativeStepOfEventsScan() { - return g_nCountOfBlocksInIterativeStep; -} -function setBlocksCountInInIterativeStepOfEventsScan( n ) { - if( ! n ) - g_nCountOfBlocksInIterativeStep = 0; - else { - g_nCountOfBlocksInIterativeStep = parseIntOrHex( n ); - if( g_nCountOfBlocksInIterativeStep < 0 ) - g_nCountOfBlocksInIterativeStep = 0; - } -} - -function getMaxIterationsInAllRangeEventsScan() { - return g_nCountOfBlocksInIterativeStep; -} -function setMaxIterationsInAllRangeEventsScan( n ) { - if( ! n ) - g_nMaxBlockScanIterationsInAllRange = 0; - else { - g_nMaxBlockScanIterationsInAllRange = parseIntOrHex( n ); - if( g_nMaxBlockScanIterationsInAllRange < 0 ) - g_nMaxBlockScanIterationsInAllRange = 0; - } -} - -async function get_web3_pastEventsIterative( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ) { - if( g_nCountOfBlocksInIterativeStep <= 0 || g_nMaxBlockScanIterationsInAllRange <= 0 ) { - details.write( - cc.fatal( "IMPORTANT NOTICE:" ) + " " + - cc.warning( "Will skip " ) + cc.attention( "iterative" ) + cc.warning( " events scan in block range from " ) + - cc.info( nBlockFrom ) + cc.warning( " to " ) + cc.info( nBlockTo ) + - cc.warning( " because it's " ) + cc.error( "DISABLED" ) + "\n" ); - return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ); - } - if( nBlockFrom == 0 && nBlockTo == "latest" ) { - const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 ); - if( ( nLatestBlockNumber / g_nCountOfBlocksInIterativeStep ) > g_nMaxBlockScanIterationsInAllRange ) { - details.write( - cc.fatal( "IMPORTANT NOTICE:" ) + " " + - cc.warning( "Will skip " ) + cc.attention( "iterative" ) + cc.warning( " scan and use scan in block range from " ) + - cc.info( nBlockFrom ) + cc.warning( " to " ) + cc.info( nBlockTo ) + "\n" ); - return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ); - } - } - details.write( - cc.debug( "Iterative scan in " ) + - cc.info( nBlockFrom ) + cc.debug( "/" ) + cc.info( nBlockTo ) + - cc.debug( " block range..." ) + "\n" ); - if( nBlockTo == "latest" ) { - const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 ); - nBlockTo = nLatestBlockNumber; - details.write( - cc.debug( "Iterative scan up to latest block " ) + - cc.attention( "#" ) + cc.info( nBlockTo ) + - cc.debug( " assumed instead of " ) + cc.attention( "latest" ) + "\n" ); - } - let idxBlockSubRangeFrom = parseIntOrHex( nBlockFrom ); - for( ; true; ) { - let idxBlockSubRangeTo = idxBlockSubRangeFrom + g_nCountOfBlocksInIterativeStep; - if( idxBlockSubRangeTo > nBlockTo ) - idxBlockSubRangeTo = nBlockTo; - try { - details.write( - cc.debug( "Iterative scan of " ) + - cc.info( idxBlockSubRangeFrom ) + cc.debug( "/" ) + cc.info( idxBlockSubRangeTo ) + - cc.debug( " block sub-range in " ) + - cc.info( nBlockFrom ) + cc.debug( "/" ) + cc.info( nBlockTo ) + - cc.debug( " block range..." ) + "\n" ); - const joAllEventsInBlock = await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, idxBlockSubRangeFrom, idxBlockSubRangeTo, joFilter ); - if( joAllEventsInBlock && joAllEventsInBlock != "" && joAllEventsInBlock.length > 0 ) { - details.write( - cc.success( "Result of " ) + cc.attention( "iterative" ) + cc.success( " scan in " ) + - cc.info( nBlockFrom ) + cc.success( "/" ) + cc.info( nBlockTo ) + - cc.success( " block range is " ) + cc.j( joAllEventsInBlock ) + "\n" ); - return joAllEventsInBlock; - } - } catch ( err ) { - details.write( - cc.error( "Got scan error during interative scan of " ) + - cc.info( idxBlockSubRangeFrom ) + cc.error( "/" ) + cc.info( idxBlockSubRangeTo ) + - cc.error( " block sub-range in " ) + cc.info( nBlockFrom ) + cc.error( "/" ) + cc.info( nBlockTo ) + - cc.error( " block range, error is: " ) + cc.warning( err.toString() ) + "\n" - ); - } - idxBlockSubRangeFrom = idxBlockSubRangeTo; - if( idxBlockSubRangeFrom == nBlockTo ) - break; - } - details.write( - cc.debug( "Result of " ) + cc.attention( "iterative" ) + cc.debug( " scan in " ) + - cc.info( nBlockFrom ) + cc.debug( "/" ) + cc.info( nBlockTo ) + - cc.debug( " block range is " ) + cc.warning( "empty" ) + "\n" ); - return ""; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function verify_transfer_error_category_name( strCategory ) { - return "" + ( strCategory ? strCategory : "default" ); -} - -const g_nMaxLastTransferErrors = 20; -const g_arrLastTransferErrors = []; -let g_mapTransferErrorCategories = { }; - -function save_transfer_error( strCategory, textLog ) { - const ts = Math.round( ( new Date() ).getTime() / 1000 ); - const c = verify_transfer_error_category_name( strCategory ); - g_arrLastTransferErrors.push( { - ts: ts, - category: "" + c, - textLog: "" + textLog.toString() - } ); - while( g_arrLastTransferErrors.length > g_nMaxLastTransferErrors ) - g_arrLastTransferErrors.shift(); - g_mapTransferErrorCategories["" + c] = true; -} - -function save_transfer_success( strCategory ) { - const c = verify_transfer_error_category_name( strCategory ); - try { delete g_mapTransferErrorCategories["" + c]; } catch ( err ) { } -} - -function save_transfer_success_all() { - g_mapTransferErrorCategories = { }; // clear all transfer error categories, out of time frame -} - -function get_last_transfer_errors( isIncludeTextLog ) { - if( typeof isIncludeTextLog == "undefined" ) - isIncludeTextLog = true; - const jarr = JSON.parse( JSON.stringify( g_arrLastTransferErrors ) ); - if( ! isIncludeTextLog ) { - for( let i = 0; i < jarr.length; ++ i ) { - const jo = jarr[i]; - if( "textLog" in jo ) - delete jo.textLog; - } - } // if( ! isIncludeTextLog ) - return jarr; -} - -function get_last_error_categories() { - return Object.keys( g_mapTransferErrorCategories ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -let g_bIsEnabledProgressiveEventsScan = true; - -function getEnabledProgressiveEventsScan() { - return g_bIsEnabledProgressiveEventsScan ? true : false; -} -function setEnabledProgressiveEventsScan( isEnabled ) { - g_bIsEnabledProgressiveEventsScan = isEnabled ? true : false; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -let g_bIsEnabledOracle = false; - -function getEnabledOracle( isEnabled ) { - return g_bIsEnabledOracle ? true : false; -} - -function setEnabledOracle( isEnabled ) { - g_bIsEnabledOracle = isEnabled ? true : false; -} - -async function do_oracle_gas_price_setup( - w3_main_net, - w3_schain, - tc_schain, - jo_community_locker, - joAccountSC, - chain_id_mainnet, - chain_id_schain, - fn_sign_o_msg, - optsPendingTxAnalysis -) { - if( ! getEnabledOracle() ) - return; - const details = log.createMemoryStream(); - const jarrReceipts = []; - const strLogPrefix = cc.info( "Oracle gas price setup:" ) + " "; - if( fn_sign_o_msg == null || fn_sign_o_msg == undefined ) { - details.write( strLogPrefix + cc.debug( "Using internal u256 signing stub function" ) + "\n" ); - fn_sign_o_msg = async function( u256, details, fnAfter ) { - details.write( strLogPrefix + cc.debug( "u256 signing callback was " ) + cc.error( "not provided" ) + "\n" ); - await fnAfter( null, u256, null ); // null - no error, null - no signatures - }; - } else - details.write( strLogPrefix + cc.debug( "Using externally provided u256 signing function" ) + "\n" ); - let strActionName = ""; - try { - strActionName = "do_oracle_gas_price_setup.latestBlockNumber()"; - const latestBlockNumber = await w3_main_net.eth.getBlockNumber(); - details.write( cc.debug( "Latest block on Main Net is " ) + cc.info( latestBlockNumber ) + "\n" ); - strActionName = "do_oracle_gas_price_setup.bnTimestampOfBlock()"; - const latestBlock = await w3_main_net.eth.getBlock( latestBlockNumber ); - let bnTimestampOfBlock = w3_main_net.utils.toBN( latestBlock.timestamp ); - details.write( - cc.debug( "Local timestamp on Main Net is " ) + cc.info( bnTimestampOfBlock.toString() ) + cc.debug( "=" ) + - cc.info( "0x" + bnTimestampOfBlock.toString( 16 ) ) + cc.debug( " (original)" ) + - "\n" ); - const bnTimeZoneOffset = w3_main_net.utils.toBN( parseInt( new Date( parseInt( bnTimestampOfBlock.toString(), 10 ) ).getTimezoneOffset(), 10 ) ); - details.write( - cc.debug( "Local time zone offset is " ) + cc.info( bnTimeZoneOffset.toString() ) + cc.debug( "=" ) + - cc.info( "0x" + bnTimeZoneOffset.toString( 16 ) ) + cc.debug( " (original)" ) + - "\n" ); - bnTimestampOfBlock = bnTimestampOfBlock.add( bnTimeZoneOffset ); - details.write( - cc.debug( "UTC timestamp on Main Net is " ) + cc.info( bnTimestampOfBlock.toString() ) + cc.debug( "=" ) + - cc.info( "0x" + bnTimestampOfBlock.toString( 16 ) ) + cc.debug( " (original)" ) + - "\n" ); - const bnValueToSubtractFromTimestamp = w3_main_net.utils.toBN( 60 ); - details.write( - cc.debug( "Value to subtract from timestamp is " ) + cc.info( bnValueToSubtractFromTimestamp ) + cc.debug( "=" ) + - cc.info( "0x" + bnValueToSubtractFromTimestamp.toString( 16 ) ) + cc.debug( " (to adjust it to past a bit)" ) + "\n" ); - bnTimestampOfBlock = bnTimestampOfBlock.sub( bnValueToSubtractFromTimestamp ); - details.write( - cc.debug( "Timestamp on Main Net is " ) + cc.info( bnTimestampOfBlock.toString() ) + cc.debug( "=" ) + - cc.info( "0x" + bnTimestampOfBlock.toString( 16 ) ) + cc.debug( " (adjusted to past a bit)" ) + - "\n" ); - strActionName = "do_oracle_gas_price_setup.getGasPrice()"; - let gasPriceOnMainNet = null; - if( IMA.getEnabledOracle() ) { - const oracleOpts = { - url: owaspUtils.w3_2_url( w3_schain ), - callOpts: { }, - nMillisecondsSleepBefore: 1000, - nMillisecondsSleepPeriod: 3000, - cntAttempts: 40, - isVerbose: ( verbose_get() >= RV_VERBOSE.information ) ? true : false, - isVerboseTraceDetails: ( verbose_get() >= RV_VERBOSE.trace ) ? true : false - }; - details.write( - cc.debug( "Will fetch " ) + cc.info( "Main Net gas price" ) + - cc.debug( " via call to " ) + cc.info( "Oracle" ) + - cc.debug( " with options " ) + cc.j( oracleOpts ) + - cc.debug( "..." ) + "\n" ); - try { - gasPriceOnMainNet = owaspUtils.ensure_starts_with_0x( ( await imaOracle.get_gas_price( oracleOpts, details ) ).toString( 16 ) ); - } catch ( err ) { - gasPriceOnMainNet = null; - details.write( - cc.error( "Failed to fetch " ) + cc.info( "Main Net gas price" ) + - cc.error( " via call to " ) + cc.info( "Oracle" ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + "\n" ); - } - } - if( gasPriceOnMainNet === null ) { - details.write( - cc.debug( "Will fetch " ) + cc.info( "Main Net gas price" ) + - cc.debug( " directly..." ) + "\n" ); - gasPriceOnMainNet = "0x" + w3_main_net.utils.toBN( await w3_main_net.eth.getGasPrice() ).toString( 16 ); - } - details.write( - cc.success( "Done, " ) + cc.info( "Oracle" ) + cc.success( " did computed new " ) + cc.info( "Main Net gas price" ) + - cc.success( "=" ) + cc.bright( w3_main_net.utils.toBN( gasPriceOnMainNet ).toString() ) + - cc.success( "=" ) + cc.bright( gasPriceOnMainNet ) + - "\n" ); - // - const joGasPriceOnMainNetOld = - await jo_community_locker.methods.mainnetGasPrice().call( { - from: joAccountSC.address( w3_schain ) - } ); - const bnGasPriceOnMainNetOld = w3_schain.utils.toBN( joGasPriceOnMainNetOld ); - details.write( - cc.debug( "Previous " ) + cc.info( "Main Net gas price" ) + cc.debug( " saved and kept in " ) + cc.info( "CommunityLocker" ) + - cc.debug( "=" ) + cc.bright( bnGasPriceOnMainNetOld.toString() ) + - cc.debug( "=" ) + cc.bright( bnGasPriceOnMainNetOld.toString( 16 ) ) + - "\n" ); - if( bnGasPriceOnMainNetOld.eq( w3_schain.utils.toBN( gasPriceOnMainNet ) ) ) { - details.write( - cc.debug( "Previous " ) + cc.info( "Main Net gas price" ) + - cc.debug( " is equal to new one, will skip setting it in " ) + cc.info( "CommunityLocker" ) + - "\n" ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_oracle_gas_price_setup", true ); - details.close(); - return; - } - // - strActionName = "do_oracle_gas_price_setup.fn_sign_o_msg()"; - await fn_sign_o_msg( gasPriceOnMainNet, details, async function( strError, u256, joGlueResult ) { - if( strError ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in do_oracle_gas_price_setup() during " + strActionName + ": " ) + cc.error( strError ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in do_oracle_gas_price_setup() during " + strActionName + ": " ) + cc.error( strError ) + "\n" ); - details.exposeDetailsTo( log, "do_oracle_gas_price_setup", false ); - save_transfer_error( "oracle", details.toString() ); - details.close(); - return; - } - // - // - strActionName = "do_oracle_gas_price_setup.formatSignature"; - let signature = joGlueResult ? joGlueResult.signature : null; - if( !signature ) - signature = { X: "0", Y: "0" }; - let hashPoint = joGlueResult ? joGlueResult.hashPoint : null; - if( !hashPoint ) - hashPoint = { X: "0", Y: "0" }; - let hint = joGlueResult ? joGlueResult.hint : null; - if( !hint ) - hint = "0"; - const sign = { - blsSignature: [ signature.X, signature.Y ], // BLS glue of signatures - hashA: hashPoint.X, // G1.X from joGlueResult.hashSrc - hashB: hashPoint.Y, // G1.Y from joGlueResult.hashSrc - counter: hint - }; - strActionName = "do_oracle_gas_price_setup.CommunityLocker.setGasPrice()"; - const methodWithArguments_setGasPrice = jo_community_locker.methods.setGasPrice( - // call params - u256, - "0x" + bnTimestampOfBlock.toString( 16 ), - sign // bls signature components - ); - const dataTx_setGasPrice = methodWithArguments_setGasPrice.encodeABI(); // the encoded ABI of the method - // - if( verbose_get() >= RV_VERBOSE.trace ) { - const joDebugArgs = [ - [ signature.X, signature.Y ], // BLS glue of signatures - hashPoint.X, // G1.X from joGlueResult.hashSrc - hashPoint.Y, // G1.Y from joGlueResult.hashSrc - hint - ]; - details.write( - strLogPrefix + - cc.debug( "....debug args for " ) + cc.debug( ": " ) + - cc.j( joDebugArgs ) + "\n" ); - } - // - const gasPrice = await tc_schain.computeGasPrice( w3_schain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_setGasPrice = await tc_schain.computeGas( methodWithArguments_setGasPrice, w3_schain, 10000000, gasPrice, joAccountSC.address( w3_schain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_setGasPrice ) + "\n" ); - // - const isIgnore_setGasPrice = false; - const strDRC_setGasPrice = "setGasPrice in message signer"; - const strErrorOfDryRun = await dry_run_call( details, w3_schain, methodWithArguments_setGasPrice, joAccountSC, strDRC_setGasPrice,isIgnore_setGasPrice, gasPrice, estimatedGas_setGasPrice, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const tcnt = await get_web3_transactionCount( details, 10, w3_schain, joAccountSC.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - const raw_tx_setGasPrice = { - chainId: chain_id_schain, - from: joAccountSC.address( w3_schain ), - nonce: tcnt, - gas: estimatedGas_setGasPrice, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: jo_community_locker.options.address, // contract address - data: dataTx_setGasPrice //, - // "value": wei_amount // 1000000000000000000 // w3_schain.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - if( chain_id_schain !== "Mainnet" ) - await checkTransactionToSchain( w3_schain, raw_tx_setGasPrice, details ); - - const tx_setGasPrice = compose_tx_instance( details, strLogPrefix, raw_tx_setGasPrice ); - const joSetGasPriceSR = await safe_sign_transaction_with_account( details, w3_schain, tx_setGasPrice, raw_tx_setGasPrice, joAccountSC ); - let joReceipt = null; - if( joSetGasPriceSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_schain, joSetGasPriceSR.txHashSent ); - else { - const serializedTx_setGasPrice = tx_setGasPrice.serialize(); - strActionName = "w3_schain.eth.sendSignedTransaction()"; - // let joReceipt = await w3_schain.eth.sendSignedTransaction( "0x" + serializedTx_setGasPrice.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_schain, serializedTx_setGasPrice, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "do_oracle_gas_price_setup/setGasPrice", - "receipt": joReceipt - } ); - print_gas_usage_report_from_array( "(intermediate result) ORACLE GAS PRICE SETUP ", jarrReceipts ); - // if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - // await async_pending_tx_complete( details, w3_schain, w3_main_net, chain_id_schain, chain_id_mainnet, "" + joReceipt.transactionHash ); - } - save_transfer_success( "oracle" ); - } ); - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in do_oracle_gas_price_setup() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in do_oracle_gas_price_setup() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.exposeDetailsTo( log, "do_oracle_gas_price_setup", false ); - save_transfer_error( "oracle", details.toString() ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ORACLE GAS PRICE SETUP ", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_oracle_gas_price_setup", true ); - details.close(); - return true; -} - -let g_isForwardS2S = true; // default S<->S transfer mode for "--s2s-transfer" is "forward" - -function get_S2S_transfer_mode_description() { - return g_isForwardS2S ? "forward" : "reverse"; -} - -function get_S2S_transfer_mode_description_colorized() { - return g_isForwardS2S ? cc.success( "forward" ) : cc.error( "reverse" ); -} - -function isForwardS2S() { - return g_isForwardS2S ? true : false; -} - -function isReverseS2S() { - return g_isForwardS2S ? false : true; -} - -function setForwardS2S( b ) { - if( b == null || b == undefined ) - b = true; - g_isForwardS2S = b ? true : false; -} - -function setReverseS2S( b ) { - if( b == null || b == undefined ) - b = true; - g_isForwardS2S = b ? false : true; -} - -function create_progressive_events_scan_plan( details, nLatestBlockNumber ) { - // assume Main Net mines 6 blocks per minute - const blks_in_1_minute = 6; - const blks_in_1_hour = blks_in_1_minute * 60; - const blks_in_1_day = blks_in_1_hour * 24; - const blks_in_1_week = blks_in_1_day * 7; - const blks_in_1_month = blks_in_1_day * 31; - const blks_in_1_year = blks_in_1_day * 366; - const blks_in_3_years = blks_in_1_year * 3; - const arr_progressive_events_scan_plan_A = [ - { nBlockFrom: nLatestBlockNumber - blks_in_1_day, nBlockTo: "latest", type: "1 day" }, - { nBlockFrom: nLatestBlockNumber - blks_in_1_week, nBlockTo: "latest", type: "1 week" }, - { nBlockFrom: nLatestBlockNumber - blks_in_1_month, nBlockTo: "latest", type: "1 month" }, - { nBlockFrom: nLatestBlockNumber - blks_in_1_year, nBlockTo: "latest", type: "1 year" }, - { nBlockFrom: nLatestBlockNumber - blks_in_3_years, nBlockTo: "latest", type: "3 years" } - ]; - const arr_progressive_events_scan_plan = []; - for( let idxPlan = 0; idxPlan < arr_progressive_events_scan_plan_A.length; ++idxPlan ) { - const joPlan = arr_progressive_events_scan_plan_A[idxPlan]; - if( joPlan.nBlockFrom >= 0 ) - arr_progressive_events_scan_plan.push( joPlan ); - } - if( arr_progressive_events_scan_plan.length > 0 ) { - const joLastPlan = arr_progressive_events_scan_plan[arr_progressive_events_scan_plan.length - 1]; - if( ! ( joLastPlan.nBlockFrom == 0 && joLastPlan.nBlockTo == "latest" ) ) - arr_progressive_events_scan_plan.push( { nBlockFrom: 0, nBlockTo: "latest", type: "entire block range" } ); - } else - arr_progressive_events_scan_plan.push( { nBlockFrom: 0, nBlockTo: "latest", type: "entire block range" } ); - return arr_progressive_events_scan_plan; -} - -async function get_web3_pastEventsProgressive( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ) { - if( ! g_bIsEnabledProgressiveEventsScan ) { - details.write( - cc.fatal( "IMPORTANT NOTICE:" ) + " " + - cc.warning( "Will skip " ) + cc.attention( "progressive" ) + cc.warning( " events scan in block range from " ) + - cc.info( nBlockFrom ) + cc.warning( " to " ) + cc.info( nBlockTo ) + - cc.warning( " because it's " ) + cc.error( "DISABLED" ) + "\n" ); - return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ); - } - if( ! ( nBlockFrom == 0 && nBlockTo == "latest" ) ) { - details.write( - cc.debug( "Will skip " ) + cc.attention( "progressive" ) + cc.debug( " scan and use scan in block range from " ) + - cc.info( nBlockFrom ) + cc.debug( " to " ) + cc.info( nBlockTo ) + "\n" ); - return await get_web3_pastEvents( details, w3, attempts, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ); - } - details.write( cc.debug( "Will run " ) + cc.attention( "progressive" ) + cc.debug( " scan..." ) + "\n" ); - const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 ); - details.write( cc.debug( "Current latest block number is " ) + cc.info( nLatestBlockNumber ) + "\n" ); - const arr_progressive_events_scan_plan = create_progressive_events_scan_plan( details, nLatestBlockNumber ); - details.write( cc.debug( "Composed " ) + cc.attention( "progressive" ) + cc.debug( " scan plan is: " ) + cc.j( arr_progressive_events_scan_plan ) + "\n" ); - let joLastPlan = { nBlockFrom: 0, nBlockTo: "latest", type: "entire block range" }; - for( let idxPlan = 0; idxPlan < arr_progressive_events_scan_plan.length; ++idxPlan ) { - const joPlan = arr_progressive_events_scan_plan[idxPlan]; - if( joPlan.nBlockFrom < 0 ) - continue; - joLastPlan = joPlan; - details.write( - cc.debug( "Progressive scan of " ) + cc.attention( "getPastEvents" ) + cc.debug( "/" ) + cc.info( strEventName ) + - cc.debug( ", from block " ) + cc.info( joPlan.nBlockFrom ) + - cc.debug( ", to block " ) + cc.info( joPlan.nBlockTo ) + - cc.debug( ", block range is " ) + cc.info( joPlan.type ) + - cc.debug( "..." ) + "\n" ); - try { - const joAllEventsInBlock = await get_web3_pastEventsIterative( details, w3, attempts, joContract, strEventName, joPlan.nBlockFrom, joPlan.nBlockTo, joFilter ); - if( joAllEventsInBlock && joAllEventsInBlock.length > 0 ) { - details.write( - cc.success( "Progressive scan of " ) + cc.attention( "getPastEvents" ) + cc.debug( "/" ) + cc.info( strEventName ) + - cc.success( ", from block " ) + cc.info( joPlan.nBlockFrom ) + - cc.success( ", to block " ) + cc.info( joPlan.nBlockTo ) + - cc.success( ", block range is " ) + cc.info( joPlan.type ) + - cc.success( ", found " ) + cc.info( joAllEventsInBlock.length ) + - cc.success( " event(s)" ) + "\n" ); - return joAllEventsInBlock; - } - } catch ( err ) {} - } - // throw new Error( - // "Could not not get Event \"" + strEventName + - // "\", from block " + joLastPlan.nBlockFrom + ", to block " + joLastPlan.nBlockTo + - // ", using progressive event scan" - // ); - details.write( - cc.error( "Could not not get Event \"" ) + cc.info( strEventName ) + - cc.error( "\", from block " ) + cc.info( joLastPlan.nBlockFrom ) + - cc.error( ", to block " ) + cc.info( joLastPlan.nBlockTo ) + - cc.debug( ", block range is " ) + cc.info( joLastPlan.type ) + - cc.error( ", using " ) + cc.attention( "progressive" ) + cc.error( " event scan" ) + "\n" ); - return []; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function get_contract_call_events( details, w3, joContract, strEventName, nBlockNumber, strTxHash, joFilter ) { - joFilter = joFilter || {}; - let nBlockFrom = nBlockNumber - 10, nBlockTo = nBlockNumber + 10; - const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3 ); - if( nBlockFrom < 0 ) - nBlockFrom = 0; - if( nBlockTo > nLatestBlockNumber ) - nBlockTo = nLatestBlockNumber; - const joAllEventsInBlock = await get_web3_pastEventsIterative( details, w3, 10, joContract, strEventName, nBlockFrom, nBlockTo, joFilter ); - const joAllTransactionEvents = []; let i; - for( i = 0; i < joAllEventsInBlock.length; ++i ) { - const joEvent = joAllEventsInBlock[i]; - if( "transactionHash" in joEvent && joEvent.transactionHash == strTxHash ) - joAllTransactionEvents.push( joEvent ); - } - return joAllTransactionEvents; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function compose_tx_instance( details, strLogPrefix, rawTx ) { - details.write( cc.attention( "TRANSACTION COMPOSER" ) + cc.normal( " is using " ) + cc.bright( "Web3" ) + cc.normal( " version " ) + cc.sunny( w3mod.version ) + "\n" ); - strLogPrefix = strLogPrefix || ""; - rawTx = JSON.parse( JSON.stringify( rawTx ) ); // clone - const joOpts = null; - /* - if( "chainId" in rawTx && typeof rawTx.chainId == "number" ) { - switch ( rawTx.chainId ) { - case 1: - delete rawTx.chainId; - joOpts = joOpts || { }; - joOpts.chain = "mainnet"; - break; - case 3: - delete rawTx.chainId; - joOpts = joOpts || { }; - joOpts.chain = "ropsten"; - break; - case 4: - delete rawTx.chainId; - joOpts = joOpts || { }; - joOpts.chain = "rinkeby"; - break; - case 5: - delete rawTx.chainId; - joOpts = joOpts || { }; - joOpts.chain = "goerli"; - break; - case 2018: - delete rawTx.chainId; - joOpts = joOpts || { }; - joOpts.chain = "dev"; - break; - } // switch( rawTx.chainId ) - } -*/ - // if( rawTx.chainId && Number(rawTx.chainId) > 1 ) { - // rawTx.nonce += 1048576; // see https://ethereum.stackexchange.com/questions/12810/need-help-signing-a-raw-transaction-with-ethereumjs-tx - // rawTx.nonce = w3mod.utils.toHex( rawTx.nonce ); - // } - details.write( strLogPrefix + cc.debug( "....composed " ) + cc.notice( JSON.stringify( rawTx ) ) + cc.debug( " with opts " ) + cc.j( joOpts ) + "\n" ); - let tx = null; - if( joOpts ) - tx = new ethereumjs_tx( rawTx, joOpts ); - else - tx = new ethereumjs_tx( rawTx ); - return tx; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -let g_bDryRunIsEnabled = true; - -function dry_run_is_enabled() { - return g_bDryRunIsEnabled ? true : false; -} - -function dry_run_enable( isEnable ) { - g_bDryRunIsEnabled = ( isEnable != null && isEnable != undefined ) ? ( isEnable ? true : false ) : true; - return g_bDryRunIsEnabled ? true : false; -} - -let g_bDryRunIsIgnored = false; - -function dry_run_is_ignored() { - return g_bDryRunIsIgnored ? true : false; -} - -function dry_run_ignore( isIgnored ) { - g_bDryRunIsIgnored = ( isIgnored != null && isIgnored != undefined ) ? ( isIgnored ? true : false ) : true; - return g_bDryRunIsIgnored ? true : false; -} - -function extract_dry_run_method_name( methodWithArguments ) { - try { - const s = "" + methodWithArguments._method.name; - return s; - } catch ( err ) { - } - return "N/A-method-name"; -} - -async function dry_run_call( details, w3, methodWithArguments, joAccount, strDRC, isIgnore, gasPrice, gasValue, ethValue ) { - details.write( cc.attention( "DRY RUN" ) + cc.normal( " is using " ) + cc.bright( "Web3" ) + cc.normal( " version " ) + cc.sunny( w3.version ) + "\n" ); - isIgnore = ( isIgnore != null && isIgnore != undefined ) ? ( isIgnore ? true : false ) : false; - const strMethodName = extract_dry_run_method_name( methodWithArguments ); - const strWillBeIgnored = isIgnore ? "IGNORED " : ""; - let strLogPrefix = cc.attention( strWillBeIgnored + "DRY RUN CALL TO THE " ) + cc.bright( strMethodName ) + cc.attention( " METHOD" ); - if( strDRC && typeof strDRC == "string" && strDRC.length ) - strLogPrefix += cc.normal( "(" ) + cc.debug( strDRC ) + cc.normal( ")" ); - strLogPrefix += cc.attention( ":" ) + " "; - if( ! dry_run_is_enabled() ) { - details.write( strLogPrefix + cc.success( "Skipped, dry run is disabled" ) + "\n" ); - return null; - } - try { - const addressFrom = joAccount.address( w3 ); - details.write( - strLogPrefix + cc.debug( " will call method" ) + - // cc.debug( " with data " ) + cc.normal( cc.safeStringifyJSON( methodWithArguments ) ) + - cc.debug( " from address " ) + cc.sunny( addressFrom ) + - "\n" ); - const joResult = await methodWithArguments.call( { - from: addressFrom, - gasPrice: gasPrice, - gas: gasValue, // 10000000 - value: "0x" + w3.utils.toBN( ethValue ).toString( 16 ) - } ); - details.write( strLogPrefix + cc.success( "got result " ) + cc.normal( cc.safeStringifyJSON( joResult ) ) + "\n" ); - } catch ( err ) { - let strErrorMessage = "" + strLogPrefix; - if( isIgnore ) - strErrorMessage += cc.warning( "IGNORED DRY RUN FAIL:" ); - else - strErrorMessage += cc.fatal( "CRITICAL DRY RUN FAIL:" ); - strErrorMessage += " " + cc.error( err ) + "\n"; - details.write( strErrorMessage ); - if( ! ( isIgnore || dry_run_is_ignored() ) ) { - details.write( - strLogPrefix + cc.fatal( "CRITICAL DRY RUN FAIL" ) + " " + - cc.error( " invoking the " ) + cc.info( strMethodName ) + cc.error( " method: " ) + - cc.warning( err.toString() ) + "\n" ); - return "CRITICAL DRY RUN FAIL invoking the \"" + strMethodName + "\" method: " + err.toString(); - } - } - return null; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function get_account_connectivity_info( joAccount ) { - const joACI = { - isBad: true, - strType: "bad", - isAutoSend: false - }; - if( "strTransactionManagerURL" in joAccount && typeof joAccount.strTransactionManagerURL == "string" && joAccount.strTransactionManagerURL.length > 0 ) { - joACI.isBad = false; - joACI.strType = "tm"; - joACI.isAutoSend = true; - } else if( "strSgxURL" in joAccount && typeof joAccount.strSgxURL == "string" && joAccount.strSgxURL.length > 0 && - "strSgxKeyName" in joAccount && typeof joAccount.strSgxKeyName == "string" && joAccount.strSgxKeyName.length > 0 - ) { - joACI.isBad = false; - joACI.strType = "sgx"; - } else if( "privateKey" in joAccount && typeof joAccount.privateKey == "string" && joAccount.privateKey.length > 0 ) { - joACI.isBad = false; - joACI.strType = "direct"; - } else { - // bad by default - } - return joACI; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const g_tm_pool = "transactions"; - -const tm_gen_random_hex = size => [ ...Array( size ) ].map( () => Math.floor( Math.random() * 16 ).toString( 16 ) ).join( "" ); - -function tm_make_id( details ) { - const prefix = "tx-"; - const unique = tm_gen_random_hex( 16 ); - const id = prefix + unique + "js"; - details.write( cc.debug( "TM - Generated id: " ) + cc.debug( id ) + "\n" ); - return id; -} - -function tm_make_record( tx = {}, score ) { - const status = "PROPOSED"; - return JSON.stringify( { - "score": score, - "status": status, - ...tx - } ); -} - -function tm_make_score( priority ) { - const ts = current_timestamp(); - return priority * Math.pow( 10, ts.toString().length ) + ts; -} - -async function tm_send( details, tx, priority = 5 ) { - details.write( cc.debug( "TM - sending tx " ) + cc.j( tx ) + - cc.debug( " ts: " ) + cc.info( current_timestamp() ) + "\n" ); - const id = tm_make_id( details ); - const score = tm_make_score( priority ); - const record = tm_make_record( tx, score ); - details.write( cc.debug( "TM - Sending score: " ) + cc.info( score ) + cc.debug( ", record: " ) + cc.info( record ) + "\n" ); - expiration = 24 * 60 * 60; // 1 day; - - await redis.multi() - .set( id, record, "EX", expiration ) - .zadd( g_tm_pool, score, id ) - .exec(); - return id; -} - -function tm_is_finished( record ) { - if( record == null ) - return null; - return [ "SUCCESS", "FAILED", "DROPPED" ].includes( record.status ); -} - -async function tm_get_record( txId ) { - const r = await redis.get( txId ); - if( r != null ) - return JSON.parse( r ); - return null; -} - -async function tm_wait( details, txId, w3, nWaitSeconds = 36000 ) { - const strPrefixDetails = cc.debug( "(gathered details)" ) + " "; - const strPrefixLog = cc.debug( "(immediate log)" ) + " "; - let strMsg = - cc.debug( "TM - will wait TX " ) + cc.info( txId ) + - cc.debug( " to complete for " ) + cc.info( nWaitSeconds ) + cc.debug( " second(s) maximum" ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - const startTs = current_timestamp(); - while( ! tm_is_finished( await tm_get_record( txId ) ) && ( current_timestamp() - startTs ) < nWaitSeconds ) - await sleep( 500 ); - const r = await tm_get_record( txId ); - strMsg = cc.debug( "TM - TX " ) + cc.info( txId ) + cc.debug( " record is " ) + cc.info( JSON.stringify( r ) ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - if( ( !r ) ) { - strMsg = cc.error( "TM - TX " ) + cc.info( txId ) + cc.error( " status is " ) + cc.warning( "NULL RECORD" ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - } else if( r.status == "SUCCESS" ) { - strMsg = cc.success( "TM - TX " ) + cc.info( txId ) + cc.success( " success" ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - } else { - strMsg = cc.error( "TM - TX " ) + cc.info( txId ) + cc.error( " status is " ) + cc.warning( r.status ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - } - if( ( !tm_is_finished( r ) ) || r.status == "DROPPED" ) { - log.write( cc.error( "TM - TX " ) + cc.info( txId ) + cc.error( " was unsuccessful, wait failed" ) + "\n" ); - return null; - } - const joReceipt = await get_web3_transactionReceipt( details, 10, w3, r.tx_hash ); - if( !joReceipt ) { - strMsg = cc.error( "TM - TX " ) + cc.info( txId ) + cc.error( " was unsuccessful, failed to fetch transaction receipt" ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - return null; - } - return joReceipt; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function tm_ensure_transaction( details, w3, priority, txAdjusted, cntAttempts, sleepMilliseconds ) { - cntAttempts = cntAttempts || 1; - sleepMilliseconds = sleepMilliseconds || ( 30 * 1000 ); - let txId = ""; - let joReceipt = null; - let idxAttempt = 0; - const strPrefixDetails = cc.debug( "(gathered details)" ) + " "; - const strPrefixLog = cc.debug( "(immediate log)" ) + " "; - let strMsg; - for( ; idxAttempt < cntAttempts; ++idxAttempt ) { - txId = await tm_send( details, txAdjusted, priority ); - strMsg = cc.debug( "TM - next TX " ) + cc.info( txId ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - joReceipt = await tm_wait( details, txId, w3 ); - if( joReceipt ) - break; - strMsg = - cc.warning( "TM - unsuccessful TX " ) + cc.info( txId ) + cc.warning( " sending attempt " ) + cc.info( idxAttempt ) + - cc.warning( " of " ) + cc.info( cntAttempts ) + cc.debug( " receipt: " ) + cc.info( joReceipt ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - await sleep( sleepMilliseconds ); - } - if( !joReceipt ) { - strMsg = - cc.fatal( "BAD ERROR:" ) + " " + cc.error( "TM TX " ) + cc.info( txId ) + - cc.error( " transaction has been dropped" ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - throw new Error( "TM unseccessful transaction " + txId ); - } - strMsg = - cc.success( "TM - successful TX " ) + cc.info( txId ) + cc.success( ", sending attempt " ) + cc.info( idxAttempt ) + - cc.success( " of " ) + cc.info( cntAttempts ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - return [ txId, joReceipt ]; -} - -async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAccount ) { - const strPrefixDetails = cc.debug( "(gathered details)" ) + " "; - const strPrefixLog = cc.debug( "(immediate log)" ) + " "; - const sendingCnt = loopTmSendingCnt++; - let strMsg = - cc.debug( "Sending transaction with account(" ) + cc.notice( "sending counter" ) + cc.debug( " is " ) + - cc.info( sendingCnt ) + cc.debug( "), raw TX object is " ) + cc.j( rawTx ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - const joSR = { - joACI: get_account_connectivity_info( joAccount ), - tx: null, - txHashSent: null - }; - switch ( joSR.joACI.strType ) { - case "tm": { - /* - details.write( - cc.debug( "Will sign with Transaction Manager wallet, transaction is " ) + cc.j( tx ) + - cc.debug( ", raw transaction is " ) + cc.j( rawTx ) + "\n" - // + cc.debug( " using account " ) + cc.j( joAccount ) + "\n" - ); - let rpcCallOpts = null; - if( "strPathSslKey" in joAccount && typeof joAccount.strPathSslKey == "string" && joAccount.strPathSslKey.length > 0 && - "strPathSslCert" in joAccount && typeof joAccount.strPathSslCert == "string" && joAccount.strPathSslCert.length > 0 - ) { - rpcCallOpts = { - }; - // details.write( cc.debug( "Will sign via Transaction Manager with SSL options " ) + cc.j( rpcCallOpts ) + "\n" ); - } - await rpcCall.create( joAccount.strTransactionManagerURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - const s = cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + cc.error( " JSON RPC call to Transaction Manager wallet failed" ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - const txAdjusted = JSON.parse( JSON.stringify( rawTx ) ); // tx // rawTx - if( "chainId" in txAdjusted ) - delete txAdjusted.chainId; - if( "gasLimit" in txAdjusted && ( ! ( "gas" in txAdjusted ) ) ) { - txAdjusted.gas = txAdjusted.gasLimit; - delete txAdjusted.gasLimit; - } - const joIn = { - "transaction_dict": JSON.stringify( txAdjusted ) - }; - details.write( cc.debug( "Calling Transaction Manager to sign-and-send with " ) + cc.j( txAdjusted ) + "\n" ); - await joCall.call( - joIn, - async function( joIn, joOut, err ) { - if( err ) { - const s = cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + cc.error( " JSON RPC call to Transaction Manager failed, error: " ) + cc.warning( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - details.write( cc.debug( "Transaction Manager sign-and-send result is: " ) + cc.j( joOut ) + "\n" ); - if( joOut && "data" in joOut && joOut.data && "transaction_hash" in joOut.data ) - joSR.txHashSent = "" + joOut.data.transaction_hash; - else { - const s = cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + cc.error( " JSON RPC call to Transaction Manager returned bad answer: " ) + cc.j( joOut ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - } ); - } ); - await sleep( 5000 ); - await wait_for_transaction_receipt( details, w3, joSR.txHashSent ); - */ - strMsg = - cc.debug( "Will sign with Transaction Manager wallet, transaction is " ) + cc.j( tx ) + - cc.debug( ", raw transaction is " ) + cc.j( rawTx ) - // + "\n" + cc.debug( " using account " ) + cc.j( joAccount ) - ; - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - const txAdjusted = JSON.parse( JSON.stringify( rawTx ) ); // tx // rawTx - if( "chainId" in txAdjusted ) - delete txAdjusted.chainId; - if( "gasLimit" in txAdjusted && ( ! ( "gas" in txAdjusted ) ) ) { - txAdjusted.gas = txAdjusted.gasLimit; - delete txAdjusted.gasLimit; - } - if( redis == null ) - redis = new Redis( joAccount.strTransactionManagerURL ); - const priority = joAccount.tm_priority || 5; - try { - const [ tx_id, joReceipt ] = await tm_ensure_transaction( details, w3, priority, txAdjusted ); - joSR.txHashSent = "" + joReceipt.transactionHash; - joSR.joReceipt = joReceipt; - joSR.tm_tx_id = tx_id; - } catch ( err ) { - strMsg = - cc.fatal( "BAD ERROR:" ) + " " + - cc.error( "TM - transaction was not sent, underlying error is: " ) + - cc.warning( err.toString() ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - // throw err; - } - } break; - case "sgx": { - details.write( - cc.debug( "Will sign with SGX wallet, transaction is " ) + cc.j( tx ) + - cc.debug( ", raw transaction is " ) + cc.j( rawTx ) + "\n" - // + cc.debug( " using account " ) + cc.j( joAccount ) + "\n" - ); - let rpcCallOpts = null; - if( "strPathSslKey" in joAccount && typeof joAccount.strPathSslKey == "string" && joAccount.strPathSslKey.length > 0 && - "strPathSslCert" in joAccount && typeof joAccount.strPathSslCert == "string" && joAccount.strPathSslCert.length > 0 - ) { - rpcCallOpts = { - "cert": fs.readFileSync( joAccount.strPathSslCert, "utf8" ), - "key": fs.readFileSync( joAccount.strPathSslKey, "utf8" ) - }; - // details.write( cc.debug( "Will sign via SGX with SSL options " ) + cc.j( rpcCallOpts ) + "\n" ); - } - await rpcCall.create( joAccount.strSgxURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - const s = cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + cc.error( " JSON RPC call to SGX wallet failed" ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - const msgHash = tx.hash( false ); - const strHash = msgHash.toString( "hex" ); - // details.write( cc.debug( "Transaction message hash is " ) + cc.j( msgHash ) + "\n" ); - const joIn = { - "method": "ecdsaSignMessageHash", - "params": { - "keyName": "" + joAccount.strSgxKeyName, - "messageHash": strHash, // "1122334455" - "base": 16 // 10 - } - }; - details.write( cc.debug( "Calling SGX to sign using ECDSA key with " ) + cc.info( joIn.method ) + cc.debug( "..." ) + "\n" ); - await joCall.call( joIn, async function( joIn, joOut, err ) { - if( err ) { - const s = cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + cc.error( " JSON RPC call to SGX wallet failed, error: " ) + cc.warning( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - details.write( cc.debug( "SGX wallet ECDSA sign result is: " ) + cc.j( joOut ) + "\n" ); - const joNeededResult = { - // "v": Buffer.from( parseIntOrHex( joOut.result.signature_v ).toString( "hex" ), "utf8" ), - // "r": Buffer.from( "" + joOut.result.signature_r, "utf8" ), - // "s": Buffer.from( "" + joOut.result.signature_s, "utf8" ) - "v": parseIntOrHex( joOut.result.signature_v, 10 ), - "r": "" + joOut.result.signature_r, - "s": "" + joOut.result.signature_s - }; - details.write( cc.debug( "Sign result to assign into transaction is: " ) + cc.j( joNeededResult ) + "\n" ); - // - // if( "_chainId" in tx && tx._chainId != null && tx._chainId != undefined ) - // tx.v += tx._chainId * 2 + 8; - // if( "_chainId" in tx && tx._chainId != null && tx._chainId != undefined ) - // joNeededResult.v += tx._chainId * 2 + 8; - // if( "_chainId" in tx && tx._chainId != null && tx._chainId != undefined ) - // joNeededResult.v += tx._chainId * 2 + 8 + 27; - let chainId = -4; - // details.write( cc.debug( "...trying tx._chainId = " ) + cc.info( tx._chainId ) + "\n" ); - if( "_chainId" in tx && tx._chainId != null && tx._chainId != undefined ) { - chainId = tx._chainId; - if( chainId == 0 ) - chainId = -4; - } - // details.write( cc.debug( "...applying chainId = " ) + cc.info( chainId ) + cc.debug( "to v = " ) + cc.info( joNeededResult.v ) + "\n" ); - // joNeededResult.v += chainId * 2 + 8 + 27; - joNeededResult.v += chainId * 2 + 8 + 27; - // details.write( cc.debug( "...result v =" ) + cc.info( joNeededResult.v ) + "\n" ); - // - // joNeededResult.v = to_eth_v( joNeededResult.v, tx._chainId ); - // - // Object.assign( tx, joNeededResult ); - tx.v = joNeededResult.v; - tx.r = joNeededResult.r; - tx.s = joNeededResult.s; - details.write( cc.debug( "Resulting adjusted transaction is: " ) + cc.j( tx ) + "\n" ); - } ); - } ); - await sleep( 3000 ); - } break; - case "direct": { - details.write( - cc.debug( "Will sign with private key, transaction is " ) + cc.notice( JSON.stringify( tx ) ) + - cc.debug( ", raw transaction is " ) + cc.notice( JSON.stringify( rawTx ) ) + "\n" - // + cc.debug( " using account " ) + cc.j( joAccount ) + "\n" - ); - const key = Buffer.from( joAccount.privateKey, "hex" ); // convert private key to buffer - tx.sign( key ); // arg is privateKey as buffer - } break; - default: { - const s = cc.fatal( "CRITICAL TRANSACTION SIGNING ERROR:" ) + - cc.error( " bad credentials information specified, no explicit SGX and no explicit private key found" ) + - // + cc.error( ", account is: " ) + cc.j( joAccount ) - "\n"; - details.write( s ); - log.write( s ); - if( isExitIfEmpty ) { - details.exposeDetailsTo( log, "safe_sign_transaction_with_account", false ); - details.close(); - process.exit( 126 ); - } - } break; - } // switch( joSR.joACI.strType ) - details.write( cc.debug( "Signed transaction is " ) + cc.notice( JSON.stringify( tx ) ) + "\n" ); - joSR.tx = tx; - strMsg = - cc.debug( "Transaction with account completed " ) + cc.notice( "sending counter" ) + - cc.debug( " is " ) + cc.info( sendingCnt ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - return joSR; -} - -async function safe_send_signed_transaction( details, w3, serializedTx, strActionName, strLogPrefix ) { - const strPrefixDetails = cc.debug( "(gathered details)" ) + " "; - const strPrefixLog = cc.debug( "(immediate log)" ) + " "; - const strMsg = - cc.attention( "SEND TRANSACTION" ) + cc.normal( " is using " ) + - cc.bright( "Web3" ) + cc.normal( " version " ) + cc.sunny( w3.version ); - details.write( strPrefixDetails + strMsg + "\n" ); - log.write( strPrefixLog + strMsg + "\n" ); - const strTX = "0x" + serializedTx.toString( "hex" ); // strTX is string starting from "0x" - details.write( strLogPrefix + cc.debug( "....signed raw TX is " ) + cc.j( strTX ) + "\n" ); - let joReceipt = null; - let bHaveReceipt = false; - try { - joReceipt = await w3.eth.sendSignedTransaction( strTX ); - bHaveReceipt = ( joReceipt != null ); - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "WARNING:" ) + cc.warning( " first attempt to send signed transaction failure during " + strActionName + ": " ) + cc.sunny( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - } - if( !bHaveReceipt ) { - try { - joReceipt = await w3.eth.sendSignedTransaction( strTX ); - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " second attempt to send signed transaction failure during " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - throw err; - } - } - return joReceipt; -} - -// -// register direction for money transfer -// main-net.DepositBox call: function addSchain(string schainName, address tokenManagerAddress) -// -async function check_is_registered_s_chain_in_deposit_boxes( // step 1 - w3_main_net, - jo_linker, - joAccountMN, - chain_id_s_chain -) { - const details = log.createMemoryStream(); - details.write( cc.info( "Main-net " ) + cc.sunny( "Linker" ) + cc.info( " address is....." ) + cc.bright( jo_linker.options.address ) + "\n" ); - details.write( cc.info( "S-Chain " ) + cc.sunny( "ID" ) + cc.info( " is......................." ) + cc.bright( chain_id_s_chain ) + "\n" ); - const strLogPrefix = cc.note( "RegChk S in depositBox:" ) + " "; - details.write( strLogPrefix + cc.debug( g_mtaStrLongSeparator ) + "\n" ); - details.write( strLogPrefix + cc.bright( "check_is_registered_s_chain_in_deposit_boxes(reg-step1)" ) + "\n" ); - details.write( strLogPrefix + cc.debug( g_mtaStrLongSeparator ) + "\n" ); - let strActionName = ""; - try { - strActionName = "check_is_registered_s_chain_in_deposit_boxes(reg-step1)"; - const addressFrom = joAccountMN.address( w3_main_net ); - const bIsRegistered = await jo_linker.methods.hasSchain( chain_id_s_chain ).call( { - from: addressFrom - } ); - details.write( strLogPrefix + cc.success( "check_is_registered_s_chain_in_deposit_boxes(reg-step1) status is: " ) + cc.attention( bIsRegistered ) + "\n" ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "check_is_registered_s_chain_in_deposit_boxes", true ); - details.close(); - return bIsRegistered; - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in check_is_registered_s_chain_in_deposit_boxes(reg-step1)() during " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "check_is_registered_s_chain_in_deposit_boxes", false ); - details.close(); - } - return false; -} - -async function invoke_has_chain( - details, - w3, // Main-Net or S-Chin - jo_linker, // Main-Net or S-Chin - joAccount, // Main-Net or S-Chin - chain_id_s_chain -) { - const strLogPrefix = cc.sunny( "Wait for added chain status:" ) + " "; - let strActionName = ""; - try { - strActionName = "invoke_has_chain(hasSchain): jo_linker.hasSchain"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const addressFrom = joAccount.address( w3 ); - const bHasSchain = await jo_linker.methods.hasSchain( - chain_id_s_chain - ).call( { - from: addressFrom - } ); - details.write( strLogPrefix + cc.success( "Got jo_linker.hasSchain() status is: " ) + cc.attention( bHasSchain ) + "\n" ); - return bHasSchain; - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( "Error in register_s_chain_in_deposit_boxes(reg-step1)() during " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - } - return false; -} - -async function wait_for_has_chain( - details, - w3, // Main-Net or S-Chin - jo_linker, // Main-Net or S-Chin - joAccount, // Main-Net or S-Chin - chain_id_s_chain, - cntWaitAttempts, - nSleepMilliseconds -) { - if( cntWaitAttempts == null || cntWaitAttempts == undefined ) - cntWaitAttempts = 100; - if( nSleepMilliseconds == null || nSleepMilliseconds == undefined ) - nSleepMilliseconds = 5; - for( let idxWaitAttempts = 0; idxWaitAttempts < cntWaitAttempts; ++ idxWaitAttempts ) { - if( await invoke_has_chain( details, w3, jo_linker, joAccount, chain_id_s_chain ) ) - return true; - details.write( cc.normal( "Sleeping " ) + cc.info( nSleepMilliseconds ) + cc.normal( " milliseconds..." ) + "\n" ); - await sleep( nSleepMilliseconds ); - } - return false; -} - -async function register_s_chain_in_deposit_boxes( // step 1 - w3_main_net, - // jo_deposit_box_eth, // only main net - // jo_deposit_box_erc20, // only main net - // jo_deposit_box_erc721, // only main net - jo_linker, - joAccountMN, - jo_token_manager_eth, // only s-chain - jo_token_manager_erc20, // only s-chain - jo_token_manager_erc721, // only s-chain - jo_token_manager_erc1155, // only s-chain - jo_token_manager_erc721_with_metadata, // only s-chain - jo_community_locker, // only s-chain - jo_token_manager_linker, - chain_id_s_chain, - cid_main_net, - tc_main_net, - cntWaitAttempts, - nSleepMilliseconds -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // register_s_chain_in_deposit_boxes - details.write( cc.info( "Main-net " ) + cc.sunny( "Linker" ) + cc.info( " address is......." ) + cc.bright( jo_linker.options.address ) + "\n" ); - details.write( cc.info( "S-Chain " ) + cc.sunny( "ID" ) + cc.info( " is......................." ) + cc.bright( chain_id_s_chain ) + "\n" ); - const strLogPrefix = cc.sunny( "Reg S in depositBoxes:" ) + " "; - details.write( strLogPrefix + cc.debug( g_mtaStrLongSeparator ) + "\n" ); - details.write( strLogPrefix + cc.bright( "reg-step1:register_s_chain_in_deposit_boxes" ) + "\n" ); - details.write( strLogPrefix + cc.debug( g_mtaStrLongSeparator ) + "\n" ); - let strActionName = ""; - try { - strActionName = "reg-step1:w3_main_net.eth.getTransactionCount()"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountMN.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Will register S-Chain in lock_and_data on Main-net" ) + "\n" ); - const methodWithArguments = jo_linker.methods.connectSchain( - chain_id_s_chain, - [ - jo_token_manager_linker.options.address, // call params - jo_community_locker.options.address, // call params - jo_token_manager_eth.options.address, // call params - jo_token_manager_erc20.options.address, // call params - jo_token_manager_erc721.options.address, // call params - jo_token_manager_erc1155.options.address, // call params - jo_token_manager_erc721_with_metadata.options.address // call params - ] - ); - const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method - // - const gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas = await tc_main_net.computeGas( methodWithArguments, w3_main_net, 3000000, gasPrice, joAccountMN.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); - // - const isIgnore = false; - const strDRC = "register_s_chain_in_deposit_boxes, step 1, connectSchain"; - const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccountMN, strDRC, isIgnore, gasPrice, estimatedGas, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const rawTx = { - chainId: cid_main_net, - nonce: tcnt, - gasPrice: gasPrice, - // gasLimit: estimatedGas, - gas: estimatedGas, // gas is optional here - to: jo_linker.options.address, // contract address - data: dataTx - }; - const tx = compose_tx_instance( details, strLogPrefix, rawTx ); - const joSR = await safe_sign_transaction_with_account( details, w3_main_net, tx, rawTx, joAccountMN ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_main_net, joSR.txHashSent ); - else { - const serializedTx = tx.serialize(); - strActionName = "reg-step1:w3_main_net.eth.sendSignedTransaction()"; - // let joReceipt = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTx.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_main_net, serializedTx, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "register_s_chain_in_deposit_boxes", - "receipt": joReceipt - } ); - } - // } else - // details.write( strLogPrefix + cc.debug( "Will wait until S-Chain owner will register S-Chain in ima-linker on Main-net" ) + "\n" ); - const isSChainStatusOKay = await wait_for_has_chain( - details, - w3_main_net, - jo_linker, - joAccountMN, - chain_id_s_chain, - cntWaitAttempts, - nSleepMilliseconds - ); - if( ! isSChainStatusOKay ) - throw new Error( "S-Chain ownership status check timeout" ); - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in register_s_chain_in_deposit_boxes() during " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "register_s_chain_in_deposit_boxes", false ); - details.close(); - return null; - } - if( expose_details_get() ) - details.exposeDetailsTo( log, "register_s_chain_in_deposit_boxes", true ); - details.close(); - return jarrReceipts; -} // async function register_deposit_box_on_s_chain(... - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function reimbursement_show_balance( - w3_main_net, - jo_community_pool, - joReceiver_main_net, - strChainName_main_net, - cid_main_net, - tc_main_net, - strReimbursementChain, - isForcePrintOut -) { - const details = log.createMemoryStream(); - let s = ""; - const strLogPrefix = cc.info( "Gas Reimbursement - Show Balance" ) + " "; - try { - const addressFrom = joReceiver_main_net; - details.write( strLogPrefix + - cc.debug( "Querying wallet " ) + cc.notice( strReimbursementChain ) + - cc.debug( "/" ) + cc.info( addressFrom ) + - cc.debug( " balance..." ) + "\n" ); - const xWei = await jo_community_pool.methods.getBalance( addressFrom, strReimbursementChain ).call(); - // - s = strLogPrefix + cc.success( "Balance(wei): " ) + cc.attention( xWei ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - const xEth = w3_main_net.utils.fromWei( xWei, "ether" ); - s = strLogPrefix + cc.success( "Balance(eth): " ) + cc.attention( xEth ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - if( expose_details_get() ) - details.exposeDetailsTo( log, "reimbursement_show_balance", true ); - details.close(); - return xWei; - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in reimbursement_show_balance(): " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "reimbursement_show_balance", false ); - details.close(); - return 0; - } -} - -async function reimbursement_estimate_amount( - w3_main_net, - jo_community_pool, - joReceiver_main_net, - strChainName_main_net, - cid_main_net, - tc_main_net, - strReimbursementChain, - isForcePrintOut -) { - const details = log.createMemoryStream(); - let s = ""; - const strLogPrefix = cc.info( "Gas Reimbursement - Estimate Amount To Recharge" ) + " "; - try { - details.write( strLogPrefix + cc.debug( "Querying wallet " ) + cc.notice( strReimbursementChain ) + cc.debug( " balance..." ) + "\n" ); - const addressReceiver = joReceiver_main_net; - const xWei = await jo_community_pool.methods.getBalance( addressReceiver, strReimbursementChain ).call(); - // - s = strLogPrefix + cc.success( "Balance(wei): " ) + cc.attention( xWei ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - const xEth = w3_main_net.utils.fromWei( xWei, "ether" ); - s = strLogPrefix + cc.success( "Balance(eth): " ) + cc.attention( xEth ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - const minTransactionGas = parseIntOrHex( await jo_community_pool.methods.minTransactionGas().call() ); - s = strLogPrefix + cc.success( "MinTransactionGas: " ) + cc.attention( minTransactionGas ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - const gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - s = strLogPrefix + cc.success( "Multiplied Gas Price: " ) + cc.attention( gasPrice ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - const minAmount = minTransactionGas * gasPrice; - s = strLogPrefix + cc.success( "Minimum recharge balance: " ) + cc.attention( minAmount ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - let amountToRecharge; - if( xWei >= minAmount ) - amountToRecharge = 1; - else - amountToRecharge = minAmount - xWei; - - s = strLogPrefix + cc.success( "Estimated amount to recharge(wei): " ) + cc.attention( amountToRecharge ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - const amountToRechargeEth = w3_main_net.utils.fromWei( amountToRecharge.toString(), "ether" ); - s = strLogPrefix + cc.success( "Estimated amount to recharge(eth): " ) + cc.attention( amountToRechargeEth ) + "\n"; - if( isForcePrintOut || verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - // - if( expose_details_get() ) - details.exposeDetailsTo( log, "reimbursement_estimate_amount", true ); - details.close(); - return amountToRecharge; - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in reimbursement_estimate_amount(): " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "reimbursement_estimate_amount", false ); - details.close(); - return 0; - } -} - -async function reimbursement_wallet_recharge( - w3_main_net, - jo_community_pool, - joAccountMN, - strChainName_main_net, - cid_main_net, - tc_main_net, - strReimbursementChain, - nReimbursementRecharge -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // reimbursement_wallet_recharge - let strActionName = ""; - const strLogPrefix = cc.info( "Gas Reimbursement - Wallet Recharge" ) + " "; - try { - details.write( strLogPrefix + cc.debug( "Recharging wallet " ) + cc.notice( strReimbursementChain ) + cc.debug( "..." ) + "\n" ); - // - strActionName = "w3_main_net.eth.getTransactionCount()"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountMN.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - const addressReceiver = joAccountMN.address( w3_main_net ); - const methodWithArguments = jo_community_pool.methods.rechargeUserWallet( - // call params, last is destination account on S-chain - strReimbursementChain, - addressReceiver - ); - const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method - // - const gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas = await tc_main_net.computeGas( methodWithArguments, w3_main_net, 3000000, gasPrice, joAccountMN.address( w3_main_net ), nReimbursementRecharge ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); - // - const isIgnore = false; - const strDRC = "reimbursement_wallet_recharge"; - const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccountMN, strDRC, isIgnore, gasPrice, estimatedGas, nReimbursementRecharge ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const rawTx = { - chainId: cid_main_net, - nonce: tcnt, - gasPrice: gasPrice, - // gasLimit: estimatedGas, - gas: estimatedGas, - to: jo_community_pool.options.address, // contract address - data: dataTx, - value: "0x" + w3_main_net.utils.toBN( nReimbursementRecharge ).toString( 16 ) // wei_how_much // how much money to send - }; - const tx = compose_tx_instance( details, strLogPrefix, rawTx ); - const joSR = await safe_sign_transaction_with_account( details, w3_main_net, tx, rawTx, joAccountMN ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_main_net, joSR.txHashSent ); - else { - const serializedTx = tx.serialize(); - strActionName = "w3_main_net.eth.sendSignedTransaction()"; - // let joReceipt = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTx.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_main_net, serializedTx, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "reimbursement_wallet_recharge", - "receipt": joReceipt - } ); - } - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "reimbursement_wallet_recharge", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "REIMBURSEMENT_WALLET_RECHARGE", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "reimbursement_wallet_recharge", true ); - details.close(); - return true; -} - -async function reimbursement_wallet_withdraw( - w3_main_net, - jo_community_pool, - joAccountMN, - strChainName_main_net, - cid_main_net, - tc_main_net, - strReimbursementChain, - nReimbursementWithdraw -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // reimbursement_wallet_withdraw - let strActionName = ""; - const strLogPrefix = cc.info( "Gas Reimbursement - Wallet Withdraw" ) + " "; - const wei_how_much = 0; - try { - details.write( strLogPrefix + cc.debug( "Recharging wallet " ) + cc.notice( strReimbursementChain ) + cc.debug( "..." ) + "\n" ); - // - strActionName = "w3_main_net.eth.getTransactionCount()"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountMN.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - const methodWithArguments = jo_community_pool.methods.withdrawFunds( - // call params, last is destination account on S-chain - strReimbursementChain, - "0x" + w3_main_net.utils.toBN( nReimbursementWithdraw ).toString( 16 ) - ); - const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method - // - const gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas = await tc_main_net.computeGas( methodWithArguments, w3_main_net, 3000000, gasPrice, joAccountMN.address( w3_main_net ), wei_how_much ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); - // - const isIgnore = false; - const strDRC = "reimbursement_wallet_withdraw"; - const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccountMN, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const rawTx = { - chainId: cid_main_net, - nonce: tcnt, - gasPrice: gasPrice, - // gasLimit: estimatedGas, - gas: estimatedGas, - to: jo_community_pool.options.address, // contract address - data: dataTx, - value: "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) // wei_how_much // how much money to send - }; - const tx = compose_tx_instance( details, strLogPrefix, rawTx ); - const joSR = await safe_sign_transaction_with_account( details, w3_main_net, tx, rawTx, joAccountMN ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_main_net, joSR.txHashSent ); - else { - const serializedTx = tx.serialize(); - strActionName = "w3_main_net.eth.sendSignedTransaction()"; - // let joReceipt = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTx.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_main_net, serializedTx, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "reimbursement_wallet_withdraw", - "receipt": joReceipt - } ); - } - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "reimbursement_wallet_withdraw", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "REIMBURSEMENT_WALLET_WITHDRAW", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "reimbursement_wallet_withdraw", true ); - details.close(); - return true; -} - -async function reimbursement_set_range( - w3_s_chain, - jo_community_locker, - joAccountSC, - strChainName_s_chain, - cid_s_chain, - tc_s_chain, - strChainName_origin_chain, - nReimbursementRange -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // reimbursement_set_range - let strActionName = ""; - const strLogPrefix = cc.info( "Gas Reimbursement - Set Minimal time interval from S2M transfers" ) + " "; - const wei_how_much = 0; - try { - details.write( strLogPrefix + cc.debug( "Setting minimal S2M interval to " ) + cc.notice( nReimbursementRange ) + cc.debug( "..." ) + "\n" ); - // - strActionName = "w3_s_chain.eth.getTransactionCount()"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const accountForSchain = joAccountSC.address( w3_s_chain ); - const tcnt = await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSC.address( w3_s_chain ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - const methodWithArguments = jo_community_locker.methods.setTimeLimitPerMessage( - // call params, last is destination account on S-chain - strChainName_origin_chain, - "0x" + w3_s_chain.utils.toBN( nReimbursementRange ).toString( 16 ) - ); - const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method - // - const gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas = await tc_s_chain.computeGas( methodWithArguments, w3_s_chain, 3000000, gasPrice, joAccountSC.address( w3_s_chain ), wei_how_much ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); - // - const isIgnore = false; - const strDRC = "reimbursement_set_range"; - const strErrorOfDryRun = await dry_run_call( details, w3_s_chain, methodWithArguments, joAccountSC, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const rawTx = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: tcnt, - gasPrice: gasPrice, - // gasLimit: estimatedGas, - gas: estimatedGas, - to: jo_community_locker.options.address, // contract address - data: dataTx, - value: 0 // how much money to send - }; - await checkTransactionToSchain( w3_s_chain, rawTx, details ); - const tx = compose_tx_instance( details, strLogPrefix, rawTx ); - const joSR = await safe_sign_transaction_with_account( details, w3_s_chain, tx, rawTx, joAccountSC ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_s_chain, joSR.txHashSent ); - else { - const serializedTx = tx.serialize(); - strActionName = "w3_s_chain.eth.sendSignedTransaction()"; - // let joReceipt = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTx.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_s_chain, serializedTx, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "reimbursement_set_range", - "receipt": joReceipt - } ); - } - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "reimbursement_set_range", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "REIMBURSEMENT_SET_RANGE", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "reimbursement_set_range", true ); - details.close(); - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// transfer money from main-net to S-chain -// main-net.DepositBox call: function deposit(string schainName, address to) public payable -// Where: -// schainName...obvious -// to.........address in S-chain -// Notice: -// this function is available for everyone in main-net -// money is sent from caller -// "value" JSON arg is used to specify amount of money to sent -// -async function do_eth_payment_from_main_net( - w3_main_net, - cid_main_net, - joAccountSrc, - joAccountDst, - jo_deposit_box, - jo_message_proxy_main_net, // for checking logs - chain_id_s_chain, - wei_how_much, // how much WEI money to send - tc_main_net -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_eth_payment_from_main_net - let strActionName = ""; - const strLogPrefix = cc.info( "M2S ETH Payment:" ) + " "; - try { - details.write( strLogPrefix + cc.debug( "Doing payment from mainnet with " ) + cc.notice( "chain_id_s_chain" ) + cc.debug( "=" ) + cc.notice( chain_id_s_chain ) + cc.debug( "..." ) + "\n" ); - // - strActionName = "w3_main_net.eth.getTransactionCount()"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountSrc.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - const methodWithArguments = jo_deposit_box.methods.deposit( - // call params, last is destination account on S-chain - chain_id_s_chain - ); - const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method - // - const gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas = await tc_main_net.computeGas( methodWithArguments, w3_main_net, 3000000, gasPrice, joAccountSrc.address( w3_main_net ), wei_how_much ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); - // - const isIgnore = false; - const strDRC = "do_eth_payment_from_main_net, deposit"; - const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccountSrc, strDRC, isIgnore, gasPrice, estimatedGas, wei_how_much ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const rawTx = { - chainId: cid_main_net, - nonce: tcnt, - gasPrice: gasPrice, - // gasLimit: estimatedGas, - gas: estimatedGas, - to: jo_deposit_box.options.address, // contract address - data: dataTx, - value: "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) // wei_how_much // how much money to send - }; - const tx = compose_tx_instance( details, strLogPrefix, rawTx ); - const joSR = await safe_sign_transaction_with_account( details, w3_main_net, tx, rawTx, joAccountSrc ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_main_net, joSR.txHashSent ); - else { - const serializedTx = tx.serialize(); - strActionName = "w3_main_net.eth.sendSignedTransaction()"; - // let joReceipt = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTx.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_main_net, serializedTx, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "do_eth_payment_from_main_net", - "receipt": joReceipt - } ); - } - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_main_net ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_main_net, jo_message_proxy_main_net, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_main_net.options.address + " contract, no events found" ); - } // if( jo_message_proxy_main_net ) - // if( jo_deposit_box ) { - // details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "Error" ) + cc.debug( " event of the " ) + cc.info( "DepositBox" ) + cc.debug( "/" ) + cc.notice( jo_deposit_box.options.address ) + cc.debug( " contract..." ) + "\n" ); - // const joEvents = await get_contract_call_events( details, w3_main_net, jo_deposit_box, "Error", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - // if( joEvents.length == 0 ) - // details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "Error" ) + cc.success( " event of the " ) + cc.info( "DepositBox" ) + cc.success( "/" ) + cc.notice( jo_deposit_box.options.address ) + cc.success( " contract, no event found" ) + "\n" ); - // else - // throw new Error( "Verification failed for the \"Error\" event of the \"DepositBox\"/" + jo_deposit_box.options.address + " contract, no events found" ); - // } // if( jo_deposit_box ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_eth_payment_from_main_net", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ETH PAYMENT FROM MAIN NET", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_eth_payment_from_main_net", true ); - details.close(); - return true; -} // async function do_eth_payment_from_main_net(... - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// transfer money from S-chain to main-net -// S-chain.TokenManager call: function exitToMain(address to) public payable -// Where: -// to.........address in main-net -// Notice: -// this function is available for everyone in S-chain -// money is sent from caller -// "value" JSON arg is used to specify amount of money to sent -// -async function do_eth_payment_from_s_chain( - w3_s_chain, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager_eth, - jo_message_proxy_s_chain, // for checking logs - wei_how_much, // how much WEI money to send - tc_s_chain -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_eth_payment_from_s_chain - let strActionName = ""; - const strLogPrefix = cc.info( "S2M ETH Payment:" ) + " "; - try { - strActionName = "w3_s_chain.eth.getTransactionCount()/do_eth_payment_from_s_chain"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - // - let gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); // - // - const accountForSchain = joAccountSrc.address( w3_s_chain ); - const tcnt = await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "jo_token_manager_eth.methods.exitToMain()/do_eth_payment_from_s_chain"; - const methodWithArguments = jo_token_manager_eth.methods.exitToMain( - // call params, last is destination account on S-chain - "0x" + w3_s_chain.utils.toBN( wei_how_much ).toString( 16 ) - ); - const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method - // - gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); // - // - const estimatedGas = await tc_s_chain.computeGas( methodWithArguments, w3_s_chain, 6000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); - // - const isIgnore = true; - const strDRC = "do_eth_payment_from_s_chain, exitToMain"; - const strErrorOfDryRun = await dry_run_call( details, w3_s_chain, methodWithArguments, joAccountSrc, strDRC, isIgnore, gasPrice, estimatedGas, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const rawTx = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: tcnt, - gasPrice: gasPrice, - // "gasLimit": 3000000, - gas: estimatedGas, - to: jo_token_manager_eth.options.address, // contract address - data: dataTx, - value: 0 // how much money to send - }; - await checkTransactionToSchain( w3_s_chain, rawTx, details ); - const tx = compose_tx_instance( details, strLogPrefix, rawTx ); - const joSR = await safe_sign_transaction_with_account( details, w3_s_chain, tx, rawTx, joAccountSrc ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_s_chain, joSR.txHashSent ); - else { - const serializedTx = tx.serialize(); - strActionName = "w3_s_chain.eth.sendSignedTransaction()"; - // let joReceipt = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTx.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_s_chain, serializedTx, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "do_eth_payment_from_s_chain", - "receipt": joReceipt - } ); - } - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_s_chain ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_s_chain, jo_message_proxy_s_chain, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_s_chain.options.address + " contract, no events found" ); - } // if( jo_message_proxy_s_chain ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_eth_payment_from_s_chain", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ETH PAYMENT FROM S-CHAIN", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_eth_payment_from_s_chain", true ); - details.close(); - return true; -} // async function do_eth_payment_from_s_chain(... - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -async function receive_eth_payment_from_s_chain_on_main_net( - w3_main_net, - cid_main_net, - joAccountMN, - jo_deposit_box_eth, - tc_main_net -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // receive_eth_payment_from_s_chain_on_main_net - let strActionName = ""; - const strLogPrefix = cc.info( "M2S ETH Receive:" ) + " "; - try { - strActionName = "w3_main_net.eth.getTransactionCount()/receive_eth_payment_from_s_chain_on_main_net"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountMN.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - const methodWithArguments = jo_deposit_box_eth.methods.getMyEth( - // call params(empty) - ); - const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method - // - const gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas = await tc_main_net.computeGas( methodWithArguments, w3_main_net, 3000000, gasPrice, joAccountMN.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas ) + "\n" ); - // - const isIgnore = false; - const strDRC = "receive_eth_payment_from_s_chain_on_main_net, getMyEth"; - const strErrorOfDryRun = await dry_run_call( details, w3_main_net, methodWithArguments, joAccountMN, strDRC, isIgnore, gasPrice, estimatedGas, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const rawTx = { - chainId: cid_main_net, - nonce: tcnt, - gas: estimatedGas, // 2100000 - gasPrice: gasPrice, - // gasLimit: estimatedGas, // 3000000 - to: jo_deposit_box_eth.options.address, // contract address - data: dataTx, - value: 0 // how much money to send - }; - const tx = compose_tx_instance( details, strLogPrefix, rawTx ); - const joSR = await safe_sign_transaction_with_account( details, w3_main_net, tx, rawTx, joAccountMN ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) - joReceipt = await get_web3_transactionReceipt( details, 10, w3_main_net, joSR.txHashSent ); - else { - const serializedTx = tx.serialize(); - strActionName = "w3_main_net.eth.sendSignedTransaction()"; - // let joReceipt = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTx.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3_main_net, serializedTx, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "receive_eth_payment_from_s_chain_on_main_net", - "receipt": joReceipt - } ); - } - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Receive payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "receive_eth_payment_from_s_chain_on_main_net", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "RECEIVE ETH ON MAIN NET", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "receive_eth_payment_from_s_chain_on_main_net", true ); - details.close(); - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function view_eth_payment_from_s_chain_on_main_net( - w3_main_net, - joAccountMN, - jo_deposit_box_eth -) { - const details = log.createMemoryStream(); - let strActionName = ""; - const strLogPrefix = cc.info( "S ETH View:" ) + " "; - try { - if( ! ( w3_main_net && joAccountMN && jo_deposit_box_eth ) ) - return null; - strActionName = "w3_main_net.eth.getTransactionCount()/view_eth_payment_from_s_chain_on_main_net"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - const tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountMN.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - const addressFrom = joAccountMN.address( w3_main_net ); - const xWei = await jo_deposit_box_eth.methods.approveTransfers( addressFrom ).call( { - from: addressFrom - } ); - details.write( strLogPrefix + cc.success( "You can receive(wei): " ) + cc.attention( xWei ) + "\n" ); - const xEth = w3_main_net.utils.fromWei( xWei, "ether" ); - const s = strLogPrefix + cc.success( "You can receive(eth): " ) + cc.attention( xEth ) + "\n"; - if( verbose_get() >= RV_VERBOSE.information ) - log.write( s ); - details.write( s ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "view_eth_payment_from_s_chain_on_main_net", true ); - details.close(); - return xWei; - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " View payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "view_eth_payment_from_s_chain_on_main_net", false ); - details.close(); - return null; - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function do_erc721_payment_from_main_net( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_deposit_box_erc721, - jo_message_proxy_main_net, // for checking logs - chain_id_s_chain, - token_id, // which ERC721 token id to send - wei_how_much, // how much ETH - jo_token_manager_erc721, // only s-chain - strCoinNameErc721_main_net, - erc721PrivateTestnetJson_main_net, - strCoinNameErc721_s_chain, - erc721PrivateTestnetJson_s_chain, - tc_main_net -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc721_payment_from_main_net - let strActionName = ""; - const strLogPrefix = cc.info( "M2S ERC721 Payment:" ) + " "; - try { - strActionName = "w3_main_net.eth.getTransactionCount()/do_erc721_payment_from_main_net"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountSrc.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC721 prepare M->S"; - const erc721ABI = erc721PrivateTestnetJson_main_net[strCoinNameErc721_main_net + "_abi"]; - const erc721Address_main_net = erc721PrivateTestnetJson_main_net[strCoinNameErc721_main_net + "_address"]; - const contractERC721 = new w3_main_net.eth.Contract( erc721ABI, erc721Address_main_net ); - // prepare the smart contract function deposit(string schainName, address to) - const depositBoxAddress = jo_deposit_box_erc721.options.address; - const methodWithArguments_approve = contractERC721.methods.approve( // same as approve in 20 - // joAccountSrc.address( w3_main_net ), - depositBoxAddress, - "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ) - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - let dataTxDeposit = null; - const methodWithArguments_rawDepositERC721 = jo_deposit_box_erc721.methods.depositERC721( - chain_id_s_chain, - erc721Address_main_net, - "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ) - ); - dataTxDeposit = methodWithArguments_rawDepositERC721.encodeABI(); - // - // - strActionName = "compute gas price for ERC721 transactions M->S"; - let gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC721/approve transaction M->S"; - const estimatedGas_approve = await tc_main_net.computeGas( methodWithArguments_approve, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "do_erc721_payment_from_main_net, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - const rawTxApprove = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc721Address_main_net, - gasPrice: gasPrice, - gas: estimatedGas_approve - }; - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC721/approve transaction M->S"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_main_net, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_main_net, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - details.write( cc.normal( "Will send ERC721/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - strActionName = "w3_main_net.eth.sendSignedTransaction()/Approve"; - // let joReceiptApprove = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_main_net, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc721_payment_from_main_net/approve", - "receipt": joReceiptApprove - } ); - } - // - // - strActionName = "create ERC721/deposit transaction M->S"; - tcnt += 1; - // - gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const estimatedGas_deposit = await tc_main_net.computeGas( methodWithArguments_rawDepositERC721, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_deposit ) + "\n" ); - // - const isIgnore_rawDepositERC721 = true; - const strDRC_rawDepositERC721 = "do_erc721_payment_from_main_net, rawDepositERC721"; - const strErrorOfDryRun_rawDepositERC721 = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC721, joAccountSrc, strDRC_rawDepositERC721, isIgnore_rawDepositERC721, gasPrice, estimatedGas_deposit, "0" ); - if( strErrorOfDryRun_rawDepositERC721 ) - throw new Error( strErrorOfDryRun_rawDepositERC721 ); - // - const rawTxDeposit = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxDeposit, - to: depositBoxAddress, - gasPrice: gasPrice, - gas: estimatedGas_deposit - // value: "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - //, value: 2000000000000000 // w3_dst.utils.toWei( (1).toString(), "ether" ) - }; - const txDeposit = compose_tx_instance( details, strLogPrefix, rawTxDeposit ); - strActionName = "sign ERC721/deposit transaction M->S"; - const joDepositSR = await safe_sign_transaction_with_account( details, w3_main_net, txDeposit, rawTxDeposit, joAccountSrc ); - let joReceiptDeposit = null; - if( joDepositSR.joACI.isAutoSend ) - joReceiptDeposit = await get_web3_transactionReceipt( details, 10, w3_main_net, joDepositSR.txHashSent ); - else { - const serializedTxDeposit = txDeposit.serialize(); - // send transactions - details.write( cc.normal( "Will send ERC721/deposit signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - strActionName = "w3_main_net.eth.sendSignedTransaction()/Deposit"; - // let joReceiptDeposit = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxDeposit.toString( "hex" ) ); - joReceiptDeposit = await safe_send_signed_transaction( details, w3_main_net, serializedTxDeposit, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Deposit: " ) + cc.j( joReceiptDeposit ) + "\n" ); - if( joReceiptDeposit && typeof joReceiptDeposit == "object" && "gasUsed" in joReceiptDeposit ) { - jarrReceipts.push( { - "description": "do_erc721_payment_from_main_net/deposit", - "receipt": joReceiptDeposit - } ); - } - // - // - const joReceipt = joReceiptDeposit; - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_main_net ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_main_net, jo_message_proxy_main_net, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_main_net.options.address + " contract, no events found" ); - } // if( jo_message_proxy_main_net ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc721_payment_from_main_net", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-721 PAYMENT FROM MAIN NET", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc721_payment_from_main_net", true ); - details.close(); - return true; -} // async function do_erc721_payment_from_main_net(... - -// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -async function do_erc20_payment_from_main_net( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_deposit_box_erc20, - jo_message_proxy_main_net, // for checking logs - chain_id_s_chain, - token_amount, // how much ERC20 tokens to send - wei_how_much, // how much ETH - jo_token_manager_erc20, // only s-chain - strCoinNameErc20_main_net, - erc20_main_net, - strCoinNameErc20_s_chain, - erc20_s_chain, - tc_main_net -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc20_payment_from_main_net - let strActionName = ""; - const strLogPrefix = cc.info( "M2S ERC20 Payment:" ) + " "; - try { - strActionName = "w3_main_net.eth.getTransactionCount()/do_erc20_payment_from_main_net"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountSrc.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC20 prepare M->S"; - const erc20ABI = erc20_main_net[strCoinNameErc20_main_net + "_abi"]; - // details.write( strLogPrefix + cc.normal("erc20_main_net = ") + cc.j(erc20_main_net) + "\n" ) - // details.write( strLogPrefix + cc.normal("strCoinNameErc20_main_net = ") + cc.info(strCoinNameErc20_main_net) + "\n" ) - const erc20Address_main_net = erc20_main_net[strCoinNameErc20_main_net + "_address"]; - // details.write( strLogPrefix + cc.normal("erc20Address_main_net = ") + cc.info(erc20Address_main_net) + "\n" ) - const contractERC20 = new w3_main_net.eth.Contract( erc20ABI, erc20Address_main_net ); - // prepare the smart contract function deposit(string schainName, address to) - const depositBoxAddress = jo_deposit_box_erc20.options.address; - const methodWithArguments_approve = contractERC20.methods.approve( - depositBoxAddress, "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - let dataTxDeposit = null; - const methodWithArguments_rawDepositERC20 = jo_deposit_box_erc20.methods.depositERC20( - chain_id_s_chain, - erc20Address_main_net, - "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - ); - dataTxDeposit = methodWithArguments_rawDepositERC20.encodeABI(); - // - // - strActionName = "compute gas price for ERC20 transactions M->S"; - let gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC20/approve transaction M->S"; - const estimatedGas_approve = await tc_main_net.computeGas( methodWithArguments_approve, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "do_erc20_payment_from_main_net, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - const rawTxApprove = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), // accountForMainnet - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc20Address_main_net, - gasPrice: gasPrice, // 0 - gas: estimatedGas_approve - }; - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC20/approve transaction M->S"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_main_net, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_main_net, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - strActionName = "w3_main_net.eth.sendSignedTransaction()/Approve"; - details.write( cc.normal( "Will send ERC20/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - // let joReceiptApprove = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_main_net, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc20_payment_from_main_net/approve", - "receipt": joReceiptApprove - } ); - } - // - // - strActionName = "create ERC20/deposit transaction M->S"; - // - gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const estimatedGas_deposit = await tc_main_net.computeGas( methodWithArguments_rawDepositERC20, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_deposit ) + "\n" ); - // - const isIgnore_rawDepositERC20 = true; - const strDRC_rawDepositERC20 = "do_erc20_payment_from_main_net, rawDepositERC20"; - const strErrorOfDryRun_rawDepositERC20 = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC20, joAccountSrc, strDRC_rawDepositERC20, isIgnore_rawDepositERC20, gasPrice, estimatedGas_deposit, "0" ); - if( strErrorOfDryRun_rawDepositERC20 ) - throw new Error( strErrorOfDryRun_rawDepositERC20 ); - // - tcnt += 1; - const rawTxDeposit = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), // accountForMainnet - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxDeposit, - to: depositBoxAddress, - gasPrice: gasPrice, // 0 - gas: estimatedGas_deposit - // value: "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - }; - const txDeposit = compose_tx_instance( details, strLogPrefix, rawTxDeposit ); - strActionName = "sign ERC20/deposit transaction M->S"; - const joDepositSR = await safe_sign_transaction_with_account( details, w3_main_net, txDeposit, rawTxDeposit, joAccountSrc ); - let joReceiptDeposit = null; - if( joDepositSR.joACI.isAutoSend ) - joReceiptDeposit = await get_web3_transactionReceipt( details, 10, w3_main_net, joDepositSR.txHashSent ); - else { - const serializedTxDeposit = txDeposit.serialize(); - // send transactions - strActionName = "w3_main_net.eth.sendSignedTransaction()/Deposit"; - details.write( cc.normal( "Will send ERC20/deposit signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - // let joReceiptDeposit = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxDeposit.toString( "hex" ) ); - joReceiptDeposit = await safe_send_signed_transaction( details, w3_main_net, serializedTxDeposit, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Deposit: " ) + cc.j( joReceiptDeposit ) + "\n" ); - if( joReceiptDeposit && typeof joReceiptDeposit == "object" && "gasUsed" in joReceiptDeposit ) { - jarrReceipts.push( { - "description": "do_erc20_payment_from_main_net/deposit", - "receipt": joReceiptDeposit - } ); - } - // - // - const joReceipt = joReceiptDeposit; - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_main_net ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_main_net, jo_message_proxy_main_net, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for th\"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_main_net.options.address + " contract, no events found" ); - } // if( jo_message_proxy_main_net ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc20_payment_from_main_net", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-20 PAYMENT FROM MAIN NET", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc20_payment_from_main_net", true ); - details.close(); - return true; -} // async function do_erc20_payment_from_main_net(... - -async function do_erc1155_payment_from_main_net( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_deposit_box_erc1155, - jo_message_proxy_main_net, // for checking logs - chain_id_s_chain, - token_id, // which ERC1155 token id to send - token_amount, // which ERC1155 token id to send - wei_how_much, // how much ETH - jo_token_manager_erc1155, // only s-chain - strCoinNameErc1155_main_net, - erc1155PrivateTestnetJson_main_net, - strCoinNameErc1155_s_chain, - erc1155PrivateTestnetJson_s_chain, - tc_main_net -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc1155_payment_from_main_net - let strActionName = ""; - const strLogPrefix = cc.info( "M2S ERC1155 Payment:" ) + " "; - try { - strActionName = "w3_main_net.eth.getTransactionCount()/do_erc1155_payment_from_main_net"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountSrc.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC1155 prepare M->S"; - const erc1155ABI = erc1155PrivateTestnetJson_main_net[strCoinNameErc1155_main_net + "_abi"]; - const erc1155Address_main_net = erc1155PrivateTestnetJson_main_net[strCoinNameErc1155_main_net + "_address"]; - const contractERC1155 = new w3_main_net.eth.Contract( erc1155ABI, erc1155Address_main_net ); - // prepare the smart contract function deposit(string schainName, address to) - const depositBoxAddress = jo_deposit_box_erc1155.options.address; - const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( // same as approve in 20 - // joAccountSrc.address( w3_main_net ), - depositBoxAddress, - true - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - let dataTxDeposit = null; - const methodWithArguments_rawDepositERC1155 = jo_deposit_box_erc1155.methods.depositERC1155( - chain_id_s_chain, - erc1155Address_main_net, - "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ), - "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - ); - dataTxDeposit = methodWithArguments_rawDepositERC1155.encodeABI(); - // - // - strActionName = "compute gas price for ERC1155 transactions M->S"; - let gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC1155/approve transaction M->S"; - const estimatedGas_approve = await tc_main_net.computeGas( methodWithArguments_approve, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "do_erc1155_payment_from_main_net, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - const rawTxApprove = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc1155Address_main_net, - gasPrice: gasPrice, - gas: estimatedGas_approve - }; - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC1155/approve transaction M->S"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_main_net, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_main_net, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - details.write( cc.normal( "Will send ERC1155/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - strActionName = "w3_main_net.eth.sendSignedTransaction()/Approve"; - // let joReceiptApprove = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_main_net, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc1155_payment_from_main_net/approve", - "receipt": joReceiptApprove - } ); - } - // - // - strActionName = "create ERC1155/deposit transaction M->S"; - tcnt += 1; - // - gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const estimatedGas_deposit = await tc_main_net.computeGas( methodWithArguments_rawDepositERC1155, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_deposit ) + "\n" ); - // - const isIgnore_rawDepositERC1155 = true; - const strDRC_rawDepositERC1155 = "do_erc1155_payment_from_main_net, rawDepositERC1155"; - const strErrorOfDryRun_rawDepositERC1155 = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC1155, joAccountSrc, strDRC_rawDepositERC1155, isIgnore_rawDepositERC1155, gasPrice, estimatedGas_deposit, "0" ); - if( strErrorOfDryRun_rawDepositERC1155 ) - throw new Error( strErrorOfDryRun_rawDepositERC1155 ); - // - const rawTxDeposit = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxDeposit, - to: depositBoxAddress, - gasPrice: gasPrice, - gas: estimatedGas_deposit - // value: "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - //, value: 2000000000000000 // w3_dst.utils.toWei( (1).toString(), "ether" ) - }; - const txDeposit = compose_tx_instance( details, strLogPrefix, rawTxDeposit ); - strActionName = "sign ERC1155/deposit transaction M->S"; - const joDepositSR = await safe_sign_transaction_with_account( details, w3_main_net, txDeposit, rawTxDeposit, joAccountSrc ); - let joReceiptDeposit = null; - if( joDepositSR.joACI.isAutoSend ) - joReceiptDeposit = await get_web3_transactionReceipt( details, 10, w3_main_net, joDepositSR.txHashSent ); - else { - const serializedTxDeposit = txDeposit.serialize(); - // send transactions - details.write( cc.normal( "Will send ERC1155/deposit signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - strActionName = "w3_main_net.eth.sendSignedTransaction()/Deposit"; - // let joReceiptDeposit = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxDeposit.toString( "hex" ) ); - joReceiptDeposit = await safe_send_signed_transaction( details, w3_main_net, serializedTxDeposit, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Deposit: " ) + cc.j( joReceiptDeposit ) + "\n" ); - if( joReceiptDeposit && typeof joReceiptDeposit == "object" && "gasUsed" in joReceiptDeposit ) { - jarrReceipts.push( { - "description": "do_erc1155_payment_from_main_net/deposit", - "receipt": joReceiptDeposit - } ); - } - // - // - const joReceipt = joReceiptDeposit; - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_main_net ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_main_net, jo_message_proxy_main_net, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_main_net.options.address + " contract, no events found" ); - } // if( jo_message_proxy_main_net ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc1155_payment_from_main_net", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-1155 PAYMENT FROM MAIN NET", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc1155_payment_from_main_net", true ); - details.close(); - return true; -} // async function do_erc1155_payment_from_main_net(... - -async function do_erc1155_batch_payment_from_main_net( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_deposit_box_erc1155, - jo_message_proxy_main_net, // for checking logs - chain_id_s_chain, - token_ids, // which ERC1155 token id to send - token_amounts, // which ERC1155 token id to send - wei_how_much, // how much ETH - jo_token_manager_erc1155, // only s-chain - strCoinNameErc1155_main_net, - erc1155PrivateTestnetJson_main_net, - strCoinNameErc1155_s_chain, - erc1155PrivateTestnetJson_s_chain, - tc_main_net -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc1155_batch_payment_from_main_net - let strActionName = ""; - const strLogPrefix = cc.info( "M2S ERC1155 Batch Payment:" ) + " "; - try { - strActionName = "w3_main_net.eth.getTransactionCount()/do_erc1155_batch_payment_from_main_net"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_main_net, joAccountSrc.address( w3_main_net ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC1155 Batch prepare M->S"; - const erc1155ABI = erc1155PrivateTestnetJson_main_net[strCoinNameErc1155_main_net + "_abi"]; - const erc1155Address_main_net = erc1155PrivateTestnetJson_main_net[strCoinNameErc1155_main_net + "_address"]; - const contractERC1155 = new w3_main_net.eth.Contract( erc1155ABI, erc1155Address_main_net ); - // prepare the smart contract function deposit(string schainName, address to) - const depositBoxAddress = jo_deposit_box_erc1155.options.address; - const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( // same as approve in 20 - // joAccountSrc.address( w3_main_net ), - depositBoxAddress, - true - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - let dataTxDeposit = null; - const methodWithArguments_rawDepositERC1155Batch = jo_deposit_box_erc1155.methods.depositERC1155Batch( - chain_id_s_chain, - erc1155Address_main_net, - token_ids, //"0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ), - token_amounts //"0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - ); - dataTxDeposit = methodWithArguments_rawDepositERC1155Batch.encodeABI(); - // - // - strActionName = "compute gas price for ERC1155 Batch transactions M->S"; - let gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC1155 Batch/approve transaction M->S"; - const estimatedGas_approve = await tc_main_net.computeGas( methodWithArguments_approve, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "do_erc1155_batch_payment_from_main_net, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_main_net, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - const rawTxApprove = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc1155Address_main_net, - gasPrice: gasPrice, - gas: estimatedGas_approve - }; - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC1155 Batch/approve transaction M->S"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_main_net, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_main_net, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - details.write( cc.normal( "Will send ERC1155 Batch/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - strActionName = "w3_main_net.eth.sendSignedTransaction()/Approve"; - // let joReceiptApprove = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_main_net, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc1155_batch_payment_from_main_net/approve", - "receipt": joReceiptApprove - } ); - } - // - // - strActionName = "create ERC1155 Batch/deposit transaction M->S"; - tcnt += 1; - // - gasPrice = await tc_main_net.computeGasPrice( w3_main_net, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const estimatedGas_deposit = await tc_main_net.computeGas( methodWithArguments_rawDepositERC1155Batch, w3_main_net, 8000000, gasPrice, joAccountSrc.address( w3_main_net ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(deposit) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_deposit ) + "\n" ); - // - const isIgnore_rawDepositERC1155Batch = true; - const strDRC_rawDepositERC1155Batch = "do_erc1155_batch_payment_from_main_net, rawDepositERC1155Batch"; - const strErrorOfDryRun_rawDepositERC1155Batch = await dry_run_call( details, w3_main_net, methodWithArguments_rawDepositERC1155Batch, joAccountSrc, strDRC_rawDepositERC1155Batch, isIgnore_rawDepositERC1155Batch, gasPrice, estimatedGas_deposit, "0" ); - if( strErrorOfDryRun_rawDepositERC1155Batch ) - throw new Error( strErrorOfDryRun_rawDepositERC1155Batch ); - // - const rawTxDeposit = { - chainId: cid_main_net, - from: joAccountSrc.address( w3_main_net ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxDeposit, - to: depositBoxAddress, - gasPrice: gasPrice, - gas: estimatedGas_deposit - // value: "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - //, value: 2000000000000000 // w3_dst.utils.toWei( (1).toString(), "ether" ) - }; - const txDeposit = compose_tx_instance( details, strLogPrefix, rawTxDeposit ); - strActionName = "sign ERC1155 Batch/deposit transaction M->S"; - const joDepositSR = await safe_sign_transaction_with_account( details, w3_main_net, txDeposit, rawTxDeposit, joAccountSrc ); - let joReceiptDeposit = null; - if( joDepositSR.joACI.isAutoSend ) - joReceiptDeposit = await get_web3_transactionReceipt( details, 10, w3_main_net, joDepositSR.txHashSent ); - else { - const serializedTxDeposit = txDeposit.serialize(); - // send transactions - details.write( cc.normal( "Will send ERC1155 Batch/deposit signed transaction from " ) + cc.warning( joAccountSrc.address( w3_main_net ) ) + "\n" ); - strActionName = "w3_main_net.eth.sendSignedTransaction()/Deposit"; - // let joReceiptDeposit = await w3_main_net.eth.sendSignedTransaction( "0x" + serializedTxDeposit.toString( "hex" ) ); - joReceiptDeposit = await safe_send_signed_transaction( details, w3_main_net, serializedTxDeposit, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Deposit: " ) + cc.j( joReceiptDeposit ) + "\n" ); - if( joReceiptDeposit && typeof joReceiptDeposit == "object" && "gasUsed" in joReceiptDeposit ) { - jarrReceipts.push( { - "description": "do_erc1155_batch_payment_from_main_net/deposit", - "receipt": joReceiptDeposit - } ); - } - // - // - const joReceipt = joReceiptDeposit; - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_main_net ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_main_net, jo_message_proxy_main_net, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_main_net.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_main_net.options.address + " contract, no events found" ); - } // if( jo_message_proxy_main_net ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc1155_batch_payment_from_main_net", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-1155 PAYMENT FROM MAIN NET", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc1155_batch_payment_from_main_net", true ); - details.close(); - return true; -} // async function do_erc1155_batch_payment_from_main_net(... - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function do_erc20_payment_from_s_chain( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager_erc20, // only s-chain - jo_message_proxy_s_chain, // for checking logs - jo_deposit_box, // only main net - token_amount, // how much ERC20 tokens to send - wei_how_much, // how much ETH - strCoinNameErc20_main_net, - joErc20_main_net, - strCoinNameErc20_s_chain, - joErc20_s_chain, - tc_s_chain -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc20_payment_from_s_chain - let strActionName = ""; - const strLogPrefix = cc.info( "S2M ERC20 Payment:" ) + " "; - try { - strActionName = "w3_s_chain.eth.getTransactionCount()/do_erc20_payment_from_s_chain"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - // - // - strActionName = "ERC20 prepare S->M"; - const accountForSchain = joAccountSrc.address( w3_s_chain ); - const erc20ABI = joErc20_s_chain[strCoinNameErc20_s_chain + "_abi"]; - const erc20Address_s_chain = joErc20_s_chain[strCoinNameErc20_s_chain + "_address"]; - const tokenManagerAddress = jo_token_manager_erc20.options.address; - const contractERC20 = new w3_s_chain.eth.Contract( erc20ABI, erc20Address_s_chain ); - // - // prepare the smart contract function deposit(string schainName, address to) - // - // const depositBoxAddress = jo_deposit_box.options.address; - const methodWithArguments_approve = contractERC20.methods.approve( - tokenManagerAddress, "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - const erc20Address_main_net = joErc20_main_net[strCoinNameErc20_main_net + "_address"]; - const methodWithArguments_rawExitToMainERC20 = jo_token_manager_erc20.methods.exitToMainERC20( - erc20Address_main_net, - "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - ); - const dataExitToMainERC20 = methodWithArguments_rawExitToMainERC20.encodeABI(); - // - // prepare for transactions - // - strActionName = "compute gas price for ERC20 transactions S->M"; - let gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC20/approve transaction S->M"; - const estimatedGas_approve = await tc_s_chain.computeGas( methodWithArguments_approve, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "do_erc20_payment_from_s_chain, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - const rawTxApprove = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc20Address_s_chain, - gasPrice: gasPrice, - gas: estimatedGas_approve - }; - await checkTransactionToSchain( w3_s_chain, rawTxApprove, details ); - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC20/approve transaction S->M"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_s_chain, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend && joDepositSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_s_chain, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - // let joReceiptApprove = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_s_chain, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc20_payment_from_s_chain/approve", - "receipt": joReceiptApprove - } ); - } - // - if( g_nSleepBetweenTransactionsOnSChainMilliseconds ) { - details.write( cc.normal( "Sleeping " ) + cc.info( g_nSleepBetweenTransactionsOnSChainMilliseconds ) + cc.normal( " milliseconds between transactions..." ) + "\n" ); - await sleep( g_nSleepBetweenTransactionsOnSChainMilliseconds ); - } - if( g_bWaitForNextBlockOnSChain ) - await wait_for_next_block_to_appear( details, w3_s_chain ); - // - // - // - // - strActionName = "create ERC20/exitToMain transaction S->M"; - const estimatedGas_rawExitToMainERC20 = await tc_s_chain.computeGas( methodWithArguments_rawExitToMainERC20, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_rawExitToMainERC20 ) + "\n" ); - tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const isIgnore_rawExitToMainERC20 = true; - const strDRC_rawExitToMainERC20 = "do_erc20_payment_from_s_chain, rawExitToMainERC20"; - const strErrorOfDryRun_rawExitToMainERC20 = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC20, joAccountSrc, strDRC_rawExitToMainERC20, isIgnore_rawExitToMainERC20, gasPrice, estimatedGas_rawExitToMainERC20, "0" ); - if( strErrorOfDryRun_rawExitToMainERC20 ) - throw new Error( strErrorOfDryRun_rawExitToMainERC20 ); - // - const rawTxExitToMainERC20 = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataExitToMainERC20, - to: tokenManagerAddress, - gasPrice: gasPrice, - gas: estimatedGas_rawExitToMainERC20 - }; - await checkTransactionToSchain( w3_s_chain, rawTxExitToMainERC20, details ); - const txExitToMainERC20 = compose_tx_instance( details, strLogPrefix, rawTxExitToMainERC20 ); - strActionName = "sign ERC20/exitToMain transaction S->M"; - const joExitToMainERC20SR = await safe_sign_transaction_with_account( details, w3_s_chain, txExitToMainERC20, rawTxExitToMainERC20, joAccountSrc ); - let joReceiptExitToMainERC20 = null; - if( joExitToMainERC20SR.joACI.isAutoSend ) - joReceiptExitToMainERC20 = await get_web3_transactionReceipt( details, 10, w3_s_chain, joExitToMainERC20SR.txHashSent ); - else { - const serializedTxExitToMainERC20 = txExitToMainERC20.serialize(); - // let joReceiptExitToMainERC20 = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxExitToMainERC20.toString( "hex" ) ); - joReceiptExitToMainERC20 = await safe_send_signed_transaction( details, w3_s_chain, serializedTxExitToMainERC20, strActionName, strLogPrefix ); - } - if( joReceiptExitToMainERC20 && typeof joReceiptExitToMainERC20 == "object" && "gasUsed" in joReceiptExitToMainERC20 ) { - jarrReceipts.push( { - "description": "do_erc20_payment_from_s_chain/exit-to-main", - "receipt": joReceiptExitToMainERC20 - } ); - } - const joReceipt = joReceiptExitToMainERC20; - details.write( strLogPrefix + cc.success( "Result receipt for ExitToMainERC20: " ) + cc.j( joReceiptExitToMainERC20 ) + "\n" ); - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_s_chain ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_s_chain, jo_message_proxy_s_chain, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_s_chain.options.address + " contract, no events found" ); - } // if( jo_message_proxy_s_chain ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc20_payment_from_s_chain", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-20 PAYMENT FROM S-CHAIN", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc20_payment_from_s_chain", true ); - details.close(); - return true; -} // async function do_erc20_payment_from_s_chain(... - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function do_erc721_payment_from_s_chain( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager_erc721, // only s-chain - jo_message_proxy_s_chain, // for checking logs - jo_deposit_box, // only main net - token_id, // which ERC721 token id to send - wei_how_much, // how much ETH - strCoinNameErc721_main_net, - joErc721_main_net, - strCoinNameErc721_s_chain, - joErc721_s_chain, - tc_s_chain -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc721_payment_from_s_chain - let strActionName = ""; - const strLogPrefix = cc.info( "S2M ERC721 Payment:" ) + " "; - try { - strActionName = "w3_s_chain.eth.getTransactionCount()/do_erc721_payment_from_s_chain"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - // - // - strActionName = "ERC721 prepare S->M"; - const accountForSchain = joAccountSrc.address( w3_s_chain ); - const erc721ABI = joErc721_s_chain[strCoinNameErc721_s_chain + "_abi"]; - const erc721Address_s_chain = joErc721_s_chain[strCoinNameErc721_s_chain + "_address"]; - const tokenManagerAddress = jo_token_manager_erc721.options.address; - const contractERC721 = new w3_s_chain.eth.Contract( erc721ABI, erc721Address_s_chain ); - // prepare the smart contract function deposit(string schainName, address to) - // const depositBoxAddress = jo_deposit_box.options.address; - const methodWithArguments_approve = contractERC721.methods.approve( - // accountForSchain, - tokenManagerAddress, - "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ) - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - let dataTxExitToMainERC721 = null; - const erc721Address_main_net = joErc721_main_net[strCoinNameErc721_main_net + "_address"]; - const methodWithArguments_rawExitToMainERC721 = jo_token_manager_erc721.methods.exitToMainERC721( - erc721Address_main_net, - "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ) - // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - ); - dataTxExitToMainERC721 = methodWithArguments_rawExitToMainERC721.encodeABI(); - // - // - strActionName = "compute gas price for ERC721 transactions S->M"; - let gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC721/approve transaction S->M"; - let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - const estimatedGas_approve = await tc_s_chain.computeGas( methodWithArguments_approve, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(transfer from) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "erc721_payment_from_s_chain, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - const rawTxApprove = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc721Address_s_chain, - gasPrice: gasPrice, - gas: estimatedGas_approve - }; - await checkTransactionToSchain( w3_s_chain, rawTxApprove, details ); - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC721/approve transaction S->M"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_s_chain, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_s_chain, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - // let joReceiptApprove = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_s_chain, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc721_payment_from_s_chain/transfer-from", - "receipt": joReceiptApprove - } ); - } - // - if( g_nSleepBetweenTransactionsOnSChainMilliseconds ) { - details.write( cc.normal( "Sleeping " ) + cc.info( g_nSleepBetweenTransactionsOnSChainMilliseconds ) + cc.normal( " milliseconds between transactions..." ) + "\n" ); - await sleep( g_nSleepBetweenTransactionsOnSChainMilliseconds ); - } - if( g_bWaitForNextBlockOnSChain ) - await wait_for_next_block_to_appear( details, w3_s_chain ); - // - // - // - // - strActionName = "create ERC721/rawExitToMain transaction S->M"; - tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const estimatedGas_exitToMainERC721 = await tc_s_chain.computeGas( methodWithArguments_rawExitToMainERC721, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(exit to main) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_exitToMainERC721 ) + "\n" ); - // - const isIgnore_rawExitToMainERC721 = true; - const strDRC_rawExitToMainERC721 = "erc721_payment_from_s_chain, rawExitToMainERC721"; - const strErrorOfDryRun_rawExitToMainERC721 = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC721, joAccountSrc, strDRC_rawExitToMainERC721, isIgnore_rawExitToMainERC721, gasPrice, estimatedGas_exitToMainERC721, "0" ); - if( strErrorOfDryRun_rawExitToMainERC721 ) - throw new Error( strErrorOfDryRun_rawExitToMainERC721 ); - // - const rawTxExitToMainERC721 = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxExitToMainERC721, - to: tokenManagerAddress, - gasPrice: gasPrice, - gas: estimatedGas_exitToMainERC721 - }; - await checkTransactionToSchain( w3_s_chain, rawTxExitToMainERC721, details ); - const txExitToMainERC721 = compose_tx_instance( details, strLogPrefix, rawTxExitToMainERC721 ); - strActionName = "sign ERC721/rawExitToMain transaction S->M"; - const joExitToMainErc721SR = await safe_sign_transaction_with_account( details, w3_s_chain, txExitToMainERC721, rawTxExitToMainERC721, joAccountSrc ); - let joReceiptExitToMainERC721 = null; - if( joExitToMainErc721SR.joACI.isAutoSend ) - joReceiptExitToMainERC721 = await get_web3_transactionReceipt( details, 10, w3_s_chain, joExitToMainErc721SR.txHashSent ); - else { - const serializedTxExitToMainERC721 = txExitToMainERC721.serialize(); - // let joReceiptExitToMainERC721 = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxExitToMainERC721.toString( "hex" ) ); - joReceiptExitToMainERC721 = await safe_send_signed_transaction( details, w3_s_chain, serializedTxExitToMainERC721, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for ExitToMainERC721: " ) + cc.j( joReceiptExitToMainERC721 ) + "\n" ); - const joReceipt = joReceiptExitToMainERC721; - details.write( strLogPrefix + cc.success( "Result receipt for ExitToMainERC721: " ) + cc.j( joReceiptExitToMainERC721 ) + "\n" ); - if( joReceiptExitToMainERC721 && typeof joReceiptExitToMainERC721 == "object" && "gasUsed" in joReceiptExitToMainERC721 ) { - jarrReceipts.push( { - "description": "do_erc721_payment_from_s_chain/exit-to-main", - "receipt": joReceiptExitToMainERC721 - } ); - } - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_s_chain ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_s_chain, jo_message_proxy_s_chain, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_s_chain.options.address + " contract, no events found" ); - } // if( jo_message_proxy_s_chain ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc721_payment_from_s_chain", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-721 PAYMENT FROM S-CHAIN", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc721_payment_from_s_chain", true ); - details.close(); - return true; -} // async function do_erc721_payment_from_s_chain(... - -async function do_erc1155_payment_from_s_chain( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager_erc1155, // only s-chain - jo_message_proxy_s_chain, // for checking logs - jo_deposit_box, // only main net - token_id, // which ERC1155 token id to send - token_amount, // which ERC1155 token id to send - wei_how_much, // how much ETH - strCoinNameErc1155_main_net, - joErc1155_main_net, - strCoinNameErc1155_s_chain, - joErc1155_s_chain, - tc_s_chain -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc1155_payment_from_s_chain - let strActionName = ""; - const strLogPrefix = cc.info( "S2M ERC1155 Payment:" ) + " "; - try { - strActionName = "w3_s_chain.eth.getTransactionCount()/do_erc1155_payment_from_s_chain"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - // - // - strActionName = "ERC1155 prepare S->M"; - const accountForSchain = joAccountSrc.address( w3_s_chain ); - const erc1155ABI = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_abi"]; - const erc1155Address_s_chain = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_address"]; - const tokenManagerAddress = jo_token_manager_erc1155.options.address; - const contractERC1155 = new w3_s_chain.eth.Contract( erc1155ABI, erc1155Address_s_chain ); - // prepare the smart contract function deposit(string schainName, address to) - // const depositBoxAddress = jo_deposit_box.options.address; - const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( - // accountForSchain, - tokenManagerAddress, - true - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - let dataTxExitToMainERC1155 = null; - const erc1155Address_main_net = joErc1155_main_net[strCoinNameErc1155_main_net + "_address"]; - const methodWithArguments_rawExitToMainERC1155 = jo_token_manager_erc1155.methods.exitToMainERC1155( - erc1155Address_main_net, - "0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ), - "0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - ); - dataTxExitToMainERC1155 = methodWithArguments_rawExitToMainERC1155.encodeABI(); - // - // - strActionName = "compute gas price for ERC1155 transactions S->M"; - let gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC1155/approve transaction S->M"; - let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - const estimatedGas_approve = await tc_s_chain.computeGas( methodWithArguments_approve, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(transfer from) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "erc1155_payment_from_s_chain, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - const rawTxApprove = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc1155Address_s_chain, - gasPrice: gasPrice, - gas: estimatedGas_approve - }; - await checkTransactionToSchain( w3_s_chain, rawTxApprove, details ); - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC1155/approve transaction S->M"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_s_chain, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_s_chain, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - // let joReceiptApprove = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_s_chain, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc1155_payment_from_s_chain/transfer-from", - "receipt": joReceiptApprove - } ); - } - // - if( g_nSleepBetweenTransactionsOnSChainMilliseconds ) { - details.write( cc.normal( "Sleeping " ) + cc.info( g_nSleepBetweenTransactionsOnSChainMilliseconds ) + cc.normal( " milliseconds between transactions..." ) + "\n" ); - await sleep( g_nSleepBetweenTransactionsOnSChainMilliseconds ); - } - if( g_bWaitForNextBlockOnSChain ) - await wait_for_next_block_to_appear( details, w3_s_chain ); - // - // - // - // - strActionName = "create ERC1155/rawExitToMain transaction S->M"; - tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const estimatedGas_exitToMainERC1155 = await tc_s_chain.computeGas( methodWithArguments_rawExitToMainERC1155, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(exit to main) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_exitToMainERC1155 ) + "\n" ); - // - const isIgnore_rawExitToMainERC1155 = true; - const strDRC_rawExitToMainERC1155 = "erc1155_payment_from_s_chain, rawExitToMainERC1155"; - const strErrorOfDryRun_rawExitToMainERC1155 = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC1155, joAccountSrc, strDRC_rawExitToMainERC1155, isIgnore_rawExitToMainERC1155, gasPrice, estimatedGas_exitToMainERC1155, "0" ); - if( strErrorOfDryRun_rawExitToMainERC1155 ) - throw new Error( strErrorOfDryRun_rawExitToMainERC1155 ); - // - const rawTxExitToMainERC1155 = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxExitToMainERC1155, - to: tokenManagerAddress, - gasPrice: gasPrice, - gas: estimatedGas_exitToMainERC1155 - }; - await checkTransactionToSchain( w3_s_chain, rawTxExitToMainERC1155, details ); - const txExitToMainERC1155 = compose_tx_instance( details, strLogPrefix, rawTxExitToMainERC1155 ); - strActionName = "sign ERC1155/rawExitToMain transaction S->M"; - const joExitToMainErc1155SR = await safe_sign_transaction_with_account( details, w3_s_chain, txExitToMainERC1155, rawTxExitToMainERC1155, joAccountSrc ); - let joReceiptExitToMainERC1155 = null; - if( joExitToMainErc1155SR.joACI.isAutoSend ) - joReceiptExitToMainERC1155 = await get_web3_transactionReceipt( details, 10, w3_s_chain, joExitToMainErc1155SR.txHashSent ); - else { - const serializedTxExitToMainERC1155 = txExitToMainERC1155.serialize(); - // let joReceiptExitToMainERC1155 = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxExitToMainERC1155.toString( "hex" ) ); - joReceiptExitToMainERC1155 = await safe_send_signed_transaction( details, w3_s_chain, serializedTxExitToMainERC1155, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for ExitToMainERC1155: " ) + cc.j( joReceiptExitToMainERC1155 ) + "\n" ); - const joReceipt = joReceiptExitToMainERC1155; - details.write( strLogPrefix + cc.success( "Result receipt for ExitToMainERC1155: " ) + cc.j( joReceiptExitToMainERC1155 ) + "\n" ); - if( joReceiptExitToMainERC1155 && typeof joReceiptExitToMainERC1155 == "object" && "gasUsed" in joReceiptExitToMainERC1155 ) { - jarrReceipts.push( { - "description": "do_erc1155_payment_from_s_chain/exit-to-main", - "receipt": joReceiptExitToMainERC1155 - } ); - } - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_s_chain ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_s_chain, jo_message_proxy_s_chain, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_s_chain.options.address + " contract, no events found" ); - } // if( jo_message_proxy_s_chain ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc1155_payment_from_s_chain", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-1155 PAYMENT FROM S-CHAIN", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc1155_payment_from_s_chain", true ); - details.close(); - return true; -} // async function do_erc1155_payment_from_s_chain(... - -async function do_erc1155_batch_payment_from_s_chain( - w3_main_net, - w3_s_chain, - cid_main_net, - cid_s_chain, - joAccountSrc, - joAccountDst, - jo_token_manager_erc1155, // only s-chain - jo_message_proxy_s_chain, // for checking logs - jo_deposit_box, // only main net - token_ids, // which ERC1155 token ids to send - token_amounts, // which ERC1155 token amounts to send - wei_how_much, // how much ETH - strCoinNameErc1155_main_net, - joErc1155_main_net, - strCoinNameErc1155_s_chain, - joErc1155_s_chain, - tc_s_chain -) { - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc1155_batch_payment_from_s_chain - let strActionName = ""; - const strLogPrefix = cc.info( "S2M ERC1155 Batch Payment:" ) + " "; - try { - strActionName = "w3_s_chain.eth.getTransactionCount()/do_erc1155_batch_payment_from_s_chain"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - // - // - strActionName = "ERC1155 Batch prepare S->M"; - const accountForSchain = joAccountSrc.address( w3_s_chain ); - const erc1155ABI = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_abi"]; - const erc1155Address_s_chain = joErc1155_s_chain[strCoinNameErc1155_s_chain + "_address"]; - const tokenManagerAddress = jo_token_manager_erc1155.options.address; - const contractERC1155 = new w3_s_chain.eth.Contract( erc1155ABI, erc1155Address_s_chain ); - // prepare the smart contract function deposit(string schainName, address to) - const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( - // accountForSchain, - tokenManagerAddress, - true - ); - const dataTxApprove = methodWithArguments_approve.encodeABI(); - let dataTxExitToMainERC1155Batch = null; - const erc1155Address_main_net = joErc1155_main_net[strCoinNameErc1155_main_net + "_address"]; - const methodWithArguments_rawExitToMainERC1155Batch = jo_token_manager_erc1155.methods.exitToMainERC1155Batch( - erc1155Address_main_net, - token_ids, //"0x" + w3_main_net.utils.toBN( token_id ).toString( 16 ), - token_amounts //"0x" + w3_main_net.utils.toBN( token_amount ).toString( 16 ) - // "0x" + w3_main_net.utils.toBN( wei_how_much ).toString( 16 ) - ); - dataTxExitToMainERC1155Batch = methodWithArguments_rawExitToMainERC1155Batch.encodeABI(); - // - // - strActionName = "compute gas price for ERC1155 Batch transactions S->M"; - let gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - // - strActionName = "create ERC1155 Batch/approve transaction S->M"; - let tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - const estimatedGas_approve = await tc_s_chain.computeGas( methodWithArguments_approve, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(transfer from) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - // - const isIgnore_approve = false; - const strDRC_approve = "erc1155_payment_from_s_chain, approve"; - const strErrorOfDryRun_approve = await dry_run_call( details, w3_s_chain, methodWithArguments_approve, joAccountSrc, strDRC_approve,isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - // - const rawTxApprove = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxApprove, - to: erc1155Address_s_chain, - gasPrice: gasPrice, - gas: estimatedGas_approve - }; - await checkTransactionToSchain( w3_s_chain, rawTxApprove, details ); - const txApprove = compose_tx_instance( details, strLogPrefix, rawTxApprove ); - strActionName = "sign ERC1155 Batch/approve transaction S->M"; - const joApproveSR = await safe_sign_transaction_with_account( details, w3_s_chain, txApprove, rawTxApprove, joAccountSrc ); - let joReceiptApprove = null; - if( joApproveSR.joACI.isAutoSend ) - joReceiptApprove = await get_web3_transactionReceipt( details, 10, w3_s_chain, joApproveSR.txHashSent ); - else { - const serializedTxApprove = txApprove.serialize(); - // let joReceiptApprove = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxApprove.toString( "hex" ) ); - joReceiptApprove = await safe_send_signed_transaction( details, w3_s_chain, serializedTxApprove, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceiptApprove ) + "\n" ); - if( joReceiptApprove && typeof joReceiptApprove == "object" && "gasUsed" in joReceiptApprove ) { - jarrReceipts.push( { - "description": "do_erc1155_batch_payment_from_s_chain/transfer-from", - "receipt": joReceiptApprove - } ); - } - // - if( g_nSleepBetweenTransactionsOnSChainMilliseconds ) { - details.write( cc.normal( "Sleeping " ) + cc.info( g_nSleepBetweenTransactionsOnSChainMilliseconds ) + cc.normal( " milliseconds between transactions..." ) + "\n" ); - await sleep( g_nSleepBetweenTransactionsOnSChainMilliseconds ); - } - if( g_bWaitForNextBlockOnSChain ) - await wait_for_next_block_to_appear( details, w3_s_chain ); - // - // - // - // - strActionName = "create ERC1155 Batch/rawExitToMain transaction S->M"; - tcnt = parseIntOrHex( await get_web3_transactionCount( details, 10, w3_s_chain, joAccountSrc.address( w3_s_chain ), null ) ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - gasPrice = await tc_s_chain.computeGasPrice( w3_s_chain, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - // - const estimatedGas_exitToMainERC1155Batch = await tc_s_chain.computeGas( methodWithArguments_rawExitToMainERC1155Batch, w3_s_chain, 8000000, gasPrice, joAccountSrc.address( w3_s_chain ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(exit to main) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_exitToMainERC1155Batch ) + "\n" ); - // - const isIgnore_rawExitToMainERC1155Batch = true; - const strDRC_rawExitToMainERC1155Batch = "erc1155_batch_payment_from_s_chain, rawExitToMainERC1155Batch"; - const strErrorOfDryRun_rawExitToMainERC1155Batch = await dry_run_call( details, w3_s_chain, methodWithArguments_rawExitToMainERC1155Batch, joAccountSrc, strDRC_rawExitToMainERC1155Batch, isIgnore_rawExitToMainERC1155Batch, gasPrice, estimatedGas_exitToMainERC1155Batch, "0" ); - if( strErrorOfDryRun_rawExitToMainERC1155Batch ) - throw new Error( strErrorOfDryRun_rawExitToMainERC1155Batch ); - // - const rawTxExitToMainERC1155Batch = { - chainId: cid_s_chain, - from: accountForSchain, - nonce: "0x" + tcnt.toString( 16 ), - data: dataTxExitToMainERC1155Batch, - to: tokenManagerAddress, - gasPrice: gasPrice, - gas: estimatedGas_exitToMainERC1155Batch - }; - await checkTransactionToSchain( w3_s_chain, rawTxExitToMainERC1155Batch, details ); - const txExitToMainERC1155Batch = compose_tx_instance( details, strLogPrefix, rawTxExitToMainERC1155Batch ); - strActionName = "sign ERC1155 Batch/rawExitToMain transaction S->M"; - const joExitToMainErc1155BatchSR = await safe_sign_transaction_with_account( details, w3_s_chain, txExitToMainERC1155Batch, rawTxExitToMainERC1155Batch, joAccountSrc ); - let joReceiptExitToMainERC1155Batch = null; - if( joExitToMainErc1155BatchSR.joACI.isAutoSend ) - joReceiptExitToMainERC1155Batch = await get_web3_transactionReceipt( details, 10, w3_s_chain, joExitToMainErc1155BatchSR.txHashSent ); - else { - const serializedTxExitToMainERC1155Batch = txExitToMainERC1155Batch.serialize(); - // let joReceiptExitToMainERC1155Batch = await w3_s_chain.eth.sendSignedTransaction( "0x" + serializedTxExitToMainERC1155Batch.toString( "hex" ) ); - joReceiptExitToMainERC1155Batch = await safe_send_signed_transaction( details, w3_s_chain, serializedTxExitToMainERC1155Batch, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for ExitToMainERC1155Batch: " ) + cc.j( joReceiptExitToMainERC1155Batch ) + "\n" ); - const joReceipt = joReceiptExitToMainERC1155Batch; - details.write( strLogPrefix + cc.success( "Result receipt for ExitToMainERC1155Batch: " ) + cc.j( joReceiptExitToMainERC1155Batch ) + "\n" ); - if( joReceiptExitToMainERC1155Batch && typeof joReceiptExitToMainERC1155Batch == "object" && "gasUsed" in joReceiptExitToMainERC1155Batch ) { - jarrReceipts.push( { - "description": "do_erc1155_batch_payment_from_s_chain/exit-to-main", - "receipt": joReceiptExitToMainERC1155Batch - } ); - } - // - // Must-have event(s) analysis as indicator(s) of success - // - if( jo_message_proxy_s_chain ) { - details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.debug( " contract ..." ) + "\n" ); - await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - const joEvents = await get_contract_call_events( details, w3_s_chain, jo_message_proxy_s_chain, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length > 0 ) - details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_s_chain.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - else - throw new Error( "Verification failed for the \"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_message_proxy_s_chain.options.address + " contract, no events found" ); - } // if( jo_message_proxy_s_chain ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc1155_batch_payment_from_s_chain", false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-1155 PAYMENT FROM S-CHAIN", jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc1155_batch_payment_from_s_chain", true ); - details.close(); - return true; -} // async function do_erc1155_batch_payment_from_s_chain(... - -// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -async function do_erc20_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc20_src, - nAmountOfToken, // how much ERC20 tokens to send - nAmountOfWei, // how much to send - strCoinNameErc20_src, - joErc20_src, - erc20_address_dst, // only reverse payment needs it - tc -) { - const isReverse = isForward ? false : true; - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc20_payment_s2s - let strActionName = ""; - const strLogPrefix = cc.info( "S2S ERC20 Payment(" + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; - try { - strActionName = "validateArgs/do_erc20_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - if( ! w3_src ) - throw new Error( "No web3 provided for source of transfer" ); - if( ! strChainName_dst ) - throw new Error( "No destination chain name provided" ); - if( ! joAccountSrc ) - throw new Error( "No account or sign TX way provided" ); - if( ! strCoinNameErc20_src ) - throw new Error( "Need full source ERC20 information, like ABI" ); - if( ! joErc20_src ) - throw new Error( "No source ERC20 ABI provided" ); - if( isReverse ) { - if( ! erc20_address_dst ) - throw new Error( "No destination ERC20 address provided" ); - } - if( ! tc ) - throw new Error( "No transaction customizer provided" ); - const erc20_abi_src = joErc20_src[strCoinNameErc20_src + "_abi"]; - const erc20_address_src = joErc20_src[strCoinNameErc20_src + "_address"]; - details.write( strLogPrefix + cc.attention( "Token Manager ERC20" ) + cc.debug( " address on source chain...." ) + cc.note( jo_token_manager_erc20_src.options.address ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC20" ) + cc.debug( " coin name........................." ) + cc.note( strCoinNameErc20_src ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC20" ) + cc.debug( " token address....................." ) + cc.note( erc20_address_src ) + "\n" ); - if( isReverse || erc20_address_dst ) - details.write( strLogPrefix + cc.attention( "Destination ERC20" ) + cc.debug( " token address................" ) + cc.note( erc20_address_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Destination chain name" ) + cc.debug( "........................." ) + cc.note( strChainName_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Amount of tokens" ) + cc.debug( " to transfer..................." ) + cc.note( nAmountOfToken ) + "\n" ); - // - strActionName = "w3_src.eth.getTransactionCount()/do_erc20_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_src, joAccountSrc.address( w3_src ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC20 prepare S->S " + ( isForward ? "forward" : "reverse" ) + " approve"; - const contractERC20 = new w3_src.eth.Contract( - erc20_abi_src, - erc20_address_src - ); - const methodWithArguments_approve = contractERC20.methods.approve( - jo_token_manager_erc20_src.options.address, "0x" + w3_src.utils.toBN( nAmountOfToken ).toString( 16 ) - ); - const dataTx_approve = methodWithArguments_approve.encodeABI(); - // - strActionName = "ERC20 prepare S->S " + ( isForward ? "forward" : "reverse" ) + " transfer"; - const methodWithArguments_transfer = jo_token_manager_erc20_src.methods.transferToSchainERC20( - strChainName_dst, - isReverse ? erc20_address_dst : erc20_address_src, - "0x" + w3_src.utils.toBN( nAmountOfToken ).toString( 16 ) - ); - const dataTx_transfer = methodWithArguments_transfer.encodeABI(); - // - // - strActionName = "compute gas price for ERC20 transactions S->S " + ( isForward ? "forward" : "reverse" ); - let gasPrice = await tc.computeGasPrice( w3_src, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - strActionName = "create ERC20/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const estimatedGas_approve = await tc.computeGas( methodWithArguments_approve, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - const isIgnore_approve = false; - const strDRC_approve = "do_erc20_payment_s2s, approve, " + ( isForward ? "forward" : "reverse" ); - const strErrorOfDryRun_approve = await dry_run_call( details, w3_src, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - const rawTx_approve = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), // accountForMainnet - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_approve, - to: erc20_address_src, - gasPrice: gasPrice, // 0 - gas: estimatedGas_approve - }; - const tx_approve = compose_tx_instance( details, strLogPrefix, rawTx_approve ); - strActionName = "sign ERC20/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_approve = await safe_sign_transaction_with_account( details, w3_src, tx_approve, rawTx_approve, joAccountSrc ); - let joReceipt_approve = null; - if( joSR_approve.joACI.isAutoSend ) - joReceipt_approve = await get_web3_transactionReceipt( details, 10, w3_src, joSR_approve.txHashSent ); - else { - const serializedTx_approve = tx_approve.serialize(); - strActionName = "w3_src.eth.sendSignedTransaction()/Approve/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC20/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_approve = await safe_send_signed_transaction( details, w3_src, serializedTx_approve, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceipt_approve ) + "\n" ); - if( joReceipt_approve && typeof joReceipt_approve == "object" && "gasUsed" in joReceipt_approve ) { - jarrReceipts.push( { - "description": "do_erc20_payment_s2s/approve/" + ( isForward ? "forward" : "reverse" ), - "receipt": joReceipt_approve - } ); - } - // - // - strActionName = "create ERC20/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - gasPrice = await tc.computeGasPrice( w3_src, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_transfer = await tc.computeGas( methodWithArguments_transfer, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_transfer ) + "\n" ); - const isIgnore_transferERC20 = true; - const strDRC_transferERC20 = "do_erc20_payment_s2s, transferERC20"; - const strErrorOfDryRun_transferERC20 = await dry_run_call( details, w3_src, methodWithArguments_transfer, joAccountSrc, strDRC_transferERC20, isIgnore_transferERC20, gasPrice, estimatedGas_transfer, "0" ); - if( strErrorOfDryRun_transferERC20 ) - throw new Error( strErrorOfDryRun_transferERC20 ); - // - tcnt += 1; - const rawTx_transfer = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_transfer, - to: jo_token_manager_erc20_src.options.address, - gasPrice: gasPrice, // 0 - gas: estimatedGas_transfer - // value: "0x" + w3_src.utils.toBN( wei_how_much ).toString( 16 ) - }; - const tx_transfer = compose_tx_instance( details, strLogPrefix, rawTx_transfer ); - strActionName = "sign ERC20/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_transfer = await safe_sign_transaction_with_account( details, w3_src, tx_transfer, rawTx_transfer, joAccountSrc ); - let joReceipt_transfer = null; - if( joSR_transfer.joACI.isAutoSend ) - joReceipt_transfer = await get_web3_transactionReceipt( details, 10, w3_src, joSR_transfer.txHashSent ); - else { - const serializedTx_transfer = tx_transfer.serialize(); - // send transactions - strActionName = "w3_src.eth.sendSignedTransaction()/Transfer/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC20/transfer signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_transfer = await safe_send_signed_transaction( details, w3_src, serializedTx_transfer, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Transfer: " ) + cc.j( joReceipt_transfer ) + "\n" ); - if( joReceipt_transfer && typeof joReceipt_transfer == "object" && "gasUsed" in joReceipt_transfer ) { - jarrReceipts.push( { - "description": "do_erc20_payment_from_src/transfer", - "receipt": joReceipt_transfer - } ); - } - // - // - // const joReceipt = joReceipt_transfer; - // - // Must-have event(s) analysis as indicator(s) of success - // - // if( jo_token_manager_erc20_src ) { - // details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_token_manager_erc20_src.options.address ) + cc.debug( " contract ..." ) + "\n" ); - // await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - // const joEvents = await get_contract_call_events( details, w3_src, jo_token_manager_erc20_src, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - // if( joEvents.length > 0 ) - // details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_token_manager_erc20_src.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - // else - // throw new Error( "Verification failed for th\"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_token_manager_erc20_src.options.address + " contract, no events found" ); - // } // if( jo_token_manager_erc20_src ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc20_payment_s2s/" + ( isForward ? "forward" : "reverse" ), false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-20 PAYMENT FROM S2S/" + ( isForward ? "forward" : "reverse" ), jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc20_payment_s2s/" + ( isForward ? "forward" : "reverse" ), true ); - details.close(); - return true; -} - -// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -async function do_erc721_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc721_src, - token_id, // which ERC721 token id to send - nAmountOfWei, // how much to send - strCoinNameErc721_src, - joErc721_src, - erc721_address_dst, // only reverse payment needs it - tc -) { - const isReverse = isForward ? false : true; - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc721_payment_s2s - let strActionName = ""; - const strLogPrefix = cc.info( "S2S ERC721 Payment(" + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; - try { - strActionName = "validateArgs/do_erc721_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - if( ! w3_src ) - throw new Error( "No web3 provided for source of transfer" ); - if( ! strChainName_dst ) - throw new Error( "No destination chain name provided" ); - if( ! joAccountSrc ) - throw new Error( "No account or sign TX way provided" ); - if( ! strCoinNameErc721_src ) - throw new Error( "Need full source ERC721 information, like ABI" ); - if( ! joErc721_src ) - throw new Error( "No source ERC721 ABI provided" ); - if( isReverse ) { - if( ! erc721_address_dst ) - throw new Error( "No destination ERC721 address provided" ); - } - if( ! tc ) - throw new Error( "No transaction customizer provided" ); - const erc721_abi_src = joErc721_src[strCoinNameErc721_src + "_abi"]; - const erc721_address_src = joErc721_src[strCoinNameErc721_src + "_address"]; - details.write( strLogPrefix + cc.attention( "Token Manager ERC721" ) + cc.debug( " address on source chain...." ) + cc.note( jo_token_manager_erc721_src.options.address ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC721" ) + cc.debug( " coin name........................." ) + cc.note( strCoinNameErc721_src ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC721" ) + cc.debug( " token address....................." ) + cc.note( erc721_address_src ) + "\n" ); - if( isReverse || erc721_address_dst ) - details.write( strLogPrefix + cc.attention( "Destination ERC721" ) + cc.debug( " token address................" ) + cc.note( erc721_address_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Destination chain name" ) + cc.debug( "........................." ) + cc.note( strChainName_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Token ID" ) + cc.debug( " to transfer..........................." ) + cc.note( token_id ) + "\n" ); - // - strActionName = "w3_src.eth.getTransactionCount()/do_erc721_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_src, joAccountSrc.address( w3_src ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC721 prepare S->S " + ( isForward ? "forward" : "reverse" ) + " approve"; - const contractERC721 = new w3_src.eth.Contract( - erc721_abi_src, - erc721_address_src - ); - const methodWithArguments_approve = contractERC721.methods.approve( - jo_token_manager_erc721_src.options.address, - "0x" + w3_src.utils.toBN( token_id ).toString( 16 ) - ); - const dataTx_approve = methodWithArguments_approve.encodeABI(); - // - strActionName = "ERC721 prepare S->S " + ( isForward ? "forward" : "reverse" ) + " transfer"; - const methodWithArguments_transfer = jo_token_manager_erc721_src.methods.transferToSchainERC721( - strChainName_dst, - isReverse ? erc721_address_dst : erc721_address_src, - "0x" + w3_src.utils.toBN( token_id ).toString( 16 ) - ); - const dataTx_transfer = methodWithArguments_transfer.encodeABI(); - // - // - strActionName = "compute gas price for ERC721 transactions S->S " + ( isForward ? "forward" : "reverse" ); - let gasPrice = await tc.computeGasPrice( w3_src, 7210000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - strActionName = "create ERC721/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const estimatedGas_approve = await tc.computeGas( methodWithArguments_approve, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - const isIgnore_approve = false; - const strDRC_approve = "do_erc721_payment_s2s, approve, " + ( isForward ? "forward" : "reverse" ); - const strErrorOfDryRun_approve = await dry_run_call( details, w3_src, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - const rawTx_approve = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), // accountForMainnet - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_approve, - to: erc721_address_src, - gasPrice: gasPrice, // 0 - gas: estimatedGas_approve - }; - const tx_approve = compose_tx_instance( details, strLogPrefix, rawTx_approve ); - strActionName = "sign ERC721/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_approve = await safe_sign_transaction_with_account( details, w3_src, tx_approve, rawTx_approve, joAccountSrc ); - let joReceipt_approve = null; - if( joSR_approve.joACI.isAutoSend ) - joReceipt_approve = await get_web3_transactionReceipt( details, 10, w3_src, joSR_approve.txHashSent ); - else { - const serializedTx_approve = tx_approve.serialize(); - strActionName = "w3_src.eth.sendSignedTransaction()/Approve/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC721/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_approve = await safe_send_signed_transaction( details, w3_src, serializedTx_approve, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceipt_approve ) + "\n" ); - if( joReceipt_approve && typeof joReceipt_approve == "object" && "gasUsed" in joReceipt_approve ) { - jarrReceipts.push( { - "description": "do_erc721_payment_s2s/approve/" + ( isForward ? "forward" : "reverse" ), - "receipt": joReceipt_approve - } ); - } - // - // - strActionName = "create ERC721/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - gasPrice = await tc.computeGasPrice( w3_src, 7210000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_transfer = await tc.computeGas( methodWithArguments_transfer, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_transfer ) + "\n" ); - const isIgnore_transferERC721 = true; - const strDRC_transferERC721 = "do_erc721_payment_s2s, transferERC721"; - const strErrorOfDryRun_transferERC721 = await dry_run_call( details, w3_src, methodWithArguments_transfer, joAccountSrc, strDRC_transferERC721, isIgnore_transferERC721, gasPrice, estimatedGas_transfer, "0" ); - if( strErrorOfDryRun_transferERC721 ) - throw new Error( strErrorOfDryRun_transferERC721 ); - // - tcnt += 1; - const rawTx_transfer = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_transfer, - to: jo_token_manager_erc721_src.options.address, - gasPrice: gasPrice, // 0 - gas: estimatedGas_transfer - // value: "0x" + w3_src.utils.toBN( wei_how_much ).toString( 16 ) - }; - const tx_transfer = compose_tx_instance( details, strLogPrefix, rawTx_transfer ); - strActionName = "sign ERC721/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_transfer = await safe_sign_transaction_with_account( details, w3_src, tx_transfer, rawTx_transfer, joAccountSrc ); - let joReceipt_transfer = null; - if( joSR_transfer.joACI.isAutoSend ) - joReceipt_transfer = await get_web3_transactionReceipt( details, 10, w3_src, joSR_transfer.txHashSent ); - else { - const serializedTx_transfer = tx_transfer.serialize(); - // send transactions - strActionName = "w3_src.eth.sendSignedTransaction()/Transfer/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC721/transfer signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_transfer = await safe_send_signed_transaction( details, w3_src, serializedTx_transfer, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Transfer: " ) + cc.j( joReceipt_transfer ) + "\n" ); - if( joReceipt_transfer && typeof joReceipt_transfer == "object" && "gasUsed" in joReceipt_transfer ) { - jarrReceipts.push( { - "description": "do_erc721_payment_from_src/transfer", - "receipt": joReceipt_transfer - } ); - } - // - // - // const joReceipt = joReceipt_transfer; - // - // Must-have event(s) analysis as indicator(s) of success - // - // if( jo_token_manager_erc721_src ) { - // details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_token_manager_erc721_src.options.address ) + cc.debug( " contract ..." ) + "\n" ); - // await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - // const joEvents = await get_contract_call_events( details, w3_src, jo_token_manager_erc721_src, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - // if( joEvents.length > 0 ) - // details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_token_manager_erc721_src.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - // else - // throw new Error( "Verification failed for th\"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_token_manager_erc721_src.options.address + " contract, no events found" ); - // } // if( jo_token_manager_erc721_src ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc721_payment_s2s/" + ( isForward ? "forward" : "reverse" ), false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-721 PAYMENT FROM S2S/" + ( isForward ? "forward" : "reverse" ), jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc721_payment_s2s/" + ( isForward ? "forward" : "reverse" ), true ); - details.close(); - return true; -} - -// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -async function do_erc1155_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc1155_src, - token_id, // which ERC721 token id to send - nAmountOfToken, // how much ERC1155 tokens to send - nAmountOfWei, // how much to send - strCoinNameErc1155_src, - joErc1155_src, - erc1155_address_dst, // only reverse payment needs it - tc -) { - const isReverse = isForward ? false : true; - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc1155_payment_s2s - let strActionName = ""; - const strLogPrefix = cc.info( "S2S ERC1155 Payment(" + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; - try { - strActionName = "validateArgs/do_erc1155_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - if( ! w3_src ) - throw new Error( "No web3 provided for source of transfer" ); - if( ! strChainName_dst ) - throw new Error( "No destination chain name provided" ); - if( ! joAccountSrc ) - throw new Error( "No account or sign TX way provided" ); - if( ! strCoinNameErc1155_src ) - throw new Error( "Need full source ERC1155 information, like ABI" ); - if( ! joErc1155_src ) - throw new Error( "No source ERC1155 ABI provided" ); - if( isReverse ) { - if( ! erc1155_address_dst ) - throw new Error( "No destination ERC1155 address provided" ); - } - if( ! tc ) - throw new Error( "No transaction customizer provided" ); - const erc1155_abi_src = joErc1155_src[strCoinNameErc1155_src + "_abi"]; - const erc1155_address_src = joErc1155_src[strCoinNameErc1155_src + "_address"]; - details.write( strLogPrefix + cc.attention( "Token Manager ERC1155" ) + cc.debug( " address on source chain...." ) + cc.note( jo_token_manager_erc1155_src.options.address ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + cc.debug( " coin name........................." ) + cc.note( strCoinNameErc1155_src ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + cc.debug( " token address....................." ) + cc.note( erc1155_address_src ) + "\n" ); - if( isReverse || erc1155_address_dst ) - details.write( strLogPrefix + cc.attention( "Destination ERC1155" ) + cc.debug( " token address................" ) + cc.note( erc1155_address_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Destination chain name" ) + cc.debug( "........................." ) + cc.note( strChainName_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Token ID" ) + cc.debug( " to transfer..........................." ) + cc.note( token_id ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Amount of tokens" ) + cc.debug( " to transfer..................." ) + cc.note( nAmountOfToken ) + "\n" ); - // - strActionName = "w3_src.eth.getTransactionCount()/do_erc1155_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_src, joAccountSrc.address( w3_src ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC1155 prepare S->S " + ( isForward ? "forward" : "reverse" ) + " approve"; - const contractERC1155 = new w3_src.eth.Contract( - erc1155_abi_src, - erc1155_address_src - ); - const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( - jo_token_manager_erc1155_src.options.address, - true - ); - const dataTx_approve = methodWithArguments_approve.encodeABI(); - // - strActionName = "ERC1155 prepare S->S " + ( isForward ? "forward" : "reverse" ) + " transfer"; - const methodWithArguments_transfer = jo_token_manager_erc1155_src.methods.transferToSchainERC1155( - strChainName_dst, - isReverse ? erc1155_address_dst : erc1155_address_src, - "0x" + w3_src.utils.toBN( token_id ).toString( 16 ), - "0x" + w3_src.utils.toBN( nAmountOfToken ).toString( 16 ) - ); - const dataTx_transfer = methodWithArguments_transfer.encodeABI(); - // - // - strActionName = "compute gas price for ERC1155 transactions S->S " + ( isForward ? "forward" : "reverse" ); - let gasPrice = await tc.computeGasPrice( w3_src, 11550000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - strActionName = "create ERC1155/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const estimatedGas_approve = await tc.computeGas( methodWithArguments_approve, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - const isIgnore_approve = false; - const strDRC_approve = "do_erc1155_payment_s2s, approve, " + ( isForward ? "forward" : "reverse" ); - const strErrorOfDryRun_approve = await dry_run_call( details, w3_src, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - const rawTx_approve = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), // accountForMainnet - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_approve, - to: erc1155_address_src, - gasPrice: gasPrice, // 0 - gas: estimatedGas_approve - }; - const tx_approve = compose_tx_instance( details, strLogPrefix, rawTx_approve ); - strActionName = "sign ERC1155/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_approve = await safe_sign_transaction_with_account( details, w3_src, tx_approve, rawTx_approve, joAccountSrc ); - let joReceipt_approve = null; - if( joSR_approve.joACI.isAutoSend ) - joReceipt_approve = await get_web3_transactionReceipt( details, 10, w3_src, joSR_approve.txHashSent ); - else { - const serializedTx_approve = tx_approve.serialize(); - strActionName = "w3_src.eth.sendSignedTransaction()/Approve/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC1155/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_approve = await safe_send_signed_transaction( details, w3_src, serializedTx_approve, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceipt_approve ) + "\n" ); - if( joReceipt_approve && typeof joReceipt_approve == "object" && "gasUsed" in joReceipt_approve ) { - jarrReceipts.push( { - "description": "do_erc1155_payment_s2s/approve/" + ( isForward ? "forward" : "reverse" ), - "receipt": joReceipt_approve - } ); - } - // - // - strActionName = "create ERC1155/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - gasPrice = await tc.computeGasPrice( w3_src, 11550000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_transfer = await tc.computeGas( methodWithArguments_transfer, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_transfer ) + "\n" ); - const isIgnore_transferERC1155 = true; - const strDRC_transferERC1155 = "do_erc1155_payment_s2s, transferERC1155"; - const strErrorOfDryRun_transferERC1155 = await dry_run_call( details, w3_src, methodWithArguments_transfer, joAccountSrc, strDRC_transferERC1155, isIgnore_transferERC1155, gasPrice, estimatedGas_transfer, "0" ); - if( strErrorOfDryRun_transferERC1155 ) - throw new Error( strErrorOfDryRun_transferERC1155 ); - // - tcnt += 1; - const rawTx_transfer = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_transfer, - to: jo_token_manager_erc1155_src.options.address, - gasPrice: gasPrice, // 0 - gas: estimatedGas_transfer - // value: "0x" + w3_src.utils.toBN( wei_how_much ).toString( 16 ) - }; - const tx_transfer = compose_tx_instance( details, strLogPrefix, rawTx_transfer ); - strActionName = "sign ERC1155/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_transfer = await safe_sign_transaction_with_account( details, w3_src, tx_transfer, rawTx_transfer, joAccountSrc ); - let joReceipt_transfer = null; - if( joSR_transfer.joACI.isAutoSend ) - joReceipt_transfer = await get_web3_transactionReceipt( details, 10, w3_src, joSR_transfer.txHashSent ); - else { - const serializedTx_transfer = tx_transfer.serialize(); - // send transactions - strActionName = "w3_src.eth.sendSignedTransaction()/Transfer/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC1155/transfer signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_transfer = await safe_send_signed_transaction( details, w3_src, serializedTx_transfer, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Transfer: " ) + cc.j( joReceipt_transfer ) + "\n" ); - if( joReceipt_transfer && typeof joReceipt_transfer == "object" && "gasUsed" in joReceipt_transfer ) { - jarrReceipts.push( { - "description": "do_erc1155_payment_from_src/transfer", - "receipt": joReceipt_transfer - } ); - } - // - // - // const joReceipt = joReceipt_transfer; - // - // Must-have event(s) analysis as indicator(s) of success - // - // if( jo_token_manager_erc1155_src ) { - // details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_token_manager_erc1155_src.options.address ) + cc.debug( " contract ..." ) + "\n" ); - // await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - // const joEvents = await get_contract_call_events( details, w3_src, jo_token_manager_erc1155_src, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - // if( joEvents.length > 0 ) - // details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_token_manager_erc1155_src.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - // else - // throw new Error( "Verification failed for th\"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_token_manager_erc1155_src.options.address + " contract, no events found" ); - // } // if( jo_token_manager_erc1155_src ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc1155_payment_s2s/" + ( isForward ? "forward" : "reverse" ), false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-1155 PAYMENT FROM S2S/" + ( isForward ? "forward" : "reverse" ), jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc1155_payment_s2s/" + ( isForward ? "forward" : "reverse" ), true ); - details.close(); - return true; -} - -// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -async function do_erc1155_batch_payment_s2s( - isForward, - w3_src, - cid_src, - strChainName_dst, - joAccountSrc, - jo_token_manager_erc1155_src, - token_ids, // which ERC1155 token id to send - token_amounts, // which ERC1155 token id to send - nAmountOfWei, // how much to send - strCoinNameErc1155_src, - joErc1155_src, - erc1155_address_dst, // only reverse payment needs it - tc -) { - const isReverse = isForward ? false : true; - const details = log.createMemoryStream(); - const jarrReceipts = []; // do_erc1155_batch_payment_s2s - let strActionName = ""; - const strLogPrefix = cc.info( "S2S Batch ERC1155 Payment(" + ( isForward ? "forward" : "reverse" ) + "):" ) + " "; - try { - strActionName = "validateArgs/do_erc1155_batch_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - if( ! w3_src ) - throw new Error( "No web3 provided for source of transfer" ); - if( ! strChainName_dst ) - throw new Error( "No destination chain name provided" ); - if( ! joAccountSrc ) - throw new Error( "No account or sign TX way provided" ); - if( ! strCoinNameErc1155_src ) - throw new Error( "Need full source ERC1155 information, like ABI" ); - if( ! joErc1155_src ) - throw new Error( "No source ERC1155 ABI provided" ); - if( isReverse ) { - if( ! erc1155_address_dst ) - throw new Error( "No destination ERC1155 address provided" ); - } - if( ! tc ) - throw new Error( "No transaction customizer provided" ); - const erc1155_abi_src = joErc1155_src[strCoinNameErc1155_src + "_abi"]; - const erc1155_address_src = joErc1155_src[strCoinNameErc1155_src + "_address"]; - details.write( strLogPrefix + cc.attention( "Token Manager ERC1155" ) + cc.debug( " address on source chain...." ) + cc.note( jo_token_manager_erc1155_src.options.address ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + cc.debug( " coin name........................." ) + cc.note( strCoinNameErc1155_src ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Source ERC1155" ) + cc.debug( " token address....................." ) + cc.note( erc1155_address_src ) + "\n" ); - if( isReverse || erc1155_address_dst ) - details.write( strLogPrefix + cc.attention( "Destination ERC1155" ) + cc.debug( " token address................" ) + cc.note( erc1155_address_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Destination chain name" ) + cc.debug( "........................." ) + cc.note( strChainName_dst ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Token IDs" ) + cc.debug( " to transfer.........................." ) + cc.j( token_ids ) + "\n" ); - details.write( strLogPrefix + cc.attention( "Amounts of tokens" ) + cc.debug( " to transfer.................." ) + cc.j( token_amounts ) + "\n" ); - // - strActionName = "w3_src.eth.getTransactionCount()/do_erc1155_batch_payment_s2s/" + ( isForward ? "forward" : "reverse" ); - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let tcnt = await get_web3_transactionCount( details, 10, w3_src, joAccountSrc.address( w3_src ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - strActionName = "ERC1155-batch prepare S->S " + ( isForward ? "forward" : "reverse" ) + " approve"; - const contractERC1155 = new w3_src.eth.Contract( - erc1155_abi_src, - erc1155_address_src - ); - const methodWithArguments_approve = contractERC1155.methods.setApprovalForAll( - jo_token_manager_erc1155_src.options.address, - true - ); - const dataTx_approve = methodWithArguments_approve.encodeABI(); - // - strActionName = "ERC1155-batch prepare S->S " + ( isForward ? "forward" : "reverse" ) + " transfer"; - const methodWithArguments_transfer = jo_token_manager_erc1155_src.methods.transferToSchainERC1155Batch( - strChainName_dst, - isReverse ? erc1155_address_dst : erc1155_address_src, - token_ids, - token_amounts - ); - const dataTx_transfer = methodWithArguments_transfer.encodeABI(); - // - // - strActionName = "compute gas price for ERC1155-batch transactions S->S " + ( isForward ? "forward" : "reverse" ); - let gasPrice = await tc.computeGasPrice( w3_src, 11550000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - strActionName = "create ERC1155-batch/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const estimatedGas_approve = await tc.computeGas( methodWithArguments_approve, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(approve) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_approve ) + "\n" ); - const isIgnore_approve = false; - const strDRC_approve = "do_erc1155_batch_payment_s2s, approve, " + ( isForward ? "forward" : "reverse" ); - const strErrorOfDryRun_approve = await dry_run_call( details, w3_src, methodWithArguments_approve, joAccountSrc, strDRC_approve, isIgnore_approve, gasPrice, estimatedGas_approve, "0" ); - if( strErrorOfDryRun_approve ) - throw new Error( strErrorOfDryRun_approve ); - const rawTx_approve = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), // accountForMainnet - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_approve, - to: erc1155_address_src, - gasPrice: gasPrice, // 0 - gas: estimatedGas_approve - }; - const tx_approve = compose_tx_instance( details, strLogPrefix, rawTx_approve ); - strActionName = "sign ERC1155-batch/approve transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_approve = await safe_sign_transaction_with_account( details, w3_src, tx_approve, rawTx_approve, joAccountSrc ); - let joReceipt_approve = null; - if( joSR_approve.joACI.isAutoSend ) - joReceipt_approve = await get_web3_transactionReceipt( details, 10, w3_src, joSR_approve.txHashSent ); - else { - const serializedTx_approve = tx_approve.serialize(); - strActionName = "w3_src.eth.sendSignedTransaction()/Approve/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC1155/approve signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_approve = await safe_send_signed_transaction( details, w3_src, serializedTx_approve, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Approve: " ) + cc.j( joReceipt_approve ) + "\n" ); - if( joReceipt_approve && typeof joReceipt_approve == "object" && "gasUsed" in joReceipt_approve ) { - jarrReceipts.push( { - "description": "do_erc1155_batch_payment_s2s/approve/" + ( isForward ? "forward" : "reverse" ), - "receipt": joReceipt_approve - } ); - } - // - // - strActionName = "create ERC1155-batch/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - gasPrice = await tc.computeGasPrice( w3_src, 11550000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_transfer = await tc.computeGas( methodWithArguments_transfer, w3_src, 8000000, gasPrice, joAccountSrc.address( w3_src ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated(transfer) " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_transfer ) + "\n" ); - const isIgnore_transferERC1155 = true; - const strDRC_transferERC1155 = "do_erc1155_batch_payment_s2s, transferERC1155"; - const strErrorOfDryRun_transferERC1155 = await dry_run_call( details, w3_src, methodWithArguments_transfer, joAccountSrc, strDRC_transferERC1155, isIgnore_transferERC1155, gasPrice, estimatedGas_transfer, "0" ); - if( strErrorOfDryRun_transferERC1155 ) - throw new Error( strErrorOfDryRun_transferERC1155 ); - // - tcnt += 1; - const rawTx_transfer = { - chainId: cid_src, - from: joAccountSrc.address( w3_src ), - nonce: "0x" + tcnt.toString( 16 ), - data: dataTx_transfer, - to: jo_token_manager_erc1155_src.options.address, - gasPrice: gasPrice, // 0 - gas: estimatedGas_transfer - // value: "0x" + w3_src.utils.toBN( wei_how_much ).toString( 16 ) - }; - const tx_transfer = compose_tx_instance( details, strLogPrefix, rawTx_transfer ); - strActionName = "sign ERC1155/transfer transaction S->S " + ( isForward ? "forward" : "reverse" ); - const joSR_transfer = await safe_sign_transaction_with_account( details, w3_src, tx_transfer, rawTx_transfer, joAccountSrc ); - let joReceipt_transfer = null; - if( joSR_transfer.joACI.isAutoSend ) - joReceipt_transfer = await get_web3_transactionReceipt( details, 10, w3_src, joSR_transfer.txHashSent ); - else { - const serializedTx_transfer = tx_transfer.serialize(); - // send transactions - strActionName = "w3_src.eth.sendSignedTransaction()/Transfer/" + ( isForward ? "forward" : "reverse" ); - details.write( cc.normal( "Will send ERC1155/transfer signed transaction from " ) + cc.warning( joAccountSrc.address( w3_src ) ) + "\n" ); - joReceipt_transfer = await safe_send_signed_transaction( details, w3_src, serializedTx_transfer, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt for Transfer: " ) + cc.j( joReceipt_transfer ) + "\n" ); - if( joReceipt_transfer && typeof joReceipt_transfer == "object" && "gasUsed" in joReceipt_transfer ) { - jarrReceipts.push( { - "description": "do_erc1155_payment_from_src/transfer", - "receipt": joReceipt_transfer - } ); - } - // - // - // const joReceipt = joReceipt_transfer; - // - // Must-have event(s) analysis as indicator(s) of success - // - // if( jo_token_manager_erc1155_src ) { - // details.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_token_manager_erc1155_src.options.address ) + cc.debug( " contract ..." ) + "\n" ); - // await sleep( g_nSleepBeforeFetchOutgoingMessageEvent ); - // const joEvents = await get_contract_call_events( details, w3_src, jo_token_manager_erc1155_src, "OutgoingMessage", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - // if( joEvents.length > 0 ) - // details.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "OutgoingMessage" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_token_manager_erc1155_src.options.address ) + cc.success( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - // else - // throw new Error( "Verification failed for th\"OutgoingMessage\" event of the \"MessageProxy\"/" + jo_token_manager_erc1155_src.options.address + " contract, no events found" ); - // } // if( jo_token_manager_erc1155_src ) - } catch ( err ) { - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Payment error in " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, "do_erc1155_batch_payment_s2s/" + ( isForward ? "forward" : "reverse" ), false ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "ERC-1155-batch PAYMENT FROM S2S/" + ( isForward ? "forward" : "reverse" ), jarrReceipts ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "do_erc1155_batch_payment_s2s/" + ( isForward ? "forward" : "reverse" ), true ); - details.close(); - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function parseIntOrHex( s ) { - if( typeof s != "string" ) - return parseInt( s ); - s = s.trim(); - if( s.length > 2 && s[0] == "0" && ( s[1] == "x" || s[1] == "X" ) ) - return parseInt( s, 16 ); - return parseInt( s, 10 ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function async_pending_tx_start( details, w3, w3_opposite, chain_id, chain_id_opposite, txHash ) { - const strLogPrefix = ""; - try { - if( chain_id == "Mainnet" ) { - details.write( strLogPrefix + cc.debug( "Reporting pending transaction " ) + cc.notice( txHash ) + + cc.debug( " start from " ) + cc.u( owaspUtils.w3_2_url( w3 ) ) + cc.debug( "..." ) + "\n" ); - const strNodeURL = owaspUtils.w3_2_url( w3_opposite ); - details.write( strLogPrefix + cc.debug( "Will report pending work cache to " ) + cc.u( strNodeURL ) + cc.debug( "..." ) + "\n" ); - const rpcCallOpts = null; - await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - const s = cc.fatal( "PENDING WORK START ERROR:" ) + cc.error( " JSON RPC call to S-Chain node failed" ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - const joIn = { - method: "skale_imaTxnInsert", - params: { - hash: "" + txHash - } - }; - details.write( cc.debug( "Starting pending work with " ) + cc.j( joIn ) + "\n" ); - await joCall.call( joIn, async function( joIn, joOut, err ) { - if( err ) { - const s = cc.fatal( "PENDING WORK START ERROR:" ) + cc.error( " JSON RPC call to S-Chain node, error: " ) + cc.warning( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - details.write( cc.debug( "Pending work start result is: " ) + cc.j( joOut ) + "\n" ); - if( joOut && "result" in joOut && "success" in joOut.result ) { - if( joOut.result.success ) { - details.write( strLogPrefix + cc.success( "Success, pending work start reported" ) + "\n" ); - return; - } else { - details.write( strLogPrefix + cc.warning( "Pending work start was not reported with success" ) + "\n" ); - return; - } - } else { - const s = cc.fatal( "PENDING WORK START ERROR:" ) + cc.error( " JSON RPC call to S-Chain node, returned bad answer: " ) + cc.j( joOut ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - } ); - } ); - } - } catch ( err ) { - const s = - strLogPrefix + cc.error( "PENDING WORK START ERROR: API call error from " ) + cc.u( owaspUtils.w3_2_url( w3 ) ) + - cc.error( ": " ) + cc.error( err ) + - "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - } -} - -async function async_pending_tx_complete( details, w3, w3_opposite, chain_id, chain_id_opposite, txHash ) { - const strLogPrefix = ""; - try { - if( chain_id == "Mainnet" ) { - details.write( strLogPrefix + cc.debug( "Reporting pending transaction " ) + cc.notice( txHash ) + + cc.debug( " completion from " ) + cc.u( owaspUtils.w3_2_url( w3 ) ) + cc.debug( "..." ) + "\n" ); - const strNodeURL = owaspUtils.w3_2_url( w3_opposite ); - details.write( strLogPrefix + cc.debug( "Will report pending work cache to " ) + cc.u( strNodeURL ) + cc.debug( "..." ) + "\n" ); - const rpcCallOpts = null; - await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - const s = cc.fatal( "PENDING WORK COMPLETE ERROR:" ) + cc.error( " JSON RPC call to S-Chain node failed" ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - const joIn = { - method: "skale_imaTxnErase", - params: { - hash: "" + txHash - } - }; - details.write( cc.debug( "Completing pending work with " ) + cc.j( joIn ) + "\n" ); - await joCall.call( joIn, async function( joIn, joOut, err ) { - if( err ) { - const s = cc.fatal( "PENDING WORK COMPLETE ERROR:" ) + cc.error( " JSON RPC call to S-Chain node, error: " ) + cc.warning( err ) + "'n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - details.write( cc.debug( "Pending work complete result is: " ) + cc.j( joOut ) + "\n" ); - if( joOut && "result" in joOut && "success" in joOut.result ) { - if( joOut.result.success ) { - details.write( strLogPrefix + cc.success( "Success, pending work complete reported" ) + "\n" ); - return; - } else { - details.write( strLogPrefix + cc.warning( "Pending work complete was not reported with success" ) + "\n" ); - return; - } - } else { - const s = cc.fatal( "PENDING WORK COMPLETE ERROR:" ) + cc.error( " JSON RPC call to S-Chain node, returned bad answer: " ) + cc.j( joOut ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - } ); - } ); - - } - } catch ( err ) { - const s = - strLogPrefix + cc.error( "PENDING WORK COMPLETE ERROR: API call error from " ) + cc.u( owaspUtils.w3_2_url( w3 ) ) + - cc.error( ": " ) + cc.error( err ) + - "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - } -} - -// function isIterable( value ) { -// return Symbol.iterator in Object( value ); -// } - -async function async_pending_tx_scanner( details, w3, w3_opposite, chain_id, chain_id_opposite, cb ) { - cb = cb || function( tx ) { }; - const strLogPrefix = ""; - try { - details.write( strLogPrefix + cc.debug( "Scanning pending transactions from " ) + cc.u( owaspUtils.w3_2_url( w3 ) ) + cc.debug( "..." ) + "\n" ); - if( chain_id == "Mainnet" ) { - const strNodeURL = owaspUtils.w3_2_url( w3_opposite ); - details.write( strLogPrefix + cc.debug( "Using pending work cache from " ) + cc.u( strNodeURL ) + cc.debug( "..." ) + "\n" ); - let havePendingWorkInfo = false; - const rpcCallOpts = null; - await rpcCall.create( strNodeURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - const s = cc.fatal( "PENDING WORK CACHE ERROR:" ) + cc.error( " JSON RPC call to S-Chain node failed" ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - const joIn = { - method: "skale_imaTxnListAll", - params: {} - }; - details.write( cc.debug( "Calling pending work cache with " ) + cc.j( joIn ) + "\n" ); - await joCall.call( joIn, async function( joIn, joOut, err ) { - if( err ) { - havePendingWorkInfo = true; - const s = cc.fatal( "PENDING WORK CACHE ERROR:" ) + cc.error( " JSON RPC call to S-Chain node, error: " ) + cc.warning( err ); - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - return; - } - details.write( cc.debug( "Pending work cache result is: " ) + cc.j( joOut ) + "\n" ); - if( joOut && "result" in joOut && "success" in joOut.result ) { - if( joOut.result.success && "allTrackedTXNs" in joOut.result && joOut.result.allTrackedTXNs.length > 0 ) { - details.write( strLogPrefix + cc.debug( "Got " ) + cc.j( joOut.result.allTrackedTXNs.length ) + cc.debug( " pending transaction(s)" ) + "\n" ); - let cntReviewedTNXs = 0; - for( const joTXE of joOut.result.allTrackedTXNs ) { - ++ cntReviewedTNXs; - const joTX = { - hash: "" + joTXE.hash, - to: "holder.value.MessageProxy" - }; - const isContinue = cb( joTX ); - if( ! isContinue ) - break; - } - details.write( strLogPrefix + cc.debug( "Reviewed " ) + cc.info( cntReviewedTNXs ) + cc.debug( " pending transaction(s)" ) + "\n" ); - havePendingWorkInfo = true; - return; - } else { - details.write( strLogPrefix + cc.debug( "Reviewed " ) + cc.info( 0 ) + cc.debug( " pending transaction(s)" ) + "\n" ); - havePendingWorkInfo = true; - return; - } - } else { - const s = cc.fatal( "PENDING WORK CACHE ERROR:" ) + cc.error( " JSON RPC call to S-Chain node, returned bad answer: " ) + cc.j( joOut ); - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - havePendingWorkInfo = true; - return; - } - } ); - } ); - let nWaitAttempt = 0; - while( ! havePendingWorkInfo ) { - await sleep( 3000 ); - ++ nWaitAttempt; - if( nWaitAttempt >= 10 ) { - havePendingWorkInfo = true; // workaround for es-lint - const s = cc.fatal( "PENDING WORK CACHE ERROR:" ) + cc.error( " Wait timeout" ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - break; - } - } - } else { // if( chain_id == "Mainnet" ) - const mapTXs = {}; - let tx_idx = 0; - while( true ) { - let have_next_tx = false; - await w3.eth.getTransactionFromBlock( "pending", tx_idx, function( err, rslt ) { - try { - if( err ) - return; - if( ! rslt ) - return; - if( typeof rslt != "object" ) - return; - have_next_tx = true; - const hash = "" + rslt.hash; - if( hash in mapTXs ) - return; - mapTXs[hash] = rslt; - // details.write( strLogPrefix + cc.debug( "Got pending transaction: " ) + cc.j( rslt ) + "\n" ); - const isContinue = cb( rslt ); - if( ! isContinue ) { - have_next_tx = false; - return; - } - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.error ) { - const s = - strLogPrefix + cc.error( "PENDING TRANSACTIONS ENUMERATION HANDLER ERROR: from " ) + cc.u( owaspUtils.w3_2_url( w3 ) ) + - cc.error( ": " ) + cc.error( err ) + - "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - } - } - } ); - if( ! have_next_tx ) - break; - ++ tx_idx; - } - details.write( strLogPrefix + cc.debug( "Got " ) + cc.j( Object.keys( mapTXs ).length ) + cc.debug( " pending transaction(s)" ) + "\n" ); - } // else from if( chain_id == "Mainnet" ) - } catch ( err ) { - const s = - strLogPrefix + cc.error( "PENDING TRANSACTIONS SCAN ERROR: API call error from " ) + cc.u( owaspUtils.w3_2_url( w3 ) ) + - cc.error( ": " ) + cc.error( err ) + - "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function find_out_reference_log_record( details, w3, jo_message_proxy, nBlockId, nMessageNumberToFind, isVerbose ) { - const strLogPrefix = ""; - const bnMessageNumberToFind = w3.utils.toBN( nMessageNumberToFind.toString() ); - const strEventName = "PreviousMessageReference"; - const arrLogRecords = await get_web3_pastEventsProgressive( - details, - w3, - 10, - jo_message_proxy, - strEventName, - nBlockId, // nBlockFrom - nBlockId, // nBlockTo - { } // filter - ); - const cntLogRecord = arrLogRecords.length; - if( isVerbose ) { - details.write( strLogPrefix + - cc.debug( "Got " ) + cc.info( cntLogRecord ) + cc.debug( " log record(s) (" ) + cc.info( strEventName ) + - cc.debug( ") with data: " ) + cc.j( arrLogRecords ) + "\n" ); - } - for( let idxLogRecord = 0; idxLogRecord < cntLogRecord; ++ idxLogRecord ) { - const joEvent = arrLogRecords[idxLogRecord]; - const joReferenceLogRecord = { // joEvent.returnValues; - currentMessage: joEvent.returnValues.currentMessage, - previousOutgoingMessageBlockId: joEvent.returnValues.previousOutgoingMessageBlockId, - currentBlockId: owaspUtils.toInteger( nBlockId.toString() ) // added field - }; - const bnCurrentMessage = w3.utils.toBN( joReferenceLogRecord.currentMessage.toString() ); - if( bnCurrentMessage.eq( bnMessageNumberToFind ) ) { - if( isVerbose ) { - details.write( strLogPrefix + - cc.success( "Found " ) + cc.info( strEventName ) + cc.success( " log record " ) + - cc.j( joReferenceLogRecord ) + cc.success( " for message " ) + cc.info( nMessageNumberToFind ) + "\n" ); - } - return joReferenceLogRecord; - } - } // for( let idxLogRecord = 0; idxLogRecord < cntLogRecord; ++ idxLogRecord ) - if( isVerbose ) { - details.write( strLogPrefix + - cc.error( "Failed to find " ) + cc.info( strEventName ) + cc.error( " log record for message " ) + - cc.info( nMessageNumberToFind ) + "\n" ); - } - return null; -} - -async function find_out_all_reference_log_records( details, w3, jo_message_proxy, nBlockId, nIncMsgCnt, nOutMsgCnt, isVerbose ) { - const strLogPrefix = ""; - if( isVerbose ) { - details.write( strLogPrefix + - cc.debug( "Optimized IMA message search algorithm will start at block " ) + cc.info( nBlockId.toString() ) + - cc.debug( ", will search for ougoing message counter " ) + cc.info( nOutMsgCnt.toString() ) + - cc.debug( " and approach down to incoming message counter " ) + cc.info( nIncMsgCnt.toString() ) + - "\n" ); - } - const arrLogRecordReferences = []; - const cntExpected = nOutMsgCnt - nIncMsgCnt; - if( cntExpected <= 0 ) { - if( isVerbose ) { - details.write( strLogPrefix + - cc.success( "Optimized IMA message search algorithm success, nothing to search, result is empty" ) + "\n" ); - } - return arrLogRecordReferences; // nothing to searcharrLogRecordReferences - } - let nWalkMsgNumber = nOutMsgCnt - 1; - let nWalkBlockId = nBlockId; - for( ; nWalkMsgNumber >= nIncMsgCnt; -- nWalkMsgNumber ) { - const joReferenceLogRecord = await find_out_reference_log_record( details, w3, jo_message_proxy, nWalkBlockId, nWalkMsgNumber, isVerbose ); - if( joReferenceLogRecord == null ) - break; - nWalkBlockId = owaspUtils.toInteger( joReferenceLogRecord.previousOutgoingMessageBlockId.toString() ); - arrLogRecordReferences.unshift( joReferenceLogRecord ); - } // for( ; nWalkMsgNumber >= nIncMsgCnt; -- nWalkMsgNumber ) - const cntFound = arrLogRecordReferences.length; - if( cntFound != cntExpected ) { - if( isVerbose ) { - details.write( strLogPrefix + - cc.error( "Optimized IMA message search algorithm fail, found " ) + cc.info( cntFound ) + - cc.error( " log record(s), expected " ) + cc.info( cntExpected ) + cc.error( " log record(s), found records are: " ) + - cc.j( arrLogRecordReferences ) + "\n" ); - } - } else { - if( isVerbose ) { - details.write( strLogPrefix + - cc.success( "Optimized IMA message search algorithm success, found all " ) + - cc.info( cntFound ) + cc.success( " log record(s): " ) + cc.j( arrLogRecordReferences ) + "\n" ); - } - } - return arrLogRecordReferences; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -let g_nTransferLoopCounter = 0; - -// -// Do real money movement from main-net to S-chain by sniffing events -// 1) main-net.MessageProxyForMainnet.getOutgoingMessagesCounter -> save to nOutMsgCnt -// 2) S-chain.MessageProxySchain.getIncomingMessagesCounter -> save to nIncMsgCnt -// 3) Will transfer all in range from [ nIncMsgCnt ... (nOutMsgCnt-1) ] ... assume current counter index is nIdxCurrentMsg -// -// One transaction transfer is: -// 1) Find events main-net.MessageProxyForMainnet.OutgoingMessage where msgCounter member is in range -// 2) Publish it to S-chain.MessageProxySchain.postIncomingMessages( -// main-net chain id // uint64 srcChainID -// nIdxCurrentMsg // uint64 startingCounter -// [srcContract] // address[] memory senders -// [dstContract] // address[] memory dstContracts -// [to] // address[] memory to -// [amount] // uint256[] memory amount / *uint256[2] memory blsSignature* / -// ) -// -async function do_transfer( - strDirection, - // - w3_src, - jo_message_proxy_src, - joAccountSrc, - w3_dst, - jo_message_proxy_dst, - // - joAccountDst, - // - chain_id_src, - chain_id_dst, - cid_src, - cid_dst, - // - jo_deposit_box_main_net, // for logs validation on mainnet - jo_token_manager_schain, // for logs validation on s-chain - // - nTransactionsCountInBlock, - nMaxTransactionsCount, - nBlockAwaitDepth, - nBlockAge, - fn_sign_messages, - joExtraSignOpts, - // - tc_dst, - // - optsPendingTxAnalysis -) { - const nTransferLoopCounter = g_nTransferLoopCounter; - ++ g_nTransferLoopCounter; - // - const strTransferErrorCategoryName = "loop-" + strDirection; - const strGatheredDetailsName = "" + strDirection + "-" + - "do_transfer-A-#" + nTransferLoopCounter + - "-" + chain_id_src + "-->" + chain_id_dst; - const strGatheredDetailsNameColored = "" + cc.bright( strDirection ) + cc.debug( "-" ) + - cc.info( "do_transfer-A-" ) + cc.debug( "-" ) + cc.notice( "#" ) + cc.note( nTransferLoopCounter ) + - cc.debug( "-" ) + cc.notice( chain_id_src ) + cc.debug( "-->" ) + cc.notice( chain_id_dst ); - const details = log.createMemoryStream( true ); - const jarrReceipts = []; - let bErrorInSigningMessages = false; - const strLogPrefix = cc.bright( strDirection ) + cc.info( " transfer from " ) + cc.notice( chain_id_src ) + cc.info( " to " ) + cc.notice( chain_id_dst ) + cc.info( ":" ) + " "; - if( fn_sign_messages == null || fn_sign_messages == undefined ) { - details.write( strLogPrefix + cc.debug( "Using internal signing stub function" ) + "\n" ); - fn_sign_messages = async function( jarrMessages, nIdxCurrentMsgBlockStart, details, joExtraSignOpts, fnAfter ) { - details.write( strLogPrefix + cc.debug( "Message signing callback was " ) + cc.error( "not provided" ) + - cc.debug( " to IMA, first real message index is:" ) + cc.info( nIdxCurrentMsgBlockStart ) + - cc.debug( ", have " ) + cc.info( jarrMessages.length ) + cc.debug( " message(s) to process:" ) + cc.j( jarrMessages ) + - "\n" ); - await fnAfter( null, jarrMessages, null ); // null - no error, null - no signatures - }; - } else - details.write( strLogPrefix + cc.debug( "Using externally provided signing function" ) + "\n" ); - nTransactionsCountInBlock = nTransactionsCountInBlock || 5; - nMaxTransactionsCount = nMaxTransactionsCount || 100; - if( nTransactionsCountInBlock < 1 ) - nTransactionsCountInBlock = 1; - if( nBlockAwaitDepth < 0 ) - nBlockAwaitDepth = 0; - if( nBlockAge < 0 ) - nBlockAge = 0; - let r; let strActionName = ""; - let nIdxCurrentMsg = 0; - let nOutMsgCnt = 0; - let nIncMsgCnt = 0; - try { - details.write( cc.info( "SRC " ) + cc.sunny( "MessageProxy" ) + cc.info( " address is....." ) + cc.bright( jo_message_proxy_src.options.address ) + "\n" ); - details.write( cc.info( "DST " ) + cc.sunny( "MessageProxy" ) + cc.info( " address is....." ) + cc.bright( jo_message_proxy_dst.options.address ) + "\n" ); - strActionName = "src-chain.MessageProxy.getOutgoingMessagesCounter()"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - let nPossibleIntegerValue = await jo_message_proxy_src.methods.getOutgoingMessagesCounter( chain_id_dst ).call( { - from: joAccountSrc.address( w3_src ) - } ); - if( !owaspUtils.validateInteger( nPossibleIntegerValue ) ) - throw new Error( "DST chain " + chain_id_dst + " returned outgoing message counter " + nPossibleIntegerValue + " which is not a valid integer" ); - nOutMsgCnt = owaspUtils.toInteger( nPossibleIntegerValue ); - details.write( strLogPrefix + cc.debug( "Result of " ) + cc.notice( strActionName ) + cc.debug( " call: " ) + cc.info( nOutMsgCnt ) + "\n" ); - // - strActionName = "dst-chain.MessageProxy.getIncomingMessagesCounter()"; - details.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( "..." ) + "\n" ); - nPossibleIntegerValue = await jo_message_proxy_dst.methods.getIncomingMessagesCounter( chain_id_src ).call( { - from: joAccountDst.address( w3_dst ) - } ); - if( !owaspUtils.validateInteger( nPossibleIntegerValue ) ) - throw new Error( "SRC chain " + chain_id_src + " returned incoming message counter " + nPossibleIntegerValue + " which is not a valid integer" ); - nIncMsgCnt = owaspUtils.toInteger( nPossibleIntegerValue ); - details.write( strLogPrefix + cc.debug( "Result of " ) + cc.notice( strActionName ) + cc.debug( " call: " ) + cc.info( nIncMsgCnt ) + "\n" ); - // - strActionName = "src-chain.MessageProxy.getIncomingMessagesCounter()"; - nPossibleIntegerValue = await jo_message_proxy_src.methods.getIncomingMessagesCounter( chain_id_dst ).call( { - from: joAccountSrc.address( w3_src ) - } ); - if( !owaspUtils.validateInteger( nPossibleIntegerValue ) ) - throw new Error( "DST chain " + chain_id_dst + " returned incoming message counter " + nPossibleIntegerValue + " which is not a valid integer" ); - const idxLastToPopNotIncluding = owaspUtils.toInteger( nPossibleIntegerValue ); - details.write( strLogPrefix + cc.debug( "Result of " ) + cc.notice( strActionName ) + cc.debug( " call: " ) + cc.info( idxLastToPopNotIncluding ) + "\n" ); - - // - // optimized scanner - // - const nBlockId = await jo_message_proxy_src.methods.getLastOutgoingMessageBlockId( chain_id_dst ).call( { - from: joAccountSrc.address( w3_src ) - } ); - // const joReferenceLogRecord = await find_out_reference_log_record( details, w3_src, jo_message_proxy_src, nBlockId, nOutMsgCnt - 1, true ); - let arrLogRecordReferences = []; - try { - arrLogRecordReferences = await find_out_all_reference_log_records( details, w3_src, jo_message_proxy_src, nBlockId, nIncMsgCnt, nOutMsgCnt, true ); - if( arrLogRecordReferences.length <= 0 ) - throw new Error( "Nothing was found by optimized IMA messages search algorithm" ); - } catch ( err ) { - arrLogRecordReferences = []; - details.write( - strLogPrefix + cc.warning( "Optimized log search is " ) + cc.error( "off" ) + - cc.warning( ". Running old IMA smart contracts?" ) + cc.success( " Please upgrade, if possible." ) + - "\n" ); - } - - // - // classic scanner with optional usage of optimizamed IMA messages search algorithm - // outer loop is block former/creator, then transfer - // - nIdxCurrentMsg = nIncMsgCnt; - let cntProcessed = 0; - while( nIdxCurrentMsg < nOutMsgCnt ) { - details.write( - strLogPrefix + cc.debug( "Entering block former iteration with " ) + cc.notice( "message counter" ) + - cc.debug( " set to " ) + cc.info( nIdxCurrentMsg ) + - "\n" ); - if( "check_time_framing" in global && ( ! global.check_time_framing() ) ) { - if( verbose_get() >= RV_VERBOSE.information ) { - log.write( - strLogPrefix + cc.error( "WARNING:" ) + " " + - cc.warning( "Time framing overflow (after entering block former iteration loop)" ) + - "\n" ); - } - details.close(); - save_transfer_success_all(); - return false; - } - const arrMessageCounters = []; - const jarrMessages = []; - const nIdxCurrentMsgBlockStart = 0 + nIdxCurrentMsg; - // - // inner loop wil create block of transactions - // - let cntAccumulatedForBlock = 0; - for( let idxInBlock = 0; nIdxCurrentMsg < nOutMsgCnt && idxInBlock < nTransactionsCountInBlock; ++nIdxCurrentMsg, ++idxInBlock, ++cntAccumulatedForBlock ) { - const idxProcessing = cntProcessed + idxInBlock; - if( idxProcessing > nMaxTransactionsCount ) - break; - // - let nBlockFrom = 0; - let nBlockTo = "latest"; - if( arrLogRecordReferences.length > 0 ) { - const joReferenceLogRecord = arrLogRecordReferences.shift(); - nBlockFrom = joReferenceLogRecord.currentBlockId; - nBlockTo = joReferenceLogRecord.currentBlockId; - } - // - strActionName = "src-chain->MessageProxy->scan-past-events()"; - details.write( - strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + - cc.debug( " for " ) + cc.info( "OutgoingMessage" ) + cc.debug( " event..." ) + - "\n" ); - r = await get_web3_pastEventsProgressive( - details, - w3_src, - 10, - jo_message_proxy_src, - "OutgoingMessage", - nBlockFrom, - nBlockTo, - { - dstChainHash: [ w3_src.utils.soliditySha3( chain_id_dst ) ], - msgCounter: [ nIdxCurrentMsg ] - } - ); - //details.write( strLogPrefix + cc.normal( "Logs search result(s): " ) + cc.j( r ) + "\n" ); - const strChainHashWeAreLookingFor = w3_src.utils.soliditySha3( chain_id_dst ); - let joValues = ""; - details.write( strLogPrefix + - cc.debug( "Will review " ) + cc.info( r.length ) + - cc.debug( " found event records(in reverse order, newest to oldest)" ) + - cc.debug( " while looking for hash " ) + cc.info( strChainHashWeAreLookingFor ) + - cc.debug( " of destination chain " ) + cc.info( chain_id_dst ) + - "\n" ); - for( let i = r.length - 1; i >= 0; i-- ) { - details.write( strLogPrefix + - cc.debug( "Will review found event record " ) + cc.info( i ) + - cc.debug( " with data " ) + cc.j( r[i] ) + - "\n" ); - if( r[i].returnValues.dstChainHash == strChainHashWeAreLookingFor ) { - joValues = r[i].returnValues; - joValues.savedBlockNumberForOptimizations = r[i].blockNumber; - details.write( strLogPrefix + - cc.debug( "Found event record " ) + cc.info( i ) + cc.debug( " reviewed and " ) + - cc.success( "accepted for processing, found event values are " ) + cc.j( joValues ) + - cc.success( ", found block number is " ) + cc.info( joValues.savedBlockNumberForOptimizations ) + - "\n" ); - break; - } else { - details.write( strLogPrefix + - cc.debug( "Found event record " ) + cc.info( i ) + cc.debug( " reviewed and " ) + - cc.warning( "skipped" ) + - "\n" ); - } - } - if( joValues == "" ) { - const strError = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + " " + cc.error( "Can't get events from MessageProxy" ); - log.write( strError + "\n" ); - details.write( strError + "\n" ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, details.toString() ); - details.close(); - return false; - } - // - // - // - if( nBlockAwaitDepth > 0 ) { - let bSecurityCheckPassed = true; - const strActionName_old = "" + strActionName; - strActionName = "security check: evaluate block depth"; - try { - const transactionHash = r[0].transactionHash; - details.write( strLogPrefix + cc.debug( "Event transactionHash is " ) + cc.info( transactionHash ) + "\n" ); - const blockNumber = r[0].blockNumber; - details.write( strLogPrefix + cc.debug( "Event blockNumber is " ) + cc.info( blockNumber ) + "\n" ); - const nLatestBlockNumber = await get_web3_blockNumber( details, 10, w3_src ); - details.write( strLogPrefix + cc.debug( "Latest blockNumber is " ) + cc.info( nLatestBlockNumber ) + "\n" ); - const nDist = nLatestBlockNumber - blockNumber; - if( nDist < nBlockAwaitDepth ) - bSecurityCheckPassed = false; - details.write( strLogPrefix + cc.debug( "Distance by blockNumber is " ) + cc.info( nDist ) + cc.debug( ", await check is " ) + ( bSecurityCheckPassed ? cc.success( "PASSED" ) : cc.error( "FAILED" ) ) + "\n" ); - } catch ( err ) { - bSecurityCheckPassed = false; - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Exception(evaluate block depth) while getting transaction hash and block number during " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, details.toString() ); - details.close(); - return false; - } - strActionName = "" + strActionName_old; - if( !bSecurityCheckPassed ) { - const s = strLogPrefix + cc.warning( "Block depth check was not passed, canceling search for transfer events" ) + "\n"; - if( verbose_get() >= RV_VERBOSE.trace ) - log.write( s ); - details.write( s ); - break; - } - } // if( nBlockAwaitDepth > 0 ) - if( nBlockAge > 0 ) { - let bSecurityCheckPassed = true; - const strActionName_old = "" + strActionName; - strActionName = "security check: evaluate block age"; - try { - const transactionHash = r[0].transactionHash; - details.write( strLogPrefix + cc.debug( "Event transactionHash is " ) + cc.info( transactionHash ) + "\n" ); - const blockNumber = r[0].blockNumber; - details.write( strLogPrefix + cc.debug( "Event blockNumber is " ) + cc.info( blockNumber ) + "\n" ); - // - // - const joBlock = await w3_src.eth.getBlock( blockNumber ); - if( !owaspUtils.validateInteger( joBlock.timestamp ) ) - throw new Error( "Block \"timestamp\" is not a valid integer value: " + joBlock.timestamp ); - const timestampBlock = owaspUtils.toInteger( joBlock.timestamp ); - details.write( strLogPrefix + cc.debug( "Block TS is " ) + cc.info( timestampBlock ) + "\n" ); - const timestampCurrent = current_timestamp(); - details.write( strLogPrefix + cc.debug( "Current TS is " ) + cc.info( timestampCurrent ) + "\n" ); - const tsDiff = timestampCurrent - timestampBlock; - details.write( strLogPrefix + cc.debug( "Diff TS is " ) + cc.info( tsDiff ) + "\n" ); - details.write( strLogPrefix + cc.debug( "Expected diff " ) + cc.info( nBlockAge ) + "\n" ); - if( tsDiff < nBlockAge ) - bSecurityCheckPassed = false; - details.write( strLogPrefix + cc.debug( "Block age check is " ) + ( bSecurityCheckPassed ? cc.success( "PASSED" ) : cc.error( "FAILED" ) ) + "\n" ); - } catch ( err ) { - bSecurityCheckPassed = false; - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Exception(evaluate block age) while getting block number and timestamp during " + strActionName + ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, details.toString() ); - details.close(); - return false; - } - strActionName = "" + strActionName_old; - if( !bSecurityCheckPassed ) { - details.write( strLogPrefix + cc.warning( "Block age check was not passed, canceling search for transfer events" ) + "\n" ); - break; - } - } // if( nBlockAge > 0 ) - // - // - // - details.write( - strLogPrefix + - cc.success( "Got event details from " ) + cc.notice( "getPastEvents()" ) + - cc.success( " event invoked with " ) + cc.notice( "msgCounter" ) + cc.success( " set to " ) + cc.info( nIdxCurrentMsg ) + - cc.success( " and " ) + cc.notice( "dstChain" ) + cc.success( " set to " ) + cc.info( chain_id_dst ) + - cc.success( ", event description: " ) + cc.j( joValues ) + // + cc.j(evs) + - "\n" - ); - // - // - details.write( strLogPrefix + cc.debug( "Will process message counter value " ) + cc.info( nIdxCurrentMsg ) + "\n" ); - arrMessageCounters.push( nIdxCurrentMsg ); - - const joMessage = { - sender: joValues.srcContract, - destinationContract: joValues.dstContract, - to: joValues.to, - amount: joValues.amount, - data: joValues.data, - savedBlockNumberForOptimizations: joValues.savedBlockNumberForOptimizations - }; - jarrMessages.push( joMessage ); - } // for( let idxInBlock = 0; nIdxCurrentMsg < nOutMsgCnt && idxInBlock < nTransactionsCountInBlock; ++ nIdxCurrentMsg, ++ idxInBlock, ++cntAccumulatedForBlock ) - if( cntAccumulatedForBlock == 0 ) - break; - if( "check_time_framing" in global && ( ! global.check_time_framing() ) ) { - if( verbose_get() >= RV_VERBOSE.information ) { - log.write( - strLogPrefix + cc.error( "WARNING:" ) + " " + - cc.warning( "Time framing overflow (after forming block of messages)" ) + - "\n" ); - } - details.close(); - save_transfer_success_all(); - return false; - } - // - // - // Analyze pending transactions potentially awaited by previous IMA agent running in previous time frame - if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) { - let joFoundPendingTX = null; - let wasIgnoredPTX = false; - try { - const strShortMessageProxyAddressToCompareWith = owaspUtils.remove_starting_0x( jo_message_proxy_dst.options.address ).toLowerCase(); - await async_pending_tx_scanner( details, w3_dst, w3_src, chain_id_dst, chain_id_src, function( joTX ) { - if( "to" in joTX ) { - if( joTX.to == "holder.value.MessageProxy" ) { - joFoundPendingTX = joTX; - return false; // stop pending tx scanner - } - const strShortToAddress = owaspUtils.remove_starting_0x( joTX.to ).toLowerCase(); - if( strShortToAddress == strShortMessageProxyAddressToCompareWith ) { - joFoundPendingTX = joTX; - return false; // stop pending tx scanner - } - } - return true; // continue pending tx scanner - } ); - if( joFoundPendingTX ) { - details.write( - strLogPrefix + cc.warning( "PENDING TRANSACTION ANALYSIS(1) from " ) + cc.u( owaspUtils.w3_2_url( w3_dst ) ) + - cc.warning( " found un-finished transaction(s) in pending queue to be processed by destination message proxy: " ) + - cc.j( joFoundPendingTX ) + - "\n" ); - if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled && - "nTimeoutSecondsBeforeSecondAttempt" in optsPendingTxAnalysis && optsPendingTxAnalysis.nTimeoutSecondsBeforeSecondAttempt > 0 - ) { - details.write( cc.debug( "Sleeping " ) + cc.info( optsPendingTxAnalysis.nTimeoutSecondsBeforeSecondAttempt ) + cc.debug( " seconds before secondary pending transactions analysis..." ) + "\n" ); - await sleep( optsPendingTxAnalysis.nTimeoutSecondsBeforeSecondAttempt * 1000 ); - // - joFoundPendingTX = null; - await async_pending_tx_scanner( w3_dst, w3_src, chain_id_dst, chain_id_src, function( joTX ) { - if( "to" in joTX ) { - if( joTX.to == "holder.value.MessageProxy" ) { - joFoundPendingTX = joTX; - return false; // stop pending tx scanner - } - const strShortToAddress = owaspUtils.remove_starting_0x( joTX.to ).toLowerCase(); - if( strShortToAddress == strShortMessageProxyAddressToCompareWith ) { - joFoundPendingTX = joTX; - return false; // stop pending tx scanner - } - } - return true; // continue pending tx scanner - } ); - if( joFoundPendingTX ) { - details.write( - strLogPrefix + cc.warning( "PENDING TRANSACTION ANALYSIS(2) from " ) + cc.u( owaspUtils.w3_2_url( w3_dst ) ) + - cc.warning( " found un-finished transaction(s) in pending queue to be processed by destination message proxy: " ) + - cc.j( joFoundPendingTX ) + - "\n" ); - if( "isIgnore2" in optsPendingTxAnalysis && ( !optsPendingTxAnalysis.isIgnore2 ) ) - return false; // return after 2nd pending transactions analysis - details.write( - strLogPrefix + cc.warning( "PENDING TRANSACTION ANALYSIS(2) from " ) + cc.u( owaspUtils.w3_2_url( w3_dst ) ) + - cc.warning( " result is " ) + cc.error( "ignored" ) + - "\n" ); - wasIgnoredPTX = true; - } - } else { - if( "isIgnore" in optsPendingTxAnalysis && ( !optsPendingTxAnalysis.isIgnore ) ) - return false; // return after first 1st transactions analysis - details.write( - strLogPrefix + cc.warning( "PENDING TRANSACTION ANALYSIS(1) from " ) + cc.u( owaspUtils.w3_2_url( w3_dst ) ) + - cc.warning( " result is " ) + cc.error( "ignored" ) + - "\n" ); - wasIgnoredPTX = true; - } - } - } catch ( err ) { - const s = - strLogPrefix + cc.error( "PENDING TRANSACTION ANALYSIS ERROR: API call error from " ) + - cc.u( owaspUtils.w3_2_url( w3_dst ) ) + cc.error( ": " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.error ) - log.write( s ); - details.write( s ); - } - if( !wasIgnoredPTX ) { - details.write( - strLogPrefix + cc.success( "PENDING TRANSACTION ANALYSIS did not found transactions to wait for complete" ) + - "\n" ); - } - if( "check_time_framing" in global && ( ! global.check_time_framing() ) ) { - if( verbose_get() >= RV_VERBOSE.information ) { - log.write( - strLogPrefix + cc.error( "WARNING:" ) + " " + - cc.warning( "Time framing overflow (after pending transactions analysis)" ) + - "\n" ); - } - details.close(); - save_transfer_success_all(); - return false; - } - } - // - // - // - if( strDirection == "S2S" ) { - strActionName = "S2S message analysis"; - if( ! joExtraSignOpts ) - throw new Error( "Could not validate S2S messages, no extra options provided to transfer algorithm" ); - if( ! joExtraSignOpts.skale_observer ) - throw new Error( "Could not validate S2S messages, no SKALE NETWORK observer provided to transfer algorithm" ); - const arr_schains_cached = joExtraSignOpts.skale_observer.get_last_cached_schains(); - if( ( !arr_schains_cached ) || arr_schains_cached.length == 0 ) - throw new Error( "Could not validate S2S messages, no S-Chains in SKALE NETWORK observer cached yet, try again later" ); - const idxSChain = joExtraSignOpts.skale_observer.find_schain_index_in_array_by_name( arr_schains_cached, chain_id_src ); - if( idxSChain < 0 ) { - throw new Error( - "Could not validate S2S messages, source S-Chain \"" + chain_id_src + - "\" is not in SKALE NETWORK observer cache yet or it's not connected to this \"" + chain_id_dst + - "\" S-Chain yet, try again later" ); - } - const cntMessages = jarrMessages.length; - const jo_schain = arr_schains_cached[idxSChain]; - const cntNodes = jo_schain.data.computed.nodes.length; - const cntNodesShouldPass = - ( cntNodes == 16 ) - ? 11 - : ( - ( cntNodes == 4 ) - ? 3 - : ( - ( cntNodes == 2 || cntNodes == 1 ) - ? ( 0 + cntNodes ) - : parseInt( ( cntNodes * 2 ) / 3 ) - ) - ); - const cntNodesMayFail = cntNodes - cntNodesShouldPass; - details.write( strLogPrefix + - cc.sunny( strDirection ) + cc.debug( " message analysis will be performed o S-Chain " ) + - cc.info( chain_id_src ) + cc.debug( " with " ) + - cc.info( cntNodes ) + cc.debug( " node(s), " ) + - cc.info( cntNodesShouldPass ) + cc.debug( " node(s) should have same message(s), " ) + - cc.info( cntNodesMayFail ) + cc.debug( " node(s) allowed to fail message(s) comparison, " ) + - cc.info( cntMessages ) + cc.debug( " message(s) to check..." ) + - "\n" ); - - // jarrMessages.push( { - // sender: joValues.srcContract, - // destinationContract: joValues.dstContract, - // to: joValues.to, - // amount: joValues.amount, - // data: joValues.data - // } ); - for( let idxMessage = 0; idxMessage < cntMessages; ++ idxMessage ) { - const idxImaMessage = arrMessageCounters[idxMessage]; - const joMessage = jarrMessages[idxMessage]; - details.write( strLogPrefix + - cc.sunny( strDirection ) + cc.debug( " message analysis for message " ) + - cc.info( idxMessage + 1 ) + cc.debug( " of " ) + cc.info( cntMessages ) + - cc.debug( " with IMA message index " ) + cc.j( idxImaMessage ) + - cc.debug( " and message envelope data:" ) + cc.j( joMessage ) + - "\n" ); - let cntPassedNodes = 0, cntFailedNodes = 0; - try { - for( let idxNode = 0; idxNode < cntNodes; ++ idxNode ) { - const jo_node = jo_schain.data.computed.nodes[idxNode]; - details.write( strLogPrefix + - cc.debug( "Validating " ) + cc.sunny( strDirection ) + cc.debug( " message " ) + cc.info( idxMessage + 1 ) + - cc.debug( " on node " ) + cc.info( jo_node.name ) + - cc.debug( " using URL " ) + cc.info( jo_node.http_endpoint_ip ) + - cc.debug( "..." ) + "\n" ); - try { - const w3_node = getWeb3FromURL( jo_node.http_endpoint_ip, details ); - const jo_message_proxy_node = new w3_node.eth.Contract( imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, imaState.joAbiPublishResult_s_chain.message_proxy_chain_address ); - const strEventName = "OutgoingMessage"; - const node_r = await get_web3_pastEventsProgressive( - details, - w3_node, - 10, - jo_message_proxy_node, - strEventName, - joMessage.savedBlockNumberForOptimizations, // 0, // nBlockFrom - joMessage.savedBlockNumberForOptimizations, // "latest", // nBlockTo - { - dstChainHash: [ w3_node.utils.soliditySha3( chain_id_dst ) ], - msgCounter: [ idxImaMessage ] - } - ); - const cntEvents = node_r.length; - details.write( strLogPrefix + - cc.debug( "Got " ) + cc.info( cntEvents ) + cc.debug( " event(s) (" ) + cc.info( strEventName ) + cc.debug( ") on node " ) + - cc.info( jo_node.name ) + cc.debug( " with data: " ) + cc.j( node_r ) + "\n" ); - for( let idxEvent = 0; idxEvent < cntEvents; ++ idxEvent ) { - const joEvent = node_r[idxEvent]; - if( owaspUtils.ensure_starts_with_0x( joMessage.sender ).toLowerCase() == - owaspUtils.ensure_starts_with_0x( joEvent.returnValues.srcContract ).toLowerCase() && - owaspUtils.ensure_starts_with_0x( joMessage.destinationContract ).toLowerCase() == - owaspUtils.ensure_starts_with_0x( joEvent.returnValues.dstContract ).toLowerCase() - ) - bEventIsFound = true; - if( bEventIsFound ) - break; - } // for( let idxEvent = 0; idxEvent < cntEvents; ++ idxEvent ) - } catch ( err ) { - ++ cntFailedNodes; - const strError = strLogPrefix + cc.fatal( strDirection + " message analysis error:" ) + " " + - cc.error( "Failed to scan events on node " ) + cc.info( jo_node.name ) + - cc.error( ", error is: " ) + cc.warning( err.toString() ) + - cc.error( ", detailed node description is: " ) + cc.j( jo_node ) + - "\n"; - details.write( strError ); - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strError ); - // details.exposeDetailsTo( log, strGatheredDetailsName, false ); - // save_transfer_error( strTransferErrorCategoryName, details.toString() ); - // details.close(); - // return false; - continue; - } - if( bEventIsFound ) { - ++ cntPassedNodes; - details.write( strLogPrefix + cc.sunny( strDirection ) + - cc.success( " message " ) + cc.info( idxMessage + 1 ) + cc.success( " validation on node " ) + - cc.info( jo_node.name ) + cc.success( " using URL " ) + cc.info( jo_node.http_endpoint_ip ) + - cc.success( " is passed" ) + "\n" ); - } else { - ++ cntFailedNodes; - const strError = strLogPrefix + cc.sunny( strDirection ) + - cc.error( " message " ) + cc.info( idxMessage + 1 ) + cc.error( " validation on node " ) + - cc.info( jo_node.name ) + cc.success( " using URL " ) + cc.info( jo_node.http_endpoint_ip ) + - cc.error( " is failed" ) + "\n"; ; - details.write( strError ); - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strError ); - } - if( cntFailedNodes > cntNodesMayFail ) - break; - if( cntPassedNodes >= cntNodesShouldPass ) { - details.write( strLogPrefix + cc.sunny( strDirection ) + - cc.success( " message " ) + cc.info( idxMessage + 1 ) + cc.success( " validation on node " ) + - cc.info( jo_node.name ) + cc.success( " using URL " ) + cc.info( jo_node.http_endpoint_ip ) + - cc.success( " is passed" ) + "\n" ); - break; - } - } // for( let idxNode = 0; idxNode < cntNodes; ++ idxNode ) - } catch ( err ) { - const strError = strLogPrefix + cc.fatal( strDirection + " message analysis error:" ) + " " + - cc.error( "Failed to process events for " ) + cc.sunny( strDirection ) + cc.error( " message " ) + - cc.info( idxMessage + 1 ) + cc.error( " on node " ) + cc.info( jo_node.name ) + - cc.success( " using URL " ) + cc.info( jo_node.http_endpoint_ip ) + - cc.debug( ", error is: " ) + cc.warning( err.toString() ) + "\n"; - details.write( strError ); - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strError ); - } - if( cntFailedNodes > cntNodesMayFail ) { - const s = - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error validating " ) + cc.sunny( strDirection ) + - cc.error( " messages, failed node count " ) + cc.info( cntFailedNodes ) + - cc.error( " is greater then allowed to fail " ) + cc.info( cntNodesMayFail ) + - "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, details.toString() ); - details.close(); - return false; - } - if( ! ( cntPassedNodes >= cntNodesShouldPass ) ) { - const s = - strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error validating " ) + cc.sunny( strDirection ) + - cc.error( " messages, passed node count " ) + cc.info( cntFailedNodes ) + - cc.error( " is less then needed count " ) + cc.info( cntNodesShouldPass ) + - "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - details.write( s ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, details.toString() ); - details.close(); - return false; - } - } // for( let idxMessage = 0; idxMessage < cntMessages; ++ idxMessage ) - - } // if( strDirection == "S2S" ) //// "S2S message analysis - // - // - // - strActionName = "sign messages"; - details.write( strLogPrefix + - cc.debug( "Will invoke message signing callback, first real message index is: " ) + - cc.info( nIdxCurrentMsgBlockStart ) + cc.info( jarrMessages.length ) + - cc.debug( " message(s) to process: " ) + cc.j( jarrMessages ) + - "\n" ); - log.write( strLogPrefix + - cc.debug( "Will invoke message signing callback, first real message index is: " ) + - cc.info( nIdxCurrentMsgBlockStart ) + cc.info( jarrMessages.length ) + - cc.debug( " message(s) to process: " ) + cc.j( jarrMessages ) + - "\n" ); - let detailsB = log.createMemoryStream( true ); - const strGatheredDetailsName = "" + strDirection + "-" + - "do_transfer-B-#" + nTransferLoopCounter + - "-" + chain_id_src + "-->" + chain_id_dst; - try { - await fn_sign_messages( - nTransferLoopCounter, - jarrMessages, nIdxCurrentMsgBlockStart, chain_id_src, - joExtraSignOpts, - async function( err, jarrMessages, joGlueResult ) { - detailsB.write( strLogPrefix + - cc.debug( "Did invoked message signing callback, first real message index is: " ) + - cc.info( nIdxCurrentMsgBlockStart ) + cc.info( jarrMessages.length ) + - cc.debug( " message(s) to process: " ) + cc.j( jarrMessages ) + - "\n" ); - log.write( strLogPrefix + cc.debug( "Did invoked message signing callback, " ) + cc.info( jarrMessages.length ) + cc.debug( " message(s) to process" ) + "\n" ); - if( err ) { - bErrorInSigningMessages = true; - const s = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error signing messages: " ) + cc.error( err ) + "\n"; - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( s ); - detailsB.write( s ); - detailsB.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, detailsB.toString() ); - detailsB.close(); - return false; - } - if( "check_time_framing" in global && ( ! global.check_time_framing() ) ) { - if( verbose_get() >= RV_VERBOSE.information ) - log.write( strLogPrefix + cc.error( "WARNING:" ) + " " + cc.warning( "Time framing overflow (after signing messages)" ) + "\n" ); - detailsB.close(); - save_transfer_success_all(); - return false; - } - strActionName = "dst-chain.getTransactionCount()"; - const tcnt = await get_web3_transactionCount( detailsB, 10, w3_dst, joAccountDst.address( w3_dst ), null ); - detailsB.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - // - // - const nBlockSize = arrMessageCounters.length; - strActionName = "dst-chain.MessageProxy.postIncomingMessages()"; - detailsB.write( strLogPrefix + - cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( " for " ) + - cc.notice( "block size" ) + cc.debug( " set to " ) + cc.info( nBlockSize ) + - cc.debug( ", " ) + cc.notice( "message counters =" ) + cc.debug( " are " ) + cc.info( JSON.stringify( arrMessageCounters ) ) + - cc.debug( "..." ) + "\n" - ); - log.write( strLogPrefix + cc.debug( "Will call " ) + cc.notice( strActionName ) + cc.debug( " for " ) + "\n" ); - // - // - let signature = joGlueResult ? joGlueResult.signature : null; - if( !signature ) - signature = { X: "0", Y: "0" }; - let hashPoint = joGlueResult ? joGlueResult.hashPoint : null; - if( !hashPoint ) - hashPoint = { X: "0", Y: "0" }; - let hint = joGlueResult ? joGlueResult.hint : null; - if( !hint ) - hint = "0"; - const sign = { - blsSignature: [ signature.X, signature.Y ], // BLS glue of signatures - hashA: hashPoint.X, // G1.X from joGlueResult.hashSrc - hashB: hashPoint.Y, // G1.Y from joGlueResult.hashSrc - counter: hint - }; - const methodWithArguments_postIncomingMessages = jo_message_proxy_dst.methods.postIncomingMessages( - // call params - chain_id_src, - nIdxCurrentMsgBlockStart, - jarrMessages, - sign //, // bls signature components - // idxLastToPopNotIncluding - ); - const dataTx_postIncomingMessages = methodWithArguments_postIncomingMessages.encodeABI(); // the encoded ABI of the method - // - if( verbose_get() >= RV_VERBOSE.trace ) { - const joDebugArgs = [ - chain_id_src, - chain_id_dst, - nIdxCurrentMsgBlockStart, - jarrMessages, - [ signature.X, signature.Y ], // BLS glue of signatures - hashPoint.X, // G1.X from joGlueResult.hashSrc - hashPoint.Y, // G1.Y from joGlueResult.hashSrc - hint - ]; - detailsB.write( strLogPrefix + - cc.debug( "....debug args for " ) + - cc.notice( "msgCounter" ) + cc.debug( " set to " ) + cc.info( nIdxCurrentMsgBlockStart ) + cc.debug( ": " ) + - cc.j( joDebugArgs ) + "\n" ); - } - // - const gasPrice = await tc_dst.computeGasPrice( w3_dst, 200000000000 ); - detailsB.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_postIncomingMessages = await tc_dst.computeGas( methodWithArguments_postIncomingMessages, w3_dst, 10000000, gasPrice, joAccountDst.address( w3_dst ), "0" ); - detailsB.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_postIncomingMessages ) + "\n" ); - let postIncomingMessagesGasLimit = estimatedGas_postIncomingMessages; - if( strDirection == "S2M" ) { - const expectedGasLimit = perMessageGasForTransfer * jarrMessages.length + additionalS2MTransferOverhead; - postIncomingMessagesGasLimit = Math.max( postIncomingMessagesGasLimit, expectedGasLimit ); - } - - const isIgnore_postIncomingMessages = false; - const strDRC_postIncomingMessages = "postIncomingMessages in message signer"; - const strErrorOfDryRun = await dry_run_call( detailsB, w3_dst, methodWithArguments_postIncomingMessages, joAccountDst, strDRC_postIncomingMessages,isIgnore_postIncomingMessages, gasPrice, estimatedGas_postIncomingMessages, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - const raw_tx_postIncomingMessages = { - chainId: cid_dst, - from: joAccountDst.address( w3_dst ), - nonce: tcnt, - gas: postIncomingMessagesGasLimit, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: jo_message_proxy_dst.options.address, // contract address - data: dataTx_postIncomingMessages //, - // "value": wei_amount // 1000000000000000000 // w3_dst.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - if( chain_id_dst !== "Mainnet" ) - await checkTransactionToSchain( w3_dst, raw_tx_postIncomingMessages, detailsB ); - - const tx_postIncomingMessages = compose_tx_instance( detailsB, strLogPrefix, raw_tx_postIncomingMessages ); - const joPostIncomingMessagesSR = await safe_sign_transaction_with_account( detailsB, w3_dst, tx_postIncomingMessages, raw_tx_postIncomingMessages, joAccountDst ); - let joReceipt = null; - if( joPostIncomingMessagesSR.joACI.isAutoSend ) { - // - // NOTICE: async_pending_tx_start()/ async_pending_tx_complete() must be called only in do_transfer() - // - if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - await async_pending_tx_start( detailsB, w3_dst, w3_src, chain_id_dst, chain_id_src, "" + joPostIncomingMessagesSR.txHashSent ); - joReceipt = await get_web3_transactionReceipt( detailsB, 10, w3_dst, joPostIncomingMessagesSR.txHashSent ); - } else { - const serializedTx_postIncomingMessages = tx_postIncomingMessages.serialize(); - strActionName = "w3_dst.eth.sendSignedTransaction()"; - // let joReceipt = await w3_dst.eth.sendSignedTransaction( "0x" + serializedTx_postIncomingMessages.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( detailsB, w3_dst, serializedTx_postIncomingMessages, strActionName, strLogPrefix ); - } - detailsB.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - if( joReceipt && typeof joReceipt == "object" && "gasUsed" in joReceipt ) { - jarrReceipts.push( { - "description": "do_transfer/postIncomingMessages()", - "detailsString": "" + strGatheredDetailsName, - "receipt": joReceipt - } ); - print_gas_usage_report_from_array( "(intermediate result) TRANSFER " + chain_id_src + " -> " + chain_id_dst, jarrReceipts ); - // - // NOTICE: async_pending_tx_start()/ async_pending_tx_complete() must be called only in do_transfer() - // - if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - await async_pending_tx_complete( detailsB, w3_dst, w3_src, chain_id_dst, chain_id_src, "" + joReceipt.transactionHash ); - } - cntProcessed += cntAccumulatedForBlock; - // - // - // - // - // - // - // - detailsB.write( strLogPrefix + cc.debug( "Validating transfer from " ) + cc.info( chain_id_src ) + cc.debug( " to " ) + cc.info( chain_id_dst ) + cc.debug( "..." ) + "\n" ); - // - // check DepositBox -> Error on Mainnet only - // - if( chain_id_dst == "Mainnet" ) { - detailsB.write( strLogPrefix + cc.debug( "Validating transfer to Main Net via MessageProxy error absence on Main Net..." ) + "\n" ); - if( jo_deposit_box_main_net ) { - if( joReceipt && "blockNumber" in joReceipt && "transactionHash" in joReceipt ) { - detailsB.write( strLogPrefix + cc.debug( "Verifying the " ) + cc.info( "PostMessageError" ) + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + cc.debug( "/" ) + cc.notice( jo_message_proxy_dst.options.address ) + cc.debug( " contract..." ) + "\n" ); - const joEvents = await get_contract_call_events( detailsB, w3_dst, jo_message_proxy_dst, "PostMessageError", joReceipt.blockNumber, joReceipt.transactionHash, {} ); - if( joEvents.length == 0 ) - detailsB.write( strLogPrefix + cc.success( "Success, verified the " ) + cc.info( "PostMessageError" ) + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + cc.success( "/" ) + cc.notice( jo_message_proxy_dst.options.address ) + cc.success( " contract, no events found" ) + "\n" ); - else { - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.warning( " Failed" ) + cc.error( " verification of the " ) + cc.warning( "PostMessageError" ) + cc.error( " event of the " ) + cc.warning( "MessageProxy" ) + cc.error( "/" ) + cc.notice( jo_message_proxy_dst.options.address ) + cc.error( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - detailsB.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.warning( " Failed" ) + cc.error( " verification of the " ) + cc.warning( "PostMessageError" ) + cc.error( " event of the " ) + cc.warning( "MessageProxy" ) + cc.error( "/" ) + cc.notice( jo_message_proxy_dst.options.address ) + cc.error( " contract, found event(s): " ) + cc.j( joEvents ) + "\n" ); - save_transfer_error( strTransferErrorCategoryName, detailsB.toString() ); - throw new Error( "Verification failed for the \"PostMessageError\" event of the \"MessageProxy\"/" + jo_message_proxy_dst.options.address + " contract, error events found" ); - } - detailsB.write( strLogPrefix + cc.success( "Done, validated transfer to Main Net via MessageProxy error absence on Main Net" ) + "\n" ); - } else - detailsB.write( strLogPrefix + cc.error( "WARNING:" ) + " " + cc.warn( "Cannot validate transfer to Main Net via MessageProxy error absence on Main Net, no valid transaction receipt provided" ) + "\n" ); - } else - detailsB.write( strLogPrefix + cc.error( "WARNING:" ) + " " + cc.warn( "Cannot validate transfer to Main Net via MessageProxy error absence on Main Net, no MessageProxy provided" ) + "\n" ); - } // if( chain_id_dst == "Mainnet" ) - - } ).catch( ( err ) => { // callback fn as argument of fn_sign_messages - bErrorInSigningMessages = true; - if( verbose_get() >= RV_VERBOSE.fatal ) { - const strErrorMessage = strLogPrefix + cc.error( "Problem in transfer handler: " ) + cc.warning( err ); - log.write( strErrorMessage + "\n" ); - detailsB.write( strErrorMessage + "\n" ); - detailsB.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, detailsB.toString() ); - detailsB.close(); - detailsB = null; - } - if( detailsB ) { - if( expose_details_get() ) - detailsB.exposeDetailsTo( log, strGatheredDetailsName, true ); - detailsB.close(); - } - } ); // fn_sign_messages - } catch ( err ) { - const strError = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " Exception from sigining messages function: " ) + cc.error( err.toString() ); - log.write( strError + "\n" ); - details.write( strError + "\n" ); - if( detailsB ) - detailsB.write( strError + "\n" ); - } - if( detailsB ) { - if( expose_details_get() ) - detailsB.exposeDetailsTo( log, strGatheredDetailsName, true ); - detailsB.close(); - } - if( bErrorInSigningMessages ) - break; - } // while( nIdxCurrentMsg < nOutMsgCnt ) - } catch ( err ) { - const strError = strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + - cc.error( " Error in " ) + strGatheredDetailsNameColored + - cc.error( " during " + strActionName + ": " ) + cc.error( err ); - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strError + "\n" ); - details.write( strError + "\n" ); - details.exposeDetailsTo( log, strGatheredDetailsName, false ); - save_transfer_error( strTransferErrorCategoryName, details.toString() ); - details.close(); - return false; - } - print_gas_usage_report_from_array( "TRANSFER " + chain_id_src + " -> " + chain_id_dst, jarrReceipts ); - if( details ) { - if( expose_details_get() && details.exposeDetailsTo ) - details.exposeDetailsTo( log, strGatheredDetailsName, true ); - details.close(); - } - if( ! bErrorInSigningMessages ) - save_transfer_success( strTransferErrorCategoryName ); - return true; -} // async function do_transfer( ... - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function do_s2s_all( // s-chain --> s-chain - imaState, - skale_observer, - w3_dst, - jo_message_proxy_dst, - joAccountDst, - chain_id_dst, - cid_dst, - jo_token_manager_schain, // for logs validation on s-chain - // - nTransactionsCountInBlock, - nMaxTransactionsCount, - nBlockAwaitDepth, - nBlockAge, - fn_sign_messages, - // - tc_dst, - // - optsPendingTxAnalysis -) { - let cntOK = 0, cntFail = 0; - const strDirection = "S2S"; - const arr_schains_cached = skale_observer.get_last_cached_schains(); - const cntSChains = arr_schains_cached.length; - for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { - const jo_schain = arr_schains_cached[idxSChain]; - const url_src = skale_observer.pick_random_schain_w3_url( jo_schain ); - const w3_src = getWeb3FromURL( url_src, log ); - const joAccountSrc = joAccountDst; // ??? - const chain_id_src = "" + jo_schain.data.name; - const cid_src = "" + jo_schain.data.computed.chainId; - let bOK = false; - try { - // ??? assuming all S-Chains have same ABIs here - const jo_message_proxy_src = new w3_src.eth.Contract( imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, imaState.joAbiPublishResult_s_chain.message_proxy_chain_address ); - const jo_deposit_box_src = new w3_src.eth.Contract( imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, imaState.joAbiPublishResult_s_chain.message_proxy_chain_address ); - const joExtraSignOpts = { - skale_observer: skale_observer, - chain_id_src: chain_id_src, - cid_src: cid_src, - chain_id_dst: chain_id_dst, - cid_dst: cid_dst, - joAccountSrc: joAccountSrc, - joAccountDst: joAccountDst, - w3_src: w3_src, - w3_dst: w3_dst - }; - bOK = - await do_transfer( - strDirection, - // - w3_src, - jo_message_proxy_src, - joAccountSrc, - w3_dst, - jo_message_proxy_dst, - // - joAccountDst, - // - chain_id_src, - chain_id_dst, - cid_src, - cid_dst, - // - jo_deposit_box_src, // for logs validation on mainnet or source S-Chain - jo_token_manager_schain, // for logs validation on s-chain - // - nTransactionsCountInBlock, - nMaxTransactionsCount, - nBlockAwaitDepth, - nBlockAge, - fn_sign_messages, - joExtraSignOpts, - // - tc_dst, - // - optsPendingTxAnalysis - ); - } catch ( err ) { - bOK = false; - if( verbose_get() >= RV_VERBOSE.fatal ) { - log.write( cc.fatal( "S2S STEP ERROR:" ) + - cc.error( " From S-Chain " ) + cc.info( chain_id_src ) + - cc.error( ", error is: " ) + cc.warning( err ) + - "\n" ); - } - } - if( bOK ) - ++ cntOK; - else - ++ cntFail; - } - if( verbose_get() >= RV_VERBOSE.debug && ( cntOK > 0 || cntFail > 0 ) ) { - let s = cc.debug( "Stats for S2S steps:" ); - if( cntOK > 0 ) - s += " " + cc.info( cntOK ) + cc.success( " S-Chain(s) processed OKay" ) + cc.debug( ", " ); - if( cntFail > 0 ) - s += " " + cc.info( cntFail ) + cc.error( " S-Chain(s) failed" ); - log.write( s + "\n" ); - } - return ( cntFail == 0 ) ? true : false; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function compose_gas_usage_report_from_array( strName, jarrReceipts ) { - if( ! ( strName && typeof strName == "string" && jarrReceipts ) ) - return ""; - let i, sumGasUsed = 0, s = "\n\n" + cc.info( "GAS USAGE REPORT FOR " ) + cc.attention( strName ) + "\n"; - for( i = 0; i < jarrReceipts.length; ++ i ) { - try { - sumGasUsed += parseInt( jarrReceipts[i].receipt.gasUsed, 10 ); - s += cc.notice( jarrReceipts[i].description ) + cc.debug( "....." ) + cc.info( jarrReceipts[i].receipt.gasUsed ) + "\n"; - } catch ( err ) { } - } - s += cc.attention( "SUM" ) + cc.debug( "....." ) + cc.info( sumGasUsed ) + "\n\n"; - return s; -} - -function print_gas_usage_report_from_array( strName, jarrReceipts ) { - const s = compose_gas_usage_report_from_array( strName, jarrReceipts ); - if( s && s.length > 0 ) - log.write( s ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// init helpers -// - -function noop() { - return null; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class TransactionCustomizer { - constructor( gasPriceMultiplier, gasMultiplier ) { - this.gasPriceMultiplier = gasPriceMultiplier ? ( 0.0 + gasPriceMultiplier ) : null; // null means use current gasPrice or recommendedGasPrice - this.gasMultiplier = gasMultiplier ? ( 0.0 + gasMultiplier ) : 1.25; - } - async computeGasPrice( w3, maxGasPrice ) { - const gasPrice = parseIntOrHex( await w3.eth.getGasPrice() ); - if( gasPrice == 0 || gasPrice == null || gasPrice == undefined || gasPrice <= 1000000000 ) - return parseIntOrHex( "1000000000" ); - else if( - this.gasPriceMultiplier != null && - this.gasPriceMultiplier != undefined && - this.gasPriceMultiplier >= 0 && - maxGasPrice != null && - maxGasPrice != undefined - ) { - if( gasPrice * this.gasPriceMultiplier > maxGasPrice ) - return parseIntOrHex( maxGasPrice ); - else - return parseIntOrHex( ( gasPrice * this.gasPriceMultiplier ).toString() ); - } else - return gasPrice; - } - async computeGas( methodWithArguments, w3, recommendedGas, gasPrice, addressFrom, ethValue ) { - let estimatedGas = 0; - try { - await methodWithArguments.estimateGas( { - from: addressFrom, - gasPrice: gasPrice, - value: "0x" + w3.utils.toBN( ethValue ).toString( 16 ) - }, function( err, estimatedGasValue ) { - if( err ) { - estimatedGas = 0; - return; - } - estimatedGas = estimatedGasValue; - } ); - } catch ( err ) { - estimatedGas = 0; - } - estimatedGas *= this.gasMultiplier; - estimatedGas = parseIntOrHex( "" + estimatedGas ); // avoid using floating point - if( estimatedGas == 0 ) - estimatedGas = recommendedGas; - return estimatedGas; - } -}; - -const tc_main_net = new TransactionCustomizer( 1.25, 1.25 ); -const tc_s_chain = new TransactionCustomizer( null, 1.25 ); -const tc_t_chain = new TransactionCustomizer( null, 1.25 ); - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function checkTransactionToSchain( w3_s_chain, tx, details ) { - const sender = tx.from; - const requiredBalance = tx.gasPrice * tx.gas; - const balance = await w3_s_chain.eth.getBalance( sender ); - if( balance < requiredBalance ) { - details.write( - cc.normal( "Insufficient funds for " ) + cc.bright( tx.from ) + - cc.normal( "; Running PoW for mining " ) + cc.bright( tx.gas ) + " gas\n" ); - const powNumber = await calculatePowNumber( sender, tx.nonce, tx.gas ); - tx.gasPrice = ethereumjs_util.addHexPrefix( powNumber ); - } - return tx; -} - -async function calculatePowNumber( address, nonce, gas ) { - const path = require( "path" ); - let _address = ethereumjs_util.addHexPrefix( address ); - _address = ethereumjs_util.toChecksumAddress( _address ); - _address = ethereumjs_util.stripHexPrefix( _address ); - const _nonce = parseIntOrHex( nonce ); - const _gas = parseIntOrHex( gas ); - const powScriptPath = path.join( __dirname, "pow" ); - const cmd = `${powScriptPath} ${_address} ${_nonce} ${_gas}`; - return await execShellCommand( cmd ); -} - -function execShellCommand( cmd ) { - const exec = require( "child_process" ).exec; - return new Promise( ( resolve, reject ) => { - exec( cmd, ( error, stdout, stderr ) => { - if( error ) - reject( new Error( stderr ) ); - else - resolve( stdout ? stdout : stderr ); - } ); - } ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -async function balanceETH( - isMainNet, - w3, - cid, - joAccount, - contractERC20 -) { - strLogPrefix = cc.info( "balanceETH() call" ) + " "; - try { - if( ! ( w3 && joAccount ) ) - return ""; - const strAddress = joAccount.address( w3 ); - if( ( !isMainNet ) && contractERC20 ) { - const balance = await contractERC20.methods.balanceOf( strAddress ).call( { from: strAddress } ); - return balance; - } - const balance = await w3.eth.getBalance( strAddress ); - return balance; - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + cc.error( err ) + "\n" ); - } - return ""; -} - -async function balanceERC20( - isMainNet, - w3, - cid, - joAccount, - strCoinName, - joABI -) { - strLogPrefix = cc.info( "balanceERC20() call" ) + " "; - try { - if( ! ( w3 && joAccount && strCoinName && joABI && ( strCoinName + "_abi" ) in joABI && ( strCoinName + "_address" ) in joABI ) ) - return ""; - const strAddress = joAccount.address( w3 ); - const contractERC20 = new w3.eth.Contract( joABI[strCoinName + "_abi"], joABI[strCoinName + "_address"] ); - const balance = await contractERC20.methods.balanceOf( strAddress ).call( { from: strAddress } ); - return balance; - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + cc.error( err ) + "\n" ); - } - return ""; -} - -async function ownerOfERC721( - isMainNet, - w3, - cid, - joAccount, - strCoinName, - joABI, - idToken -) { - strLogPrefix = cc.info( "ownerOfERC721() call" ) + " "; - try { - if( ! ( w3 && joAccount && strCoinName && joABI && ( strCoinName + "_abi" ) in joABI && ( strCoinName + "_address" ) in joABI ) ) - return ""; - const strAddress = joAccount.address( w3 ); - const contractERC721 = new w3.eth.Contract( joABI[strCoinName + "_abi"], joABI[strCoinName + "_address"] ); - const owner = await contractERC721.methods.ownerOf( idToken ).call( { from: strAddress } ); - return owner; - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + cc.error( err ) + "\n" ); - } - return ""; -} - -async function balanceERC1155( - isMainNet, - w3, - cid, - joAccount, - strCoinName, - joABI, - idToken -) { - strLogPrefix = cc.info( "balanceERC1155() call" ) + " "; - try { - if( ! ( w3 && joAccount && strCoinName && joABI && ( strCoinName + "_abi" ) in joABI && ( strCoinName + "_address" ) in joABI ) ) - return ""; - const strAddress = joAccount.address( w3 ); - const contractERC1155 = new w3.eth.Contract( joABI[strCoinName + "_abi"], joABI[strCoinName + "_address"] ); - const balance = await contractERC1155.methods.balanceOf( strAddress, idToken ).call( { from: strAddress } ); - return balance; - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "ERROR:" ) + " " + cc.error( err ) + "\n" ); - } - return ""; -} - -async function mintERC20( - w3, - cid, - chainName, - joAccount, - strAddressMintTo, - nAmount, - strTokenContractAddress, - joTokenContractABI, - tc -) { - let strActionName = "mintERC20() init"; - const strLogPrefix = cc.info( "mintERC20() call" ) + " "; - const details = log.createMemoryStream(); - try { - details.write( strLogPrefix + cc.debug( "Mint " ) + cc.info( "ERC20" ) + cc.debug( " token amount " ) + cc.notice( nAmount ) + "\n" ); - if( ! ( w3 && - joAccount && - strAddressMintTo && typeof strAddressMintTo == "string" && strAddressMintTo.length > 0 && - strTokenContractAddress && typeof strTokenContractAddress == "string" && strTokenContractAddress.length > 0 && - joTokenContractABI - ) ) - throw new Error( "Missing valid arguments" ); - strActionName = "mintERC20() instantiate token contract"; - const contract = new w3.eth.Contract( joTokenContractABI, strTokenContractAddress ); - const methodWithArguments_mint = contract.methods.mint( - // call params - strAddressMintTo, - "0x" + w3.utils.toBN( nAmount ).toString( 16 ) - ); - const dataTx_mint = methodWithArguments_mint.encodeABI(); // the encoded ABI of the method - const gasPrice = await tc.computeGasPrice( w3, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_mint = await tc.computeGas( methodWithArguments_mint, w3, 10000000, gasPrice, joAccount.address( w3 ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_mint ) + "\n" ); - // - strActionName = "mintERC20() dry run"; - const isIgnore_mint = false; - const strDRC_mint = "mintERC20() in message signer"; - const strErrorOfDryRun = await dry_run_call( details, w3, methodWithArguments_mint, joAccount, strDRC_mint,isIgnore_mint, gasPrice, estimatedGas_mint, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - strActionName = "mintERC20() fetch transaction count"; - const tcnt = await get_web3_transactionCount( details, 10, w3, joAccount.address( w3 ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - strActionName = "mintERC20() compose transaction"; - const raw_tx_mint = { - chainId: cid, - from: joAccount.address( w3 ), - nonce: tcnt, - gas: estimatedGas_mint, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: contract.options.address, // contract address - data: dataTx_mint //, - // "value": wei_amount // 1000000000000000000 // w3.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - strActionName = "mintERC20() check transaction on S-Chain"; - if( chainName !== "Mainnet" ) - await checkTransactionToSchain( w3, raw_tx_mint, details ); - // - strActionName = "mintERC20() prepare composed transaction"; - const tx_mint = compose_tx_instance( details, strLogPrefix, raw_tx_mint ); - strActionName = "mintERC20() sign transaction"; - const joSR = await safe_sign_transaction_with_account( details, w3, tx_mint, raw_tx_mint, joAccount ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) { - // if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - // await async_pending_tx_start( details, w3, w3, cid, cid, "" + joSR.txHashSent ); - joReceipt = await get_web3_transactionReceipt( details, 10, w3, joSR.txHashSent ); - } else { - const serializedTx_mint = tx_mint.serialize(); - strActionName = "w3.eth.sendSignedTransaction()"; - // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_mint.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3, serializedTx_mint, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - print_gas_usage_report_from_array( "MINT ERC20 ", [ { - "description": "mintERC20()/mint", - "receipt": joReceipt - } ] ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "mintERC20", true ); - details.close(); - return joReceipt; // can be used as "true" boolean value - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in mintERC20() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in mintERC20() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.exposeDetailsTo( log, "mintERC20()", false ); - details.close(); - return false; - } -} - -async function mintERC721( - w3, - cid, - chainName, - joAccount, - strAddressMintTo, - idToken, - strTokenContractAddress, - joTokenContractABI, - tc -) { - let strActionName = "mintERC721() init"; - const strLogPrefix = cc.info( "mintERC721() call" ) + " "; - const details = log.createMemoryStream(); - try { - details.write( strLogPrefix + cc.debug( "Mint " ) + cc.info( "ERC721" ) + cc.debug( " token ID " ) + cc.notice( idToken ) + "\n" ); - if( ! ( w3 && - joAccount && - strAddressMintTo && typeof strAddressMintTo == "string" && strAddressMintTo.length > 0 && - strTokenContractAddress && typeof strTokenContractAddress == "string" && strTokenContractAddress.length > 0 && - joTokenContractABI - ) ) - throw new Error( "Missing valid arguments" ); - strActionName = "mintERC721() instantiate token contract"; - const contract = new w3.eth.Contract( joTokenContractABI, strTokenContractAddress ); - const methodWithArguments_mint = contract.methods.mint( - // call params - strAddressMintTo, - "0x" + w3.utils.toBN( idToken ).toString( 16 ) - ); - const dataTx_mint = methodWithArguments_mint.encodeABI(); // the encoded ABI of the method - const gasPrice = await tc.computeGasPrice( w3, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_mint = await tc.computeGas( methodWithArguments_mint, w3, 10000000, gasPrice, joAccount.address( w3 ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_mint ) + "\n" ); - // - strActionName = "mintERC721() dry run"; - const isIgnore_mint = false; - const strDRC_mint = "mintERC721() in message signer"; - const strErrorOfDryRun = await dry_run_call( details, w3, methodWithArguments_mint, joAccount, strDRC_mint,isIgnore_mint, gasPrice, estimatedGas_mint, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - strActionName = "mintERC721() fetch transaction count"; - const tcnt = await get_web3_transactionCount( details, 10, w3, joAccount.address( w3 ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - strActionName = "mintERC721() compose transaction"; - const raw_tx_mint = { - chainId: cid, - from: joAccount.address( w3 ), - nonce: tcnt, - gas: estimatedGas_mint, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: contract.options.address, // contract address - data: dataTx_mint //, - // "value": wei_amount // 1000000000000000000 // w3.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - strActionName = "mintERC721() check transaction on S-Chain"; - if( chainName !== "Mainnet" ) - await checkTransactionToSchain( w3, raw_tx_mint, details ); - // - strActionName = "mintERC721() prepare composed transaction"; - const tx_mint = compose_tx_instance( details, strLogPrefix, raw_tx_mint ); - strActionName = "mintERC721() sign transaction"; - const joSR = await safe_sign_transaction_with_account( details, w3, tx_mint, raw_tx_mint, joAccount ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) { - // if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - // await async_pending_tx_start( details, w3, w3, cid, cid, "" + joSR.txHashSent ); - joReceipt = await get_web3_transactionReceipt( details, 10, w3, joSR.txHashSent ); - } else { - const serializedTx_mint = tx_mint.serialize(); - strActionName = "w3.eth.sendSignedTransaction()"; - // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_mint.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3, serializedTx_mint, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - print_gas_usage_report_from_array( "MINT ERC721 ", [ { - "description": "mintERC721()/mint", - "receipt": joReceipt - } ] ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "mintERC721", true ); - details.close(); - return joReceipt; // can be used as "true" boolean value - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in mintERC721() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in mintERC721() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.exposeDetailsTo( log, "mintERC721()", false ); - details.close(); - return false; - } -} - -async function mintERC1155( - w3, - cid, - chainName, - joAccount, - strAddressMintTo, - idToken, - nAmount, - strTokenContractAddress, - joTokenContractABI, - tc -) { - let strActionName = "mintERC1155() init"; - const strLogPrefix = cc.info( "mintERC1155() call" ) + " "; - const details = log.createMemoryStream(); - try { - details.write( strLogPrefix + cc.debug( "Mint " ) + cc.info( "ERC1155" ) + cc.debug( " token ID " ) + cc.notice( idToken ) + cc.debug( " token amount " ) + cc.notice( nAmount ) + "\n" ); - if( ! ( w3 && - joAccount && - strAddressMintTo && typeof strAddressMintTo == "string" && strAddressMintTo.length > 0 && - strTokenContractAddress && typeof strTokenContractAddress == "string" && strTokenContractAddress.length > 0 && - joTokenContractABI - ) ) - throw new Error( "Missing valid arguments" ); - strActionName = "mintERC1155() instantiate token contract"; - const contract = new w3.eth.Contract( joTokenContractABI, strTokenContractAddress ); - const methodWithArguments_mint = contract.methods.mint( - // call params - strAddressMintTo, - "0x" + w3.utils.toBN( idToken ).toString( 16 ), - "0x" + w3.utils.toBN( nAmount ).toString( 16 ), - [] // data - ); - const dataTx_mint = methodWithArguments_mint.encodeABI(); // the encoded ABI of the method - const gasPrice = await tc.computeGasPrice( w3, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_mint = await tc.computeGas( methodWithArguments_mint, w3, 10000000, gasPrice, joAccount.address( w3 ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_mint ) + "\n" ); - // - strActionName = "mintERC1155() dry run"; - const isIgnore_mint = false; - const strDRC_mint = "mintERC1155() in message signer"; - const strErrorOfDryRun = await dry_run_call( details, w3, methodWithArguments_mint, joAccount, strDRC_mint,isIgnore_mint, gasPrice, estimatedGas_mint, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - strActionName = "mintERC1155() fetch transaction count"; - const tcnt = await get_web3_transactionCount( details, 10, w3, joAccount.address( w3 ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - strActionName = "mintERC1155() compose transaction"; - const raw_tx_mint = { - chainId: cid, - from: joAccount.address( w3 ), - nonce: tcnt, - gas: estimatedGas_mint, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: contract.options.address, // contract address - data: dataTx_mint //, - // "value": wei_amount // 1000000000000000000 // w3.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - strActionName = "mintERC1155() check transaction on S-Chain"; - if( chainName !== "Mainnet" ) - await checkTransactionToSchain( w3, raw_tx_mint, details ); - // - strActionName = "mintERC1155() prepare composed transaction"; - const tx_mint = compose_tx_instance( details, strLogPrefix, raw_tx_mint ); - strActionName = "mintERC1155() sign transaction"; - const joSR = await safe_sign_transaction_with_account( details, w3, tx_mint, raw_tx_mint, joAccount ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) { - // if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - // await async_pending_tx_start( details, w3, w3, cid, cid, "" + joSR.txHashSent ); - joReceipt = await get_web3_transactionReceipt( details, 10, w3, joSR.txHashSent ); - } else { - const serializedTx_mint = tx_mint.serialize(); - strActionName = "w3.eth.sendSignedTransaction()"; - // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_mint.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3, serializedTx_mint, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - print_gas_usage_report_from_array( "MINT ERC1155 ", [ { - "description": "mintERC1155()/mint", - "receipt": joReceipt - } ] ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "mintERC1155", true ); - details.close(); - return joReceipt; // can be used as "true" boolean value - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in mintERC1155() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in mintERC1155() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.exposeDetailsTo( log, "mintERC1155()", false ); - details.close(); - return false; - } -} - -async function burnERC20( - w3, - cid, - chainName, - joAccount, - strAddressBurnFrom, - nAmount, - strTokenContractAddress, - joTokenContractABI, - tc -) { - let strActionName = "burnERC20() init"; - const strLogPrefix = cc.info( "burnERC20() call" ) + " "; - const details = log.createMemoryStream(); - try { - details.write( strLogPrefix + cc.debug( "Burn " ) + cc.info( "ERC20" ) + cc.debug( " token amount " ) + cc.notice( nAmount ) + "\n" ); - if( ! ( w3 && - joAccount && - strAddressBurnFrom && typeof strAddressBurnFrom == "string" && strAddressBurnFrom.length > 0 && - strTokenContractAddress && typeof strTokenContractAddress == "string" && strTokenContractAddress.length > 0 && - joTokenContractABI - ) ) - throw new Error( "Missing valid arguments" ); - strActionName = "burnERC20() instantiate token contract"; - const contract = new w3.eth.Contract( joTokenContractABI, strTokenContractAddress ); - const methodWithArguments_burn = contract.methods.burnFrom( - // call params - strAddressBurnFrom, - "0x" + w3.utils.toBN( nAmount ).toString( 16 ) - ); - const dataTx_burn = methodWithArguments_burn.encodeABI(); // the encoded ABI of the method - const gasPrice = await tc.computeGasPrice( w3, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_burn = await tc.computeGas( methodWithArguments_burn, w3, 10000000, gasPrice, joAccount.address( w3 ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_burn ) + "\n" ); - // - strActionName = "burnERC20() dry run"; - const isIgnore_burn = false; - const strDRC_burn = "burnERC20() in message signer"; - const strErrorOfDryRun = await dry_run_call( details, w3, methodWithArguments_burn, joAccount, strDRC_burn,isIgnore_burn, gasPrice, estimatedGas_burn, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - strActionName = "burnERC20() fetch transaction count"; - const tcnt = await get_web3_transactionCount( details, 10, w3, joAccount.address( w3 ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - strActionName = "burnERC20() compose transaction"; - const raw_tx_burn = { - chainId: cid, - from: joAccount.address( w3 ), - nonce: tcnt, - gas: estimatedGas_burn, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: contract.options.address, // contract address - data: dataTx_burn //, - // "value": wei_amount // 1000000000000000000 // w3.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - strActionName = "burnERC20() check transaction on S-Chain"; - if( chainName !== "Mainnet" ) - await checkTransactionToSchain( w3, raw_tx_burn, details ); - // - strActionName = "burnERC20() prepare composed transaction"; - const tx_burn = compose_tx_instance( details, strLogPrefix, raw_tx_burn ); - strActionName = "burnERC20() sign transaction"; - const joSR = await safe_sign_transaction_with_account( details, w3, tx_burn, raw_tx_burn, joAccount ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) { - // if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - // await async_pending_tx_start( details, w3, w3, cid, cid, "" + joSR.txHashSent ); - joReceipt = await get_web3_transactionReceipt( details, 10, w3, joSR.txHashSent ); - } else { - const serializedTx_burn = tx_burn.serialize(); - strActionName = "w3.eth.sendSignedTransaction()"; - // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_burn.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3, serializedTx_burn, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - print_gas_usage_report_from_array( "BURN ERC20 ", [ { - "description": "burnERC20()/burn", - "receipt": joReceipt - } ] ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "burnERC20", true ); - details.close(); - return joReceipt; // can be used as "true" boolean value - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in burnERC20() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in burnERC20() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.exposeDetailsTo( log, "burnERC20()", false ); - details.close(); - return false; - } -} - -async function burnERC721( - w3, - cid, - chainName, - joAccount, - // strAddressBurnFrom, - idToken, - strTokenContractAddress, - joTokenContractABI, - tc -) { - let strActionName = "burnERC721() init"; - const strLogPrefix = cc.info( "burnERC721() call" ) + " "; - const details = log.createMemoryStream(); - try { - details.write( strLogPrefix + cc.debug( "Burn " ) + cc.info( "ERC721" ) + cc.debug( " token ID " ) + cc.notice( idToken ) + "\n" ); - if( ! ( w3 && - joAccount && - //strAddressBurnFrom && typeof strAddressBurnFrom == "string" && strAddressBurnFrom.length > 0 && - strTokenContractAddress && typeof strTokenContractAddress == "string" && strTokenContractAddress.length > 0 && - joTokenContractABI - ) ) - throw new Error( "Missing valid arguments" ); - strActionName = "burnERC721() instantiate token contract"; - const contract = new w3.eth.Contract( joTokenContractABI, strTokenContractAddress ); - const methodWithArguments_burn = contract.methods.burn( - // call params - //strAddressBurnFrom, - "0x" + w3.utils.toBN( idToken ).toString( 16 ) - ); - const dataTx_burn = methodWithArguments_burn.encodeABI(); // the encoded ABI of the method - const gasPrice = await tc.computeGasPrice( w3, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_burn = await tc.computeGas( methodWithArguments_burn, w3, 10000000, gasPrice, joAccount.address( w3 ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_burn ) + "\n" ); - // - strActionName = "burnERC721() dry run"; - const isIgnore_burn = false; - const strDRC_burn = "burnERC721() in message signer"; - const strErrorOfDryRun = await dry_run_call( details, w3, methodWithArguments_burn, joAccount, strDRC_burn,isIgnore_burn, gasPrice, estimatedGas_burn, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - strActionName = "burnERC721() fetch transaction count"; - const tcnt = await get_web3_transactionCount( details, 10, w3, joAccount.address( w3 ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - strActionName = "burnERC721() compose transaction"; - const raw_tx_burn = { - chainId: cid, - from: joAccount.address( w3 ), - nonce: tcnt, - gas: estimatedGas_burn, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: contract.options.address, // contract address - data: dataTx_burn //, - // "value": wei_amount // 1000000000000000000 // w3.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - strActionName = "burnERC721() check transaction on S-Chain"; - if( chainName !== "Mainnet" ) - await checkTransactionToSchain( w3, raw_tx_burn, details ); - // - strActionName = "burnERC721() prepare composed transaction"; - const tx_burn = compose_tx_instance( details, strLogPrefix, raw_tx_burn ); - strActionName = "burnERC721() sign transaction"; - const joSR = await safe_sign_transaction_with_account( details, w3, tx_burn, raw_tx_burn, joAccount ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) { - // if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - // await async_pending_tx_start( details, w3, w3, cid, cid, "" + joSR.txHashSent ); - joReceipt = await get_web3_transactionReceipt( details, 10, w3, joSR.txHashSent ); - } else { - const serializedTx_burn = tx_burn.serialize(); - strActionName = "w3.eth.sendSignedTransaction()"; - // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_burn.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3, serializedTx_burn, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - print_gas_usage_report_from_array( "BURN ERC721 ", [ { - "description": "burnERC721()/burn", - "receipt": joReceipt - } ] ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "burnERC721", true ); - details.close(); - return joReceipt; // can be used as "true" boolean value - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in burnERC721() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in burnERC721() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.exposeDetailsTo( log, "burnERC721()", false ); - details.close(); - return false; - } -} - -async function burnERC1155( - w3, - cid, - chainName, - joAccount, - strAddressBurnFrom, - idToken, - nAmount, - strTokenContractAddress, - joTokenContractABI, - tc -) { - let strActionName = "burnERC1155() init"; - const strLogPrefix = cc.info( "burnERC1155() call" ) + " "; - const details = log.createMemoryStream(); - try { - details.write( strLogPrefix + cc.debug( "Burn " ) + cc.info( "ERC1155" ) + cc.debug( " token ID " ) + cc.notice( idToken ) + cc.debug( " token amount " ) + cc.notice( nAmount ) + "\n" ); - if( ! ( w3 && - joAccount && - strAddressBurnFrom && typeof strAddressBurnFrom == "string" && strAddressBurnFrom.length > 0 && - strTokenContractAddress && typeof strTokenContractAddress == "string" && strTokenContractAddress.length > 0 && - joTokenContractABI - ) ) - throw new Error( "Missing valid arguments" ); - strActionName = "burnERC1155() instantiate token contract"; - const contract = new w3.eth.Contract( joTokenContractABI, strTokenContractAddress ); - const methodWithArguments_burn = contract.methods.burn( - // call params - strAddressBurnFrom, - "0x" + w3.utils.toBN( idToken ).toString( 16 ), - "0x" + w3.utils.toBN( nAmount ).toString( 16 ) - ); - const dataTx_burn = methodWithArguments_burn.encodeABI(); // the encoded ABI of the method - const gasPrice = await tc.computeGasPrice( w3, 200000000000 ); - details.write( strLogPrefix + cc.debug( "Using computed " ) + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.notice( gasPrice ) + "\n" ); - const estimatedGas_burn = await tc.computeGas( methodWithArguments_burn, w3, 10000000, gasPrice, joAccount.address( w3 ), "0" ); - details.write( strLogPrefix + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + cc.notice( estimatedGas_burn ) + "\n" ); - // - strActionName = "burnERC1155() dry run"; - const isIgnore_burn = false; - const strDRC_burn = "burnERC1155() in message signer"; - const strErrorOfDryRun = await dry_run_call( details, w3, methodWithArguments_burn, joAccount, strDRC_burn,isIgnore_burn, gasPrice, estimatedGas_burn, "0" ); - if( strErrorOfDryRun ) - throw new Error( strErrorOfDryRun ); - // - strActionName = "burnERC1155() fetch transaction count"; - const tcnt = await get_web3_transactionCount( details, 10, w3, joAccount.address( w3 ), null ); - details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( tcnt ) + cc.debug( " from " ) + cc.notice( strActionName ) + "\n" ); - strActionName = "burnERC1155() compose transaction"; - const raw_tx_burn = { - chainId: cid, - from: joAccount.address( w3 ), - nonce: tcnt, - gas: estimatedGas_burn, - gasPrice: gasPrice, - // "gasLimit": 3000000, - to: contract.options.address, // contract address - data: dataTx_burn //, - // "value": wei_amount // 1000000000000000000 // w3.utils.toWei( (1).toString(), "ether" ) // how much money to send - }; - strActionName = "burnERC1155() check transaction on S-Chain"; - if( chainName !== "Mainnet" ) - await checkTransactionToSchain( w3, raw_tx_burn, details ); - // - strActionName = "burnERC1155() prepare composed transaction"; - const tx_burn = compose_tx_instance( details, strLogPrefix, raw_tx_burn ); - strActionName = "burnERC1155() sign transaction"; - const joSR = await safe_sign_transaction_with_account( details, w3, tx_burn, raw_tx_burn, joAccount ); - let joReceipt = null; - if( joSR.joACI.isAutoSend ) { - // if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled ) - // await async_pending_tx_start( details, w3, w3, cid, cid, "" + joSR.txHashSent ); - joReceipt = await get_web3_transactionReceipt( details, 10, w3, joSR.txHashSent ); - } else { - const serializedTx_burn = tx_burn.serialize(); - strActionName = "w3.eth.sendSignedTransaction()"; - // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_burn.toString( "hex" ) ); - joReceipt = await safe_send_signed_transaction( details, w3, serializedTx_burn, strActionName, strLogPrefix ); - } - details.write( strLogPrefix + cc.success( "Result receipt: " ) + cc.j( joReceipt ) + "\n" ); - print_gas_usage_report_from_array( "BURN ERC1155 ", [ { - "description": "burnERC1155()/burn", - "receipt": joReceipt - } ] ); - if( expose_details_get() ) - details.exposeDetailsTo( log, "burnERC1155", true ); - details.close(); - return joReceipt; // can be used as "true" boolean value - } catch ( err ) { - if( verbose_get() >= RV_VERBOSE.fatal ) - log.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in burnERC1155() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.write( strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Error in burnERC1155() during " + strActionName + ": " ) + cc.error( err ) + "\n" ); - details.exposeDetailsTo( log, "burnERC1155()", false ); - details.close(); - return false; - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -module.exports.longSeparator = g_mtaStrLongSeparator; -module.exports.noop = noop; -module.exports.cc = cc; -module.exports.log = log; -module.exports.sleep = sleep; -module.exports.owaspUtils = owaspUtils; -module.exports.w3mod = w3mod; -module.exports.ethereumjs_tx = ethereumjs_tx; -module.exports.ethereumjs_wallet = ethereumjs_wallet; -module.exports.ethereumjs_util = ethereumjs_util; - -module.exports.VERBOSE = VERBOSE; -module.exports.RV_VERBOSE = RV_VERBOSE; -module.exports.expose_details_get = expose_details_get; -module.exports.expose_details_set = expose_details_set; -module.exports.verbose_get = verbose_get; -module.exports.verbose_set = verbose_set; -module.exports.verbose_parse = verbose_parse; -module.exports.verbose_list = verbose_list; - -module.exports.dry_run_is_enabled = dry_run_is_enabled; -module.exports.dry_run_enable = dry_run_enable; -module.exports.dry_run_is_ignored = dry_run_is_ignored; -module.exports.dry_run_ignore = dry_run_ignore; -module.exports.dry_run_call = dry_run_call; -module.exports.get_account_connectivity_info = get_account_connectivity_info; -module.exports.safe_sign_transaction_with_account = safe_sign_transaction_with_account; -module.exports.safe_send_signed_transaction = safe_send_signed_transaction; - -module.exports.invoke_has_chain = invoke_has_chain; -module.exports.wait_for_has_chain = wait_for_has_chain; -module.exports.register_s_chain_in_deposit_boxes = register_s_chain_in_deposit_boxes; // step 1 -// module.exports.register_main_net_depositBox_on_s_chain = register_main_net_depositBox_on_s_chain; // step 2A -// module.exports.register_main_net_on_s_chain = register_main_net_on_s_chain; // step 2B - -module.exports.check_is_registered_s_chain_in_deposit_boxes = check_is_registered_s_chain_in_deposit_boxes; // step 1 -// module.exports.check_is_registered_main_net_depositBox_on_s_chain = check_is_registered_main_net_depositBox_on_s_chain; // step 2A -// module.exports.check_is_registered_main_net_on_s_chain = check_is_registered_main_net_on_s_chain; // step 2B - -module.exports.reimbursement_show_balance = reimbursement_show_balance; -module.exports.reimbursement_estimate_amount = reimbursement_estimate_amount; -module.exports.reimbursement_wallet_recharge = reimbursement_wallet_recharge; -module.exports.reimbursement_wallet_withdraw = reimbursement_wallet_withdraw; -module.exports.reimbursement_set_range = reimbursement_set_range; - -module.exports.do_eth_payment_from_main_net = do_eth_payment_from_main_net; -module.exports.do_eth_payment_from_s_chain = do_eth_payment_from_s_chain; -module.exports.receive_eth_payment_from_s_chain_on_main_net = receive_eth_payment_from_s_chain_on_main_net; -module.exports.view_eth_payment_from_s_chain_on_main_net = view_eth_payment_from_s_chain_on_main_net; -module.exports.do_erc20_payment_from_main_net = do_erc20_payment_from_main_net; -module.exports.do_erc20_payment_from_s_chain = do_erc20_payment_from_s_chain; -module.exports.do_erc20_payment_s2s = do_erc20_payment_s2s; -module.exports.do_erc721_payment_from_main_net = do_erc721_payment_from_main_net; -module.exports.do_erc721_payment_from_s_chain = do_erc721_payment_from_s_chain; -module.exports.do_erc721_payment_s2s = do_erc721_payment_s2s; -module.exports.do_erc1155_payment_from_main_net = do_erc1155_payment_from_main_net; -module.exports.do_erc1155_payment_from_s_chain = do_erc1155_payment_from_s_chain; -module.exports.do_erc1155_payment_s2s = do_erc1155_payment_s2s; -module.exports.do_erc1155_batch_payment_from_main_net = do_erc1155_batch_payment_from_main_net; -module.exports.do_erc1155_batch_payment_from_s_chain = do_erc1155_batch_payment_from_s_chain; -module.exports.do_erc1155_batch_payment_s2s = do_erc1155_batch_payment_s2s; -module.exports.do_transfer = do_transfer; - -module.exports.do_s2s_all = do_s2s_all; -module.exports.verify_transfer_error_category_name = verify_transfer_error_category_name; -module.exports.save_transfer_error = save_transfer_error; -module.exports.save_transfer_success = save_transfer_success; -module.exports.save_transfer_success_all = save_transfer_success_all; -module.exports.get_last_transfer_errors = get_last_transfer_errors; -module.exports.get_last_error_categories = get_last_error_categories; - -module.exports.compose_gas_usage_report_from_array = compose_gas_usage_report_from_array; -module.exports.print_gas_usage_report_from_array = print_gas_usage_report_from_array; - -module.exports.TransactionCustomizer = TransactionCustomizer; -module.exports.tc_main_net = tc_main_net; -module.exports.tc_s_chain = tc_s_chain; -module.exports.tc_t_chain = tc_t_chain; - -module.exports.compose_tx_instance = compose_tx_instance; - -module.exports.getSleepBetweenTransactionsOnSChainMilliseconds = getSleepBetweenTransactionsOnSChainMilliseconds; -module.exports.setSleepBetweenTransactionsOnSChainMilliseconds = setSleepBetweenTransactionsOnSChainMilliseconds; -module.exports.getWaitForNextBlockOnSChain = getWaitForNextBlockOnSChain; -module.exports.setWaitForNextBlockOnSChain = setWaitForNextBlockOnSChain; -module.exports.get_web3_blockNumber = get_web3_blockNumber; -module.exports.get_web3_pastEvents = get_web3_pastEvents; -module.exports.get_web3_pastEventsIterative = get_web3_pastEventsIterative; -module.exports.get_web3_pastEventsProgressive = get_web3_pastEventsProgressive; -module.exports.getBlocksCountInInIterativeStepOfEventsScan = getBlocksCountInInIterativeStepOfEventsScan; -module.exports.setBlocksCountInInIterativeStepOfEventsScan = setBlocksCountInInIterativeStepOfEventsScan; -module.exports.getMaxIterationsInAllRangeEventsScan = getMaxIterationsInAllRangeEventsScan; -module.exports.setMaxIterationsInAllRangeEventsScan = setMaxIterationsInAllRangeEventsScan; -module.exports.getEnabledProgressiveEventsScan = getEnabledProgressiveEventsScan; -module.exports.setEnabledProgressiveEventsScan = setEnabledProgressiveEventsScan; -module.exports.getEnabledOracle = getEnabledOracle; -module.exports.setEnabledOracle = setEnabledOracle; -module.exports.do_oracle_gas_price_setup = do_oracle_gas_price_setup; - -module.exports.get_S2S_transfer_mode_description = get_S2S_transfer_mode_description; -module.exports.get_S2S_transfer_mode_description_colorized = get_S2S_transfer_mode_description_colorized; -module.exports.isForwardS2S = isForwardS2S; -module.exports.isReverseS2S = isReverseS2S; -module.exports.setForwardS2S = setForwardS2S; -module.exports.setReverseS2S = setReverseS2S; - -module.exports.parseIntOrHex = parseIntOrHex; - -module.exports.balanceETH = balanceETH; -module.exports.balanceERC20 = balanceERC20; -module.exports.ownerOfERC721 = ownerOfERC721; -module.exports.balanceERC1155 = balanceERC1155; -module.exports.mintERC20 = mintERC20; -module.exports.mintERC721 = mintERC721; -module.exports.mintERC1155 = mintERC1155; -module.exports.burnERC20 = burnERC20; -module.exports.burnERC721 = burnERC721; -module.exports.burnERC1155 = burnERC1155; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/npms/skale-ima/index.mjs b/npms/skale-ima/index.mjs new file mode 100644 index 000000000..ac1612f33 --- /dev/null +++ b/npms/skale-ima/index.mjs @@ -0,0 +1,1530 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file index.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as log from "../skale-log/log.mjs"; +import * as cc from "../skale-cc/cc.mjs"; + +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as loop from "../../agent/loop.mjs"; +import * as pwa from "../../agent/pwa.mjs"; +import * as state from "../../agent/state.mjs"; +import * as imaHelperAPIs from "./imaHelperAPIs.mjs"; +import * as imaTx from "./imaTx.mjs"; +import * as imaGasUsage from "./imaGasUsageOperations.mjs"; +import * as imaEventLogScan from "./imaEventLogScan.mjs"; +import * as imaTransferErrorHandling from "./imaTransferErrorHandling.mjs"; + +cc.enable( false ); +log.addStdout(); + +const perMessageGasForTransfer = 1000000; +const additionalS2MTransferOverhead = 200000; + +async function findOutReferenceLogRecord( + details, strLogPrefix, + ethersProvider, joMessageProxy, + bnBlockId, nMessageNumberToFind, isVerbose +) { + const bnMessageNumberToFind = owaspUtils.toBN( nMessageNumberToFind.toString() ); + const strEventName = "PreviousMessageReference"; + const arrLogRecords = await imaEventLogScan.safeGetPastEventsProgressive( + details, strLogPrefix, + ethersProvider, 10, joMessageProxy, strEventName, + bnBlockId, bnBlockId, joMessageProxy.filters[strEventName]() + ); + const cntLogRecord = arrLogRecords.length; + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.debug( "Got " ) + cc.info( cntLogRecord ) + + cc.debug( " log record(s) (" ) + cc.info( strEventName ) + + cc.debug( ") with data: " ) + cc.j( arrLogRecords ) + "\n" ); + } + } + for( let idxLogRecord = 0; idxLogRecord < cntLogRecord; ++ idxLogRecord ) { + const joEvent = arrLogRecords[idxLogRecord]; + const eventValuesByName = { + "currentMessage": joEvent.args[0], + "previousOutgoingMessageBlockId": joEvent.args[1] + }; + const joReferenceLogRecord = { + "currentMessage": eventValuesByName.currentMessage, + "previousOutgoingMessageBlockId": + eventValuesByName.previousOutgoingMessageBlockId, + "currentBlockId": bnBlockId + }; + const bnCurrentMessage = + owaspUtils.toBN( joReferenceLogRecord.currentMessage.toString() ); + if( bnCurrentMessage.eq( bnMessageNumberToFind ) ) { + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + cc.success( "Found " ) + cc.info( strEventName ) + + cc.success( " log record " ) + cc.j( joReferenceLogRecord ) + + cc.success( " for message " ) + cc.info( nMessageNumberToFind ) + "\n" ); + } + } + return joReferenceLogRecord; + } + } + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + cc.error( "Failed to find " ) + cc.info( strEventName ) + + cc.error( " log record for message " ) + cc.info( nMessageNumberToFind ) + "\n" ); + } + } + return null; +} + +async function findOutAllReferenceLogRecords( + details, strLogPrefix, + ethersProvider, joMessageProxy, + bnBlockId, nIncMsgCnt, nOutMsgCnt, isVerbose +) { + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + + cc.debug( "Optimized IMA message search algorithm will start at block " ) + + cc.info( bnBlockId.toString() ) + + cc.debug( ", will search for outgoing message counter " ) + + cc.info( nOutMsgCnt.toString() ) + + cc.debug( " and approach down to incoming message counter " ) + + cc.info( nIncMsgCnt.toString() ) + "\n" ); + } + } + const arrLogRecordReferences = []; + const cntExpected = nOutMsgCnt - nIncMsgCnt; + if( cntExpected <= 0 ) { + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().notice ) { + details.write( strLogPrefix + + cc.success( "Optimized IMA message search algorithm success, " + + "nothing to search, result is empty" ) + "\n" ); + } + } + return arrLogRecordReferences; // nothing to search + } + let nWalkMsgNumber = nOutMsgCnt - 1; + let nWalkBlockId = bnBlockId; + for( ; nWalkMsgNumber >= nIncMsgCnt; -- nWalkMsgNumber ) { + const joReferenceLogRecord = + await findOutReferenceLogRecord( + details, strLogPrefix, + ethersProvider, joMessageProxy, + nWalkBlockId, nWalkMsgNumber, isVerbose + ); + if( joReferenceLogRecord == null ) + break; + nWalkBlockId = owaspUtils.toBN( joReferenceLogRecord.previousOutgoingMessageBlockId ); + arrLogRecordReferences.unshift( joReferenceLogRecord ); + } + const cntFound = arrLogRecordReferences.length; + if( cntFound != cntExpected ) { + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + details.write( strLogPrefix + + cc.error( "Optimized IMA message search algorithm fail, found " ) + + cc.info( cntFound ) + + cc.error( " log record(s), expected " ) + cc.info( cntExpected ) + + cc.error( " log record(s), found records are: " ) + + cc.j( arrLogRecordReferences ) + "\n" ); + } + } + } else { + if( isVerbose ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + details.write( strLogPrefix + + cc.success( "Optimized IMA message search algorithm success, found all " ) + + cc.info( cntFound ) + cc.success( " log record(s): " ) + + cc.j( arrLogRecordReferences ) + "\n" ); + } + } + } + return arrLogRecordReferences; +} + +let gTransferLoopCounter = 0; + +// Do real money movement from main-net to S-chain by sniffing events +// 1) main-net.MessageProxyForMainnet.getOutgoingMessagesCounter -> save to nOutMsgCnt +// 2) S-chain.MessageProxySchain.getIncomingMessagesCounter -> save to nIncMsgCnt +// 3) Will transfer all in range from [ nIncMsgCnt ... (nOutMsgCnt-1) ] ... +// assume current counter index is nIdxCurrentMsg +// +// One transaction transfer is: +// 1) Find events main-net.MessageProxyForMainnet.OutgoingMessage +// where msgCounter member is in range +// 2) Publish it to S-chain.MessageProxySchain.postIncomingMessages( +// main-net chain id // uint64 srcChainID +// nIdxCurrentMsg // uint64 startingCounter +// [srcContract] // address[] memory senders +// [dstContract] // address[] memory dstContracts +// [to] // address[] memory to +// [amount] // uint256[] memory amount / *uint256[2] memory blsSignature* / +// ) +async function doQueryOutgoingMessageCounter( optsTransfer ) { + let nPossibleIntegerValue = 0; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefixShort + + cc.info( "SRC " ) + cc.sunny( "MessageProxy" ) + cc.info( " address is....." ) + + cc.bright( optsTransfer.joMessageProxySrc.address ) + + "\n" ); + optsTransfer.details.write( optsTransfer.strLogPrefixShort + + cc.info( "DST " ) + cc.sunny( "MessageProxy" ) + cc.info( " address is....." ) + + cc.bright( optsTransfer.joMessageProxyDst.address ) + + "\n" ); + } + optsTransfer.strActionName = "src-chain.MessageProxy.getOutgoingMessagesCounter()"; + try { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Will call " ) + cc.notice( optsTransfer.strActionName ) + + cc.debug( "..." ) + + "\n" ); + } + nPossibleIntegerValue = + await optsTransfer.joMessageProxySrc.callStatic.getOutgoingMessagesCounter( + optsTransfer.chainNameDst, + { from: optsTransfer.joAccountSrc.address() } ); + if( !owaspUtils.validateInteger( nPossibleIntegerValue ) ) { + throw new Error( + "DST chain " + optsTransfer.chainNameDst + + " returned outgoing message counter " + + nPossibleIntegerValue + " which is not a valid integer" + ); + } + optsTransfer.nOutMsgCnt = owaspUtils.toInteger( nPossibleIntegerValue ); + if( log.verboseGet() >= log.verboseReversed().information ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Result of " ) + cc.notice( optsTransfer.strActionName ) + + cc.debug( " call: " ) + cc.info( optsTransfer.nOutMsgCnt ) + + "\n" ); + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = cc.fatal( "IMMEDIATE ERROR LOG:" ) + + cc.error( " error caught during " ) + cc.attention( optsTransfer.strActionName ) + + cc.error( ", error optsTransfer.details: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + } + + optsTransfer.strActionName = "dst-chain.MessageProxy.getIncomingMessagesCounter()"; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Will call " ) + cc.notice( optsTransfer.strActionName ) + + cc.debug( "..." ) + "\n" ); + } + nPossibleIntegerValue = + await optsTransfer.joMessageProxyDst.callStatic.getIncomingMessagesCounter( + optsTransfer.chainNameSrc, + { from: optsTransfer.joAccountDst.address() } ); + if( !owaspUtils.validateInteger( nPossibleIntegerValue ) ) { + throw new Error( + "SRC chain " + optsTransfer.chainNameSrc + " returned incoming message counter " + + nPossibleIntegerValue + " which is not a valid integer" ); + } + optsTransfer.nIncMsgCnt = owaspUtils.toInteger( nPossibleIntegerValue ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Result of " ) + cc.notice( optsTransfer.strActionName ) + + cc.debug( " call: " ) + cc.info( optsTransfer.nIncMsgCnt ) + "\n" ); + } + + optsTransfer.strActionName = "src-chain.MessageProxy.getIncomingMessagesCounter()"; + nPossibleIntegerValue = + await optsTransfer.joMessageProxySrc.callStatic.getIncomingMessagesCounter( + optsTransfer.chainNameDst, + { from: optsTransfer.joAccountSrc.address() } ); + if( !owaspUtils.validateInteger( nPossibleIntegerValue ) ) { + throw new Error( + "DST chain " + optsTransfer.chainNameDst + " returned incoming message counter " + + nPossibleIntegerValue + " which is not a valid integer" ); + } + const idxLastToPopNotIncluding = owaspUtils.toInteger( nPossibleIntegerValue ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Result of " ) + cc.notice( optsTransfer.strActionName ) + + cc.debug( " call: " ) + cc.info( idxLastToPopNotIncluding ) + "\n" ); + } + + // optimized scanner + const bnBlockId = + owaspUtils.toBN( + await optsTransfer.joMessageProxySrc.callStatic.getLastOutgoingMessageBlockId( + optsTransfer.chainNameDst, + { from: optsTransfer.joAccountSrc.address() } ) ); + optsTransfer.arrLogRecordReferences = []; + try { + optsTransfer.arrLogRecordReferences = + await findOutAllReferenceLogRecords( + optsTransfer.details, optsTransfer.strLogPrefixShort, + optsTransfer.ethersProviderSrc, optsTransfer.joMessageProxySrc, + bnBlockId, optsTransfer.nIncMsgCnt, optsTransfer.nOutMsgCnt, true + ); + } catch ( err ) { + optsTransfer.arrLogRecordReferences = []; + if( log.verboseGet() >= log.verboseReversed().error ) { + optsTransfer.details.write( + optsTransfer.strLogPrefix + cc.warning( "Optimized log search is " ) + + cc.error( "off" ) + cc.warning( ". Running old IMA smart contracts?" ) + + cc.success( " Please upgrade, if possible." ) + + cc.warning( " This message is based on error: " ) + + cc.success( " Please upgrade, if possible." ) + + cc.warning( " Error is: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.warning( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return true; +} + +async function analyzeGatheredRecords( optsTransfer, r ) { + let joValues = ""; + const strChainHashWeAreLookingFor = + owaspUtils.ethersMod.ethers.utils.id( optsTransfer.chainNameDst ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + cc.debug( "Will review " ) + + cc.info( r.length ) + + cc.debug( " found event records(in reverse order, newest to oldest)" ) + + cc.debug( " while looking for hash " ) + cc.info( strChainHashWeAreLookingFor ) + + cc.debug( " of destination chain " ) + cc.info( optsTransfer.chainNameDst ) + "\n" ); + } + for( let i = r.length - 1; i >= 0; i-- ) { + const joEvent = r[i]; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Will review found event record " ) + cc.info( i ) + + cc.debug( " with data " ) + cc.j( joEvent ) + "\n" ); + } + const eventValuesByName = { + "dstChainHash": joEvent.args[0], + "msgCounter": joEvent.args[1], + "srcContract": joEvent.args[2], + "dstContract": joEvent.args[3], + "data": joEvent.args[4] + }; + if( eventValuesByName.dstChainHash == strChainHashWeAreLookingFor ) { + joValues = eventValuesByName; + joValues.savedBlockNumberForOptimizations = r[i].blockNumber; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Found event record " ) + cc.info( i ) + + cc.debug( " reviewed and " ) + + cc.success( "accepted for processing, found event values are " ) + + cc.j( joValues ) + cc.success( ", found block number is " ) + + cc.info( joValues.savedBlockNumberForOptimizations ) + "\n" ); + } + break; + } else { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Found event record " ) + cc.info( i ) + + cc.debug( " reviewed and " ) + cc.warning( "skipped" ) + "\n" ); + } + } + } + if( joValues == "" ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + " " + + cc.error( "Can't get events from MessageProxy" ) + "\n"; + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + optsTransfer.details.exposeDetailsTo( + log, optsTransfer.strGatheredDetailsName, false ); + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() ); + optsTransfer.details.close(); + return null; // caller will return false if we return null here + } + return joValues; +} + +async function gatherMessages( optsTransfer ) { + optsTransfer.arrMessageCounters = []; + optsTransfer.jarrMessages = []; + optsTransfer.nIdxCurrentMsgBlockStart = 0 + optsTransfer.nIdxCurrentMsg; + let r; + optsTransfer.cntAccumulatedForBlock = 0; + for( let idxInBlock = 0; // inner loop wil create block of transactions + optsTransfer.nIdxCurrentMsg < optsTransfer.nOutMsgCnt && + idxInBlock < optsTransfer.nTransactionsCountInBlock; + ++optsTransfer.nIdxCurrentMsg, ++idxInBlock, ++optsTransfer.cntAccumulatedForBlock + ) { + const idxProcessing = optsTransfer.cntProcessed + idxInBlock; + if( idxProcessing > optsTransfer.nMaxTransactionsCount ) + break; + let nBlockFrom = 0, nBlockTo = "latest"; + if( optsTransfer.arrLogRecordReferences.length > 0 ) { + const joReferenceLogRecord = optsTransfer.arrLogRecordReferences.shift(); + nBlockFrom = joReferenceLogRecord.currentBlockId; + nBlockTo = joReferenceLogRecord.currentBlockId; + } + optsTransfer.strActionName = "src-chain->MessageProxy->scan-past-events()"; + const strEventName = "OutgoingMessage"; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + cc.debug( "Will call " ) + + cc.notice( optsTransfer.strActionName ) + cc.debug( " for " ) + + cc.info( strEventName ) + cc.debug( " event..." ) + "\n" ); + } + r = await imaEventLogScan.safeGetPastEventsProgressive( + optsTransfer.details, optsTransfer.strLogPrefixShort, optsTransfer.ethersProviderSrc, + 10, optsTransfer.joMessageProxySrc, strEventName, nBlockFrom, nBlockTo, + optsTransfer.joMessageProxySrc.filters[strEventName]( + owaspUtils.ethersMod.ethers.utils.id( optsTransfer.chainNameDst ), // dstChainHash + optsTransfer.nIdxCurrentMsg // msgCounter + ) ); + const joValues = await analyzeGatheredRecords( optsTransfer, r ); + if( joValues == null ) + return false; + if( optsTransfer.nBlockAwaitDepth > 0 ) { + let bSecurityCheckPassed = true; + const strActionNameOld = "" + optsTransfer.strActionName; + optsTransfer.strActionName = "security check: evaluate block depth"; + try { + const transactionHash = r[0].transactionHash; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Event transactionHash is " ) + cc.info( transactionHash ) + + "\n" ); + } + const blockNumber = r[0].blockNumber; + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Event blockNumber is " ) + cc.info( blockNumber ) + "\n" ); + const nLatestBlockNumber = await imaHelperAPIs.safeGetBlockNumber( + optsTransfer.details, 10, optsTransfer.ethersProviderSrc ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Latest blockNumber is " ) + cc.info( nLatestBlockNumber ) + + "\n" ); + } + const nDist = nLatestBlockNumber - blockNumber; + if( nDist < optsTransfer.nBlockAwaitDepth ) + bSecurityCheckPassed = false; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Distance by blockNumber is " ) + cc.info( nDist ) + + cc.debug( ", await check is " ) + ( bSecurityCheckPassed + ? cc.success( "PASSED" ) : cc.error( "FAILED" ) ) + "\n" ); + } + } catch ( err ) { + bSecurityCheckPassed = false; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Exception(evaluate block depth) while " + + "getting transaction hash and block number during " + + optsTransfer.strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + optsTransfer.details.write( s ); + if( log.id != optsTransfer.details.id ) + log.write( s ); + } + optsTransfer.details.exposeDetailsTo( + log, optsTransfer.strGatheredDetailsName, false ); + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() ); + optsTransfer.details.close(); + return false; + } + optsTransfer.strActionName = "" + strActionNameOld; + if( !bSecurityCheckPassed ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + const s = optsTransfer.strLogPrefix + cc.warning( "Block depth check was " + + "not passed, canceling search for transfer events" ) + "\n"; + optsTransfer.details.write( s ); + if( log.id != optsTransfer.details.id ) + log.write( s ); + } + break; + } + } + if( optsTransfer.nBlockAge > 0 ) { + let bSecurityCheckPassed = true; + const strActionNameOld = "" + optsTransfer.strActionName; + optsTransfer.strActionName = "security check: evaluate block age"; + try { + const transactionHash = r[0].transactionHash; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Event transactionHash is " ) + cc.info( transactionHash ) + + "\n" ); + } + const blockNumber = r[0].blockNumber; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Event blockNumber is " ) + cc.info( blockNumber ) + "\n" ); + } + const joBlock = await optsTransfer.ethersProviderSrc.getBlock( blockNumber ); + if( !owaspUtils.validateInteger( joBlock.timestamp ) ) { + throw new Error( "Block \"timestamp\" is not a valid integer value: " + + joBlock.timestamp ); + } + const timestampBlock = owaspUtils.toInteger( joBlock.timestamp ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Block TS is " ) + cc.info( timestampBlock ) + "\n" ); + } + const timestampCurrent = imaHelperAPIs.currentTimestamp(); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Current TS is " ) + cc.info( timestampCurrent ) + "\n" ); + } + const tsDiff = timestampCurrent - timestampBlock; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Diff TS is " ) + cc.info( tsDiff ) + "\n" ); + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Expected diff " ) + cc.info( optsTransfer.nBlockAge ) + "\n" ); + } + if( tsDiff < optsTransfer.nBlockAge ) + bSecurityCheckPassed = false; + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Block age check is " ) + ( bSecurityCheckPassed + ? cc.success( "PASSED" ) : cc.error( "FAILED" ) ) + "\n" ); + } catch ( err ) { + bSecurityCheckPassed = false; + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = owaspUtils.extractErrorMessage( err ); + const s = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Exception(evaluate block age) while " + + "getting block number and timestamp during " + + optsTransfer.strActionName + ": " ) + cc.error( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + optsTransfer.details.write( s ); + if( log.id != optsTransfer.details.id ) + log.write( s ); + } + optsTransfer.details.exposeDetailsTo( + log, optsTransfer.strGatheredDetailsName, false ); + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() ); + optsTransfer.details.close(); + return false; + } + optsTransfer.strActionName = "" + strActionNameOld; + if( !bSecurityCheckPassed ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.warning( "Block age check was not passed, " + + "canceling search for transfer events" ) + "\n" ); + } + break; + } + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.success( "Got event optsTransfer.details from " ) + + cc.notice( "getPastEvents()" ) + cc.success( " event invoked with " ) + + cc.notice( "msgCounter" ) + cc.success( " set to " ) + + cc.info( optsTransfer.nIdxCurrentMsg ) + cc.success( " and " ) + + cc.notice( "dstChain" ) + cc.success( " set to " ) + + cc.info( optsTransfer.chainNameDst ) + cc.success( ", event description: " ) + + cc.j( joValues ) + + // + cc.j(evs) + + "\n" ); + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Will process message counter value " ) + + cc.info( optsTransfer.nIdxCurrentMsg ) + "\n" ); + } + optsTransfer.arrMessageCounters.push( optsTransfer.nIdxCurrentMsg ); + const joMessage = { + "sender": joValues.srcContract, + "destinationContract": joValues.dstContract, + "to": joValues.to, + "amount": joValues.amount, + "data": joValues.data, + "savedBlockNumberForOptimizations": + joValues.savedBlockNumberForOptimizations + }; + optsTransfer.jarrMessages.push( joMessage ); + } +} + +async function preCheckAllMessagesSign( optsTransfer, err, jarrMessages, joGlueResult ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + const strDidInvokedSigningCallbackMessage = + optsTransfer.strLogPrefix + + cc.debug( "Did invoked message signing callback, " + + "first real message index is: " ) + + cc.info( optsTransfer.nIdxCurrentMsgBlockStart ) + + cc.debug( ", have " ) + cc.info( optsTransfer.jarrMessages.length ) + + cc.debug( " message(s) to process " ) + cc.j( optsTransfer.jarrMessages ) + "\n"; + optsTransfer.details.write( strDidInvokedSigningCallbackMessage ); + if( log.id != optsTransfer.details.id ) + log.write( strDidInvokedSigningCallbackMessage ); + } + if( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + optsTransfer.bErrorInSigningMessages = true; + const strError = owaspUtils.extractErrorMessage( err ); + const s = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error signing messages: " ) + cc.error( strError ) + "\n"; + optsTransfer.details.write( s ); + if( log.id != optsTransfer.details.id ) + log.write( s ); + } + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() ); + return false; + } + if( ! loop.checkTimeFraming( + null, optsTransfer.strDirection, optsTransfer.joRuntimeOpts ) + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + const strWarning = optsTransfer.strLogPrefix + cc.warning( "WARNING:" ) + " " + + cc.warning( "Time framing overflow (after signing messages)" ) + "\n"; + optsTransfer.details.write( strWarning ); + if( log.id != optsTransfer.details.id ) + log.write( strWarning ); + } + imaTransferErrorHandling.saveTransferSuccessAll(); + return false; + } + return true; +} + +async function callbackAllMessagesSign( optsTransfer, err, jarrMessages, joGlueResult ) { + if( ! await preCheckAllMessagesSign( optsTransfer, err, jarrMessages, joGlueResult ) ) + return; + const nBlockSize = optsTransfer.arrMessageCounters.length; + optsTransfer.strActionName = "dst-chain.MessageProxy.postIncomingMessages()"; + if( log.verboseGet() >= log.verboseReversed().debug ) { + const strWillCallPostIncomingMessagesAction = optsTransfer.strLogPrefix + + cc.debug( "Will call " ) + cc.notice( optsTransfer.strActionName ) + + cc.debug( " for " ) + cc.notice( "block size" ) + cc.debug( " set to " ) + + cc.info( nBlockSize ) + cc.debug( ", " ) + cc.notice( "message counters =" ) + + cc.debug( " are " ) + cc.info( JSON.stringify( optsTransfer.arrMessageCounters ) ) + + cc.debug( "..." ) + "\n"; + optsTransfer.details.write( strWillCallPostIncomingMessagesAction ); + if( log.id != optsTransfer.details.id ) + log.write( strWillCallPostIncomingMessagesAction ); + } + let signature = joGlueResult ? joGlueResult.signature : null; + if( !signature ) + signature = { X: "0", Y: "0" }; + let hashPoint = joGlueResult ? joGlueResult.hashPoint : null; + if( !hashPoint ) + hashPoint = { X: "0", Y: "0" }; + let hint = joGlueResult ? joGlueResult.hint : null; + if( !hint ) + hint = "0"; + const sign = { + blsSignature: [ signature.X, signature.Y ], // BLS glue of signatures + hashA: hashPoint.X, // G1.X from joGlueResult.hashSrc + hashB: hashPoint.Y, // G1.Y from joGlueResult.hashSrc + counter: hint + }; + const arrArgumentsPostIncomingMessages = [ + optsTransfer.chainNameSrc, optsTransfer.nIdxCurrentMsgBlockStart, + optsTransfer.jarrMessages, sign ]; + if( log.verboseGet() >= log.verboseReversed().debug ) { + const joDebugArgs = [ + optsTransfer.chainNameSrc, optsTransfer.chainNameDst, + optsTransfer.nIdxCurrentMsgBlockStart, + optsTransfer.jarrMessages, [ signature.X, signature.Y ], // BLS glue of signatures + hashPoint.X, // G1.X from joGlueResult.hashSrc + hashPoint.Y, // G1.Y from joGlueResult.hashSrc + hint ]; + optsTransfer.details.write( optsTransfer.strLogPrefix + cc.debug( "....debug args for " ) + + cc.notice( "msgCounter" ) + cc.debug( " set to " ) + + cc.info( optsTransfer.nIdxCurrentMsgBlockStart ) + cc.debug( ": " ) + + cc.j( joDebugArgs ) + "\n" ); + } + optsTransfer.strActionName = optsTransfer.strDirection + " - Post incoming messages"; + const weiHowMuchPostIncomingMessages = undefined; + const gasPrice = + await optsTransfer.transactionCustomizerDst.computeGasPrice( + optsTransfer.ethersProviderDst, 200000000000 ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + cc.debug( "Using computed " ) + + cc.info( "gasPrice" ) + cc.debug( "=" ) + cc.j( gasPrice ) + "\n" ); + } + let estimatedGasPostIncomingMessages = + await optsTransfer.transactionCustomizerDst.computeGas( + optsTransfer.details, optsTransfer.ethersProviderDst, + "MessageProxy", optsTransfer.joMessageProxyDst, + "postIncomingMessages", arrArgumentsPostIncomingMessages, + optsTransfer.joAccountDst, optsTransfer.strActionName, + gasPrice, 10000000, weiHowMuchPostIncomingMessages, null ); + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Using estimated " ) + cc.info( "gas" ) + cc.debug( "=" ) + + cc.notice( estimatedGasPostIncomingMessages ) + "\n" ); + } + if( optsTransfer.strDirection == "S2M" ) { + const expectedGasLimit = perMessageGasForTransfer * optsTransfer.jarrMessages.length + + additionalS2MTransferOverhead; + estimatedGasPostIncomingMessages = + Math.max( estimatedGasPostIncomingMessages, expectedGasLimit ); + } + const isIgnorePostIncomingMessages = false; + const strErrorOfDryRun = + await imaTx.dryRunCall( + optsTransfer.details, optsTransfer.ethersProviderDst, + "MessageProxy", optsTransfer.joMessageProxyDst, + "postIncomingMessages", arrArgumentsPostIncomingMessages, + optsTransfer.joAccountDst, optsTransfer.strActionName, + isIgnorePostIncomingMessages, + gasPrice, estimatedGasPostIncomingMessages, + weiHowMuchPostIncomingMessages, null ); + if( strErrorOfDryRun ) + throw new Error( strErrorOfDryRun ); + const opts = { + isCheckTransactionToSchain: + ( optsTransfer.chainNameDst !== "Mainnet" ) ? true : false + }; + const joReceipt = + await imaTx.payedCall( + optsTransfer.details, optsTransfer.ethersProviderDst, + "MessageProxy", optsTransfer.joMessageProxyDst, + "postIncomingMessages", arrArgumentsPostIncomingMessages, + optsTransfer.joAccountDst, optsTransfer.strActionName, + gasPrice, estimatedGasPostIncomingMessages, + weiHowMuchPostIncomingMessages, opts ); + if( joReceipt && typeof joReceipt == "object" ) { + optsTransfer.jarrReceipts.push( { + "description": "doTransfer/postIncomingMessages()", + "optsTransfer.detailsString": + "" + optsTransfer.strGatheredDetailsName, + "receipt": joReceipt + } ); + imaGasUsage.printGasUsageReportFromArray( "(intermediate result) TRANSFER " + + optsTransfer.chainNameSrc + " -> " + optsTransfer.chainNameDst, + optsTransfer.jarrReceipts, optsTransfer.details ); + } + optsTransfer.cntProcessed += optsTransfer.cntAccumulatedForBlock; + if( log.verboseGet() >= log.verboseReversed().information ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Validating transfer from " ) + + cc.info( optsTransfer.chainNameSrc ) + cc.debug( " to " ) + + cc.info( optsTransfer.chainNameDst ) + cc.debug( "..." ) + "\n" ); + } + // check DepositBox -> Error on Mainnet only + if( optsTransfer.chainNameDst == "Mainnet" ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Validating transfer to Main Net via MessageProxy " + + "error absence on Main Net..." ) + "\n" ); + } + if( optsTransfer.joDepositBoxMainNet ) { + if( joReceipt && "blockNumber" in joReceipt && + "transactionHash" in joReceipt ) { + const strEventName = "PostMessageError"; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Verifying the " ) + cc.info( strEventName ) + + cc.debug( " event of the " ) + cc.info( "MessageProxy" ) + + cc.debug( "/" ) + + cc.notice( optsTransfer.joMessageProxyDst.address ) + + cc.debug( " contract..." ) + "\n" ); + } + const joEvents = await imaEventLogScan.getContractCallEvents( + optsTransfer.details, optsTransfer.strLogPrefixShort, + optsTransfer.ethersProviderDst, + optsTransfer.joMessageProxyDst, strEventName, + joReceipt.blockNumber, joReceipt.transactionHash, + optsTransfer.joMessageProxyDst.filters[strEventName]() ); + if( joEvents.length == 0 ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.success( "Success, verified the " ) + cc.info( strEventName ) + + cc.success( " event of the " ) + cc.info( "MessageProxy" ) + + cc.success( "/" ) + + cc.notice( optsTransfer.joMessageProxyDst.address ) + + cc.success( " contract, no events found" ) + "\n" ); + } + } else { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = optsTransfer.strLogPrefix + + cc.fatal( "CRITICAL ERROR:" ) + cc.warning( " Failed" ) + + cc.error( " verification of the " ) + + cc.warning( "PostMessageError" ) + cc.error( " event of the " ) + + cc.warning( "MessageProxy" ) + cc.error( "/" ) + + cc.notice( optsTransfer.joMessageProxyDst.address ) + + cc.error( " contract, found event(s): " ) + cc.j( joEvents ) + "\n"; + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, + optsTransfer.details.toString() ); + throw new Error( "Verification failed for the \"PostMessageError\" " + + "event of the \"MessageProxy\"/" + optsTransfer.joMessageProxyDst.address + + " contract, error events found" ); + } + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.success( "Done, validated transfer to Main Net " + + "via MessageProxy error absence on Main Net" ) + "\n" ); + } + } else { + if( log.verboseGet() >= log.verboseReversed().warning ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.warning( "WARNING:" ) + " " + + cc.warn( "Cannot validate transfer to Main Net via " + + "MessageProxy error absence on Main Net, " + + "no valid transaction receipt provided" ) + "\n" ); + } + } + } else { + if( log.verboseGet() >= log.verboseReversed().warning ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.warning( "WARNING:" ) + " " + + cc.warn( "Cannot validate transfer to Main Net " + + "via MessageProxy error absence on Main Net, " + + "no MessageProxy provided" ) + "\n" ); + } + } + } +} + +async function handleAllMessagesSigning( optsTransfer ) { + await optsTransfer.fnSignMessages( + optsTransfer.nTransferLoopCounter, + optsTransfer.jarrMessages, optsTransfer.nIdxCurrentMsgBlockStart, + optsTransfer.chainNameSrc, + optsTransfer.joExtraSignOpts, + async function( err, jarrMessages, joGlueResult ) { + await callbackAllMessagesSign( optsTransfer, err, jarrMessages, joGlueResult ); + } ).catch( ( err ) => { + // callback fn as argument of optsTransfer.fnSignMessages + optsTransfer.bErrorInSigningMessages = true; + if( log.verboseGet() >= log.verboseReversed().error ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + const strErrorMessage = optsTransfer.strLogPrefix + + cc.error( "Problem in transfer handler: " ) + + cc.warning( strError ); + optsTransfer.details.write( strErrorMessage + "\n" ); + if( log.id != optsTransfer.details.id ) + log.write( strErrorMessage + "\n" ); + } + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, + optsTransfer.details.toString() ); + } + } ); + return true; +} + +async function checkOutgoingMessageEvent( optsTransfer, joSChain ) { + const cntNodes = joSChain.data.computed.nodes.length; + const cntMessages = optsTransfer.jarrMessages.length; + for( let idxMessage = 0; idxMessage < cntMessages; ++ idxMessage ) { + const idxImaMessage = optsTransfer.arrMessageCounters[idxMessage]; + const joMessage = optsTransfer.jarrMessages[idxMessage]; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.sunny( optsTransfer.strDirection ) + + cc.debug( " message analysis for message " ) + cc.info( idxMessage + 1 ) + + cc.debug( " of " ) + cc.info( cntMessages ) + + cc.debug( " with IMA message index " ) + cc.j( idxImaMessage ) + + cc.debug( " and message envelope data:" ) + cc.j( joMessage ) + "\n" ); + } + let cntPassedNodes = 0, cntFailedNodes = 0, joNode = null; + try { + for( let idxNode = 0; idxNode < cntNodes; ++ idxNode ) { + joNode = joSChain.data.computed.nodes[idxNode]; + // eslint-disable-next-line dot-notation + const strUrlHttp = joNode["http_endpoint_ip"]; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Validating " ) + cc.sunny( optsTransfer.strDirection ) + + cc.debug( " message " ) + cc.info( idxMessage + 1 ) + + cc.debug( " on node " ) + cc.info( joNode.name ) + + cc.debug( " using URL " ) + cc.info( strUrlHttp ) + cc.debug( "..." ) + + "\n" ); + } + let bEventIsFound = false; + try { + // eslint-disable-next-line dot-notation + const ethersProviderNode = + owaspUtils.getEthersProviderFromURL( strUrlHttp ); + const joMessageProxyNode = + new owaspUtils.ethersMod.ethers.Contract( + optsTransfer.imaState.chainProperties.sc + .joAbiIMA.message_proxy_chain_address, + optsTransfer.imaState.chainProperties.sc + .joAbiIMA.message_proxy_chain_abi, + ethersProviderNode + ); + const strEventName = "OutgoingMessage"; + const node_r = await imaEventLogScan.safeGetPastEventsProgressive( + optsTransfer.details, optsTransfer.strLogPrefixShort, + ethersProviderNode, 10, joMessageProxyNode, strEventName, + joMessage.savedBlockNumberForOptimizations, + joMessage.savedBlockNumberForOptimizations, + joMessageProxyNode.filters[strEventName]( + owaspUtils.ethersMod.ethers.utils.id( optsTransfer.chainNameDst ), + idxImaMessage // msgCounter + ) + ); + const cntEvents = node_r.length; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + cc.debug( "Got " ) + + cc.info( cntEvents ) + cc.debug( " event(s) (" ) + + cc.info( strEventName ) + cc.debug( ") on node " ) + + cc.info( joNode.name ) + cc.debug( " with data: " ) + + cc.j( node_r ) + "\n" ); + } + for( let idxEvent = 0; idxEvent < cntEvents; ++ idxEvent ) { + const joEvent = node_r[idxEvent]; + const eventValuesByName = { + "dstChainHash": joEvent.args[0], + "msgCounter": joEvent.args[1], + "srcContract": joEvent.args[2], + "dstContract": joEvent.args[3], + "data": joEvent.args[4] + }; + if( owaspUtils.ensureStartsWith0x( + joMessage.sender ).toLowerCase() == + owaspUtils.ensureStartsWith0x( + eventValuesByName.srcContract ).toLowerCase() && + owaspUtils.ensureStartsWith0x( + joMessage.destinationContract ).toLowerCase() == + owaspUtils.ensureStartsWith0x( + eventValuesByName.dstContract ).toLowerCase() + ) { + bEventIsFound = true; + break; + } + } + } catch ( err ) { + ++ cntFailedNodes; + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = optsTransfer.strLogPrefix + + cc.fatal( optsTransfer.strDirection + + " message analysis error:" ) + " " + + cc.error( "Failed to scan events on node " ) + cc.info( joNode.name ) + + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", detailed node description is: " ) + cc.j( joNode ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n"; + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + continue; + } + if( bEventIsFound ) { + ++ cntPassedNodes; + if( log.verboseGet() >= log.verboseReversed().information ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.sunny( optsTransfer.strDirection ) + cc.success( " message " ) + + cc.info( idxMessage + 1 ) + cc.success( " validation on node " ) + + cc.info( joNode.name ) + cc.success( " using URL " ) + + cc.info( strUrlHttp ) + cc.success( " is passed" ) + "\n" ); + } + } else { + ++ cntFailedNodes; + if( log.verboseGet() >= log.verboseReversed().error ) { + // eslint-disable-next-line dot-notation + const strError = optsTransfer.strLogPrefix + + cc.sunny( optsTransfer.strDirection ) + cc.error( " message " ) + + cc.info( idxMessage + 1 ) + cc.error( " validation on node " ) + + cc.info( joNode.name ) + cc.success( " using URL " ) + + cc.info( strUrlHttp ) + cc.error( " is failed" ) + "\n"; + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + } + if( cntFailedNodes > optsTransfer.cntNodesMayFail ) + break; + if( cntPassedNodes >= optsTransfer.cntNodesShouldPass ) { + if( log.verboseGet() >= log.verboseReversed().information ) { + // eslint-disable-next-line dot-notation + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.sunny( optsTransfer.strDirection ) + cc.success( " message " ) + + cc.info( idxMessage + 1 ) + cc.success( " validation on node " ) + + cc.info( joNode.name ) + cc.success( " using URL " ) + + cc.info( strUrlHttp ) + cc.success( " is passed" ) + "\n" ); + } + break; + } + } + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + // eslint-disable-next-line dot-notation + const strUrlHttp = joNode ? joNode["http_endpoint_ip"] : ""; + const strError = optsTransfer.strLogPrefix + + cc.fatal( optsTransfer.strDirection + " message analysis error:" ) + + " " + cc.error( "Failed to process events for " ) + + cc.sunny( optsTransfer.strDirection ) + cc.error( " message " ) + + cc.info( idxMessage + 1 ) + cc.error( " on node " ) + + ( joNode + ? cc.info( joNode.name ) + : cc.error( "<>" ) ) + + cc.error( " using URL " ) + + ( joNode ? cc.info( strUrlHttp ) : cc.error( "<>" ) ) + + cc.error( ", error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + } + if( cntFailedNodes > optsTransfer.cntNodesMayFail ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error validating " ) + cc.sunny( optsTransfer.strDirection ) + + cc.error( " messages, failed node count " ) + cc.info( cntFailedNodes ) + + cc.error( " is greater then allowed to fail " ) + + cc.info( optsTransfer.cntNodesMayFail ) + "\n"; + optsTransfer.details.write( s ); + if( log.id != optsTransfer.details.id ) + log.write( s ); + } + optsTransfer.details.exposeDetailsTo( + log, optsTransfer.strGatheredDetailsName, false ); + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, + optsTransfer.details.toString() ); + optsTransfer.details.close(); + return false; + } + if( ! ( cntPassedNodes >= optsTransfer.cntNodesShouldPass ) ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const s = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error validating " ) + cc.sunny( optsTransfer.strDirection ) + + cc.error( " messages, passed node count " ) + cc.info( cntFailedNodes ) + + cc.error( " is less then needed count " ) + + cc.info( optsTransfer.cntNodesShouldPass ) + "\n"; + optsTransfer.details.write( s ); + if( log.id != optsTransfer.details.id ) + log.write( s ); + } + optsTransfer.details.exposeDetailsTo( + log, optsTransfer.strGatheredDetailsName, false ); + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() ); + optsTransfer.details.close(); + return false; + } + } + return true; +} + +async function doMainTransferLoopActions( optsTransfer ) { + // classic scanner with optional usage of optimized IMA messages search algorithm + // outer loop is block former/creator, then transfer + optsTransfer.nIdxCurrentMsg = optsTransfer.nIncMsgCnt; + while( optsTransfer.nIdxCurrentMsg < optsTransfer.nOutMsgCnt ) { + if( optsTransfer.nStepsDone > optsTransfer.nTransferSteps ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + const strWarning = optsTransfer.strLogPrefix + cc.warning( "WARNING:" ) + " " + + cc.warning( "Transfer step count overflow" ) + "\n"; + optsTransfer.details.write( strWarning ); + if( log.id != optsTransfer.details.id ) + log.write( strWarning ); + } + optsTransfer.details.close(); + imaTransferErrorHandling.saveTransferSuccessAll(); + return false; + } + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsTransfer.details.write( + optsTransfer.strLogPrefix + cc.debug( "Entering block former iteration with " ) + + cc.notice( "message counter" ) + cc.debug( " set to " ) + + cc.info( optsTransfer.nIdxCurrentMsg ) + cc.debug( ", transfer step number is " ) + + cc.info( optsTransfer.nStepsDone ) + cc.debug( ", can transfer up to " ) + + cc.info( optsTransfer.nMaxTransactionsCount ) + cc.debug( " message(s) per step" ) + + cc.debug( ", can perform up to " ) + cc.info( optsTransfer.nTransferSteps ) + + cc.debug( " transfer step(s)" ) + "\n" ); + } + if( ! loop.checkTimeFraming( + null, optsTransfer.strDirection, optsTransfer.joRuntimeOpts ) ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + const strWarning = optsTransfer.strLogPrefix + cc.warning( "WARNING:" ) + " " + + cc.warning( "Time framing overflow " + + "(after entering block former iteration loop)" ) + "\n"; + optsTransfer.details.write( strWarning ); + if( log.id != optsTransfer.details.id ) + log.write( strWarning ); + } + optsTransfer.details.close(); + imaTransferErrorHandling.saveTransferSuccessAll(); + return false; + } + await gatherMessages( optsTransfer ); + if( optsTransfer.cntAccumulatedForBlock == 0 ) + break; + if( ! loop.checkTimeFraming( + null, optsTransfer.strDirection, optsTransfer.joRuntimeOpts ) + ) { + if( log.verboseGet() >= log.verboseReversed().warning ) { + const strWarning = optsTransfer.strLogPrefix + cc.warning( "WARNING:" ) + " " + + cc.warning( "Time framing overflow (after forming block of messages)" ) + "\n"; + optsTransfer.details.write( strWarning ); + if( log.id != optsTransfer.details.id ) + log.write( strWarning ); + } + optsTransfer.details.close(); + imaTransferErrorHandling.saveTransferSuccessAll(); + return false; + } + if( optsTransfer.strDirection == "S2S" ) { + optsTransfer.strActionName = "S2S message analysis"; + if( ! optsTransfer.joExtraSignOpts ) { + throw new Error( + "Could not validate S2S messages, " + + "no extra options provided to transfer algorithm" ); + } + if( ! optsTransfer.joExtraSignOpts.skaleObserver ) { + throw new Error( + "Could not validate S2S messages, " + + "no SKALE NETWORK observer provided to transfer algorithm" ); + } + const arrSChainsCached = + optsTransfer.joExtraSignOpts.skaleObserver.getLastCachedSChains(); + if( ( !arrSChainsCached ) || arrSChainsCached.length == 0 ) { + throw new Error( + "Could not validate S2S messages, " + + "no S-Chains in SKALE NETWORK observer cached yet, try again later" ); + } + const idxSChain = + optsTransfer.joExtraSignOpts.skaleObserver.findSChainIndexInArrayByName( + arrSChainsCached, optsTransfer.chainNameSrc ); + if( idxSChain < 0 ) { + throw new Error( + "Could not validate S2S messages, source S-Chain \"" + + optsTransfer.chainNameSrc + + "\" is not in SKALE NETWORK observer " + + "cache yet or it's not connected to this \"" + optsTransfer.chainNameDst + + "\" S-Chain yet, try again later" ); + } + const cntMessages = optsTransfer.jarrMessages.length; + const joSChain = arrSChainsCached[idxSChain]; + const cntNodes = joSChain.data.computed.nodes.length; + optsTransfer.cntNodesShouldPass = + ( cntNodes == 16 ) + ? 11 + : ( + ( cntNodes == 4 ) + ? 3 + : ( + ( cntNodes == 2 || cntNodes == 1 ) + ? ( 0 + cntNodes ) + : parseInt( ( cntNodes * 2 ) / 3 ) + ) + ); + optsTransfer.cntNodesMayFail = cntNodes - optsTransfer.cntNodesShouldPass; + if( log.verboseGet() >= log.verboseReversed().trace ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.sunny( optsTransfer.strDirection ) + + cc.debug( " message analysis will be performed o S-Chain " ) + + cc.info( optsTransfer.chainNameSrc ) + cc.debug( " with " ) + + cc.info( cntNodes ) + cc.debug( " node(s), " ) + + cc.info( optsTransfer.cntNodesShouldPass ) + + cc.debug( " node(s) should have same message(s), " ) + + cc.info( optsTransfer.cntNodesMayFail ) + + cc.debug( " node(s) allowed to fail message(s) comparison, " ) + + cc.info( cntMessages ) + cc.debug( " message(s) to check..." ) + "\n" ); + } + if( ! ( await checkOutgoingMessageEvent( optsTransfer, joSChain ) ) ) + return false; + } + + optsTransfer.strActionName = "sign messages"; + if( log.verboseGet() >= log.verboseReversed().information ) { + const strWillInvokeSigningCallbackMessage = + optsTransfer.strLogPrefix + + cc.debug( "Will invoke message signing callback, " + + "first real message index is: " ) + + cc.info( optsTransfer.nIdxCurrentMsgBlockStart ) + + cc.debug( ", have " ) + cc.info( optsTransfer.jarrMessages.length ) + + cc.debug( " message(s) to process " ) + cc.j( optsTransfer.jarrMessages ) + + "\n"; + optsTransfer.details.write( strWillInvokeSigningCallbackMessage ); + if( log.id != optsTransfer.details.id ) + log.write( strWillInvokeSigningCallbackMessage ); + } + // will re-open optsTransfer.details B log here for next step, + // it can be delayed so we will flush accumulated optsTransfer.details A now + if( log.exposeDetailsGet() && optsTransfer.details.exposeDetailsTo ) { + optsTransfer.details.exposeDetailsTo( + log, optsTransfer.strGatheredDetailsName, true ); + } + optsTransfer.details.close(); + optsTransfer.details = optsTransfer.imaState.isDynamicLogInDoTransfer + ? log : log.createMemoryStream( true ); + optsTransfer.strGatheredDetailsName = + optsTransfer.strDirection + "/#" + optsTransfer.nTransferLoopCounter + "-" + + "doTransfer-B-" + optsTransfer.chainNameSrc + "-->" + optsTransfer.chainNameDst; + optsTransfer.strGatheredDetailsName_colored = + cc.bright( optsTransfer.strDirection ) + cc.debug( "/" ) + cc.attention( "#" ) + + cc.sunny( optsTransfer.nTransferLoopCounter ) + cc.debug( "-" ) + + cc.info( "doTransfer-B-" ) + cc.notice( optsTransfer.chainNameSrc ) + + cc.debug( "-->" ) + cc.notice( optsTransfer.chainNameDst ); + + try { + if( ! ( await handleAllMessagesSigning( optsTransfer ) ) ) + return false; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = + optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Exception from signing messages function: " ) + + cc.error( owaspUtils.extractErrorMessage( err ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n" ); + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + } + if( optsTransfer.bErrorInSigningMessages ) + break; + ++ optsTransfer.nStepsDone; + } + return true; +} + +export async function doTransfer( + strDirection, + joRuntimeOpts, + ethersProviderSrc, + joMessageProxySrc, + joAccountSrc, + ethersProviderDst, + joMessageProxyDst, + joAccountDst, + chainNameSrc, + chainNameDst, + chainIdSrc, + chainIdDst, + joDepositBoxMainNet, // for logs validation on mainnet + joTokenManagerSChain, // for logs validation on s-chain + nTransactionsCountInBlock, + nTransferSteps, + nMaxTransactionsCount, + nBlockAwaitDepth, + nBlockAge, + fnSignMessages, + joExtraSignOpts, + transactionCustomizerDst +) { + const optsTransfer = { + strDirection: strDirection, + joRuntimeOpts: joRuntimeOpts, + ethersProviderSrc: ethersProviderSrc, + joMessageProxySrc: joMessageProxySrc, + joAccountSrc: joAccountSrc, + ethersProviderDst: ethersProviderDst, + joMessageProxyDst: joMessageProxyDst, + joAccountDst: joAccountDst, + chainNameSrc: chainNameSrc, + chainNameDst: chainNameDst, + chainIdSrc: chainIdSrc, + chainIdDst: chainIdDst, + joDepositBoxMainNet: joDepositBoxMainNet, // for logs validation on mainnet + joTokenManagerSChain: joTokenManagerSChain, // for logs validation on s-chain + nTransactionsCountInBlock: nTransactionsCountInBlock, + nTransferSteps: nTransferSteps, + nMaxTransactionsCount: nMaxTransactionsCount, + nBlockAwaitDepth: nBlockAwaitDepth, + nBlockAge: nBlockAge, + fnSignMessages: fnSignMessages, + joExtraSignOpts: joExtraSignOpts, + transactionCustomizerDst: transactionCustomizerDst, + imaState: state.get(), + nTransferLoopCounter: 0 + gTransferLoopCounter, + strTransferErrorCategoryName: "loop-" + strDirection, + strGatheredDetailsName: "", + strGatheredDetailsName_colored: "", + details: null, + jarrReceipts: [], + bErrorInSigningMessages: false, + strLogPrefixShort: "", + strLogPrefix: "", + nStepsDone: 0, + strActionName: "", + nIdxCurrentMsg: 0, + nOutMsgCnt: 0, + nIncMsgCnt: 0, + cntProcessed: 0, + arrMessageCounters: [], + jarrMessages: [], + nIdxCurrentMsgBlockStart: 0, + cntAccumulatedForBlock: 0, + arrLogRecordReferences: [] + }; + ++ gTransferLoopCounter; + optsTransfer.strGatheredDetailsName = + optsTransfer.strDirection + "/#" + optsTransfer.nTransferLoopCounter + + "-" + "doTransfer-A" + "-" + + optsTransfer.chainNameSrc + "-->" + optsTransfer.chainNameDst; + optsTransfer.strGatheredDetailsName_colored = + cc.bright( optsTransfer.strDirection ) + cc.debug( "/" ) + cc.attention( "#" ) + + cc.sunny( optsTransfer.nTransferLoopCounter ) + cc.debug( "-" ) + + cc.info( "doTransfer-A-" ) + cc.debug( "-" ) + cc.notice( optsTransfer.chainNameSrc ) + + cc.debug( "-->" ) + cc.notice( optsTransfer.chainNameDst ); + optsTransfer.details = optsTransfer.imaState.isDynamicLogInDoTransfer + ? log : log.createMemoryStream( true ); + optsTransfer.strLogPrefixShort = cc.bright( optsTransfer.strDirection ) + cc.debug( "/" ) + + cc.attention( "#" ) + cc.sunny( optsTransfer.nTransferLoopCounter ) + " "; + optsTransfer.strLogPrefix = optsTransfer.strLogPrefixShort + cc.info( "transfer loop from " ) + + cc.notice( optsTransfer.chainNameSrc ) + cc.info( " to " ) + + cc.notice( optsTransfer.chainNameDst ) + cc.info( ":" ) + " "; + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + cc.debug( "Message signing is " ) + + cc.onOff( optsTransfer.imaState.bSignMessages ) + "\n" ); + } + if( optsTransfer.fnSignMessages == null || + optsTransfer.fnSignMessages == undefined || + ( ! optsTransfer.imaState.bSignMessages ) + ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Using internal signing stub function" ) + "\n" ); + } + optsTransfer.fnSignMessages = async function( + nTransferLoopCounter, jarrMessages, nIdxCurrentMsgBlockStart, strFromChainName, + joExtraSignOpts, fnAfter + ) { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Message signing callback was " ) + cc.error( "not provided" ) + + cc.debug( " to IMA, first real message index is:" ) + + cc.info( nIdxCurrentMsgBlockStart ) + cc.debug( ", have " ) + + cc.info( optsTransfer.jarrMessages.length ) + + cc.debug( " message(s) to process " ) + + cc.j( optsTransfer.jarrMessages ) + "\n" ); + } + await fnAfter( null, jarrMessages, null ); // null - no error, null - no signatures + }; + } else { + if( log.verboseGet() >= log.verboseReversed().debug ) { + optsTransfer.details.write( optsTransfer.strLogPrefix + + cc.debug( "Using externally provided signing function" ) + "\n" ); + } + } + optsTransfer.nTransactionsCountInBlock = optsTransfer.nTransactionsCountInBlock || 5; + optsTransfer.nTransferSteps = optsTransfer.nTransferSteps || Number.MAX_SAFE_INTEGER; + optsTransfer.nMaxTransactionsCount = + optsTransfer.nMaxTransactionsCount || Number.MAX_SAFE_INTEGER; + if( optsTransfer.nTransactionsCountInBlock < 1 ) + optsTransfer.nTransactionsCountInBlock = 1; + if( optsTransfer.nBlockAwaitDepth < 0 ) + optsTransfer.nBlockAwaitDepth = 0; + if( optsTransfer.nBlockAge < 0 ) + optsTransfer.nBlockAge = 0; + try { + if( ! ( await doQueryOutgoingMessageCounter( optsTransfer ) ) ) + return false; + if( ! ( await doMainTransferLoopActions( optsTransfer ) ) ) + return false; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().critical ) { + const strError = optsTransfer.strLogPrefix + cc.fatal( "CRITICAL ERROR:" ) + + cc.error( " Error in " ) + optsTransfer.strGatheredDetailsName_colored + + cc.error( " during " + optsTransfer.strActionName + ": " ) + + cc.error( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + + "\n"; + optsTransfer.details.write( strError ); + if( log.id != optsTransfer.details.id ) + log.write( strError ); + } + optsTransfer.details.exposeDetailsTo( log, optsTransfer.strGatheredDetailsName, false ); + imaTransferErrorHandling.saveTransferError( + optsTransfer.strTransferErrorCategoryName, optsTransfer.details.toString() ); + optsTransfer.details.close(); + return false; + } + imaGasUsage.printGasUsageReportFromArray( + "TRANSFER " + optsTransfer.chainNameSrc + " -> " + + optsTransfer.chainNameDst, optsTransfer.jarrReceipts, optsTransfer.details ); + if( optsTransfer.details ) { + if( log.exposeDetailsGet() && optsTransfer.details.exposeDetailsTo ) { + optsTransfer.details.exposeDetailsTo( + log, optsTransfer.strGatheredDetailsName, true ); + } + optsTransfer.details.close(); + } + if( ! optsTransfer.bErrorInSigningMessages ) + imaTransferErrorHandling.saveTransferSuccess( optsTransfer.strTransferErrorCategoryName ); + return true; +} + +export async function doAllS2S( // s-chain --> s-chain + joRuntimeOpts, + imaState, + skaleObserver, + ethersProviderDst, + joMessageProxyDst, + joAccountDst, + chainNameDst, + chainIdDst, + joTokenManagerSChain, // for logs validation on s-chain + nTransactionsCountInBlock, + nTransferSteps, + nMaxTransactionsCount, + nBlockAwaitDepth, + nBlockAge, + fnSignMessages, + transactionCustomizerDst +) { + let cntOK = 0, cntFail = 0, nIndexS2S = 0; + const strDirection = "S2S"; + const arrSChainsCached = skaleObserver.getLastCachedSChains(); + const cntSChains = arrSChainsCached.length; + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.debug( "Have " ) + cc.info( cntSChains ) + + cc.debug( " S-Chain(s) connected to this S-Chain for performing S2S transfers." ) + + "\n" ); + } + for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { + const joSChain = arrSChainsCached[idxSChain]; + const urlSrc = skaleObserver.pickRandomSChainUrl( joSChain ); + const ethersProviderSrc = owaspUtils.getEthersProviderFromURL( urlSrc ); + const joAccountSrc = joAccountDst; // ??? + const chainNameSrc = "" + joSChain.data.name; + const chainIdSrc = "" + joSChain.data.computed.chainId; + if( log.verboseGet() >= log.verboseReversed().information ) { + log.write( cc.debug( "S2S transfer walk trough " ) + cc.info( chainNameSrc ) + + cc.debug( "/" ) + cc.info( chainIdSrc ) + cc.debug( " S-Chain..." ) + "\n" ); + } + let bOK = false; + try { + nIndexS2S = idxSChain; + if( ! await pwa.checkOnLoopStart( imaState, "s2s", nIndexS2S ) ) { + imaState.loopState.s2s.wasInProgress = false; + if( log.verboseGet() >= log.verboseReversed().notice ) { + log.write( cc.warning( "Skipped(s2s) due to cancel mode reported from PWA" ) + + "\n" ); + } + } else { + if( loop.checkTimeFraming( null, "s2s", joRuntimeOpts ) ) { + // ??? assuming all S-Chains have same ABIs here + const joMessageProxySrc = + new owaspUtils.ethersMod.ethers.Contract( + imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_address, + imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_abi, + ethersProviderSrc + ); + const joDepositBoxSrc = + new owaspUtils.ethersMod.ethers.Contract( + imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_address, + imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_abi, + ethersProviderSrc + ); + const joExtraSignOpts = { + skaleObserver: skaleObserver, + chainNameSrc: chainNameSrc, + chainIdSrc: chainIdSrc, + chainNameDst: chainNameDst, + chainIdDst: chainIdDst, + joAccountSrc: joAccountSrc, + joAccountDst: joAccountDst, + ethersProviderSrc: ethersProviderSrc, + ethersProviderDst: ethersProviderDst + }; + joRuntimeOpts.idxChainKnownForS2S = idxSChain; + joRuntimeOpts.cntChainsKnownForS2S = cntSChains; + joRuntimeOpts.joExtraSignOpts = joExtraSignOpts; + + imaState.loopState.s2s.isInProgress = true; + await pwa.notifyOnLoopStart( imaState, "s2s", nIndexS2S ); + + bOK = + await doTransfer( + strDirection, + joRuntimeOpts, + ethersProviderSrc, + joMessageProxySrc, + joAccountSrc, + ethersProviderDst, + joMessageProxyDst, + joAccountDst, + chainNameSrc, + chainNameDst, + chainIdSrc, + chainIdDst, + joDepositBoxSrc, // for logs validation on mainnet or source S-Chain + joTokenManagerSChain, // for logs validation on s-chain + nTransactionsCountInBlock, + nTransferSteps, + nMaxTransactionsCount, + nBlockAwaitDepth, + nBlockAge, + fnSignMessages, + joExtraSignOpts, + transactionCustomizerDst + ); + imaState.loopState.s2s.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "s2s", nIndexS2S ); + } else { + bOK = true; + if( log.verboseGet() >= log.verboseReversed().notice ) { + const strLogPrefix = cc.attention( "S2S Loop:" ) + " "; + log.write( strLogPrefix + + cc.warning( "Skipped(s2s) due to time framing check" ) + "\n" ); + } + } + } + } catch ( err ) { + bOK = false; + if( log.verboseGet() >= log.verboseReversed().error ) { + const strError = owaspUtils.extractErrorMessage( err ); + log.write( cc.fatal( "S2S STEP ERROR:" ) + cc.error( " From S-Chain " ) + + cc.info( chainNameSrc ) + cc.error( ", error is: " ) + cc.warning( strError ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + imaState.loopState.s2s.isInProgress = false; + await pwa.notifyOnLoopEnd( imaState, "s2s", nIndexS2S ); + } + if( bOK ) + ++ cntOK; + else + ++ cntFail; + } + joRuntimeOpts.idxChainKnownForS2S = 0; // reset/clear + joRuntimeOpts.cntChainsKnownForS2S = 0; // reset/clear + if( "joExtraSignOpts" in joRuntimeOpts ) + delete joRuntimeOpts.joExtraSignOpts; // reset/clear + if( log.verboseGet() >= log.verboseReversed().debug && ( cntOK > 0 || cntFail > 0 ) ) { + let s = cc.debug( "Stats for S2S steps:" ); + if( cntOK > 0 ) { + s += " " + cc.info( cntOK ) + + cc.success( " S-Chain(s) processed OKay" ) + cc.debug( ", " ); + } + if( cntFail > 0 ) { + s += " " + cc.info( cntFail ) + + cc.error( " S-Chain(s) failed" ); + } + log.write( s + "\n" ); + } + return ( cntFail == 0 ) ? true : false; +} diff --git a/npms/skale-ima/package.json b/npms/skale-ima/package.json index f425aa5d4..6cd9b0495 100644 --- a/npms/skale-ima/package.json +++ b/npms/skale-ima/package.json @@ -21,21 +21,18 @@ }, "license": "AGPL-3.0", "author": "SKALE", - "files": [ - "LICENSE", - "README.md", - "index.js", - "cc.js", - "log.js" - ], - "main": "index.js", - "scripts": {}, + "scripts": { + "check-outdated": "yarn outdated", + "upgrade-to-latest": "yarn upgrade --latest" + }, "dependencies": { - "ethereumjs-tx": "1.3.7", - "ethereumjs-wallet": "^1.0.2", - "ethereumjs-util": "^7.1.4", - "web3": "^1.6.1", - "ioredis": "^4.28.2" + "sha3": "2.1.4", + "number-to-bn": "^1.7.0", + "ethers": "^5.7.2", + "@ethersproject/experimental": "^5.7.0", + "solc": "0.8.6", + "ioredis": "^4.28.2", + "ethereumjs-util": "^7.1.5" }, "devDependencies": {}, "resolutions": { diff --git a/npms/skale-ima/yarn.lock b/npms/skale-ima/yarn.lock index 677be220b..7234c619b 100644 --- a/npms/skale-ima/yarn.lock +++ b/npms/skale-ima/yarn.lock @@ -2,241 +2,368 @@ # yarn lockfile v1 -"@ethereumjs/common@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" - integrity sha512-DEHjW6e38o+JmB/NO3GZBpW4lpaiBpkFgXF6jLcJ6gETBYpEyaA5nTimsWBUJR3Vmtm/didUEbNjajskugZORg== - dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.1" +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + 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" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/experimental@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" + integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== + dependencies: + "@ethersproject/web" "^5.7.0" + ethers "^5.7.0" + scrypt-js "3.0.1" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" -"@ethereumjs/common@^2.6.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348" - integrity sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA== +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.3" - -"@ethereumjs/tx@^3.3.2": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.4.0.tgz#7eb1947eefa55eb9cf05b3ca116fb7a3dbd0bce7" - integrity sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw== - dependencies: - "@ethereumjs/common" "^2.6.0" - ethereumjs-util "^7.1.3" - -"@ethersproject/abi@5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" - integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== - dependencies: - "@ethersproject/address" "^5.0.4" - "@ethersproject/bignumber" "^5.0.7" - "@ethersproject/bytes" "^5.0.4" - "@ethersproject/constants" "^5.0.4" - "@ethersproject/hash" "^5.0.4" - "@ethersproject/keccak256" "^5.0.3" - "@ethersproject/logger" "^5.0.5" - "@ethersproject/properties" "^5.0.3" - "@ethersproject/strings" "^5.0.4" - -"@ethersproject/abstract-provider@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e" - integrity sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/networks" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/web" "^5.4.0" - -"@ethersproject/abstract-signer@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz#e4e9abcf4dd4f1ba0db7dff9746a5f78f355ea81" - integrity sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA== - dependencies: - "@ethersproject/abstract-provider" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - -"@ethersproject/address@^5.0.4", "@ethersproject/address@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.4.0.tgz#ba2d00a0f8c4c0854933b963b9a3a9f6eb4a37a3" - integrity sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - -"@ethersproject/base64@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.4.0.tgz#7252bf65295954c9048c7ca5f43e5c86441b2a9a" - integrity sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ== - dependencies: - "@ethersproject/bytes" "^5.4.0" - -"@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.0": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.2.tgz#44232e015ae4ce82ac034de549eb3583c71283d8" - integrity sha512-oIBDhsKy5bs7j36JlaTzFgNPaZjiNDOXsdSgSpXRucUl+UA6L/1YLlFeI3cPAoodcenzF4nxNPV13pcy7XbWjA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - bn.js "^4.11.9" - -"@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.4.0.tgz#56fa32ce3bf67153756dbaefda921d1d4774404e" - integrity sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.4.0.tgz#ee0bdcb30bf1b532d2353c977bf2ef1ee117958a" - integrity sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - -"@ethersproject/hash@^5.0.4": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0" - integrity sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA== - dependencies: - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" - integrity sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - js-sha3 "0.5.7" - -"@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.4.1.tgz#503bd33683538b923c578c07d1c2c0dd18672054" - integrity sha512-DZ+bRinnYLPw1yAC64oRl0QyVZj43QeHIhVKfD/+YwSz4wsv1pfwb5SOFjz+r710YEWzU6LrhuSjpSO+6PeE4A== - -"@ethersproject/networks@^5.4.0": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.2.tgz#2247d977626e97e2c3b8ee73cd2457babde0ce35" - integrity sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.1.tgz#9f051f976ce790142c6261ccb7b826eaae1f2f36" - integrity sha512-cyCGlF8wWlIZyizsj2PpbJ9I7rIlUAfnHYwy/T90pdkSn/NFTa5YWZx2wTJBe9V7dD65dcrrEMisCRUJiq6n3w== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/rlp@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" - integrity sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/signing-key@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.4.0.tgz#2f05120984e81cf89a3d5f6dec5c68ee0894fbec" - integrity sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - bn.js "^4.11.9" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" - integrity sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.4.0.tgz#a159d035179334bd92f340ce0f77e83e9e1522e0" - integrity sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ== - dependencies: - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - "@ethersproject/signing-key" "^5.4.0" - -"@ethersproject/web@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" - integrity sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og== - dependencies: - "@ethersproject/base64" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" "@types/bn.js@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" - integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== dependencies: "@types/node" "*" "@types/node@*": - version "16.10.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.1.tgz#f3647623199ca920960006b3dccf633ea905f243" - integrity sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w== - -"@types/node@^12.12.6": - version "12.20.27" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.27.tgz#4141fcad57c332a120591de883e26fe4bb14aaea" - integrity sha512-qZdePUDSLAZRXXV234bLBEUM0nAQjoxbcSwp1rqSMUe1rZ47mwU6OjciR/JvF1Oo8mc0ys6GE0ks0HGgqAZoGg== + version "18.13.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850" + integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg== "@types/pbkdf2@^3.0.0": version "3.1.0" @@ -257,18 +384,10 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -aes-js@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== ajv@^6.12.3: version "6.12.6" @@ -303,21 +422,6 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -330,21 +434,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -360,10 +454,10 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.2, base-x@^3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" - integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== +base-x@^3.0.2: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== dependencies: safe-buffer "^5.0.1" @@ -379,15 +473,15 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bignumber.js@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" - integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== blakejs@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" - integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== block-stream@*: version "0.0.9" @@ -396,41 +490,20 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^3.5.0: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.9: +bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -body-parser@1.19.0, body-parser@^1.16.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" +bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== brace-expansion@^1.1.7: version "1.1.11" @@ -440,12 +513,12 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brorand@^1.0.1, brorand@^1.1.0: +brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: +browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -457,52 +530,10 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: inherits "^2.0.1" safe-buffer "^5.0.1" -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== dependencies: base-x "^3.0.2" @@ -515,15 +546,10 @@ bs58check@^2.1.2: create-hash "^1.1.0" safe-buffer "^5.1.2" -buffer-to-arraybuffer@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== buffer@6.0.3: version "6.0.3" @@ -533,47 +559,6 @@ buffer@6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -bufferutil@^4.0.1: - version "4.0.4" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.4.tgz#ab81373d313a6ead0d734e98c448c722734ae7bb" - integrity sha512-VNxjXUCrF3LvbLgwfkTb5LsFvk6pGIn7OBb9x+3o+iJ6mKw0JTUp4chBFc88hi1aspeZGeZG9jAIbpFYPQSLZw== - dependencies: - node-gyp-build "^4.2.0" - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: - 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" - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -584,17 +569,6 @@ chownr@^1.1.4: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -cids@^0.7.1: - version "0.7.5" - resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" - integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== - dependencies: - buffer "^5.5.0" - class-is "^1.1.0" - multibase "~0.6.0" - multicodec "^1.0.0" - multihashes "~0.4.15" - cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -603,18 +577,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -class-is@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" - integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - cluster-key-slot@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" @@ -632,6 +594,16 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -642,42 +614,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-hash@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" - integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== - dependencies: - cids "^0.7.1" - multicodec "^0.5.5" - multihashes "^0.4.15" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -cookiejar@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -688,30 +624,6 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@^2.8.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -crc-32@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" - integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" @@ -723,7 +635,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -735,31 +647,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -crypto-browserify@3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -767,13 +654,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -debug@2.6.9, debug@^2.2.0: - 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@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -788,35 +668,11 @@ debug@^4.3.1: dependencies: ms "2.1.2" -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -832,48 +688,11 @@ denque@^1.1.0: resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dom-walk@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" - integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -882,12 +701,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: +elliptic@6.5.4, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -900,128 +714,6 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -es-abstract@^1.18.5: - version "1.18.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" - integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-string "^1.0.7" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eth-ens-namehash@2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - -eth-lib@0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" - integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -eth-lib@^0.1.26: - version "0.1.29" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" - integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -ethereum-bloom-filters@^1.0.6: - version "1.0.10" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" - integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== - dependencies: - js-sha3 "^0.8.0" - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= - ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -1043,51 +735,7 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereumjs-tx@1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-util@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.1.tgz#236ef435f46820f0c420a708c0559b5897952069" - integrity sha512-1CGBmCp3m8IMGHhAJF/icH8qjCJrfQtaZ9KW+cAVV8kyN5Lc1IRq3KjV77ILOutrCwiyf5y2gMyCrAUMoCf2Ag== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.4" - -ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23" - integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethereumjs-util@^7.1.4: +ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -1098,42 +746,43 @@ ethereumjs-util@^7.1.4: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethereumjs-wallet@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz#2c000504b4c71e8f3782dabe1113d192522e99b6" - integrity sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA== - dependencies: - aes-js "^3.1.2" - bs58check "^2.1.2" - ethereum-cryptography "^0.1.3" - ethereumjs-util "^7.1.2" - randombytes "^2.1.0" - scrypt-js "^3.0.1" - utf8 "^3.0.0" - uuid "^8.3.2" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@0.1.6, ethjs-util@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: +ethers@^5.7.0, ethers@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== @@ -1141,54 +790,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" - integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== - -express@^4.14.0: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -ext@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" - integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== - dependencies: - type "^2.5.0" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -1214,23 +815,10 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +follow-redirects@^1.12.1: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== forever-agent@~0.6.1: version "0.6.1" @@ -1246,24 +834,16 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -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 sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== dependencies: graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" fs-minipass@^1.2.7: version "1.2.7" @@ -1287,11 +867,6 @@ fstream@^1.0.0, fstream@^1.0.12: mkdirp ">=0.5 0" rimraf "2" -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== - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1306,42 +881,6 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -1361,56 +900,16 @@ glob@^7.0.3, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -global@~4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" - integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== - dependencies: - min-document "^2.19.0" - process "^0.11.10" - -got@9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -got@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.1.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -1424,47 +923,11 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= -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" - hash-base@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" @@ -1491,38 +954,6 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -1532,21 +963,14 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@0.4.24, iconv-lite@^0.4.4: +iconv-lite@^0.4.4: 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" -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== - dependencies: - punycode "2.1.0" - -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -1566,30 +990,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, 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 sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - ioredis@^4.28.2: version "4.28.2" resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.2.tgz#493ccd5d869fd0ec86c96498192718171f6c9203" @@ -1607,46 +1017,6 @@ ioredis@^4.28.2: redis-parser "^3.0.0" standard-as-callback "^2.1.0" -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== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -1659,89 +1029,12 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-function@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" - integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - -is-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" - integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== - -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" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-stream@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.3, is-typed-array@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" - integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -1761,20 +1054,7 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" - -js-sha3@0.5.7, js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= - -js-sha3@^0.8.0: +js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== @@ -1784,11 +1064,6 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - 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" @@ -1804,10 +1079,10 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== optionalDependencies: graceful-fs "^4.1.6" @@ -1822,20 +1097,20 @@ jsprim@^1.2.2: verror "1.10.0" keccak@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + version "3.0.3" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== dependencies: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" readable-stream "^3.6.0" -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" lodash.defaults@^4.2.0: version "4.2.0" @@ -1852,16 +1127,6 @@ lodash.isarguments@^3.1.0: resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -1871,58 +1136,23 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== mime-db@1.49.0: version "1.49.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@~2.1.19: version "2.1.32" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== dependencies: mime-db "1.49.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-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= - dependencies: - dom-walk "^0.1.0" - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -1960,18 +1190,6 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= - dependencies: - mkdirp "*" - -mkdirp@*: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -1979,21 +1197,6 @@ mkdirp@*: dependencies: minimist "^1.2.5" -mock-fs@^4.1.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" - integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -2004,56 +1207,11 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multibase@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" - integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multibase@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" - integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multicodec@^0.5.5: - version "0.5.7" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" - integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== - dependencies: - varint "^5.0.0" - -multicodec@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" - integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== - dependencies: - buffer "^5.6.0" - varint "^5.0.0" - -multihashes@^0.4.15, multihashes@~0.4.15: - version "0.4.21" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" - integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== - dependencies: - buffer "^5.5.0" - multibase "^0.7.0" - varint "^5.0.0" - nan@^2.14.0: version "2.15.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= - needle@^2.2.1: version "2.9.1" resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684" @@ -2063,16 +1221,6 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -2084,9 +1232,9 @@ node-addon-api@^3.0.0: integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== node-gyp-build@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" - integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== node-gyp@3.x: version "3.8.0" @@ -2137,11 +1285,6 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - npm-bundled@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -2178,10 +1321,10 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= -number-to-bn@1.7.0: +number-to-bn@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -2191,46 +1334,12 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -oboe@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" - integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= - dependencies: - http-https "^1.0.0" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -2242,7 +1351,7 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-tmpdir@^1.0.0: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -2255,65 +1364,17 @@ osenv@0, osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - 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== -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= - dependencies: - p-finally "^1.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-headers@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" - integrity sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw== - -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-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 sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -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 sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -pbkdf2@^3.0.17, pbkdf2@^3.0.3: +pbkdf2@^3.0.17: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -2329,123 +1390,33 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -printj@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" - integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== - 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== -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -proxy-addr@~2.0.5: - 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" - psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: +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" -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -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.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -2495,7 +1466,7 @@ redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" -request@^2.79.0, request@^2.87.0: +request@^2.87.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -2521,14 +1492,12 @@ request@^2.79.0, request@^2.87.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" +require-from-string@^2.0.0: + 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== -rimraf@2, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -2543,23 +1512,23 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.4: - version "2.2.6" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c" - integrity sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg== +rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: - bn.js "^4.11.1" - -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== + bn.js "^5.2.0" safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, 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== +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== + "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -2570,7 +1539,7 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scrypt-js@^3.0.0, scrypt-js@^3.0.1: +scrypt-js@3.0.1, scrypt-js@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== @@ -2581,15 +1550,15 @@ scrypt-js@^3.0.0, scrypt-js@^3.0.1: nan "^2.14.0" secp256k1@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.2.tgz#15dd57d0f0b9fdb54ac1fa1694f40e5e9a54f4a1" - integrity sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== dependencies: - elliptic "^6.5.2" + elliptic "^6.5.4" node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -semver@^5.3.0: +semver@^5.3.0, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2599,46 +1568,6 @@ semver@~5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" - set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -2647,12 +1576,7 @@ set-blocking@~2.0.0: setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" @@ -2669,33 +1593,25 @@ sha3@2.1.4: dependencies: buffer "6.0.3" -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.0: version "3.0.4" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== -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@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== - dependencies: - decompress-response "^3.3.0" - once "^1.3.1" - simple-concat "^1.0.0" +solc@0.8.6: + version "0.8.6" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.6.tgz#e4341fa6780137df97b94a0cfbd59b3f2037d0e0" + integrity sha512-miiDaWdaUnD7A6Cktb/2ug9f+ajcOCDYRr7vgbPEsMoutSlBtp5rca57oMg8iHSuM7jilwdxePujWI/+rbNftQ== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" sqlite3@5.0.2: version "5.0.2" @@ -2727,16 +1643,6 @@ standard-as-callback@^2.1.0: resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -2754,22 +1660,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -2810,23 +1700,6 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -swarm-js@^0.1.40: - version "0.1.40" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" - integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" - tar@^2.0.0: version "2.2.2" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" @@ -2836,7 +1709,7 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4, tar@^4.0.2: +tar@^4: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -2849,20 +1722,12 @@ tar@^4, tar@^4.0.2: safe-buffer "^5.2.1" yallist "^3.1.1" -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" tough-cookie@~2.5.0: version "2.5.0" @@ -2884,56 +1749,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -type-is@~1.6.17, 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" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" - integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -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 sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -2941,89 +1756,16 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= - -utf-8-validate@^5.0.2: - version "5.0.6" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.6.tgz#e1b3e0a5cc8648a3b44c1799fbb170d1aaaffe80" - integrity sha512-hoY0gOf9EkCw+nimK21FVKHUIG1BMqSiRwxB/q3A9yKZOrOI99PP77BxmarDqWz6rG3vVYiBWfhG8z2Tl+7fZA== - dependencies: - node-gyp-build "^4.2.0" - -utf8@3.0.0, utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== - 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 sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util@^0.12.0: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -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== - -varint@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" - integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -3033,269 +1775,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -web3-bzz@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.1.tgz#8430eb3cbb69baaee4981d190b840748c37a9ec2" - integrity sha512-JbnFNbRlwwHJZPtVuCxo7rC4U4OTg+mPsyhjgPQJJhS0a6Y54OgVWYk9UA/95HqbmTJwTtX329gJoSsseEfrng== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - -web3-core-helpers@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.1.tgz#cb21047306871f4cf0fedfece7d47ea2aa96141b" - integrity sha512-om2PZvK1uoWcgMq6JfcSx3241LEIVF6qi2JuHz2SLKiKEW5UsBUaVx0mNCmcZaiuYQCyOsLS3r33q5AdM+v8ng== - dependencies: - web3-eth-iban "1.6.1" - web3-utils "1.6.1" - -web3-core-method@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.1.tgz#4ae91c639bf1da85ebfd8b99595da6a2235d7b98" - integrity sha512-szH5KyIWIaULQDBdDvevQUCHV9lsExJ/oV0ePqK+w015D2SdMPMuhii0WB+HCePaksWO+rr/GAypvV9g2T3N+w== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-utils "1.6.1" - -web3-core-promievent@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.1.tgz#f650dea9361e2edf02691015b213fcc8ea499992" - integrity sha512-byJ5s2MQxrWdXd27pWFmujfzsTZK4ik8rDgIV1RFDFc+rHZ2nZhq+VWk7t/Nkrj7EaVXncEgTdPEHc18nx+ocQ== - dependencies: - eventemitter3 "4.0.4" - -web3-core-requestmanager@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.1.tgz#d9c08b0716c9cda546a0c02767b7e08deb04448a" - integrity sha512-4y7etYEUtkfflyYVBfN1oJtCbVFNhNX1omlEYzezhTnPj3/dT7n+dhUXcqvIhx9iKA13unGfpFge80XNFfcB8A== - dependencies: - util "^0.12.0" - web3-core-helpers "1.6.1" - web3-providers-http "1.6.1" - web3-providers-ipc "1.6.1" - web3-providers-ws "1.6.1" - -web3-core-subscriptions@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.1.tgz#4dfc1f74137354d4ac9eaa628aa916c5e2cc8741" - integrity sha512-WZwxsYttIojyGQ5RqxuQcKg0IJdDCFpUe4EncS3QKZwxPqWzGmgyLwE0rm7tP+Ux1waJn5CUaaoSCBxWGSun1g== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - -web3-core@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.1.tgz#b41f08fdc9ea1082d15384a3d6fa93a47c3fc1b4" - integrity sha512-m+b7UfYvU5cQUAh6NRfxRzH/5B3to1AdEQi1HIQt570cDWlObOOmoO9tY6iJnI5w4acxIO19LqjDMqEJGBYyRQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-requestmanager "1.6.1" - web3-utils "1.6.1" - -web3-eth-abi@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.6.1.tgz#15b937e3188570754d50bbac51a4bb0578600d1d" - integrity sha512-svhYrAlXP9XQtV7poWKydwDJq2CaNLMtmKydNXoOBLcQec6yGMP+v20pgrxF2H6wyTK+Qy0E3/5ciPOqC/VuoQ== - dependencies: - "@ethersproject/abi" "5.0.7" - web3-utils "1.6.1" - -web3-eth-accounts@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.1.tgz#aeb0dfb52c4391773550569732975b471212583f" - integrity sha512-rGn3jwnuOKwaQRu4SiShz0YAQ87aVDBKs4HO43+XTCI1q1Y1jn3NOsG3BW9ZHaOckev4+zEyxze/Bsh2oEk24w== - dependencies: - "@ethereumjs/common" "^2.5.0" - "@ethereumjs/tx" "^3.3.2" - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-util "^7.0.10" - scrypt-js "^3.0.1" - uuid "3.3.2" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-eth-contract@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.1.tgz#4b0a2c0b37015d70146e54c7cb3f035a58fbeec0" - integrity sha512-GXqTe3mF6kpbOAakiNc7wtJ120/gpuKMTZjuGFKeeY8aobRLfbfgKzM9IpyqVZV2v5RLuGXDuurVN2KPgtu3hQ== - dependencies: - "@types/bn.js" "^4.11.5" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-utils "1.6.1" - -web3-eth-ens@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.1.tgz#801bd5fb5237377ec2ed8517a9fe4634f2269c7a" - integrity sha512-ngprtbnoRgxg8s1wXt9nXpD3h1P+p7XnKXrp/8GdFI9uDmrbSQPRfzBw86jdZgOmy78hAnWmrHI6pBInmgi2qQ== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-contract "1.6.1" - web3-utils "1.6.1" - -web3-eth-iban@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.1.tgz#20bbed75723e3e9ff98e624979629d26329462b6" - integrity sha512-91H0jXZnWlOoXmc13O9NuQzcjThnWyAHyDn5Yf7u6mmKOhpJSGF/OHlkbpXt1Y4v2eJdEPaVFa+6i8aRyagE7Q== - dependencies: - bn.js "^4.11.9" - web3-utils "1.6.1" - -web3-eth-personal@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.1.tgz#9b524fb9f92b51163f46920ee2663d34a4897c8d" - integrity sha512-ItsC89Ln02+irzJjK6ALcLrMZfbVUCqVbmb/ieDKJ+eLW3pNkBNwoUzaydh92d5NzxNZgNxuQWVdlFyYX2hkEw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-eth@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.1.tgz#a25aba1ac213d872ecf3f81c7b4ab8072ecae224" - integrity sha512-kOV1ZgCKypSo5BQyltRArS7ZC3bRpIKAxSgzl7pUFinUb/MxfbM9KGeNxUXoCfTSErcCQJaDjcS6bSre5EMKuQ== - dependencies: - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-accounts "1.6.1" - web3-eth-contract "1.6.1" - web3-eth-ens "1.6.1" - web3-eth-iban "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-net@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.1.tgz#7a630a804ec9f81908ae52ccbb4ebbb9530b3906" - integrity sha512-gpnqKEIwfUHh5ik7wsQFlCje1DfcmGv+Sk7LCh1hCqn++HEDQxJ/mZCrMo11ZZpZHCH7c87imdxTg96GJnRxDw== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-providers-http@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.1.tgz#b59b14eefef23b98c327806f5f566303a73bd435" - integrity sha512-xBoKOJxu10+kO3ikamXmBfrWZ/xpQOGy0ocdp7Y81B17En5TXELwlmMXt1UlIgWiyYDhjq4OwlH/VODYqHXy3A== - dependencies: - web3-core-helpers "1.6.1" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.1.tgz#7ba460589d46896bb3d124288deed1b6a72d517e" - integrity sha512-anyoIZlpMzwEQI4lwylTzDrHsVp20v0QUtSTp2B5jInBinmQtyCE7vnbX20jEQ4j5uPwfJabKNtoJsk6a3O4WQ== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.6.1" - -web3-providers-ws@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.1.tgz#f7ee71f158971102b865e99ea7911f483e0507e9" - integrity sha512-FWMEFYb4rYFYRgSFBf/O1Ex4p/YKSlN+JydCtdlJwRimd89qm95CTfs4xGjCskwvXMjV2sarH+f1NPwJXicYpg== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - websocket "^1.0.32" - -web3-shh@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.1.tgz#eebaab2e5e6be80fe2585c6c094fa10a03349ca7" - integrity sha512-oP00HbAtybLCGlLOZUYXOdeB9xq88k2l0TtStvKBtmFqRt+zVk5TxEeuOnVPRxNhcA2Un8RUw6FtvgZlWStu9A== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-net "1.6.1" - -web3-utils@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.6.1.tgz#befcb23922b00603ab56d8c5b4158468dc494aca" - integrity sha512-RidGKv5kOkcerI6jQqDFDoTllQQqV+rPhTzZHhmbqtFObbYpU93uc+yG1LHivRTQhA6llIx67iudc/vzisgO+w== - dependencies: - bn.js "^4.11.9" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - -web3@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.1.tgz#c9e68fe7b3073adddf35393441f950ec69b92735" - integrity sha512-c299lLiyb2/WOcxh7TinwvbATaMmrgNIeAzbLbmOKHI0LcwyfsB1eu2ReOIrfrCYDYRW2KAjYr7J7gHawqDNPQ== - dependencies: - web3-bzz "1.6.1" - web3-core "1.6.1" - web3-eth "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-shh "1.6.1" - web3-utils "1.6.1" - -websocket@^1.0.32: - version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" - integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - 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" - -which-typed-array@^1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" - integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.7" - which@1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -3315,61 +1794,10 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -xhr-request-promise@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" - integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== - dependencies: - xhr-request "^1.1.0" - -xhr-request@^1.0.1, xhr-request@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== - dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= - dependencies: - cookiejar "^2.1.1" - -xhr@^2.0.4, xhr@^2.3.3: - version "2.6.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" - integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== - dependencies: - global "~4.4.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== yallist@^3.0.0, yallist@^3.1.1: version "3.1.1" diff --git a/npms/skale-log/log.js b/npms/skale-log/log.js deleted file mode 100644 index 115677532..000000000 --- a/npms/skale-log/log.js +++ /dev/null @@ -1,314 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * SKALE IMA is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * SKALE IMA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with SKALE IMA. If not, see . - */ - -/** - * @file log.js - * @copyright SKALE Labs 2019-Present - */ - -const cc = require( "../skale-cc/cc.js" ); -const fs = require( "fs" ); -let g_arrStreams = []; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function n2s( n, sz ) { - let s = "" + n; - while( s.length < sz ) - s = "0" + s; - return s; -} - -function generate_timestamp_string( ts, isColorized ) { - isColorized = ( typeof isColorized == "undefined" ) ? true : ( isColorized ? true : false ); - ts = ( ts instanceof Date ) ? ts : new Date(); - const cc_date = function( x ) { return isColorized ? cc.date( x ) : x; }; - const cc_time = function( x ) { return isColorized ? cc.time( x ) : x; }; - const cc_frac_time = function( x ) { return isColorized ? cc.frac_time( x ) : x; }; - const cc_bright = function( x ) { return isColorized ? cc.bright( x ) : x; }; - const s = - "" + cc_date( n2s( ts.getUTCFullYear(), 4 ) ) + - cc_bright( "-" ) + cc_date( n2s( ts.getUTCMonth() + 1, 2 ) ) + - cc_bright( "-" ) + cc_date( n2s( ts.getUTCDate(), 2 ) ) + - " " + cc_time( n2s( ts.getUTCHours(), 2 ) ) + - cc_bright( ":" ) + cc_time( n2s( ts.getUTCMinutes(), 2 ) ) + - cc_bright( ":" ) + cc_time( n2s( ts.getUTCSeconds(), 2 ) ) + - cc_bright( "." ) + cc_frac_time( n2s( ts.getUTCMilliseconds(), 3 ) ) - ; - return s; -} - -function generate_timestamp_prefix( ts, isColorized ) { - return generate_timestamp_string( ts, isColorized ) + cc.bright( ":" ) + " "; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function removeAllStreams() { - let i = 0; let cnt = 0; - try { - cnt = g_arrStreams.length; - for( i = 0; i < cnt; ++i ) { - try { - const objEntry = g_arrStreams[i]; - objEntry.objStream.close(); - } catch ( err ) { - } - } - } catch ( err ) { - } - g_arrStreams = []; -} - -function getStreamWithFilePath( strFilePath ) { - try { - let i = 0; const cnt = g_arrStreams.length; - for( i = 0; i < cnt; ++i ) { - try { - const objEntry = g_arrStreams[i]; - if( objEntry.strPath === strFilePath ) - return objEntry; - } catch ( err ) { - } - } - } catch ( err ) { - } - return null; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function createStandardOutputStream() { - try { - const objEntry = { - strPath: "stdout", - nMaxSizeBeforeRotation: -1, - nMaxFilesCount: -1, - objStream: null, - write: function( s ) { - const x = "" + s; try { - if( this.objStream ) - this.objStream.write( x ); - } catch ( err ) { } - }, - close: function() { this.objStream = null; }, - open: function() { try { this.objStream = process.stdout; } catch ( err ) { } }, - size: function() { return 0; }, - rotate: function( nBytesToWrite ) { }, - toString: function() { return "" + strFilePath; }, - exposeDetailsTo: function( otherStream, strTitle, isSuccess ) { } - }; - objEntry.open(); - return objEntry; - } catch ( err ) { - } - return null; -} - -function insertStandardOutputStream() { - let objEntry = getStreamWithFilePath( "stdout" ); - if( objEntry !== null ) - return true; - objEntry = createStandardOutputStream(); - if( !objEntry ) - return false; - g_arrStreams.push( objEntry ); - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function createMemoryOutputStream( isAutoAddTimestamps ) { - try { - const objEntry = { - strPath: "memory", - nMaxSizeBeforeRotation: -1, - nMaxFilesCount: -1, - strAccumulatedLogText: "", - isWithTimestamps: ( isAutoAddTimestamps || ( typeof isAutoAddTimestamps == "undefined" ) ) ? true : false, - write: function( s ) { - let strPrefix = ""; - if( this.isWithTimestamps ) - strPrefix = generate_timestamp_prefix( null, true ); - this.strAccumulatedLogText += strPrefix + s; - }, - clear: function() { this.strAccumulatedLogText = ""; }, - close: function() { this.clear(); }, - open: function() { this.clear(); }, - size: function() { return 0; }, - rotate: function( nBytesToWrite ) { this.strAccumulatedLogText = ""; }, - toString: function() { return "" + this.strAccumulatedLogText; }, - exposeDetailsTo: function( otherStream, strTitle, isSuccess ) { - strTitle = strTitle ? ( cc.bright( " (" ) + cc.attention( strTitle ) + cc.bright( ")" ) ) : ""; - const strSuccessPrefix = isSuccess ? cc.success( "SUCCESS" ) : cc.fatal( "ERROR" ); - otherStream.write( - cc.bright( "\n\n\n--- --- --- --- --- GATHERED " ) + strSuccessPrefix + cc.bright( " DETAILS FOR LATEST(" ) + cc.sunny( strTitle ) + cc.bright( " action (" ) + cc.sunny( "BEGIN" ) + cc.bright( ") --- --- ------ --- \n\n" ) + - this.strAccumulatedLogText + - cc.bright( "\n--- --- --- --- --- GATHERED " ) + strSuccessPrefix + cc.bright( " DETAILS FOR LATEST(" ) + cc.sunny( strTitle ) + cc.bright( " action (" ) + cc.sunny( "END" ) + cc.bright( ") --- --- --- --- ---\n\n\n\n" ) - ); - } - }; - objEntry.open(); - return objEntry; - } catch ( err ) { - } - return null; -} - -function insertMemoryOutputStream() { - let objEntry = getStreamWithFilePath( "memory" ); - if( objEntry !== null ) - return true; - objEntry = createMemoryOutputStream(); - if( !objEntry ) - return false; - g_arrStreams.push( objEntry ); - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function createFileOutput( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ) { - try { - // const fd = fs.openSync( "" + strFilePath, "a", fs.constants.O_NONBLOCK | fs.constants.O_WR ); - const objEntry = { - strPath: "" + strFilePath, - nMaxSizeBeforeRotation: 0 + nMaxSizeBeforeRotation, - nMaxFilesCount: 0 + nMaxFilesCount, - objStream: null, - write: function( s ) { const x = "" + s; this.rotate( x.length ); fs.appendFileSync( this.objStream, x, "utf8" ); }, - close: function() { - if( !this.objStream ) - return; fs.closeSync( this.objStream ); this.objStream = null; - }, - open: function() { this.objStream = fs.openSync( this.strPath, "a", fs.constants.O_NONBLOCK | fs.constants.O_WR ); }, - size: function() { try { return fs.lstatSync( this.strPath ).size; } catch ( err ) { return 0; } }, - rotate: function( nBytesToWrite ) { - try { - if( this.nMaxSizeBeforeRotation <= 0 || this.nMaxFilesCount <= 1 ) - return; - this.close(); - const nFileSize = this.size(); - const nNextSize = nFileSize + nBytesToWrite; - if( nNextSize <= this.nMaxSizeBeforeRotation ) { - this.open(); - return; - } - let i = 0; const cnt = 0 + this.nMaxFilesCount; - for( i = 0; i < cnt; ++i ) { - const j = this.nMaxFilesCount - i - 1; - const strPath = "" + this.strPath + ( ( j === 0 ) ? "" : ( "." + j ) ); - if( j == ( cnt - 1 ) ) { - try { fs.unlinkSync( strPath ); } catch ( err ) { } - continue; - } - const strPathPrev = "" + this.strPath + "." + ( j + 1 ); - try { fs.unlinkSync( strPathPrev ); } catch ( err ) { } - try { fs.renameSync( strPath, strPathPrev ); } catch ( err ) { } - } // for( i = 0; i < cnt; ++ i ) - } catch ( err ) { - } - try { - this.open(); - } catch ( err ) { - } - }, - toString: function() { return "" + strFilePath; }, - exposeDetailsTo: function( otherStream, strTitle, isSuccess ) { } - }; - objEntry.open(); - return objEntry; - } catch ( err ) { - console.log( "CRITICAL ERROR: Failed to open file system log stream for " + strFilePath + ", error is " + JSON.stringify( err ) ); - } - return null; -} -function insertFileOutput( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ) { - let objEntry = getStreamWithFilePath( "" + strFilePath ); - if( objEntry !== null ) - return true; - objEntry = createFileOutput( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ); - if( !objEntry ) - return false; - g_arrStreams.push( objEntry ); - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -module.exports = { - generate_timestamp_string: generate_timestamp_string, - generate_timestamp_prefix: generate_timestamp_prefix, - cc: cc, - write: function() { - let s = generate_timestamp_prefix( null, true ); let i = 0; let cnt = 0; - try { - for( i = 0; i < arguments.length; ++i ) { - try { - s += arguments[i]; - } catch ( err ) { - } - } - } catch ( err ) { - } - try { - if( s.length <= 0 ) - return; - cnt = g_arrStreams.length; - for( i = 0; i < cnt; ++i ) { - try { - const objEntry = g_arrStreams[i]; - objEntry.write( s ); - } catch ( err ) { - } - } - } catch ( err ) { - } - }, - removeAll: function() { - removeAllStreams(); - }, - addStdout: function() { - return insertStandardOutputStream(); - }, - addMemory: function() { - return insertMemoryOutputStream(); - }, - createMemoryStream: function( isAutoAddTimestamps ) { - return createMemoryOutputStream( isAutoAddTimestamps ); - }, - add: function( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ) { - return insertFileOutput( - strFilePath, - ( nMaxSizeBeforeRotation <= 0 ) ? -1 : nMaxSizeBeforeRotation, - ( nMaxFilesCount <= 1 ) ? -1 : nMaxFilesCount - ); - }, - getStreamWithFilePath: getStreamWithFilePath -}; // module.exports - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/npms/skale-log/log.mjs b/npms/skale-log/log.mjs new file mode 100644 index 000000000..08b9b66bd --- /dev/null +++ b/npms/skale-log/log.mjs @@ -0,0 +1,468 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file log.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as cc from "../skale-cc/cc.mjs"; +import * as fs from "fs"; + +let gArrStreams = []; + +let gFlagLogWithTimeStamps = true; + +let gIdentifierAllocatorCounter = 0; + +export function getPrintTimestamps() { + return gFlagLogWithTimeStamps; +} + +export function setPrintTimestamps( b ) { + gFlagLogWithTimeStamps = b ? true : false; +} + +export function n2s( n, sz ) { + let s = "" + n; + while( s.length < sz ) + s = "0" + s; + return s; +} + +export function generateTimestampString( ts, isColorized ) { + isColorized = + ( typeof isColorized == "undefined" ) + ? true : ( isColorized ? true : false ); + ts = ( ts instanceof Date ) ? ts : new Date(); + const ccDate = function( x ) { return isColorized ? cc.date( x ) : x; }; + const ccTime = function( x ) { return isColorized ? cc.time( x ) : x; }; + const ccFractionPartOfTime = function( x ) { return isColorized ? cc.frac_time( x ) : x; }; + const ccBright = function( x ) { return isColorized ? cc.bright( x ) : x; }; + const s = + "" + ccDate( n2s( ts.getUTCFullYear(), 4 ) ) + + ccBright( "-" ) + ccDate( n2s( ts.getUTCMonth() + 1, 2 ) ) + + ccBright( "-" ) + ccDate( n2s( ts.getUTCDate(), 2 ) ) + + " " + ccTime( n2s( ts.getUTCHours(), 2 ) ) + + ccBright( ":" ) + ccTime( n2s( ts.getUTCMinutes(), 2 ) ) + + ccBright( ":" ) + ccTime( n2s( ts.getUTCSeconds(), 2 ) ) + + ccBright( "." ) + ccFractionPartOfTime( n2s( ts.getUTCMilliseconds(), 3 ) ) + ; + return s; +} + +export function generateTimestampPrefix( ts, isColorized ) { + return generateTimestampString( ts, isColorized ) + cc.bright( ":" ) + " "; +} + +export function removeAllStreams() { + let i = 0; let cnt = 0; + try { + cnt = gArrStreams.length; + for( i = 0; i < cnt; ++i ) { + try { + const objEntry = gArrStreams[i]; + objEntry.objStream.close(); + } catch ( err ) { + } + } + } catch ( err ) { + } + gArrStreams = []; +} + +export function getStreamWithFilePath( strFilePath ) { + try { + let i = 0; const cnt = gArrStreams.length; + for( i = 0; i < cnt; ++i ) { + try { + const objEntry = gArrStreams[i]; + if( objEntry.strPath === strFilePath ) + return objEntry; + } catch ( err ) { + } + } + } catch ( err ) { + } + return null; +} + +export function createStandardOutputStream() { + try { + const objEntry = { + "id": gIdentifierAllocatorCounter ++, + "strPath": "stdout", + "nMaxSizeBeforeRotation": -1, + "nMaxFilesCount": -1, + "objStream": null, + "haveOwnTimestamps": false, + "strOwnIndent": "", + "write": function( s ) { + const x = + this.strOwnIndent + + + ( this.haveOwnTimestamps ? generateTimestampPrefix( null, true ) : "" ) + + s; + try { + if( this.objStream ) + this.objStream.write( x ); + } catch ( err ) { } + }, + "close": function() { this.objStream = null; }, + "open": function() { try { this.objStream = process.stdout; } catch ( err ) { } }, + "size": function() { return 0; }, + "rotate": function( nBytesToWrite ) { }, + "toString": function() { return "" + strFilePath; }, + "exposeDetailsTo": function( otherStream, strTitle, isSuccess ) { } + }; + objEntry.open(); + return objEntry; + } catch ( err ) { + } + return null; +} + +export function insertStandardOutputStream() { + let objEntry = getStreamWithFilePath( "stdout" ); + if( objEntry !== null ) + return true; + objEntry = createStandardOutputStream(); + if( !objEntry ) + return false; + gArrStreams.push( objEntry ); + return true; +} + +export function createMemoryOutputStream() { + try { + const objEntry = { + "id": gIdentifierAllocatorCounter ++, + "strPath": "memory", + "nMaxSizeBeforeRotation": -1, + "nMaxFilesCount": -1, + "strAccumulatedLogText": "", + "haveOwnTimestamps": true, + "strOwnIndent": " ", + "write": function( s ) { + if( this.strAccumulatedLogText.length == 0 || + this.strAccumulatedLogText[this.strAccumulatedLogText.length - 1] == "\n" + ) { + this.strAccumulatedLogText += this.strOwnIndent; + if( this.haveOwnTimestamps ) + this.strAccumulatedLogText += generateTimestampPrefix( null, true ); + } + this.strAccumulatedLogText += s; + }, + "clear": function() { this.strAccumulatedLogText = ""; }, + "close": function() { this.clear(); }, + "open": function() { this.clear(); }, + "size": function() { return 0; }, + "rotate": function( nBytesToWrite ) { this.strAccumulatedLogText = ""; }, + "toString": function() { return "" + this.strAccumulatedLogText; }, + "exposeDetailsTo": function( otherStream, strTitle, isSuccess ) { + if( ! ( this.strAccumulatedLogText && + typeof this.strAccumulatedLogText == "string" && + this.strAccumulatedLogText.length > 0 ) ) + return; + strTitle = strTitle + ? ( cc.bright( " (" ) + cc.attention( strTitle ) + cc.bright( ")" ) ) : ""; + const strSuccessPrefix = isSuccess + ? cc.success( "SUCCESS" ) : cc.fatal( "ERROR" ); + otherStream.write( + cc.bright( "\n--- --- --- --- --- GATHERED " ) + strSuccessPrefix + + cc.bright( " DETAILS FOR LATEST(" ) + cc.sunny( strTitle ) + + cc.bright( " action (" ) + cc.sunny( "BEGIN" ) + + cc.bright( ") --- --- ------ --- \n" ) + + this.strAccumulatedLogText + + cc.bright( "--- --- --- --- --- GATHERED " ) + strSuccessPrefix + + cc.bright( " DETAILS FOR LATEST(" ) + cc.sunny( strTitle ) + + cc.bright( " action (" ) + cc.sunny( "END" ) + + cc.bright( ") --- --- --- --- ---\n" + ) + ); + } + }; + objEntry.open(); + return objEntry; + } catch ( err ) { + } + return null; +} + +export function insertMemoryOutputStream() { + let objEntry = getStreamWithFilePath( "memory" ); + if( objEntry !== null ) + return true; + objEntry = createMemoryOutputStream(); + if( !objEntry ) + return false; + gArrStreams.push( objEntry ); + return true; +} + +export function createFileOutput( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ) { + try { + const objEntry = { + "id": gIdentifierAllocatorCounter ++, + "strPath": "" + strFilePath, + "nMaxSizeBeforeRotation": 0 + nMaxSizeBeforeRotation, + "nMaxFilesCount": 0 + nMaxFilesCount, + "objStream": null, + "haveOwnTimestamps": false, + "strOwnIndent": "", + "write": function( s ) { + const x = + this.strOwnIndent + + ( this.haveOwnTimestamps ? generateTimestampPrefix( null, true ) : "" ) + + s; + try { + this.rotate( x.length ); + fs.appendFileSync( this.objStream, x, "utf8" ); + } catch ( err ) { } + }, + "close": function() { + if( !this.objStream ) + return; + fs.closeSync( this.objStream ); + this.objStream = null; + }, + "open": function() { + this.objStream = + fs.openSync( this.strPath, "a", fs.constants.O_NONBLOCK | fs.constants.O_WR ); + }, + "size": function() { + try { return fs.lstatSync( this.strPath ).size; } catch ( err ) { return 0; } + }, + "rotate": function( nBytesToWrite ) { + try { + if( this.nMaxSizeBeforeRotation <= 0 || this.nMaxFilesCount <= 1 ) + return; + this.close(); + const nFileSize = this.size(); + const nNextSize = nFileSize + nBytesToWrite; + if( nNextSize <= this.nMaxSizeBeforeRotation ) { + this.open(); + return; + } + let i = 0; const cnt = 0 + this.nMaxFilesCount; + for( i = 0; i < cnt; ++i ) { + const j = this.nMaxFilesCount - i - 1; + const strPath = "" + this.strPath + ( ( j === 0 ) ? "" : ( "." + j ) ); + if( j == ( cnt - 1 ) ) { + try { fs.unlinkSync( strPath ); } catch ( err ) { } + continue; + } + const strPathPrev = "" + this.strPath + "." + ( j + 1 ); + try { fs.unlinkSync( strPathPrev ); } catch ( err ) { } + try { fs.renameSync( strPath, strPathPrev ); } catch ( err ) { } + } + } catch ( err ) { + } + try { + this.open(); + } catch ( err ) { + } + }, + "toString": function() { return "" + strFilePath; }, + "exposeDetailsTo": function( otherStream, strTitle, isSuccess ) { } + }; + objEntry.open(); + return objEntry; + } catch ( err ) { + console.log( + "CRITICAL ERROR: Failed to open file system log stream for " + strFilePath + + ", error is " + JSON.stringify( err ) + ); + } + return null; +} +export function insertFileOutput( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ) { + let objEntry = getStreamWithFilePath( "" + strFilePath ); + if( objEntry !== null ) + return true; + objEntry = createFileOutput( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ); + if( !objEntry ) + return false; + gArrStreams.push( objEntry ); + return true; +} + +export function write() { + let s = getPrintTimestamps() ? generateTimestampPrefix( null, true ) : "", i = 0; + try { + for( i = 0; i < arguments.length; ++i ) { + try { + s += arguments[i]; + } catch ( err ) { + } + } + } catch ( err ) { + } + try { + if( s.length <= 0 ) + return; + const cnt = gArrStreams.length; + for( i = 0; i < cnt; ++i ) { + try { + const objEntry = gArrStreams[i]; + objEntry.write( s ); + } catch ( err ) { + } + } + } catch ( err ) { + } +} + +export function removeAll() { + removeAllStreams(); +} + +export function addStdout() { + return insertStandardOutputStream(); +} + +export function addMemory() { + return insertMemoryOutputStream(); +} + +export function createMemoryStream() { + return createMemoryOutputStream(); +} + +export function add( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount ) { + return insertFileOutput( + strFilePath, + ( nMaxSizeBeforeRotation <= 0 ) ? -1 : nMaxSizeBeforeRotation, + ( nMaxFilesCount <= 1 ) ? -1 : nMaxFilesCount + ); +} + +export function close() { + // for compatibility with created streams +} + +export function exposeDetailsTo() { + // for compatibility with created streams +} + +export function toString() { + // for compatibility with created streams + return ""; +} + +const gMapVerbose = { + 0: "silent", + 1: "fatal", + 2: "critical", + 3: "error", + 4: "warning", + 5: "attention", + 6: "information", + 7: "notice", + 8: "debug", + 9: "trace" +}; +function computeVerboseAlias() { + const m = {}; + for( const key in gMapVerbose ) { + if( !gMapVerbose.hasOwnProperty( key ) ) + continue; // skip loop if the property is from prototype + const name = gMapVerbose[key]; + m[name] = parseInt( key ); + } + m.empty = 0 + parseInt( m.silent ); // alias + m.none = 0 + parseInt( m.silent ); // alias + m.stop = 0 + parseInt( m.fatal ); // alias + m.bad = 0 + parseInt( m.critical ); // alias + m.err = 0 + parseInt( m.error ); // alias + m.warn = 0 + parseInt( m.warning ); // alias + m.attn = 0 + parseInt( m.attention ); // alias + m.info = 0 + parseInt( m.information ); // alias + m.note = 0 + parseInt( m.notice ); // alias + m.dbg = 0 + parseInt( m.debug ); // alias + m.crazy = 0 + parseInt( m.trace ); // alias + m.detailed = 0 + parseInt( m.trace ); // alias + return m; +} +let gMapReversedVerbose = null; + +export function verbose() { return gMapVerbose; } +export function verboseReversed() { + if( ! gMapReversedVerbose ) + gMapReversedVerbose = computeVerboseAlias(); + return gMapReversedVerbose; +} +export function verboseLevelAsTextForLog( vl ) { + if( typeof vl == "undefined" ) + vl = verboseGet(); + if( vl in gMapVerbose ) { + const tl = gMapVerbose[vl]; + return tl; + } + return "unknown(" + JSON.stringify( y ) + ")"; +} + +let gFlagIsExposeDetails = false; +let gVerboseLevel = 0 + verboseReversed().information; + +export function exposeDetailsGet() { + return gFlagIsExposeDetails ? true : false; +} +export function exposeDetailsSet( isExpose ) { + gFlagIsExposeDetails = isExpose ? true : false; +} + +export function verboseGet() { + return 0 + gVerboseLevel; +} +export function verboseSet( vl ) { + gVerboseLevel = parseInt( vl ); +} + +export function verboseParse( s ) { + let n = 5; + try { + const isNumbersOnly = /^\d+$/.test( s ); + if( isNumbersOnly ) + n = cc.toInteger( s ); + else { + const ch0 = s[0].toLowerCase(); + for( const key in gMapVerbose ) { + if( !gMapVerbose.hasOwnProperty( key ) ) + continue; // skip loop if the property is from prototype + const name = gMapVerbose[key]; + const ch1 = name[0].toLowerCase(); + if( ch0 == ch1 ) { + n = key; + return n; + } + } + } + } catch ( err ) { } + return n; +} + +export function verboseList() { + for( const key in gMapVerbose ) { + if( !gMapVerbose.hasOwnProperty( key ) ) + continue; // skip loop if the property is from prototype + const name = gMapVerbose[key]; + console.log( " " + cc.info( key ) + cc.sunny( "=" ) + cc.bright( name ) ); + } +} diff --git a/npms/skale-observer/README.md b/npms/skale-observer/README.md index 19c60cc3a..a4b24fec1 100644 --- a/npms/skale-observer/README.md +++ b/npms/skale-observer/README.md @@ -2,7 +2,7 @@ ## General Description -**SKALE Network Browser** (**SNB**) or **SKALE Observer** is part of IMA resposible for providing description of all SKALE chains. This is done via set of calls to **SKALE Mananger**. +**SKALE Network Browser** (**SNB**) or **SKALE Observer** is part of IMA responsible for providing description of all SKALE chains. This is done via set of calls to **SKALE Manager**. **SNB** maintains cache of S-Chain descriptions and refreshes all descriptions periodically. These descriptions and needed for S-Chain to S-Chain IMA message transfers when IMA needs to know how to connect to other S-Chain. @@ -12,15 +12,13 @@ First SKALE network scan is performed by **SNB** on IMA startup. Next network de ## Implementation details -The `SchainsInternal.numberOfSchains` contract call returns number of created S-Chains to load from **SKALE Mananger**. For each of S-Chains we need to get its hash by index what is done `SchainsInternal.schainsAtSystem` contract call. Then contract call to `SchainsInternal.schains` returns basic S-Chain description by hash. Obtained basic S-Chain description does not describe nodes and they must be loaded via set of contract calls. The `SchainsInternal.getNodesInGroup` contract call returns array of node identifiers for all S-Chain nodes. The `Nodes.nodes` contract call returns node description by node id. Returned node description includes IP adderess, domain name and, base port of a node, maintanance state flag. Then call to `SchainsInternal.getSchainIdsForNode` contract call allows to find effective node base port and compute per-protocol ports (`http`, `https`, `ws`, `wss`). +The `SchainsInternal.numberOfSchains` contract call returns number of created S-Chains to load from **SKALE Manager**. For each of S-Chains we need to get its hash by index what is done `SchainsInternal.schainsAtSystem` contract call. Then contract call to `SchainsInternal.schains` returns basic S-Chain description by hash. Obtained basic S-Chain description does not describe nodes and they must be loaded via set of contract calls. The `SchainsInternal.getNodesInGroup` contract call returns array of node identifiers for all S-Chain nodes. The `Nodes.nodes` contract call returns node description by node id. Returned node description includes IP address, domain name and, base port of a node, maintenance state flag. Then call to `SchainsInternal.getSchainHashesForNode` contract call allows to find effective node base port and compute per-protocol ports (`http`, `https`, `ws`, `wss`). Cache of S-Chain descriptions is result of download process described above. When new S-Chain descriptions are downloaded, they replace old ones. By default this is performed once in an hour. S-Chain descriptions directly affect on S-Chain to S-Chain transfers because they contain JSON RPC URLs of all `skaled`s of all S-Chains. -**SNB** can be invoked from command line of IMA agent in one of the following ways - - The`--browse-skale-network` command line options invokes download entire SKALE network description, all S-Chains, all `skaled` nodes. - - The `--browse-connected-schains` command line options invokes download of which are S-Chains conected to S-Chain with name specified in `--id-s-chain` command line parameter. +**SNB** can be invoked from command line of IMA agent using `--browse-skale-network` or `--browse-connected-schains` command line options. The`--browse-skale-network` command line options invokes download entire SKALE network description, all S-Chains, all `skaled` nodes. The `--browse-connected-schains` command line options invokes download of which are S-Chains connected to S-Chain with name specified in `--id-s-chain` command line parameter. Example of **SNB** invocation: @@ -39,7 +37,7 @@ node agent/main.js --colors --browse-skale-network \ --key-s-chain=... ``` -Example of downloaded S-Chains description containg 2 S-Chains named `Bob1000` and `Bob1001`, 2 `skaled` nodes each: +Example of downloaded S-Chains description containing 2 S-Chains named `Bob1000` and `Bob1001`, 2 `skaled` nodes each: ```json [ diff --git a/npms/skale-observer/observer.js b/npms/skale-observer/observer.js deleted file mode 100644 index 21b702d86..000000000 --- a/npms/skale-observer/observer.js +++ /dev/null @@ -1,655 +0,0 @@ - -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * SKALE IMA is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * SKALE IMA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with SKALE IMA. If not, see . - */ - -/** - * @file observer.js - * @copyright SKALE Labs 2019-Present - */ - -const network_layer = require( "../skale-cool-socket/socket.js" ); -const { Worker } = require( "worker_threads" ); -const path = require( "path" ); - -const owaspUtils = require( "../skale-owasp/owasp-util.js" ); -const cc = owaspUtils.cc; - -const w3mod = require( "web3" ); -// const ethereumjs_tx = require( "ethereumjs-tx" ); -// const ethereumjs_wallet = require( "ethereumjs-wallet" ); -// const ethereumjs_util = require( "ethereumjs-util" ); - -const PORTS_PER_SCHAIN = 64; - -function getWeb3FromURL( strURL, log ) { - let w3 = null; - log = log || { write: console.log }; - try { - const u = cc.safeURL( strURL ); - const strProtocol = u.protocol.trim().toLowerCase().replace( ":", "" ).replace( "/", "" ); - if( strProtocol == "ws" || strProtocol == "wss" ) { - const w3ws = new w3mod.providers.WebsocketProvider( strURL, { - // see: https://github.com/ChainSafe/web3.js/tree/1.x/packages/web3-providers-ws#usage - clientConfig: { - // // if requests are large: - // maxReceivedFrameSize: 100000000, // bytes - default: 1MiB - // maxReceivedMessageSize: 100000000, // bytes - default: 8MiB - // keep a connection alive - keepalive: true, - keepaliveInterval: 200000 // ms - }, - reconnect: { // enable auto reconnection - auto: true, - delay: 5000, // ms - maxAttempts: 10000000, // 10 million times - onTimeout: false - } - } ); - w3 = new w3mod( w3ws ); - } else { - const w3http = new w3mod.providers.HttpProvider( strURL ); - w3 = new w3mod( w3http ); - } - } catch ( err ) { - log.write( cc.fatal( "CRITICAL ERROR:" ) + cc.error( " Failed to create " ) + - cc.attention( "Web3" ) + cc.error( " connection to " ) + cc.info( strURL ) + - cc.error( ": " ) + cc.warning( err.toString() ) ); - w3 = null; - } - return w3; -} - -function get_schain_index_in_node( schain_id, schains_ids_on_node ) { - let i = 0; - for( const schain_id_on_node of schains_ids_on_node ) { - if( schain_id == schain_id_on_node ) - return i; - ++ i; - } - throw new Error( "S-Chain " + schain_id + " is not found in the list: " + JSON.stringify( schains_ids_on_node ) ); -} - -function get_schain_base_port_on_node( schain_id, schains_ids_on_node, node_base_port ) { - const schain_index = get_schain_index_in_node( schain_id, schains_ids_on_node ); - return calc_schain_base_port( node_base_port, schain_index ); -} - -function calc_schain_base_port( node_base_port, schain_index ) { - return parseInt( node_base_port ) + parseInt( schain_index ) * PORTS_PER_SCHAIN; -} - -function compose_endpoints( jo_schain, node_dict, endpoint_type ) { - node_dict["http_endpoint_" + endpoint_type] = "http://" + node_dict[endpoint_type] + ":" + jo_schain.data.computed.ports.httpRpcPort; - node_dict["https_endpoint_" + endpoint_type] = "https://" + node_dict[endpoint_type] + ":" + jo_schain.data.computed.ports.httpsRpcPort; - node_dict["ws_endpoint_" + endpoint_type] = "ws://" + node_dict[endpoint_type] + ":" + jo_schain.data.computed.ports.wsRpcPort; - node_dict["wss_endpoint_" + endpoint_type] = "wss://" + node_dict[endpoint_type] + ":" + jo_schain.data.computed.ports.wssRpcPort; - node_dict["info_http_endpoint_" + endpoint_type] = "http://" + node_dict[endpoint_type] + ":" + jo_schain.data.computed.ports.infoHttpRpcPort; -} - -const SkaledPorts = { - PROPOSAL: 0, - CATCHUP: 1, - WS_JSON: 2, - HTTP_JSON: 3, - BINARY_CONSENSUS: 4, - ZMQ_BROADCAST: 5, - IMA_MONITORING: 6, - WSS_JSON: 7, - HTTPS_JSON: 8, - INFO_HTTP_JSON: 9 -}; - -function calc_ports( jo_schain, schain_base_port ) { - // TO-DO: these temporary port values should be in "node", not in "schain" - jo_schain.data.computed.ports = { - httpRpcPort: schain_base_port + SkaledPorts.HTTP_JSON, - httpsRpcPort: schain_base_port + SkaledPorts.HTTPS_JSON, - wsRpcPort: schain_base_port + SkaledPorts.WS_JSON, - wssRpcPort: schain_base_port + SkaledPorts.WSS_JSON, - infoHttpRpcPort: schain_base_port + SkaledPorts.INFO_HTTP_JSON - }; -} - -// see https://github.com/skalenetwork/skale-proxy/blob/develop/endpoints.py -async function load_schain_parts( w3, jo_schain, addressFrom, opts ) { - if( ! opts.imaState ) - throw new Error( "Cannot load S-Chain parts in observer, no imaState is provided" ); - jo_schain.data.computed = {}; - const schain_id = w3.utils.soliditySha3( jo_schain.data.name ); - const chainId = owaspUtils.compute_chain_id_from_schain_name( w3, jo_schain.data.name ); - const node_ids = await opts.imaState.jo_schains_internal.methods.getNodesInGroup( schain_id ).call( { from: addressFrom } ); - const nodes = []; - for( const node_id of node_ids ) { - if( opts && opts.bStopNeeded ) - return; - const node = await opts.imaState.jo_nodes.methods.nodes( node_id ).call( { from: addressFrom } ); - const node_dict = { - id: node_id, - name: node[0], - ip: owaspUtils.ip_from_hex( node[1] ), - base_port: node[3], - domain: await opts.imaState.jo_nodes.methods.getNodeDomainName( node_id ).call( { from: addressFrom } ), - isMaintenance: await opts.imaState.jo_nodes.methods.isNodeInMaintenance( node_id ).call( { from: addressFrom } ) - }; - if( opts && opts.bStopNeeded ) - return; - const schain_ids = await opts.imaState.jo_schains_internal.methods.getSchainHashesForNode( node_id ).call( { from: addressFrom } ); - node_dict.schain_base_port = get_schain_base_port_on_node( schain_id, schain_ids, node_dict.base_port ); - calc_ports( jo_schain, node_dict.schain_base_port ); - compose_endpoints( jo_schain, node_dict, "ip" ); - compose_endpoints( jo_schain, node_dict, "domain" ); - nodes.push( node_dict ); - if( opts && opts.bStopNeeded ) - return; - } - // const schain = await opts.imaState.jo_schains_internal.methods.schains( schain_id ).call( { from: addressFrom } ); - // jo_schain.data.computed.schain = schain; - jo_schain.data.computed.schain_id = schain_id; - jo_schain.data.computed.chainId = chainId; - jo_schain.data.computed.nodes = nodes; -} - -async function get_schains_count( w3, addressFrom, opts ) { - if( ! opts.imaState ) - throw new Error( "Cannot get S-Chains count, no imaState is provided" ); - const cntSChains = await opts.imaState.jo_schains_internal.methods.numberOfSchains().call( { from: addressFrom } ); - return cntSChains; -} - -function remove_schain_desc_data_num_keys( jo_schain ) { - const cnt = Object.keys( jo_schain ).length; - for( let i = 0; i < cnt; ++ i ) { - try { - delete jo_schain[i]; - } catch ( err ) { - } - } -} - -async function load_schain( w3, addressFrom, idxSChain, hash, cntSChains, opts ) { - if( ! opts.imaState ) - throw new Error( "Cannot load S-Chain description in observer, no imaState is provided" ); - if( opts && opts.details ) - opts.details.write( cc.debug( "Loading S-Chain " ) + cc.notice( "#" ) + cc.info( idxSChain + 1 ) + cc.debug( " of " ) + cc.info( cntSChains ) + cc.debug( "..." ) + "\n" ); - hash = hash || await opts.imaState.jo_schains_internal.methods.schainsAtSystem( idxSChain ).call( { from: addressFrom } ); - if( opts && opts.details ) - opts.details.write( cc.debug( " Hash " ) + cc.attention( hash ) + "\n" ); - if( opts && opts.bStopNeeded ) - return null; - let jo_data = await opts.imaState.jo_schains_internal.methods.schains( hash ).call( { from: addressFrom } ); - jo_data = JSON.parse( JSON.stringify( jo_data ) ); - const jo_schain = { data: jo_data }; - remove_schain_desc_data_num_keys( jo_schain.data, addressFrom ); - if( opts && opts.bStopNeeded ) - return null; - await load_schain_parts( w3, jo_schain, addressFrom, opts ); - if( opts && opts.details ) { - opts.details.write( cc.debug( " Desc " ) + cc.j( jo_schain.data ) + "\n" ); - opts.details.write( cc.success( "Done" ) + "\n" ); - } - jo_schain.isConnected = false; - return jo_schain; -} - -async function load_schains( w3, addressFrom, opts ) { - if( ! opts.imaState ) - throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); - const cntSChains = await get_schains_count( w3, addressFrom, opts ); - if( opts && opts.details ) - opts.details.write( cc.debug( "Have " ) + cc.info( cntSChains ) + cc.debug( " S-Chain(s) to load..." ) + "\n" ); - const arr_schains = []; - for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { - if( opts && opts.bStopNeeded ) - break; - const jo_schain = await load_schain( w3, addressFrom, idxSChain, null, cntSChains, opts ); - if( ! jo_schain ) - break; - arr_schains.push( jo_schain ); - } - if( opts && opts.details ) { - opts.details.write( - cc.success( "All " ) + cc.info( cntSChains ) + - cc.debug( " S-Chain(s) loaded:" ) + cc.j( arr_schains ) + - "\n" ); - } - return arr_schains; -} - -async function load_cached_schains_simplified( w3, addressFrom, opts ) { - if( ! opts.imaState ) - throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); - if( opts && opts.details ) - opts.details.write( cc.debug( "Will request all S-Chain(s) hashes..." ) + "\n" ); - const arrSChainHashes = await opts.imaState.jo_schains_internal.methods.getSchains().call( { from: addressFrom } ); - const cntSChains = arrSChainHashes.length; - if( opts && opts.details ) - opts.details.write( cc.debug( "Have all " ) + cc.info( cntSChains ) + cc.debug( " S-Chain(s) hashes: " ) + cc.j( arrSChainHashes ) + "\n" ); - const arr_schains = []; - for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { - if( opts && opts.bStopNeeded ) - break; - const strSChainHash = arrSChainHashes[idxSChain]; - const strSChainName = await opts.imaState.jo_schains_internal.methods.getSchainName( strSChainHash ).call( { from: addressFrom } ); - if( opts && opts.details ) - opts.details.write( cc.debug( "S-Chain " ) + cc.notice( idxSChain ) + cc.debug( " hash " ) + cc.notice( strSChainHash ) + cc.debug( " corresponds to S-Chain name " ) + cc.notice( strSChainName ) + "\n" ); - if( opts && opts.bStopNeeded ) - break; - const jo_schain = await load_schain( w3, addressFrom, idxSChain, strSChainHash, cntSChains, opts ); - if( ! jo_schain ) - break; - arr_schains.push( jo_schain ); - } - return arr_schains; -} - -async function load_schains_connected_only( w3_main_net, w3_s_chain, strChainNameConnectedTo, addressFrom, opts ) { - if( ! opts.imaState ) - throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); - if( opts && opts.details ) - opts.details.write( cc.debug( "Will request all S-Chain(s) hashes..." ) + "\n" ); - const arrSChainHashes = await opts.imaState.jo_schains_internal.methods.getSchains().call( { from: addressFrom } ); - const cntSChains = arrSChainHashes.length; - if( opts && opts.details ) - opts.details.write( cc.debug( "Have all " ) + cc.info( cntSChains ) + cc.debug( " S-Chain(s) hashes: " ) + cc.j( arrSChainHashes ) + "\n" ); - const jo_message_proxy_s_chain = - new w3_s_chain.eth.Contract( - opts.imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, - opts.imaState.joAbiPublishResult_s_chain.message_proxy_chain_address - ); - const arr_schains = []; - for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { - try { - if( opts && opts.bStopNeeded ) - break; - const strSChainHash = arrSChainHashes[idxSChain]; - const strSChainName = await opts.imaState.jo_schains_internal.methods.getSchainName( strSChainHash ).call( { from: addressFrom } ); - if( opts && opts.details ) - opts.details.write( cc.debug( "S-Chain " ) + cc.notice( idxSChain ) + cc.debug( " hash " ) + cc.notice( strSChainHash ) + cc.debug( " corresponds to S-Chain name " ) + cc.notice( strSChainName ) + "\n" ); - if( opts && opts.bStopNeeded ) - break; - // - if( strChainNameConnectedTo == strSChainName ) { - if( opts && opts.details ) - opts.details.write( cc.debug( "Skip this S-Chain " ) + cc.info( strSChainName ) + cc.debug( " connected status check" ) + "\n" ); - continue; - } - if( opts && opts.details ) { - opts.details.write( - cc.debug( "Querying connected status between S-Chain " ) + cc.info( strSChainName ) + cc.debug( " and S-Chain " ) + - cc.info( strChainNameConnectedTo ) + cc.debug( "..." ) + "\n" ); - } - const isConnected = await jo_message_proxy_s_chain.methods.isConnectedChain( strSChainName ).call( { from: addressFrom } ); - if( opts && opts.details ) - opts.details.write( cc.debug( "Got S-Chain " ) + cc.info( strSChainName ) + cc.debug( " connected status: " ) + cc.yn( isConnected ) + "\n" ); - if( ! isConnected ) - continue; - const jo_schain = await load_schain( w3_main_net, addressFrom, idxSChain, strSChainHash, cntSChains, opts ); - if( ! jo_schain ) - break; - jo_schain.isConnected = true; - arr_schains.push( jo_schain ); - } catch ( err ) { - if( opts && opts.details ) { - opts.details.write( cc.error( "Got error: " ) + cc.warning( err.toString() ) + "\n" ); - opts.details.write( err.stack ); - } - } - } - return arr_schains; -} - -async function check_connected_schains( strChainNameConnectedTo, arr_schains, addressFrom, opts ) { - if( ! opts.imaState ) - throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); - const cntSChains = arr_schains.length; - for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { - if( opts && opts.bStopNeeded ) - break; - const jo_schain = arr_schains[idxSChain]; - jo_schain.isConnected = false; - if( jo_schain.data.name == strChainNameConnectedTo ) - continue; - try { - const url = pick_random_schain_w3_url( jo_schain ); - if( opts && opts.details ) { - opts.details.write( - cc.debug( "Querying via URL " ) + cc.u( url ) + cc.debug( " to S-Chain " ) + - cc.info( jo_schain.data.name ) + cc.debug( " whether it's connected to S-Chain " ) + - cc.info( strChainNameConnectedTo ) + cc.debug( "..." ) + "\n" ); - } - const w3 = getWeb3FromURL( url, opts.details ); - const jo_message_proxy_s_chain = new w3.eth.Contract( opts.imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, opts.imaState.joAbiPublishResult_s_chain.message_proxy_chain_address ); - jo_schain.isConnected = await jo_message_proxy_s_chain.methods.isConnectedChain( strChainNameConnectedTo ).call( { from: addressFrom } ); - if( opts && opts.details ) { - opts.details.write( - cc.debug( "Got " ) + cc.yn( jo_schain.isConnected ) + "\n" ); - } - } catch ( err ) { - if( opts && opts.details ) { - opts.details.write( cc.error( "Got error: " ) + cc.warning( err.toString() ) + "\n" ); - opts.details.write( err.stack ); - } - } - } - return arr_schains; -} - -async function filter_schains_marked_as_connected( arr_schains, opts ) { - const arr_connected_schains = []; - const cntSChains = arr_schains.length; - for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { - if( opts && opts.bStopNeeded ) - break; - const jo_schain = arr_schains[idxSChain]; - if( jo_schain.isConnected ) - arr_connected_schains.push( jo_schain ); - } - return arr_connected_schains; -} - -function find_schain_index_in_array_by_name( arr_schains, strSChainName ) { - for( let idxSChain = 0; idxSChain < arr_schains.length; ++ idxSChain ) { - const jo_schain = arr_schains[idxSChain]; - if( jo_schain.data.name.toString() == strSChainName.toString() ) - return idxSChain; - } - return -1; -} - -function merge_schains_array_from_to( arrSrc, arrDst, arrNew, arrOld, opts ) { - arrNew.splice( 0, arrNew.length ); - arrOld.splice( 0, arrOld.length ); - let i, j, cnt; - cnt = arrSrc.length; - if( opts && opts.details ) - opts.details.write( cc.debug( "Before merging, have " ) + cc.info( cnt ) + cc.debug( " S-Chain(s) to review" ) + "\n" ); - for( i = 0; i < cnt; ++ i ) { - const jo_schain = arrSrc[i]; - j = find_schain_index_in_array_by_name( arrDst, jo_schain.data.name ); - if( j < 0 ) { - if( opts && opts.details ) - opts.details.write( cc.debug( "Found new " ) + cc.notice( "#" ) + cc.info( i + 1 ) + cc.debug( " S-Chain " ) + cc.j( jo_schain ) + "\n" ); - arrNew.push( jo_schain ); - } - } - if( opts && opts.details ) - opts.details.write( cc.debug( "Summary, found new " ) + cc.info( arrNew.length ) + cc.debug( " S-Chain(s)" ) + "\n" ); - cnt = arrDst.length; - for( i = 0; i < cnt; ++ i ) { - const jo_schain = arrDst[i]; - j = find_schain_index_in_array_by_name( arrSrc, jo_schain.data.name ); - if( j < 0 ) { - if( opts && opts.details ) - opts.details.write( cc.debug( "Found old S-Chain " ) + cc.notice( "#" ) + cc.info( i + 1 ) + cc.debug( " " ) + cc.j( jo_schain ) + "\n" ); - arrOld.push( jo_schain ); - } - } - if( opts && opts.details ) - opts.details.write( cc.debug( "Summary, found old " ) + cc.info( arrOld.length ) + cc.debug( " S-Chain(s)" ) + "\n" ); - if( arrNew.length > 0 ) { - if( opts && opts.details ) - opts.details.write( cc.debug( "Merging new " ) + cc.info( arrNew.length ) + cc.debug( " S-Chain(s)" ) + "\n" ); - for( i = 0; i < arrNew.length; ++ i ) { - const jo_schain = arrNew[i]; - arrDst.push( jo_schain ); - } - if( opts && opts.details ) - opts.details.write( cc.success( "Done" ) + "\n" ); - } - if( arrOld.length > 0 ) { - if( opts && opts.details ) - opts.details.write( cc.debug( "Removing old " ) + cc.info( arrOld.length ) + cc.debug( " S-Chain(s)" ) + "\n" ); - for( i = 0; i < arrOld.length; ++ i ) { - const jo_schain = arrOld[i]; - j = find_schain_index_in_array_by_name( arrDst, jo_schain.data.name ); - arrDst.splice( j, 1 ); - } - if( opts && opts.details ) - opts.details.write( cc.success( "Done" ) + "\n" ); - } - if( opts && opts.details ) - opts.details.write( cc.success( "Finally, have " ) + cc.info( arrDst.length ) + cc.success( " S-Chain(s)" ) + "\n" ); -} - -let g_arr_schains_cached = []; - -async function cache_schains( strChainNameConnectedTo, w3_main_net, w3_s_chain, addressFrom, opts ) { - let strError = null; - try { - let arr_schains = []; - if( strChainNameConnectedTo && ( typeof strChainNameConnectedTo == "string" ) && strChainNameConnectedTo.length > 0 ) { - arr_schains = await load_schains_connected_only( - w3_main_net, - w3_s_chain, - strChainNameConnectedTo, - addressFrom, - opts - ); - } else - arr_schains = await load_schains( w3_main_net, addressFrom, opts ); - - g_arr_schains_cached = arr_schains; - - if( opts && opts.details ) { - opts.details.write( - cc.debug( "Connected " ) + cc.attention( "S-Chains" ) + cc.debug( " cache was updated in this thread: " ) + - cc.j( g_arr_schains_cached ) + "\n" ); - } - if( opts.fn_chache_changed ) - opts.fn_chache_changed( g_arr_schains_cached, null ); // null - no error - } catch ( err ) { - strError = err.toString(); - if( ! strError ) - strError = "unknown exception during S-Chains download"; - if( opts.fn_chache_changed ) - opts.fn_chache_changed( g_arr_schains_cached, strError ); - if( opts && opts.details ) { - opts.details.write( cc.fatal( "ERROR:" ) + cc.error( " Failed to cache: " ) + cc.error( err ) + "\n" ); - opts.details.write( err.stack ); - } - } - return strError; // null on success -} - -function get_last_cached_schains() { - return JSON.parse( JSON.stringify( g_arr_schains_cached ) ); -} - -const impl_sleep = ( milliseconds ) => { return new Promise( resolve => setTimeout( resolve, milliseconds ) ); }; - -let g_worker = null; -let g_client = null; - -async function ensure_have_worker( opts ) { - if( g_worker ) - return g_worker; - const url = "skale_observer_worker_server"; - g_worker = new Worker( path.join( __dirname, "observer_worker.js" ) ); - // console.log( "Will connect to " + url ); - g_worker.on( "message", jo => { - if( network_layer.out_of_worker_apis.on_message( g_worker, jo ) ) - return; - } ); - g_client = new network_layer.OutOfWorkerSocketClientPipe( url, g_worker ); - g_client.on( "message", function( eventData ) { - const joMessage = eventData.message; - // console.log( "CLIENT <<<", JSON.stringify( joMessage ) ); - switch ( joMessage.method ) { - case "periodic_caching_do_now": - g_arr_schains_cached = joMessage.message; - if( opts && opts.details ) { - opts.details.write( - cc.debug( "Connected " ) + cc.attention( "S-Chains" ) + - cc.debug( " cache was updated using data arrived from SNB worker: " ) + - cc.j( g_arr_schains_cached ) + "\n" ); - } - break; - case "log": - log.write( cc.attention( "SNB WORKER" ) + " " + joMessage.message ); - break; - } // switch ( joMessage.method ) - } ); - await impl_sleep( 1000 ); - const jo = { - method: "init", - message: { - opts: { - imaState: { - "joAbiPublishResult_skale_manager": opts.imaState.joAbiPublishResult_skale_manager, - "joAbiPublishResult_main_net": opts.imaState.joAbiPublishResult_main_net, - "joAbiPublishResult_s_chain": opts.imaState.joAbiPublishResult_s_chain, - "bHaveSkaleManagerABI": opts.imaState.bHaveSkaleManagerABI, - "bHaveImaAbiMainNet": opts.imaState.bHaveImaAbiMainNet, - "bNoWaitSChainStarted": opts.imaState.bNoWaitSChainStarted, - "nMaxWaitSChainAttempts": opts.imaState.nMaxWaitSChainAttempts, - "strURL_main_net": opts.imaState.strURL_main_net, - "strChainName_main_net": opts.imaState.strChainName_main_net, - "cid_main_net": opts.imaState.cid_main_net, - "strURL_s_chain": opts.imaState.strURL_s_chain, - "strChainName_s_chain": opts.imaState.strChainName_s_chain, - "cid_s_chain": opts.imaState.cid_s_chain, - "nNodeNumber": opts.imaState.nNodeNumber, // S-Chain node number(zero based) - "nNodesCount": opts.imaState.nNodesCount, - "nTimeFrameSeconds": opts.imaState.nTimeFrameSeconds, // 0-disable, 60-recommended - "nNextFrameGap": opts.imaState.nNextFrameGap, - "joAccount_main_net": { - "privateKey": opts.imaState.joAccount_main_net.privateKey, - // "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": opts.imaState.joAccount_main_net.strTransactionManagerURL, - "tm_priority": opts.imaState.joAccount_main_net.tm_priority, - "strSgxURL": opts.imaState.joAccount_main_net.strSgxURL, - "strSgxKeyName": opts.imaState.joAccount_main_net.strSgxKeyName, - "strPathSslKey": opts.imaState.joAccount_main_net.strPathSslKey, - "strPathSslCert": opts.imaState.joAccount_main_net.strPathSslCert - }, - "joAccount_s_chain": { - "privateKey": opts.imaState.joAccount_s_chain.privateKey, - // "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": opts.imaState.joAccount_s_chain.strTransactionManagerURL, - "tm_priority": opts.imaState.joAccount_s_chain.tm_priority, - "strSgxURL": opts.imaState.joAccount_s_chain.strSgxURL, - "strSgxKeyName": opts.imaState.joAccount_s_chain.strSgxKeyName, - "strPathSslKey": opts.imaState.joAccount_s_chain.strPathSslKey, - "strPathSslCert": opts.imaState.joAccount_s_chain.strPathSslCert - }, - // "tc_main_net": IMA.tc_main_net, - // "tc_s_chain": IMA.tc_s_chain, - // "doEnableDryRun": function( isEnable ) { return IMA.dry_run_enable( isEnable ); }, - // "doIgnoreDryRun": function( isIgnore ) { return IMA.dry_run_ignore( isIgnore ); }, - "joSChainDiscovery": { - "isSilentReDiscovery": opts.imaState.joSChainDiscovery.isSilentReDiscovery, - "repeatIntervalMilliseconds": opts.imaState.joSChainDiscovery.repeatIntervalMilliseconds // zero to disable (for debugging only) - } - } - }, - "cc": { - "isEnabled": cc.isEnabled() - } - } - }; - g_client.send( jo ); -} - -async function periodic_caching_start( strChainNameConnectedTo, w3_main_net, w3_s_chain, addressFrom, opts ) { - await ensure_have_worker( opts ); - const jo = { - method: "periodic_caching_start", - message: { - secondsToReDiscoverSkaleNetwork: parseInt( opts.secondsToReDiscoverSkaleNetwork ), - strChainNameConnectedTo: strChainNameConnectedTo, - addressFrom: addressFrom - } - }; - g_client.send( jo ); -} -async function periodic_caching_stop() { - await ensure_have_worker( opts ); - const jo = { - method: "periodic_caching_stop", - message: { - } - }; - g_client.send( jo ); -} - -function pick_random_schain_node_index( jo_schain ) { - let min = 0, max = jo_schain.data.computed.nodes.length - 1; - min = Math.ceil( min ); - max = Math.floor( max ); - const idxNode = Math.floor( Math.random() * ( max - min + 1 ) ) + min; - return idxNode; -} -function pick_random_schain_node( jo_schain ) { - const idxNode = pick_random_schain_node_index( jo_schain ); - return jo_schain.data.computed.nodes[idxNode]; -} - -function pick_random_schain_w3_url( jo_schain ) { - const jo_node = pick_random_schain_node( jo_schain ); - return "" + jo_node.http_endpoint_ip; -} - -async function discover_chain_id( strURL ) { - let ret = null; - const rpcCallOpts = null; - await rpcCall.create( strURL, rpcCallOpts, async function( joCall, err ) { - if( err ) { - //ret = "Failed to create RPC (" + strURL + ") call: " + err.toString(); - return; - } - await joCall.call( { - "method": "eth_chainId", - "params": [] - }, async function( joIn, joOut, err ) { - if( err ) { - //ret = "Failed to query RPC (" + strURL + ") for chain ID: " + err.toString(); - return; - } - if( ! ( "result" in joOut && joOut.result ) ) { - //ret = "Failed to query RPC (" + strURL + ") for chain ID, got bad result: " + JSON.stringify( joOut ); - return; - } - ret = joOut.result; - } ); // joCall.call ... - } ); // rpcCall.create ... - return ret; -} - -module.exports.w3mod = w3mod; -module.exports.getWeb3FromURL = getWeb3FromURL; -module.exports.owaspUtils = owaspUtils; -module.exports.cc = cc; -module.exports.get_schains_count = get_schains_count; -module.exports.load_schain = load_schain; -module.exports.load_schains = load_schains; -module.exports.load_cached_schains_simplified = load_cached_schains_simplified; -module.exports.load_schains_connected_only = load_schains_connected_only; -module.exports.check_connected_schains = check_connected_schains; -module.exports.filter_schains_marked_as_connected = filter_schains_marked_as_connected; -module.exports.find_schain_index_in_array_by_name = find_schain_index_in_array_by_name; -module.exports.merge_schains_array_from_to = merge_schains_array_from_to; -module.exports.cache_schains = cache_schains; -module.exports.get_last_cached_schains = get_last_cached_schains; -module.exports.periodic_caching_start = periodic_caching_start; -module.exports.periodic_caching_stop = periodic_caching_stop; -module.exports.pick_random_schain_node_index = pick_random_schain_node_index; -module.exports.pick_random_schain_node = pick_random_schain_node; -module.exports.pick_random_schain_w3_url = pick_random_schain_w3_url; -module.exports.discover_chain_id = discover_chain_id; diff --git a/npms/skale-observer/observer.mjs b/npms/skale-observer/observer.mjs new file mode 100644 index 000000000..a914f82ab --- /dev/null +++ b/npms/skale-observer/observer.mjs @@ -0,0 +1,1260 @@ + +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file observer.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as path from "path"; +import * as url from "url"; +import * as networkLayer from "../skale-cool-socket/socket.mjs"; +import { Worker } from "worker_threads"; +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as cc from "../skale-cc/cc.mjs"; +import * as log from "../skale-log/log.mjs"; +import * as rpcCall from "../../agent/rpcCall.mjs"; + +import { UniversalDispatcherEvent, EventDispatcher } + from "../skale-cool-socket/eventDispatcher.mjs"; + +import * as EMC from "ethereum-multicall"; + +const __dirname = path.dirname( url.fileURLToPath( import.meta.url ) ); + +let gIntervalPeriodicCaching = null; +let gFlagHaveParallelResult = false; + +const PORTS_PER_SCHAIN = 64; + +export const events = new EventDispatcher(); + +export function getSChainIndexInNode( computedSChainId, arrChainIdsOnNode ) { + let i = 0; + for( const chainIdOnNode of arrChainIdsOnNode ) { + if( computedSChainId == chainIdOnNode ) + return i; + ++ i; + } + throw new Error( + "S-Chain " + computedSChainId + " is not found in the list: " + + JSON.stringify( arrChainIdsOnNode ) ); +} + +export function getSChainBasePortOnNode( computedSChainId, arrChainIdsOnNode, basePortOfNode ) { + const indexOfSChain = getSChainIndexInNode( computedSChainId, arrChainIdsOnNode ); + return calcSChainBasePort( basePortOfNode, indexOfSChain ); +} + +export function calcSChainBasePort( basePortOfNode, indexOfSChain ) { + return parseInt( basePortOfNode ) + parseInt( indexOfSChain ) * PORTS_PER_SCHAIN; +} + +export function composeEndPoints( joSChain, nodeDict, strEndPointType ) { + nodeDict["http_endpoint_" + strEndPointType] = + "http://" + nodeDict[strEndPointType] + ":" + joSChain.data.computed.ports.httpRpcPort; + nodeDict["https_endpoint_" + strEndPointType] = + "https://" + nodeDict[strEndPointType] + ":" + joSChain.data.computed.ports.httpsRpcPort; + nodeDict["ws_endpoint_" + strEndPointType] = + "ws://" + nodeDict[strEndPointType] + ":" + joSChain.data.computed.ports.wsRpcPort; + nodeDict["wss_endpoint_" + strEndPointType] = + "wss://" + nodeDict[strEndPointType] + ":" + joSChain.data.computed.ports.wssRpcPort; + nodeDict["info_http_endpoint_" + strEndPointType] = + "http://" + nodeDict[strEndPointType] + ":" + joSChain.data.computed.ports.infoHttpRpcPort; + nodeDict["ima_agent_endpoint_" + strEndPointType] = + "http://" + nodeDict[strEndPointType] + ":" + joSChain.data.computed.ports.imaAgentRpcPort; +} + +export const SkaledPorts = { + PROPOSAL: 0, + CATCHUP: 1, + WS_JSON: 2, + HTTP_JSON: 3, + BINARY_CONSENSUS: 4, + ZMQ_BROADCAST: 5, + IMA_MONITORING: 6, + WSS_JSON: 7, + HTTPS_JSON: 8, + INFO_HTTP_JSON: 9, + IMA_AGENT_JSON: 10 +}; + +export function calcPorts( joSChain, basePortOfSChain ) { + // TO-DO: these temporary port values should be in "node", not in "schain" + joSChain.data.computed.ports = { + httpRpcPort: basePortOfSChain + SkaledPorts.HTTP_JSON, + httpsRpcPort: basePortOfSChain + SkaledPorts.HTTPS_JSON, + wsRpcPort: basePortOfSChain + SkaledPorts.WS_JSON, + wssRpcPort: basePortOfSChain + SkaledPorts.WSS_JSON, + infoHttpRpcPort: basePortOfSChain + SkaledPorts.INFO_HTTP_JSON, + imaAgentRpcPort: basePortOfSChain + SkaledPorts.IMA_AGENT_JSON + }; +} + +const gArrChainIdsSupportedByMulticall = [ + 1, // Mainnet + 3, // Kovan + 4, // Rinkeby + 5, // Görli + 10, // Ropsten + 42, // Sepolia + 137, // Optimism + 69, // Optimism Kovan + 100, // Optimism Görli + 420, // Arbitrum + 42161, // Arbitrum Görli + 421611, // Arbitrum Rinkeby + 421613, // Polygon + 80001, // Mumbai + 11155111, // Gnosis Chain (xDai) + 43114, // Avalanche + 43113, // Avalanche Fuji + 4002, // Fantom Testnet + 250, // Fantom Opera + 56, // BNB Smart Chain + 97, // BNB Smart Chain Testnet + 1284, // Moonbeam + 1285, // Moonriver + 1287, // Moonbase Alpha Testnet + 1666600000, // Harmony + 25, // Cronos + 122, // Fuse + 19, // Songbird Canary Network + 16, // Coston Testnet + 288, // Boba + 1313161554, // Aurora + 592, // Astar + 66, // OKC + 128, // Heco Chain + 1088, // Metis + 30, // RSK + 31, // RSK Testnet + 9001, // Evmos + 9000, // Evmos Testnet + 108, // Thundercore + 18, // Thundercore Testnet + 26863, // Oasis + 42220, // Celo + 71402, // Godwoken + 71401, // Godwoken Testnet + 8217, // Klatyn + 2001, // Milkomeda + 321, // KCC + 111 // Etherlite +]; + +async function isMulticallAvailable( mn ) { + if( mn && mn.ethersProvider ) { + const { chainId } = await mn.ethersProvider.getNetwork(); + const bnChainId = owaspUtils.toBN( chainId ); + for( let i = 0; i < gArrChainIdsSupportedByMulticall.length; ++ i ) { + const walkChainId = gArrChainIdsSupportedByMulticall[i]; + const bnWalkChainId = owaspUtils.toBN( walkChainId ); + if( bnWalkChainId.eq( bnChainId ) ) + return true; + } + } + return false; +} + +// see https://github.com/skalenetwork/skale-proxy/blob/develop/endpoints.py +export async function loadSChainParts( joSChain, addressFrom, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + if( ! opts.imaState ) + throw new Error( "Cannot load S-Chain parts in observer, no imaState is provided" ); + let isEMC = false; + if( opts.imaState.isEnabledMultiCall ) + isEMC = await isMulticallAvailable( opts.imaState.chainProperties.mn ); + joSChain.data.computed = {}; + const computedSChainId = owaspUtils.ethersMod.ethers.utils.id( joSChain.data.name ); + const chainId = owaspUtils.computeChainIdFromSChainName( joSChain.data.name ); + const arrNodeIds = + await opts.imaState.joSChainsInternal.callStatic.getNodesInGroup( + computedSChainId, + { from: addressFrom } ); + const nodes = []; + if( isEMC ) { + const multicall = new EMC.Multicall( { + ethersProvider: opts.imaState.chainProperties.mn.ethersProvider, + tryAggregate: true + } ); + const strRef0 = "Nodes-nodes"; + const strRef1 = "Nodes-getNodeDomainName"; + const strRef2 = "Nodes-isNodeInMaintenance"; + const strRef3 = "SchainsInternal-getSchainHashesForNode"; + const contractCallContext = [ { + reference: strRef0, + contractAddress: opts.imaState.joNodes.address, + abi: opts.imaState.joAbiSkaleManager.nodes_abi, + calls: [ ] + }, { + reference: strRef1, + contractAddress: opts.imaState.joNodes.address, + abi: opts.imaState.joAbiSkaleManager.nodes_abi, + calls: [ ] + }, { + reference: strRef2, + contractAddress: opts.imaState.joNodes.address, + abi: opts.imaState.joAbiSkaleManager.nodes_abi, + calls: [ ] + }, { + reference: strRef3, + contractAddress: opts.imaState.joSChainsInternal.address, + abi: opts.imaState.joAbiSkaleManager.schains_internal_abi, + calls: [ ] + } ]; + for( const nodeId of arrNodeIds ) { + if( opts && opts.bStopNeeded ) + return; + contractCallContext[0].calls.push( + { + reference: strRef0, + methodName: "nodes", + methodParameters: [ nodeId ] + } ); + contractCallContext[1].calls.push( + { + reference: strRef1, + methodName: "getNodeDomainName", + methodParameters: [ nodeId ] + } ); + contractCallContext[2].calls.push( + { + reference: strRef2, + methodName: "isNodeInMaintenance", + methodParameters: [ nodeId ] + } ); + contractCallContext[3].calls.push( + { + reference: strRef3, + methodName: "getSchainHashesForNode", + methodParameters: [ nodeId ] + } ); + } + const rawResults = await multicall.call( contractCallContext ); + let idxResult = 0; + for( const nodeId of arrNodeIds ) { + const values0 = + rawResults.results[strRef0].callsReturnContext[idxResult].returnValues; + const values1 = + rawResults.results[strRef1].callsReturnContext[idxResult].returnValues; + const values2 = + rawResults.results[strRef2].callsReturnContext[idxResult].returnValues; + const values3 = + rawResults.results[strRef3].callsReturnContext[idxResult].returnValues; + const nodeDict = { + "id": nodeId, + "name": values0[0], + "ip": owaspUtils.ipFromHex( values0[1] ), + "basePort": values0[3], + "domain": values1[0], + "isMaintenance": values2[0] + }; + if( opts && opts.bStopNeeded ) + return; + const arrFetchedSChainIds = values3; + nodeDict.basePortOfSChain = getSChainBasePortOnNode( + computedSChainId, arrFetchedSChainIds, nodeDict.basePort ); + calcPorts( joSChain, nodeDict.basePortOfSChain ); + composeEndPoints( joSChain, nodeDict, "ip" ); + composeEndPoints( joSChain, nodeDict, "domain" ); + nodes.push( nodeDict ); + if( opts && opts.bStopNeeded ) + return; + ++ idxResult; + } + } else { + for( const nodeId of arrNodeIds ) { + if( opts && opts.bStopNeeded ) + return; + const node = + await opts.imaState.joNodes.callStatic.nodes( nodeId, { from: addressFrom } ); + const nodeDict = { + "id": nodeId, + "name": node[0], + "ip": owaspUtils.ipFromHex( node[1] ), + "basePort": node[3], + "domain": + await opts.imaState.joNodes.callStatic.getNodeDomainName( + nodeId, { from: addressFrom } ), + "isMaintenance": + await opts.imaState.joNodes.callStatic.isNodeInMaintenance( + nodeId, { from: addressFrom } ) + }; + if( opts && opts.bStopNeeded ) + return; + const arrFetchedSChainIds = + await opts.imaState.joSChainsInternal.callStatic.getSchainHashesForNode( + nodeId, { from: addressFrom } ); + nodeDict.basePortOfSChain = + getSChainBasePortOnNode( + computedSChainId, arrFetchedSChainIds, nodeDict.basePort ); + calcPorts( joSChain, nodeDict.basePortOfSChain ); + composeEndPoints( joSChain, nodeDict, "ip" ); + composeEndPoints( joSChain, nodeDict, "domain" ); + nodes.push( nodeDict ); + if( opts && opts.bStopNeeded ) + return; + } + } + joSChain.data.computed.computedSChainId = computedSChainId; + joSChain.data.computed.chainId = chainId; + joSChain.data.computed.nodes = nodes; +} + +export async function getSChainsCount( addressFrom, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + if( ! opts.imaState ) + throw new Error( "Cannot get S-Chains count, no imaState is provided" ); + const cntSChains = + await opts.imaState.joSChainsInternal.callStatic.numberOfSchains( + { from: addressFrom } ); + return cntSChains; +} + +export function removeSChainDescDataNumKeys( joSChain ) { + const cnt = Object.keys( joSChain ).length; + for( let i = 0; i < cnt; ++ i ) { + try { + delete joSChain[i]; + } catch ( err ) { + } + } +} + +function process_sc_data( rawData ) { + // convert needed fields of struct ISchainsInternal.Schain + const joData = { + // for debugging we can use here: "rawData": rawData, + "name": rawData[0], + "owner": rawData[1] + }; + // for debugging we can use here: joData = owaspUtils.cloneObjectByRootKeys( joData ); + return joData; +} + +export async function loadSChain( addressFrom, idxSChain, hash, joData, cntSChains, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + if( ! opts.imaState ) + throw new Error( "Cannot load S-Chain description in observer, no imaState is provided" ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Loading S-Chain " ) + cc.notice( "#" ) + + cc.info( idxSChain + 1 ) + cc.debug( " of " ) + cc.info( cntSChains ) + + cc.debug( "..." ) + "\n" ); + } + } + hash = hash || + await opts.imaState.joSChainsInternal.callStatic.schainsAtSystem( + idxSChain, { from: addressFrom } ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + opts.details.write( cc.debug( " Hash " ) + cc.attention( hash ) + "\n" ); + } + if( opts && opts.bStopNeeded ) + return null; + joData = joData || + process_sc_data( await opts.imaState.joSChainsInternal.callStatic.schains( + hash, { from: addressFrom } ) ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + opts.details.write( cc.debug( " Data of chain is " ) + cc.j( joData ) + "\n" ); + } + const joSChain = { "data": joData }; + removeSChainDescDataNumKeys( joSChain.data, addressFrom ); + if( opts && opts.bStopNeeded ) + return null; + await loadSChainParts( joSChain, addressFrom, opts ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( " Desc " ) + cc.j( joSChain.data ) + "\n" ); + opts.details.write( cc.success( "Done" ) + "\n" ); + } + } + joSChain.isConnected = false; + return joSChain; +} + +export async function loadSChains( addressFrom, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + if( ! opts.imaState ) + throw new Error( "Cannot load S-Chains parts in observer, no imaState is provided" ); + let isEMC = false; + if( opts.imaState.isEnabledMultiCall ) + isEMC = await isMulticallAvailable( opts.imaState.chainProperties.mn ); + if( isEMC ) + return await loadSChainsWithEMC( addressFrom, opts ); + return await loadSChainsOptimal( addressFrom, opts ); +} + +export async function loadSChainsWithEMC( addressFrom, opts ) { + const cntSChains = await getSChainsCount( addressFrom, opts ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Have " ) + cc.info( cntSChains ) + + cc.debug( " S-Chain(s) to load..." ) + "\n" ); + } + } + const multicall = new EMC.Multicall( { + ethersProvider: opts.imaState.chainProperties.mn.ethersProvider, + tryAggregate: true + } ); + const cntGroupMax = 30, cntLastExtraGroup = cntSChains % cntGroupMax; + const bHaveExtraGroup = ( cntLastExtraGroup > 0 ) ? true : false; + const cntGroups = Math.floor( cntSChains / cntGroupMax ) + ( bHaveExtraGroup ? 1 : 0 ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( + cc.debug( " Have " ) + cc.info( cntGroups ) + + cc.debug( " multicall group(s), max possible " ) + cc.attention( cntGroupMax ) + + cc.debug( " call(s) in each" ) + "\n" ); + if( bHaveExtraGroup ) { + opts.details.write( + cc.debug( " Have last extra multicall group with " ) + + cc.attention( cntLastExtraGroup ) + cc.debug( " call(s) in it" ) + "\n" ); + } + } + } + const arrSChainHashes = []; + for( let idxGroup = 0; idxGroup < cntGroups; ++ idxGroup ) { + if( opts && opts.bStopNeeded ) + return null; + const idxFirstChainInGroup = idxGroup * cntGroupMax; + const cntInThisGroup = ( idxGroup == ( cntGroups - 1 ) && bHaveExtraGroup ) + ? cntLastExtraGroup : cntGroupMax; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( + cc.debug( " Processing chain hashes in multicall group #" ) + + cc.info( idxGroup ) + cc.debug( " with " ) + cc.attention( cntInThisGroup ) + + cc.debug( " call(s) in it..." ) + "\n" ); + } + } + const strRef3 = "SchainsInternal-schainsAtSystem"; + const contractCallContext = [ { + reference: strRef3, + contractAddress: opts.imaState.joSChainsInternal.address, + abi: opts.imaState.joAbiSkaleManager.schains_internal_abi, + calls: [ ] + } ]; + for( let idxSChain = 0; idxSChain < cntInThisGroup; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + return null; + contractCallContext[0].calls.push( + { + reference: strRef3, + methodName: "schainsAtSystem", + methodParameters: [ idxFirstChainInGroup + idxSChain ] + } ); + } + const rawResults = await multicall.call( contractCallContext ); + if( opts && opts.bStopNeeded ) + return null; + for( let idxSChain = 0; idxSChain < cntInThisGroup; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + return null; + const idxResult = 0 + idxSChain; + const values3 = + rawResults.results[strRef3].callsReturnContext[idxResult].returnValues; + const hash = values3[0]; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( + cc.debug( " Hash of chain #" ) + + cc.info( idxFirstChainInGroup + idxSChain ) + + cc.debug( " is " ) + cc.attention( hash ) + "\n" ); + } + } + arrSChainHashes.push( hash ); + } + if( opts && opts.bStopNeeded ) + return null; + } + if( opts && opts.bStopNeeded ) + return null; + const arrSChainDataRecords = []; + for( let idxGroup = 0; idxGroup < cntGroups; ++ idxGroup ) { + if( opts && opts.bStopNeeded ) + return null; + const idxFirstChainInGroup = idxGroup * cntGroupMax; + const cntInThisGroup = ( idxGroup == ( cntGroups - 1 ) && bHaveExtraGroup ) + ? cntLastExtraGroup : cntGroupMax; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( + cc.debug( " Processing chain data in multicall group #" ) + + cc.info( idxGroup ) + cc.debug( " with " ) + cc.attention( cntInThisGroup ) + + cc.debug( " call(s) in it..." ) + "\n" ); + } + } + const strRef3 = "SchainsInternal-schains"; + const contractCallContext = [ { + reference: strRef3, + contractAddress: opts.imaState.joSChainsInternal.address, + abi: opts.imaState.joAbiSkaleManager.schains_internal_abi, + calls: [ ] + } ]; + for( let idxSChain = 0; idxSChain < cntInThisGroup; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + return null; + const hash = arrSChainHashes[idxFirstChainInGroup + idxSChain]; + contractCallContext[0].calls.push( + { + reference: strRef3, + methodName: "schains", + methodParameters: [ hash ] + } ); + } + const rawResults = await multicall.call( contractCallContext ); + if( opts && opts.bStopNeeded ) + return null; + for( let idxSChain = 0; idxSChain < cntInThisGroup; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + return null; + const idxResult = 0 + idxSChain; + const values3 = + rawResults.results[strRef3].callsReturnContext[idxResult].returnValues; + const joData = process_sc_data( values3 ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( + cc.debug( " Data of chain #" ) + + cc.info( idxFirstChainInGroup + idxSChain ) + + cc.debug( " is " ) + cc.j( joData ) + "\n" ); + } + } + arrSChainDataRecords.push( joData ); + } + if( opts && opts.bStopNeeded ) + return null; + } + const arrSChains = []; + for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + break; + const hash = arrSChainHashes[idxSChain]; + const joData = arrSChainDataRecords[idxSChain]; + const joSChain = await loadSChain( // with hash + joData + addressFrom, idxSChain, hash, joData, cntSChains, opts ); + if( ! joSChain ) + break; + arrSChains.push( joSChain ); + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.success( "All " ) + cc.info( cntSChains ) + + cc.debug( " S-Chain(s) loaded:" ) + cc.j( arrSChains ) + "\n" ); + } + } + return arrSChains; +} + +export async function loadSChainsOptimal( addressFrom, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + if( ! opts.imaState ) + throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); + const cntSChains = await getSChainsCount( addressFrom, opts ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Have " ) + cc.info( cntSChains ) + + cc.debug( " S-Chain(s) to load..." ) + "\n" ); + } + } + const arrSChains = []; + for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + break; + const joSChain = await loadSChain( + addressFrom, idxSChain, null, null, cntSChains, opts ); + if( ! joSChain ) + break; + arrSChains.push( joSChain ); + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.success( "All " ) + cc.info( cntSChains ) + + cc.debug( " S-Chain(s) loaded:" ) + cc.j( arrSChains ) + "\n" ); + } + } + return arrSChains; +} + +export async function loadCachedSChainsSimplified( addressFrom, opts ) { + if( ! opts.imaState ) + throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + opts.details.write( cc.debug( "Will request all S-Chain(s) hashes..." ) + "\n" ); + } + const arrSChainHashes = + await opts.imaState.joSChainsInternal.callStatic.getSchains( + { from: addressFrom } ); + const cntSChains = arrSChainHashes.length; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Have all " ) + cc.info( cntSChains ) + + cc.debug( " S-Chain(s) hashes: " ) + cc.j( arrSChainHashes ) + "\n" ); + } + } + const arrSChains = []; + for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + break; + const strSChainHash = arrSChainHashes[idxSChain]; + const strSChainName = + await opts.imaState.joSChainsInternal.callStatic.getSchainName( + strSChainHash, { from: addressFrom } ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "S-Chain " ) + cc.notice( idxSChain ) + + cc.debug( " hash " ) + cc.notice( strSChainHash ) + + cc.debug( " corresponds to S-Chain name " ) + cc.notice( strSChainName ) + + "\n" ); + } + } + if( opts && opts.bStopNeeded ) + break; + const joSChain = await loadSChain( + addressFrom, idxSChain, strSChainHash, null, cntSChains, opts ); + if( ! joSChain ) + break; + arrSChains.push( joSChain ); + } + return arrSChains; +} + +export async function loadSChainsConnectedOnly( + strChainNameConnectedTo, + addressFrom, + opts +) { + if( ! opts.imaState ) + throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + opts.details.write( cc.debug( "Will request all S-Chain(s) hashes..." ) + "\n" ); + } + const arrSChainHashes = + await opts.imaState.joSChainsInternal.callStatic.getSchains( + { from: addressFrom } ); + const cntSChains = arrSChainHashes.length; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Have all " ) + cc.info( cntSChains ) + + cc.debug( " S-Chain(s) hashes: " ) + cc.j( arrSChainHashes ) + "\n" ); + } + } + const joMessageProxySChain = + new owaspUtils.ethersMod.ethers.Contract( + opts.imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_address, + opts.imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_abi, + opts.imaState.chainProperties.sc.ethersProvider + ); + const arrSChains = []; + for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { + try { + if( opts && opts.bStopNeeded ) + break; + const strSChainHash = arrSChainHashes[idxSChain]; + const strSChainName = + await opts.imaState.joSChainsInternal.callStatic.getSchainName( + strSChainHash, { from: addressFrom } ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "S-Chain " ) + cc.notice( idxSChain ) + + cc.debug( " hash " ) + cc.notice( strSChainHash ) + + cc.debug( " corresponds to S-Chain name " ) + cc.notice( strSChainName ) + + "\n" ); + } + } + if( opts && opts.bStopNeeded ) + break; + + if( strChainNameConnectedTo == strSChainName ) { + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Skip this S-Chain " ) + + cc.info( strSChainName ) + cc.debug( " connected status check" ) + + "\n" ); + } + } + continue; + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Querying connected status between S-Chain " ) + + cc.info( strSChainName ) + cc.debug( " and S-Chain " ) + + cc.info( strChainNameConnectedTo ) + cc.debug( "..." ) + "\n" ); + } + } + const isConnected = + await joMessageProxySChain.callStatic.isConnectedChain( + strSChainName, { from: addressFrom } ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Got S-Chain " ) + cc.info( strSChainName ) + + cc.debug( " connected status: " ) + cc.yn( isConnected ) + "\n" ); + } + } + if( ! isConnected ) + continue; + const joSChain = await loadSChain( + addressFrom, idxSChain, strSChainHash, null, cntSChains, opts ); + if( ! joSChain ) + break; + joSChain.isConnected = true; + arrSChains.push( joSChain ); + } catch ( err ) { + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + opts.details.write( cc.error( "Got error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + } + } + return arrSChains; +} + +export async function checkConnectedSChains( + strChainNameConnectedTo, arrSChains, addressFrom, opts +) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + if( ! opts.imaState ) + throw new Error( "Cannot load S-Chains in observer, no imaState is provided" ); + const cntSChains = arrSChains.length; + for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + break; + const joSChain = arrSChains[idxSChain]; + joSChain.isConnected = false; + if( joSChain.data.name == strChainNameConnectedTo ) + continue; + try { + const url = pickRandomSChainUrl( joSChain ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Querying via URL " ) + cc.u( url ) + + cc.debug( " to S-Chain " ) + cc.info( joSChain.data.name ) + + cc.debug( " whether it's connected to S-Chain " ) + + cc.info( strChainNameConnectedTo ) + cc.debug( "..." ) + "\n" ); + } + } + const ethersProvider = owaspUtils.getEthersProviderFromURL( url ); + const joMessageProxySChain = + new owaspUtils.ethersMod.ethers.Contract( + opts.imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_address, + opts.imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_abi, + ethersProvider + ); + joSChain.isConnected = + await joMessageProxySChain.callStatic.isConnectedChain( + strChainNameConnectedTo, { from: addressFrom } ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + opts.details.write( cc.debug( "Got " ) + cc.yn( joSChain.isConnected ) + "\n" ); + } + } catch ( err ) { + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + opts.details.write( cc.error( "Got error: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + } + } + return arrSChains; +} + +export async function filterSChainsMarkedAsConnected( arrSChains, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + const arrConnectedSChains = []; + const cntSChains = arrSChains.length; + for( let idxSChain = 0; idxSChain < cntSChains; ++ idxSChain ) { + if( opts && opts.bStopNeeded ) + break; + const joSChain = arrSChains[idxSChain]; + if( joSChain.isConnected ) + arrConnectedSChains.push( joSChain ); + } + return arrConnectedSChains; +} + +export function findSChainIndexInArrayByName( arrSChains, strSChainName ) { + for( let idxSChain = 0; idxSChain < arrSChains.length; ++ idxSChain ) { + const joSChain = arrSChains[idxSChain]; + if( joSChain.data.name.toString() == strSChainName.toString() ) + return idxSChain; + } + return -1; +} + +export function mergeSChainsArrayFromTo( arrSrc, arrDst, arrNew, arrOld, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + arrNew.splice( 0, arrNew.length ); + arrOld.splice( 0, arrOld.length ); + let i, j, cnt; + cnt = arrSrc.length; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Before merging, have " ) + cc.info( cnt ) + + cc.debug( " S-Chain(s) to review" ) + "\n" ); + } + } + for( i = 0; i < cnt; ++ i ) { + const joSChain = arrSrc[i]; + j = findSChainIndexInArrayByName( arrDst, joSChain.data.name ); + if( j < 0 ) { + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Found new " ) + cc.notice( "#" ) + + cc.info( i + 1 ) + cc.debug( " S-Chain " ) + cc.j( joSChain ) + "\n" ); + } + } + arrNew.push( joSChain ); + } + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Summary, found new " ) + cc.info( arrNew.length ) + + cc.debug( " S-Chain(s)" ) + "\n" ); + } + } + cnt = arrDst.length; + for( i = 0; i < cnt; ++ i ) { + const joSChain = arrDst[i]; + j = findSChainIndexInArrayByName( arrSrc, joSChain.data.name ); + if( j < 0 ) { + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Found old S-Chain " ) + cc.notice( "#" ) + + cc.info( i + 1 ) + cc.debug( " " ) + cc.j( joSChain ) + "\n" ); + } + } + arrOld.push( joSChain ); + } + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Summary, found old " ) + cc.info( arrOld.length ) + + cc.debug( " S-Chain(s)" ) + "\n" ); + } + } + if( arrNew.length > 0 ) { + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Merging new " ) + cc.info( arrNew.length ) + + cc.debug( " S-Chain(s)" ) + "\n" ); + } + } + for( i = 0; i < arrNew.length; ++ i ) { + const joSChain = arrNew[i]; + arrDst.push( joSChain ); + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + opts.details.write( cc.success( "Done" ) + "\n" ); + } + } + if( arrOld.length > 0 ) { + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Removing old " ) + cc.info( arrOld.length ) + + cc.debug( " S-Chain(s)" ) + "\n" ); + } + } + for( i = 0; i < arrOld.length; ++ i ) { + const joSChain = arrOld[i]; + j = findSChainIndexInArrayByName( arrDst, joSChain.data.name ); + arrDst.splice( j, 1 ); + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) + opts.details.write( cc.success( "Done" ) + "\n" ); + } + } + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.success( "Finally, have " ) + cc.info( arrDst.length ) + + cc.success( " S-Chain(s)" ) + "\n" ); + } + } +} + +let gArrSChainsCached = []; + +export async function cacheSChains( strChainNameConnectedTo, addressFrom, opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + let strError = null; + try { + const arrSChains = await loadSChains( addressFrom, opts ); + if( strChainNameConnectedTo && + ( typeof strChainNameConnectedTo == "string" ) && + strChainNameConnectedTo.length > 0 + ) { + await checkConnectedSChains( + strChainNameConnectedTo, + arrSChains, + addressFrom, + opts + ); + gArrSChainsCached = await filterSChainsMarkedAsConnected( + arrSChains, + opts + ); + } else + gArrSChainsCached = arrSChains; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Connected " ) + cc.attention( "S-Chains" ) + + cc.debug( " cache was updated in this thread: " ) + + cc.j( gArrSChainsCached ) + "\n" ); + } + } + if( opts.fnCacheChanged ) + opts.fnCacheChanged( gArrSChainsCached, null ); // null - no error + } catch ( err ) { + strError = owaspUtils.extractErrorMessage( err ); + if( ! strError ) + strError = "unknown exception during S-Chains download"; + if( opts.fnCacheChanged ) + opts.fnCacheChanged( gArrSChainsCached, strError ); + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + opts.details.write( cc.fatal( "ERROR:" ) + + cc.error( " Failed to cache: " ) + cc.error( err ) ); + opts.details.write( cc.stack( err.stack ) ); + } + } + } + return strError; // null on success +} + +export function getLastCachedSChains() { + return JSON.parse( JSON.stringify( gArrSChainsCached ) ); +} + +export function setLastCachedSChains( arrSChainsCached ) { + if( arrSChainsCached && typeof arrSChainsCached == "object" ) { + gArrSChainsCached = JSON.parse( JSON.stringify( arrSChainsCached ) ); + events.dispatchEvent( + new UniversalDispatcherEvent( + "chainsCacheChanged", + { "detail": { "arrSChainsCached": getLastCachedSChains() } } ) ); + } +} + +const sleepImpl = ( milliseconds ) => { + return new Promise( resolve => setTimeout( resolve, milliseconds ) ); +}; + +let gWorker = null; +let gClient = null; + +export async function ensureHaveWorker( opts ) { + owaspUtils.ensureObserverOptionsInitialized( opts ); + if( gWorker ) + return gWorker; + const url = "skale_observer_worker_server"; + gWorker = + new Worker( + path.join( __dirname, "observerWorker.mjs" ), + { "type": "module" } + ); + gWorker.on( "message", jo => { + if( networkLayer.outOfWorkerAPIs.onMessage( gWorker, jo ) ) + return; + } ); + gClient = new networkLayer.OutOfWorkerSocketClientPipe( url, gWorker ); + gClient.on( "message", function( eventData ) { + const joMessage = eventData.message; + switch ( joMessage.method ) { + case "periodicCachingDoNow": + setLastCachedSChains( joMessage.message ); + gFlagHaveParallelResult = true; + if( opts && opts.details ) { + if( log.verboseGet() >= log.verboseReversed().trace ) { + opts.details.write( cc.debug( "Connected " ) + cc.attention( "S-Chains" ) + + cc.debug( " cache was updated using data arrived from SNB worker: " ) + + cc.j( gArrSChainsCached ) + "\n" ); + } + } + break; + case "log": + log.write( cc.attention( "SNB WORKER" ) + " " + joMessage.message ); + break; + } // switch ( joMessage.method ) + } ); + await sleepImpl( 1000 ); + const jo = { + "method": "init", + "message": { + "opts": { + "imaState": { + "verbose_": log.verboseGet(), + "expose_details_": log.exposeDetailsGet(), + "bNoWaitSChainStarted": opts.imaState.bNoWaitSChainStarted, + "nMaxWaitSChainAttempts": opts.imaState.nMaxWaitSChainAttempts, + "nNodeNumber": opts.imaState.nNodeNumber, + "nNodesCount": opts.imaState.nNodesCount, + "nTimeFrameSeconds": opts.imaState.nTimeFrameSeconds, + "nNextFrameGap": opts.imaState.nNextFrameGap, + "chainProperties": { + "mn": { + "joAccount": { + "privateKey": opts.imaState.chainProperties.mn.joAccount.privateKey, + "strTransactionManagerURL": + opts.imaState.chainProperties.mn + .joAccount.strTransactionManagerURL, + "nTmPriority": + opts.imaState.chainProperties.mn + .joAccount.nTmPriority, + "strSgxURL": + opts.imaState.chainProperties.mn + .joAccount.strSgxURL, + "strSgxKeyName": + opts.imaState.chainProperties.mn + .joAccount.strSgxKeyName, + "strPathSslKey": + opts.imaState.chainProperties.mn + .joAccount.strPathSslKey, + "strPathSslCert": + opts.imaState.chainProperties.mn + .joAccount.strPathSslCert, + "strBlsKeyName": + opts.imaState.chainProperties.mn + .joAccount.strBlsKeyName + }, + "strURL": opts.imaState.chainProperties.mn.strURL, + "strChainName": opts.imaState.chainProperties.mn.strChainName, + "chainId": opts.imaState.chainProperties.mn.chainId, + "joAbiIMA": opts.imaState.chainProperties.mn.joAbiIMA, + "bHaveAbiIMA": opts.imaState.chainProperties.mn.bHaveAbiIMA + }, + "sc": { + "joAccount": { + "privateKey": + opts.imaState.chainProperties.sc.joAccount.privateKey, + "strTransactionManagerURL": + opts.imaState.chainProperties.sc + .joAccount.strTransactionManagerURL, + "nTmPriority": + opts.imaState.chainProperties.sc + .joAccount.nTmPriority, + "strSgxURL": + opts.imaState.chainProperties.sc + .joAccount.strSgxURL, + "strSgxKeyName": + opts.imaState.chainProperties.sc + .joAccount.strSgxKeyName, + "strPathSslKey": + opts.imaState.chainProperties.sc + .joAccount.strPathSslKey, + "strPathSslCert": + opts.imaState.chainProperties.sc + .joAccount.strPathSslCert, + "strBlsKeyName": + opts.imaState.chainProperties.sc + .joAccount.strBlsKeyName + }, + "strURL": opts.imaState.chainProperties.sc.strURL, + "strChainName": opts.imaState.chainProperties.sc.strChainName, + "chainId": opts.imaState.chainProperties.sc.chainId, + "joAbiIMA": opts.imaState.chainProperties.sc.joAbiIMA, + "bHaveAbiIMA": opts.imaState.chainProperties.sc.bHaveAbiIMA + } + }, + "joAbiSkaleManager": opts.imaState.joAbiSkaleManager, + "bHaveSkaleManagerABI": opts.imaState.bHaveSkaleManagerABI, + "joSChainDiscovery": { + "isSilentReDiscovery": + opts.imaState.joSChainDiscovery.isSilentReDiscovery, + "repeatIntervalMilliseconds": + opts.imaState.joSChainDiscovery.repeatIntervalMilliseconds + } + } + }, + "cc": { + "isEnabled": cc.isEnabled() + } + } + }; + gClient.send( jo ); +} + +async function inThreadPeriodicCachingStart( strChainNameConnectedTo, addressFrom, opts ) { + if( gIntervalPeriodicCaching != null ) + return; + try { + const fnDoCachingNow = async function() { + await cacheSChains( strChainNameConnectedTo, addressFrom, opts ); + }; + gIntervalPeriodicCaching = + setInterval( + fnDoCachingNow, + parseInt( opts.secondsToReDiscoverSkaleNetwork ) * 1000 ); + await fnDoCachingNow(); + return true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Failed to start in-thread periodic SNB refresh, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return false; +} + +async function parallelPeriodicCachingStart( strChainNameConnectedTo, addressFrom, opts ) { + gFlagHaveParallelResult = false; + try { + const nSecondsToWaitParallel = 60; + setTimeout( function() { + if( gFlagHaveParallelResult ) + return; + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Failed to start parallel periodic SNB refresh, error is: " ) + + cc.warning( "timeout of " ) + cc.info( nSecondsToWaitParallel ) + + cc.warning( " reached, will restart periodic SNB refresh " + + "in non-parallel mode" ) + "\n" ); + } + periodicCachingStop(); + inThreadPeriodicCachingStart( strChainNameConnectedTo, addressFrom, opts ); + }, nSecondsToWaitParallel * 1000 ); + owaspUtils.ensureObserverOptionsInitialized( opts ); + await ensureHaveWorker( opts ); + const jo = { + "method": "periodicCachingStart", + "message": { + "secondsToReDiscoverSkaleNetwork": + parseInt( opts.secondsToReDiscoverSkaleNetwork ), + "strChainNameConnectedTo": strChainNameConnectedTo, + "addressFrom": addressFrom + } + }; + gClient.send( jo ); + return true; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Failed to start parallel periodic SNB refresh, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + return false; +} + +export async function periodicCachingStart( strChainNameConnectedTo, addressFrom, opts ) { + gFlagHaveParallelResult = false; + const bParallelMode = + ( opts && "bParallelMode" in opts && + typeof opts.bParallelMode != "undefined" && + opts.bParallelMode ) + ? true : false; + let wasStarted = false; + if( bParallelMode ) { + wasStarted = + parallelPeriodicCachingStart( strChainNameConnectedTo, addressFrom, opts ); + } + if( wasStarted ) + return; + inThreadPeriodicCachingStart( strChainNameConnectedTo, addressFrom, opts ); +} + +export async function periodicCachingStop() { + if( gWorker && gClient ) { + try { + const jo = { + "method": "periodicCachingStop", + "message": { } + }; + gClient.send( jo ); + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Failed to stop parallel periodic SNB refresh, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + } + } + if( gIntervalPeriodicCaching ) { + try { + clearInterval( gIntervalPeriodicCaching ); + gIntervalPeriodicCaching = null; + } catch ( err ) { + if( log.verboseGet() >= log.verboseReversed().error ) { + log.write( cc.error( "Failed to stop in-thread periodic SNB refresh, error is: " ) + + cc.warning( owaspUtils.extractErrorMessage( err ) ) + + cc.error( ", stack is: " ) + "\n" + cc.stack( err.stack ) + "\n" ); + } + gIntervalPeriodicCaching = null; // clear it anyway + } + } + gFlagHaveParallelResult = false; +} + +export function pickRandomSChainNodeIndex( joSChain ) { + let min = 0, max = joSChain.data.computed.nodes.length - 1; + min = Math.ceil( min ); + max = Math.floor( max ); + const idxNode = Math.floor( Math.random() * ( max - min + 1 ) ) + min; + return idxNode; +} +export function pickRandomSChainNode( joSChain ) { + const idxNode = pickRandomSChainNodeIndex( joSChain ); + return joSChain.data.computed.nodes[idxNode]; +} + +export function pickRandomSChainUrl( joSChain ) { + const joNode = pickRandomSChainNode( joSChain ); + // eslint-disable-next-line dot-notation + return "" + joNode["http_endpoint_ip"]; +} + +export async function discoverChainId( strURL ) { + let ret = null; + const rpcCallOpts = null; + await rpcCall.create( strURL, rpcCallOpts, async function( joCall, err ) { + if( err ) { + if( joCall ) + await joCall.disconnect(); + return; + } + await joCall.call( { + "method": "eth_chainId", + "params": [] + }, async function( joIn, joOut, err ) { + if( err ) { + await joCall.disconnect(); + return; + } + if( ! ( "result" in joOut && joOut.result ) ) { + await joCall.disconnect(); + return; + } + ret = joOut.result; + await joCall.disconnect(); + } ); // joCall.call ... + } ); // rpcCall.create ... + return ret; +} diff --git a/npms/skale-observer/observerWorker.mjs b/npms/skale-observer/observerWorker.mjs new file mode 100644 index 000000000..520814c4d --- /dev/null +++ b/npms/skale-observer/observerWorker.mjs @@ -0,0 +1,270 @@ + +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file observerWorker.mjs + * @copyright SKALE Labs 2019-Present + */ + +import { + parentPort +} from "worker_threads"; +import * as networkLayer from "../skale-cool-socket/socket.mjs"; +import { SocketServer } from "../skale-cool-socket/socketServer.mjs"; +import * as cc from "../skale-cc/cc.mjs"; +import * as owaspUtils from "../skale-owasp/owaspUtils.mjs"; +import * as skaleObserver from "./observer.mjs"; +import * as log from "../skale-log/log.mjs"; + +const gURL = "skale_observer_worker_server"; + +parentPort.on( "message", jo => { + if( networkLayer.inWorkerAPIs.onMessage( jo ) ) + return; +} ); + +const sleep = ( milliseconds ) => { + return new Promise( resolve => setTimeout( resolve, milliseconds ) ); +}; + +function doSendMessage( type, endpoint, workerUUID, data ) { + const jo = networkLayer.socketReceivedDataReverseMarshall( data ); + const joSend = { + "workerMessageType": + ( type && typeof type == "string" && type.length > 0 ) + ? type : "inWorkerMessage", + "workerEndPoint": endpoint, + "workerUUID": workerUUID, + "data": jo + }; + parentPort.postMessage( networkLayer.socketSentDataMarshall( joSend ) ); +} + +class ObserverServer extends SocketServer { + constructor( acceptor ) { + super( acceptor ); + const self = this; + self.opts = null; + self.intervalPeriodicSchainsCaching = null; + self.bIsPeriodicCachingStepInProgress = false; + self.mapApiHandlers.init = function( joMessage, joAnswer, eventData, socket ) { + self.log = function() { + const args = Array.prototype.slice.call( arguments ); + const jo = { + "method": "log", + "error": null, + "message": args.join( " " ) + }; + const isFlush = true; + socket.send( jo, isFlush ); + }; + self.opts = JSON.parse( JSON.stringify( joMessage.message.opts ) ); + self.opts.details = { + write: self.log + }; + cc.enable( joMessage.message.cc.isEnabled ); + log.verboseSet( self.opts.imaState.verbose_ ); + log.exposeDetailsSet( self.opts.imaState.expose_details_ ); + joAnswer.message = { + "method": "" + joMessage.method, + "error": null + }; + self.opts.imaState.chainProperties.mn.joAccount.address = + owaspUtils.fnAddressImpl_; + self.opts.imaState.chainProperties.sc.joAccount.address = + owaspUtils.fnAddressImpl_; + if( self.opts.imaState.chainProperties.mn.strURL && + typeof self.opts.imaState.chainProperties.mn.strURL == "string" && + self.opts.imaState.chainProperties.mn.strURL.length > 0 + ) { + const u = self.opts.imaState.chainProperties.mn.strURL; + self.opts.imaState.chainProperties.mn.ethersProvider = + owaspUtils.getEthersProviderFromURL( u ); + } else { + if( log.verboseGet() >= log.verboseReversed().warning ) { + self.log( cc.warning( "WARNING:" ) + cc.warning( " No " ) + + cc.note( "Main-net" ) + + cc.warning( " URL specified in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + "\n" ); + } + } + + if( self.opts.imaState.chainProperties.sc.strURL && + typeof self.opts.imaState.chainProperties.sc.strURL == "string" && + self.opts.imaState.chainProperties.sc.strURL.length > 0 + ) { + const u = self.opts.imaState.chainProperties.sc.strURL; + self.opts.imaState.chainProperties.sc.ethersProvider = + owaspUtils.getEthersProviderFromURL( u ); + } else { + if( log.verboseGet() >= log.verboseReversed().warning ) { + self.log( cc.warning( "WARNING:" ) + cc.warning( " No " ) + + cc.note( "Main-net" ) + + cc.warning( " URL specified in command line arguments" ) + + cc.debug( "(needed for particular operations only)" ) + "\n" ); + } + } + self.opts.imaState.joNodes = + new owaspUtils.ethersMod.ethers.Contract( + self.opts.imaState.joAbiSkaleManager.nodes_address, + self.opts.imaState.joAbiSkaleManager.nodes_abi, + self.opts.imaState.chainProperties.mn.ethersProvider + ); + self.opts.imaState.joSChains = + new owaspUtils.ethersMod.ethers.Contract( + self.opts.imaState.joAbiSkaleManager.schains_address, + self.opts.imaState.joAbiSkaleManager.schains_abi, + self.opts.imaState.chainProperties.mn.ethersProvider + ); + self.opts.imaState.joSChainsInternal = + new owaspUtils.ethersMod.ethers.Contract( + self.opts.imaState.joAbiSkaleManager.schains_internal_address, + self.opts.imaState.joAbiSkaleManager.schains_internal_abi, + self.opts.imaState.chainProperties.mn.ethersProvider + ); + + self.opts.imaState.joMessageProxySChain = + new owaspUtils.ethersMod.ethers.Contract( + self.opts.imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_address, + self.opts.imaState.chainProperties.sc.joAbiIMA.message_proxy_chain_abi, + self.opts.imaState.chainProperties.sc.ethersProvider + ); + if( log.verboseGet() >= log.verboseReversed().information ) { + self.log( cc.debug( "Full init compete for in-worker SNB server" ) + " " + + cc.notice( gURL ) + "\n" ); + } + return joAnswer; + }; + self.mapApiHandlers.periodicCachingStart = + function( joMessage, joAnswer, eventData, socket ) { + self.periodicCachingStart( + socket, + joMessage.message.secondsToReDiscoverSkaleNetwork, + joMessage.message.strChainNameConnectedTo, + joMessage.message.addressFrom + ); + joAnswer.message = { + "method": "" + joMessage.method, + "error": null + }; + return joAnswer; + }; + self.mapApiHandlers.periodicCachingStop = + function( joMessage, joAnswer, eventData, socket ) { + self.periodicCachingStop(); + joAnswer.message = { + "method": "" + joMessage.method, + "error": null + }; + return joAnswer; + }; + if( log.verboseGet() >= log.verboseReversed().information ) { + self.log( cc.debug( "Initialized in-worker SNB server" ) + " " + + cc.notice( gURL ) + "\n" ); + } + } + dispose() { + const self = this; + self.isDisposing = true; + if( self.intervalPeriodicSchainsCaching ) { + clearInterval( self.intervalPeriodicSchainsCaching ); + self.intervalPeriodicSchainsCaching = null; + } + super.dispose(); + } + async periodicCachingDoNow( + socket, secondsToReDiscoverSkaleNetwork, strChainNameConnectedTo, addressFrom + ) { + const self = this; + if( self.bIsPeriodicCachingStepInProgress ) + return null; + let strError = null; + self.bIsPeriodicCachingStepInProgress = true; + for( let idxAttempt = 0; idxAttempt < 10; ++ idxAttempt ) { + try { + strError = + await skaleObserver.cacheSChains( + strChainNameConnectedTo, + addressFrom, + self.opts + ); + if( ! strError ) + break; + } catch ( err ) { + strError = owaspUtils.extractErrorMessage( err ); + if( ! strError ) + strError = "runtime error without description"; + } + await sleep( 5 * 1000 ); + } + self.bIsPeriodicCachingStepInProgress = false; + if( strError ) + return strError; + const arrSChains = skaleObserver.getLastCachedSChains(); + const jo = { + "method": "periodicCachingDoNow", + "error": null, + "message": arrSChains + }; + const isFlush = true; + socket.send( jo, isFlush ); + return null; + } + async periodicCachingStart( + socket, secondsToReDiscoverSkaleNetwork, strChainNameConnectedTo, addressFrom + ) { + const self = this; + await self.periodicCachingStop(); + if( secondsToReDiscoverSkaleNetwork <= 0 ) + return false; + const fnAsyncHandler = async function() { + await self.periodicCachingDoNow( + socket, secondsToReDiscoverSkaleNetwork, strChainNameConnectedTo, addressFrom ); + }; + self.intervalPeriodicSchainsCaching = setInterval( function() { + if( self.bIsPeriodicCachingStepInProgress ) + return; + fnAsyncHandler() + .then( () => { + } ).catch( () => { + } ); + }, secondsToReDiscoverSkaleNetwork * 1000 ); + fnAsyncHandler(); // initial async call + return true; + } + async periodicCachingStop() { + const self = this; + if( ! self.intervalPeriodicSchainsCaching ) + return false; + clearInterval( self.intervalPeriodicSchainsCaching ); + self.intervalPeriodicSchainsCaching = null; + self.bIsPeriodicCachingStepInProgress = false; + return true; + } +}; + +const acceptor = new networkLayer.InWorkerSocketServerAcceptor( gURL, doSendMessage ); +const server = new ObserverServer( acceptor ); +server.on( "dispose", function() { + const self = server; + if( log.verboseGet() >= log.verboseReversed().debug ) + self.log( cc.debug( "Disposed in-worker SNB server" ) + " " + cc.notice( gURL ) + "\n" ); +} ); diff --git a/npms/skale-observer/observer_worker.js b/npms/skale-observer/observer_worker.js deleted file mode 100644 index 9b799a93d..000000000 --- a/npms/skale-observer/observer_worker.js +++ /dev/null @@ -1,210 +0,0 @@ - -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * SKALE IMA is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * SKALE IMA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with SKALE IMA. If not, see . - */ - -/** - * @file observer_worker.js - * @copyright SKALE Labs 2019-Present - */ - -const { - parentPort - //, workerData -} = require( "worker_threads" ); -const network_layer = require( "../skale-cool-socket/socket.js" ); -const { Server } = require( "../skale-cool-socket/server.js" ); -const owaspUtils = require( "../skale-owasp/owasp-util.js" ); -const cc = owaspUtils.cc; - -const skale_observer = require( "./observer.js" ); - -const g_url = "skale_observer_worker_server"; - -parentPort.on( "message", jo => { - if( network_layer.in_worker_apis.on_message( jo ) ) - return; -} ); - -function doSendMessage( type, endpoint, worker_uuid, data ) { - const jo = network_layer.socket_received_data_reverse_marshall( data ); - const joSend = { - worker_message_type: ( type && typeof type == "string" && type.length > 0 ) ? type : "in_worker_message", - worker_endpoint: endpoint, - worker_uuid: worker_uuid, - data: jo - }; - parentPort.postMessage( network_layer.socket_sent_data_marshall( joSend ) ); -} - -class ObserverServer extends Server { - constructor( acceptor ) { - super( acceptor ); - const self = this; - self.opts = null; - self.intervalPeriodicSchainsCaching = null; - self.bIsPeriodicCachingStepInProgress = false; - self.mapApiHandlers.init = function( joMessage, joAnswer, eventData, socket ) { - self.log = function() { - const args = Array.prototype.slice.call( arguments ); - const jo = { - method: "log", - error: null, - message: args.join( " " ) - }; - const isFlush = true; - socket.send( jo, isFlush ); - }; - self.opts = JSON.parse( JSON.stringify( joMessage.message.opts ) ); - self.opts.details = { - write: self.log - }; - // self.log( cc.debug( "Initialized in-worker options:" ) + " " + cc.j( self.opts ) + "\n" ); - // - self.opts.imaState.joAccount_main_net.address = owaspUtils.fn_address_impl_; - self.opts.imaState.joAccount_s_chain.address = owaspUtils.fn_address_impl_; - // - if( self.opts.imaState.strURL_main_net && typeof self.opts.imaState.strURL_main_net == "string" && self.opts.imaState.strURL_main_net.length > 0 ) { - const u = self.opts.imaState.strURL_main_net; - self.opts.imaState.w3_main_net = skale_observer.getWeb3FromURL( u, self.log ); - } else { - self.log( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Main-net" ) + - cc.warning( " URL specified in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - if( self.opts.imaState.strURL_s_chain && typeof self.opts.imaState.strURL_s_chain == "string" && self.opts.imaState.strURL_s_chain.length > 0 ) { - const u = self.opts.imaState.strURL_s_chain; - self.opts.imaState.w3_s_chain = skale_observer.getWeb3FromURL( u, self.log ); - } else { - self.log( - cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Main-net" ) + - cc.warning( " URL specified in command line arguments" ) + - cc.debug( "(needed for particular operations only)" ) + - "\n" ); - } - // - self.opts.imaState.jo_nodes = new self.opts.imaState.w3_main_net.eth.Contract( self.opts.imaState.joAbiPublishResult_skale_manager.nodes_abi, self.opts.imaState.joAbiPublishResult_skale_manager.nodes_address ); - self.opts.imaState.jo_schains = new self.opts.imaState.w3_main_net.eth.Contract( self.opts.imaState.joAbiPublishResult_skale_manager.schains_abi, self.opts.imaState.joAbiPublishResult_skale_manager.schains_address ); - self.opts.imaState.jo_schains_internal = new self.opts.imaState.w3_main_net.eth.Contract( self.opts.imaState.joAbiPublishResult_skale_manager.schains_internal_abi, self.opts.imaState.joAbiPublishResult_skale_manager.schains_internal_address ); - // - self.opts.imaState.jo_message_proxy_s_chain = new imaState.w3_s_chain.eth.Contract( self.opts.imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, self.opts.imaState.joAbiPublishResult_s_chain.message_proxy_chain_address ); - // - cc.enable( joMessage.message.cc.isEnabled ); - joAnswer.message = { - method: "" + joMessage.method, - error: null - }; - self.log( cc.debug( "Full init compete for in-worker SNB server" ) + " " + cc.notice( g_url ) + "\n" ); - return joAnswer; - }; - self.mapApiHandlers.periodic_caching_start = function( joMessage, joAnswer, eventData, socket ) { - self.periodic_caching_start( - socket, - joMessage.message.secondsToReDiscoverSkaleNetwork, - joMessage.message.strChainNameConnectedTo, - joMessage.message.addressFrom - ); - joAnswer.message = { - method: "" + joMessage.method, - error: null - }; - return joAnswer; - }; - self.mapApiHandlers.periodic_caching_stop = function( joMessage, joAnswer, eventData, socket ) { - self.periodic_caching_stop(); - joAnswer.message = { - method: "" + joMessage.method, - error: null - }; - return joAnswer; - }; - self.log( cc.debug( "Initialized in-worker SNB server" ) + " " + cc.notice( g_url ) + "\n" ); - } - dispose() { - const self = this; - self.isDisposing = true; - if( self.intervalPeriodicSchainsCaching ) { - clearInterval( self.intervalPeriodicSchainsCaching ); - self.intervalPeriodicSchainsCaching = null; - } - super.dispose(); - } - async periodic_caching_do_now( socket, secondsToReDiscoverSkaleNetwork, strChainNameConnectedTo, addressFrom ) { - const self = this; - if( self.bIsPeriodicCachingStepInProgress ) - return; - self.bIsPeriodicCachingStepInProgress = true; - // const strError = - await skale_observer.cache_schains( - strChainNameConnectedTo, - self.opts.imaState.w3_main_net, - self.opts.imaState.w3_s_chain, - addressFrom, - self.opts - ); - self.bIsPeriodicCachingStepInProgress = false; - const arr_schains = skale_observer.get_last_cached_schains(); - // self.log( cc.normal( "Got " ) + cc.info( "SKALE NETWORK" ) + cc.normal( " information in worker: " ) + cc.j( arr_schains ) + "\n" ); - const jo = { - method: "periodic_caching_do_now", - error: null, - message: arr_schains - }; - const isFlush = true; - socket.send( jo, isFlush ); - } - async periodic_caching_start( socket, secondsToReDiscoverSkaleNetwork, strChainNameConnectedTo, addressFrom ) { - const self = this; - await self.periodic_caching_stop(); - if( secondsToReDiscoverSkaleNetwork <= 0 ) - return false; - const fn_async_handler = async function() { - await self.periodic_caching_do_now( socket, secondsToReDiscoverSkaleNetwork, strChainNameConnectedTo, addressFrom ); - }; - self.intervalPeriodicSchainsCaching = setInterval( function() { - if( self.bIsPeriodicCachingStepInProgress ) - return; - fn_async_handler() - .then( () => { - } ).catch( () => { - } ); - }, secondsToReDiscoverSkaleNetwork * 1000 ); - fn_async_handler(); // initial async call - return true; - } - async periodic_caching_stop() { - const self = this; - if( ! self.intervalPeriodicSchainsCaching ) - return false; - clearInterval( self.intervalPeriodicSchainsCaching ); - self.intervalPeriodicSchainsCaching = null; - self.bIsPeriodicCachingStepInProgress = false; - return true; - } -}; - -const acceptor = new network_layer.InWorkerSocketServerAcceptor( g_url, doSendMessage ); -const server = new ObserverServer( acceptor ); -server.on( "dispose", function() { - const self = server; - self.log( cc.debug( "Disposed in-worker SNB server" ) + " " + cc.notice( g_url ) + "\n" ); -} ); diff --git a/npms/skale-observer/package.json b/npms/skale-observer/package.json index 6aff75501..10ccafa8d 100644 --- a/npms/skale-observer/package.json +++ b/npms/skale-observer/package.json @@ -3,13 +3,17 @@ "private": true, "license": "AGPL-3.0", "author": "SKALE Labs and contributors", - "scripts": {}, + "scripts": { + "check-outdated": "yarn outdated", + "upgrade-to-latest": "yarn upgrade --latest" + }, "dependencies": { - "ethereumjs-tx": "2.1.2", - "ethereumjs-wallet": "^1.0.2", - "ethereumjs-util": "^7.1.4", - "web3": "^1.6.1", - "uuid": "3.3.3", + "number-to-bn": "^1.7.0", + "ethers": "^5.7.2", + "@ethersproject/experimental": "^5.7.0", + "ethereum-multicall": "^2.16.1", + "solc": "0.8.6", + "uuid": "^9.0.0", "sha3": "2.1.4" }, "devDependencies": {}, diff --git a/npms/skale-observer/yarn.lock b/npms/skale-observer/yarn.lock index e04aa5e45..71704f000 100644 --- a/npms/skale-observer/yarn.lock +++ b/npms/skale-observer/yarn.lock @@ -2,265 +2,366 @@ # yarn lockfile v1 -"@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348" - integrity sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA== - dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.3" - -"@ethereumjs/tx@^3.3.2": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.4.0.tgz#7eb1947eefa55eb9cf05b3ca116fb7a3dbd0bce7" - integrity sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw== - dependencies: - "@ethereumjs/common" "^2.6.0" - ethereumjs-util "^7.1.3" - -"@ethersproject/abi@5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" - integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== - dependencies: - "@ethersproject/address" "^5.0.4" - "@ethersproject/bignumber" "^5.0.7" - "@ethersproject/bytes" "^5.0.4" - "@ethersproject/constants" "^5.0.4" - "@ethersproject/hash" "^5.0.4" - "@ethersproject/keccak256" "^5.0.3" - "@ethersproject/logger" "^5.0.5" - "@ethersproject/properties" "^5.0.3" - "@ethersproject/strings" "^5.0.4" - -"@ethersproject/abstract-provider@^5.5.0": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" - integrity sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/networks" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/web" "^5.5.0" - -"@ethersproject/abstract-signer@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" - integrity sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - -"@ethersproject/address@^5.0.4", "@ethersproject/address@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" - integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - -"@ethersproject/base64@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" - integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - -"@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" - integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - bn.js "^4.11.9" - -"@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" - integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== - dependencies: - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" - integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - -"@ethersproject/hash@^5.0.4": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" - integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== - dependencies: - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - -"@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" - integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== - dependencies: - "@ethersproject/bytes" "^5.5.0" +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + 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" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/experimental@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" + integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== + dependencies: + "@ethersproject/web" "^5.7.0" + ethers "^5.7.0" + scrypt-js "3.0.1" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" - integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== - -"@ethersproject/networks@^5.5.0": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.1.tgz#b7f7b9fb88dec1ea48f739b7fb9621311aa8ce6c" - integrity sha512-tYRDM4zZtSUcKnD4UMuAlj7SeXH/k5WC4SP2u1Pn57++JdXHkRu2zwNkgNogZoxHzhm9Q6qqurDBVptHOsW49Q== - dependencies: - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" - integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== - dependencies: - "@ethersproject/logger" "^5.5.0" +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== -"@ethersproject/rlp@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" - integrity sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.0.10": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" -"@ethersproject/signing-key@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" - integrity sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng== +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - bn.js "^4.11.9" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" - integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" - integrity sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA== - dependencies: - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - "@ethersproject/signing-key" "^5.5.0" - -"@ethersproject/web@^5.5.0": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316" - integrity sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg== - dependencies: - "@ethersproject/base64" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - -"@types/bn.js@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" - integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== - dependencies: - "@types/node" "*" - -"@types/node@*": - version "17.0.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.8.tgz#50d680c8a8a78fe30abe6906453b21ad8ab0ad7b" - integrity sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg== - -"@types/node@^12.12.6": - version "12.20.41" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.41.tgz#81d7734c5257da9f04354bd9084a6ebbdd5198a5" - integrity sha512-f6xOqucbDirG7LOzedpvzjP3UTmHttRou3Mosx3vL9wr9AIQGhcPgVnqa8ihpZYnxyM1rxeNCvTyukPKZtq10Q== - -"@types/pbkdf2@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" - integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== - dependencies: - "@types/node" "*" - -"@types/secp256k1@^4.0.1": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" - integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== - dependencies: - "@types/node" "*" +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" 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== -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -aes-js@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== ajv@^6.12.3: version "6.12.6" @@ -275,7 +376,7 @@ ajv@^6.12.3: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== ansi-regex@^5.0.1: version "5.0.1" @@ -295,21 +396,6 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -320,45 +406,28 @@ asn1@~0.2.3: assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== 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== -base-x@^3.0.2, base-x@^3.0.8: - version "3.0.9" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" - integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== - dependencies: - safe-buffer "^5.0.1" - base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -367,62 +436,36 @@ base64-js@^1.3.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" -bignumber.js@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" - integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== - -blakejs@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" - integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + integrity sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ== dependencies: inherits "~2.0.0" -bluebird@^3.5.0: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.9: +bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -body-parser@1.19.1, body-parser@^1.16.0: - version "1.19.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== - dependencies: - bytes "3.1.1" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" - type-is "~1.6.18" +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== brace-expansion@^1.1.7: version "1.1.11" @@ -432,90 +475,10 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brorand@^1.0.1, brorand@^1.1.0: +brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= - dependencies: - base-x "^3.0.2" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - -buffer-to-arraybuffer@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== buffer@6.0.3: version "6.0.3" @@ -525,92 +488,20 @@ buffer@6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -bufferutil@^4.0.1: - version "4.0.6" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.6.tgz#ebd6c67c7922a0e902f053e5d8be5ec850e48433" - integrity sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw== - dependencies: - node-gyp-build "^4.3.0" - -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" - integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: - 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" - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -cids@^0.7.1: - version "0.7.5" - resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" - integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== - dependencies: - buffer "^5.5.0" - class-is "^1.1.0" - multibase "~0.6.0" - multicodec "^1.0.0" - multihashes "~0.4.15" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -class-is@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" - integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -619,148 +510,43 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + 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 sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -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-hash@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" - integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== - dependencies: - cids "^0.7.1" - multicodec "^0.5.5" - multihashes "^0.4.15" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== - -cookiejar@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" - integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== 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== -cors@^2.8.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -crc-32@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" - integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - 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" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - 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" - -crypto-browserify@3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" -debug@2.6.9, debug@^2.2.0: - 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@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -768,101 +554,35 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dom-walk@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" - integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: +elliptic@6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -880,284 +600,49 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -es-abstract@^1.18.5: - version "1.19.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" - is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eth-ens-namehash@2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - -eth-lib@0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" - integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -eth-lib@^0.1.26: - version "0.1.29" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" - integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -ethereum-bloom-filters@^1.0.6: - version "1.0.10" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" - integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== - dependencies: - js-sha3 "^0.8.0" - -ethereum-cryptography@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" - integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== - dependencies: - "@types/pbkdf2" "^3.0.0" - "@types/secp256k1" "^4.0.1" - blakejs "^1.1.0" - browserify-aes "^1.2.0" - bs58check "^2.1.2" - create-hash "^1.2.0" - create-hmac "^1.1.7" - hash.js "^1.1.7" - keccak "^3.0.0" - pbkdf2 "^3.0.17" - randombytes "^2.1.0" - safe-buffer "^5.1.2" - scrypt-js "^3.0.0" - secp256k1 "^4.0.1" - setimmediate "^1.0.5" - -ethereumjs-common@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" - integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== - -ethereumjs-tx@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" - integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== - dependencies: - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.0.0" - -ethereumjs-util@^6.0.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23" - integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethereumjs-wallet@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz#2c000504b4c71e8f3782dabe1113d192522e99b6" - integrity sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA== - dependencies: - aes-js "^3.1.2" - bs58check "^2.1.2" - ethereum-cryptography "^0.1.3" - ethereumjs-util "^7.1.2" - randombytes "^2.1.0" - scrypt-js "^3.0.1" - utf8 "^3.0.0" - uuid "^8.3.2" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" - integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== - -express@^4.14.0: - version "4.17.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.1" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.4.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.9.6" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" - setprototypeof "1.2.0" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -ext@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" - integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== - dependencies: - type "^2.5.0" +ethereum-multicall@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/ethereum-multicall/-/ethereum-multicall-2.16.1.tgz#4a0e110b02b4c7a3431361822035fa8dfa3e11cd" + integrity sha512-24MgG22WGHxavIsb6E46Pa6MpkHAkP3pau6R0rQFB4m9gQIxpv5by0Gj4vx7FMjXisFbjlcxVP32hZQXYRP6Yw== + dependencies: + "@ethersproject/providers" "^5.0.10" + ethers "^5.0.15" + +ethers@^5.0.15, ethers@^5.7.0, ethers@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" extend@~3.0.2: version "3.0.2" @@ -1167,7 +652,7 @@ extend@~3.0.2: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== extsprintf@^1.2.0: version "1.4.1" @@ -1184,28 +669,15 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +follow-redirects@^1.12.1: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== form-data@~2.3.2: version "2.3.3" @@ -1216,24 +688,16 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -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 sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== dependencies: graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" fs-minipass@^1.2.7: version "1.2.7" @@ -1245,7 +709,7 @@ fs-minipass@^1.2.7: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fstream@^1.0.0, fstream@^1.0.12: version "1.0.12" @@ -1257,15 +721,10 @@ fstream@^1.0.0, fstream@^1.0.12: mkdirp ">=0.5 0" rimraf "2" -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== - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -1276,115 +735,34 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" glob@^7.0.3, glob@^7.1.3: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + 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.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -global@~4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" - integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== - dependencies: - min-document "^2.19.0" - process "^0.11.10" - -got@9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -got@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" @@ -1394,57 +772,12 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -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" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -1455,57 +788,29 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.1" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@0.4.24, iconv-lite@^0.4.4: +iconv-lite@^0.4.4: 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" -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== - dependencies: - punycode "2.1.0" - -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -1520,12 +825,12 @@ ignore-walk@^3.0.1: inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + 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.4, inherits@~2.0.0, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, 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== @@ -1535,59 +840,10 @@ ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -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== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" @@ -1596,147 +852,40 @@ is-fullwidth-code-point@^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-function@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" - integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= - -is-negative-zero@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - -is-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" - integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== - -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" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== - -is-stream@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.3, is-typed-array@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" - integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-weakref@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + 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 sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -js-sha3@0.8.0, js-sha3@^0.8.0: +js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== json-schema-traverse@^0.4.1: version "0.4.1" @@ -1751,12 +900,12 @@ json-schema@0.4.0: json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== optionalDependencies: graceful-fs "^4.1.6" @@ -1770,92 +919,29 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" -keccak@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" -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== +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= +mime-types@^2.1.12, mime-types@~2.1.19: + 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: - dom-walk "^0.1.0" + mime-db "1.52.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" @@ -1865,19 +951,19 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@^3.0.4, 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" -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" @@ -1894,89 +980,22 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= - dependencies: - mkdirp "*" - -mkdirp@*: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "^1.2.5" - -mock-fs@^4.1.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" - integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + minimist "^1.2.6" -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.3, ms@^2.1.1: +ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multibase@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" - integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multibase@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" - integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multicodec@^0.5.5: - version "0.5.7" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" - integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== - dependencies: - varint "^5.0.0" - -multicodec@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" - integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== - dependencies: - buffer "^5.6.0" - varint "^5.0.0" - -multihashes@^0.4.15, multihashes@~0.4.15: - version "0.4.21" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" - integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== - dependencies: - buffer "^5.5.0" - multibase "^0.7.0" - varint "^5.0.0" - nan@^2.14.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== needle@^2.2.1: version "2.9.1" @@ -1987,31 +1006,11 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== - node-addon-api@^3.0.0: version "3.2.1" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== -node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" - integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== - node-gyp@3.x: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" @@ -2049,7 +1048,7 @@ node-pre-gyp@^0.11.0: "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== dependencies: abbrev "1" @@ -2061,11 +1060,6 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - npm-bundled@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -2100,12 +1094,12 @@ npm-packlist@^1.1.6: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== -number-to-bn@1.7.0: +number-to-bn@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -2115,61 +1109,27 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -oboe@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" - integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= - dependencies: - http-https "^1.0.0" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== -os-tmpdir@^1.0.0: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== osenv@0, osenv@^0.1.4: version "0.1.5" @@ -2179,191 +1139,35 @@ osenv@0, osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= - dependencies: - p-finally "^1.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-headers@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" - integrity sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw== - -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-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 sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -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 sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -pbkdf2@^3.0.17, pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - 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" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -printj@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" - integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== 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== -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -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" - psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, 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" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -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.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== - dependencies: - bytes "3.1.1" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== rc@^1.2.7: version "1.2.8" @@ -2388,16 +1192,7 @@ readable-stream@^2.0.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -request@^2.79.0, request@^2.87.0: +request@^2.87.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -2423,36 +1218,19 @@ request@^2.79.0, request@^2.87.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" +require-from-string@^2.0.0: + 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== -rimraf@2, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.2.3, rlp@^2.2.4: - version "2.2.7" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" - integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== - dependencies: - bn.js "^5.2.0" - -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -2472,7 +1250,7 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scrypt-js@^3.0.0, scrypt-js@^3.0.1: +scrypt-js@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== @@ -2482,16 +1260,7 @@ scrypt-js@^3.0.0, scrypt-js@^3.0.1: dependencies: nan "^2.14.0" -secp256k1@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.2.tgz#15dd57d0f0b9fdb54ac1fa1694f40e5e9a54f4a1" - integrity sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg== - dependencies: - elliptic "^6.5.2" - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - -semver@^5.3.0: +semver@^5.3.0, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2499,70 +1268,12 @@ semver@^5.3.0: semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - -send@0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" - integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "1.8.1" - mime "1.6.0" - ms "2.1.3" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" - integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.2" - -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" + integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw== set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== sha3@2.1.4: version "2.1.4" @@ -2571,33 +1282,25 @@ sha3@2.1.4: dependencies: buffer "6.0.3" -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.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - -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@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== - dependencies: - decompress-response "^3.3.0" - once "^1.3.1" - simple-concat "^1.0.0" + 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== + +solc@0.8.6: + version "0.8.6" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.6.tgz#e4341fa6780137df97b94a0cfbd59b3f2037d0e0" + integrity sha512-miiDaWdaUnD7A6Cktb/2ug9f+ajcOCDYRr7vgbPEsMoutSlBtp5rca57oMg8iHSuM7jilwdxePujWI/+rbNftQ== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" sqlite3@5.0.2: version "5.0.2" @@ -2610,9 +1313,9 @@ sqlite3@5.0.2: node-gyp "3.x" sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -2624,20 +1327,10 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -2652,29 +1345,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -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" @@ -2685,7 +1355,7 @@ string_decoder@~1.1.1: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" @@ -2699,31 +1369,14 @@ strip-ansi@^6.0.1: strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== dependencies: is-hex-prefixed "1.0.0" strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -swarm-js@^0.1.40: - version "0.1.40" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" - integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== tar@^2.0.0: version "2.2.2" @@ -2734,7 +1387,7 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4, tar@^4.0.2: +tar@^4: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -2747,20 +1400,12 @@ tar@^4, tar@^4.0.2: safe-buffer "^5.2.1" yallist "^3.1.1" -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -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== +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" tough-cookie@~2.5.0: version "2.5.0" @@ -2773,64 +1418,14 @@ tough-cookie@~2.5.0: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -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" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" - integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -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 sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== uri-js@^4.2.2: version "4.4.1" @@ -2839,366 +1434,30 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= - -utf-8-validate@^5.0.2: - version "5.0.8" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.8.tgz#4a735a61661dbb1c59a0868c397d2fe263f14e58" - integrity sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA== - dependencies: - node-gyp-build "^4.3.0" - -utf8@3.0.0, utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== - -util-deprecate@^1.0.1, 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 sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util@^0.12.0: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -uuid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -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== - -varint@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" - integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -web3-bzz@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.1.tgz#8430eb3cbb69baaee4981d190b840748c37a9ec2" - integrity sha512-JbnFNbRlwwHJZPtVuCxo7rC4U4OTg+mPsyhjgPQJJhS0a6Y54OgVWYk9UA/95HqbmTJwTtX329gJoSsseEfrng== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - -web3-core-helpers@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.1.tgz#cb21047306871f4cf0fedfece7d47ea2aa96141b" - integrity sha512-om2PZvK1uoWcgMq6JfcSx3241LEIVF6qi2JuHz2SLKiKEW5UsBUaVx0mNCmcZaiuYQCyOsLS3r33q5AdM+v8ng== - dependencies: - web3-eth-iban "1.6.1" - web3-utils "1.6.1" - -web3-core-method@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.1.tgz#4ae91c639bf1da85ebfd8b99595da6a2235d7b98" - integrity sha512-szH5KyIWIaULQDBdDvevQUCHV9lsExJ/oV0ePqK+w015D2SdMPMuhii0WB+HCePaksWO+rr/GAypvV9g2T3N+w== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-utils "1.6.1" - -web3-core-promievent@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.1.tgz#f650dea9361e2edf02691015b213fcc8ea499992" - integrity sha512-byJ5s2MQxrWdXd27pWFmujfzsTZK4ik8rDgIV1RFDFc+rHZ2nZhq+VWk7t/Nkrj7EaVXncEgTdPEHc18nx+ocQ== - dependencies: - eventemitter3 "4.0.4" - -web3-core-requestmanager@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.1.tgz#d9c08b0716c9cda546a0c02767b7e08deb04448a" - integrity sha512-4y7etYEUtkfflyYVBfN1oJtCbVFNhNX1omlEYzezhTnPj3/dT7n+dhUXcqvIhx9iKA13unGfpFge80XNFfcB8A== - dependencies: - util "^0.12.0" - web3-core-helpers "1.6.1" - web3-providers-http "1.6.1" - web3-providers-ipc "1.6.1" - web3-providers-ws "1.6.1" - -web3-core-subscriptions@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.1.tgz#4dfc1f74137354d4ac9eaa628aa916c5e2cc8741" - integrity sha512-WZwxsYttIojyGQ5RqxuQcKg0IJdDCFpUe4EncS3QKZwxPqWzGmgyLwE0rm7tP+Ux1waJn5CUaaoSCBxWGSun1g== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - -web3-core@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.1.tgz#b41f08fdc9ea1082d15384a3d6fa93a47c3fc1b4" - integrity sha512-m+b7UfYvU5cQUAh6NRfxRzH/5B3to1AdEQi1HIQt570cDWlObOOmoO9tY6iJnI5w4acxIO19LqjDMqEJGBYyRQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-requestmanager "1.6.1" - web3-utils "1.6.1" - -web3-eth-abi@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.6.1.tgz#15b937e3188570754d50bbac51a4bb0578600d1d" - integrity sha512-svhYrAlXP9XQtV7poWKydwDJq2CaNLMtmKydNXoOBLcQec6yGMP+v20pgrxF2H6wyTK+Qy0E3/5ciPOqC/VuoQ== - dependencies: - "@ethersproject/abi" "5.0.7" - web3-utils "1.6.1" - -web3-eth-accounts@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.1.tgz#aeb0dfb52c4391773550569732975b471212583f" - integrity sha512-rGn3jwnuOKwaQRu4SiShz0YAQ87aVDBKs4HO43+XTCI1q1Y1jn3NOsG3BW9ZHaOckev4+zEyxze/Bsh2oEk24w== - dependencies: - "@ethereumjs/common" "^2.5.0" - "@ethereumjs/tx" "^3.3.2" - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-util "^7.0.10" - scrypt-js "^3.0.1" - uuid "3.3.2" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-eth-contract@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.1.tgz#4b0a2c0b37015d70146e54c7cb3f035a58fbeec0" - integrity sha512-GXqTe3mF6kpbOAakiNc7wtJ120/gpuKMTZjuGFKeeY8aobRLfbfgKzM9IpyqVZV2v5RLuGXDuurVN2KPgtu3hQ== - dependencies: - "@types/bn.js" "^4.11.5" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-utils "1.6.1" - -web3-eth-ens@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.1.tgz#801bd5fb5237377ec2ed8517a9fe4634f2269c7a" - integrity sha512-ngprtbnoRgxg8s1wXt9nXpD3h1P+p7XnKXrp/8GdFI9uDmrbSQPRfzBw86jdZgOmy78hAnWmrHI6pBInmgi2qQ== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-contract "1.6.1" - web3-utils "1.6.1" - -web3-eth-iban@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.1.tgz#20bbed75723e3e9ff98e624979629d26329462b6" - integrity sha512-91H0jXZnWlOoXmc13O9NuQzcjThnWyAHyDn5Yf7u6mmKOhpJSGF/OHlkbpXt1Y4v2eJdEPaVFa+6i8aRyagE7Q== - dependencies: - bn.js "^4.11.9" - web3-utils "1.6.1" - -web3-eth-personal@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.1.tgz#9b524fb9f92b51163f46920ee2663d34a4897c8d" - integrity sha512-ItsC89Ln02+irzJjK6ALcLrMZfbVUCqVbmb/ieDKJ+eLW3pNkBNwoUzaydh92d5NzxNZgNxuQWVdlFyYX2hkEw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-eth@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.1.tgz#a25aba1ac213d872ecf3f81c7b4ab8072ecae224" - integrity sha512-kOV1ZgCKypSo5BQyltRArS7ZC3bRpIKAxSgzl7pUFinUb/MxfbM9KGeNxUXoCfTSErcCQJaDjcS6bSre5EMKuQ== - dependencies: - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-accounts "1.6.1" - web3-eth-contract "1.6.1" - web3-eth-ens "1.6.1" - web3-eth-iban "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-net@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.1.tgz#7a630a804ec9f81908ae52ccbb4ebbb9530b3906" - integrity sha512-gpnqKEIwfUHh5ik7wsQFlCje1DfcmGv+Sk7LCh1hCqn++HEDQxJ/mZCrMo11ZZpZHCH7c87imdxTg96GJnRxDw== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-providers-http@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.1.tgz#b59b14eefef23b98c327806f5f566303a73bd435" - integrity sha512-xBoKOJxu10+kO3ikamXmBfrWZ/xpQOGy0ocdp7Y81B17En5TXELwlmMXt1UlIgWiyYDhjq4OwlH/VODYqHXy3A== - dependencies: - web3-core-helpers "1.6.1" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.1.tgz#7ba460589d46896bb3d124288deed1b6a72d517e" - integrity sha512-anyoIZlpMzwEQI4lwylTzDrHsVp20v0QUtSTp2B5jInBinmQtyCE7vnbX20jEQ4j5uPwfJabKNtoJsk6a3O4WQ== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.6.1" - -web3-providers-ws@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.1.tgz#f7ee71f158971102b865e99ea7911f483e0507e9" - integrity sha512-FWMEFYb4rYFYRgSFBf/O1Ex4p/YKSlN+JydCtdlJwRimd89qm95CTfs4xGjCskwvXMjV2sarH+f1NPwJXicYpg== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - websocket "^1.0.32" - -web3-shh@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.1.tgz#eebaab2e5e6be80fe2585c6c094fa10a03349ca7" - integrity sha512-oP00HbAtybLCGlLOZUYXOdeB9xq88k2l0TtStvKBtmFqRt+zVk5TxEeuOnVPRxNhcA2Un8RUw6FtvgZlWStu9A== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-net "1.6.1" - -web3-utils@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.6.1.tgz#befcb23922b00603ab56d8c5b4158468dc494aca" - integrity sha512-RidGKv5kOkcerI6jQqDFDoTllQQqV+rPhTzZHhmbqtFObbYpU93uc+yG1LHivRTQhA6llIx67iudc/vzisgO+w== - dependencies: - bn.js "^4.11.9" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - -web3@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.1.tgz#c9e68fe7b3073adddf35393441f950ec69b92735" - integrity sha512-c299lLiyb2/WOcxh7TinwvbATaMmrgNIeAzbLbmOKHI0LcwyfsB1eu2ReOIrfrCYDYRW2KAjYr7J7gHawqDNPQ== - dependencies: - web3-bzz "1.6.1" - web3-core "1.6.1" - web3-eth "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-shh "1.6.1" - web3-utils "1.6.1" - -websocket@^1.0.32: - version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" - integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - 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" - -which-typed-array@^1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" - integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.7" - which@1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -3216,63 +1475,12 @@ wide-align@^1.1.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -xhr-request-promise@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" - integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== - dependencies: - xhr-request "^1.1.0" - -xhr-request@^1.0.1, xhr-request@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== - dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= - dependencies: - cookiejar "^2.1.1" - -xhr@^2.0.4, xhr@^2.3.3: - version "2.6.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" - integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== - dependencies: - global "~4.4.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== yallist@^3.0.0, yallist@^3.1.1: version "3.1.1" diff --git a/npms/skale-owasp/owasp-util.js b/npms/skale-owasp/owasp-util.js deleted file mode 100644 index c7e51d941..000000000 --- a/npms/skale-owasp/owasp-util.js +++ /dev/null @@ -1,671 +0,0 @@ - -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * SKALE IMA is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * SKALE IMA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with SKALE IMA. If not, see . - */ - -/** - * @file owasp-util.js - * @copyright SKALE Labs 2019-Present - */ - -// introduction: https://github.com/Checkmarx/JS-SCP -// main PDF with rules to follow: https://www.gitbook.com/download/pdf/book/checkmarx/JS-SCP -// top 10 hit parade: https://owasp.org/www-project-top-ten/ - -const fs = require( "fs" ); -// const path = require( "path" ); -// const url = require( "url" ); -// const os = require( "os" ); - -const cc = require( "../skale-cc/cc.js" ); -const w3mod = require( "web3" ); -const ethereumjs_tx = require( "ethereumjs-tx" ); -const ethereumjs_wallet = require( "ethereumjs-wallet" ); -const ethereumjs_util = require( "ethereumjs-util" ); - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function rxIsInt( val ) { - try { - const intRegex = /^-?\d+$/; - if( !intRegex.test( val ) ) - return false; - const intVal = parseInt( val, 10 ); - if( parseFloat( val ) == intVal && ( !isNaN( intVal ) ) ) - return true; - } catch ( err ) { - } - return false; -} - -function rxIsFloat( val ) { - try { - const floatRegex = /^-?\d+(?:[.,]\d*?)?$/; - if( !floatRegex.test( val ) ) - return false; - val = parseFloat( val ); - if( isNaN( val ) ) - return false; - return true; - } catch ( err ) { - } - return false; -} - -function validateRadix( value, radix ) { - value = "" + ( value ? value.toString() : "10" ); - value = value.trim(); - radix = ( radix == null || radix == undefined ) - ? ( ( value.length > 2 && value[0] == "0" && ( value[1] == "x" || value[1] == "X" ) ) ? 16 : 10 ) - : parseInt( radix, 10 ); - return radix; -} - -function validateInteger( value, radix ) { - try { - value = "" + value; - value = value.trim(); - if( value.length < 1 ) - return false; - radix = validateRadix( value, radix ); - if( ( !isNaN( value ) ) && - ( parseInt( Number( value ), radix ) == value || radix !== 10 ) && - ( !isNaN( parseInt( value, radix ) ) ) - ) - return true; - } catch ( err ) { - } - return false; -} - -function toInteger( value, radix ) { - try { - radix = validateRadix( value, radix ); - if( !validateInteger( value, radix ) ) - return NaN; - return parseInt( value, radix ); - } catch ( err ) { - } - return false; -} - -function validateFloat( value ) { - try { - const f = parseFloat( value ); - if( isNaN( f ) ) - return false; - return true; - } catch ( err ) { - } - return false; -} - -function toFloat( value ) { - try { - const f = parseFloat( value ); - return f; - } catch ( err ) { - } - return false; -} - -function validateURL( s ) { - const u = toURL( s ); - if( u == null ) - return false; - return true; -} - -function toURL( s ) { - try { - if( s == null || s == undefined ) - return null; - if( typeof s !== "string" ) - return null; - s = s.trim(); - if( s.length <= 0 ) - return null; - const sc = s[0]; - if( sc == "\"" || sc == "'" ) { - const cnt = s.length; - if( s[cnt - 1] == sc ) { - const ss = s.substring( 1, cnt - 1 ); - const u = toURL( ss ); - if( u != null && u != undefined ) - u.strStrippedStringComma = sc; - return u; - } - return null; - } - const u = new URL( s ); - if( !u.hostname ) - return null; - if( u.hostname.length === 0 ) - return null; - u.strStrippedStringComma = null; - return u; - } catch ( err ) { - return null; - } -} - -function toStringURL( s, defValue ) { - defValue = defValue || ""; - try { - const u = toURL( s ); - if( u == null || u == undefined ) - return defValue; - return u.toString(); - } catch ( err ) { - return defValue; - } -} - -function toBoolean( value ) { - let b = false; - try { - if( typeof value === "boolean" ) - return value; - if( typeof value === "string" ) { - const ch = value[0].toLowerCase(); - if( ch == "y" || ch == "t" ) - b = true; else if( validateInteger( value ) ) - b = !!toInteger( value ); else if( validateFloat( value ) ) - b = !!toFloat( value ); else - b = !!b; - } else - b = !!b; - } catch ( err ) { - b = false; - } - b = !!b; - return b; -} - -// see https://ethereum.stackexchange.com/questions/1374/how-can-i-check-if-an-ethereum-address-is-valid -function validateEthAddress( value ) { - try { - if( ethereumjs_util.isValidAddress( ensure_starts_with_0x( value ) ) ) - return true; - } catch ( err ) { - } - return false; -} - -// see https://gist.github.com/miguelmota/20fcd7c5c2604907dcbba749ea3f1e8c -function validateEthPrivateKey( value ) { - try { - value = "" + ( value ? value.toString() : "" ); - const buffer = Buffer.from( remove_starting_0x( value ), "hex" ); - if( ethereumjs_util.isValidPrivate( buffer ) ) - return true; - } catch ( err ) { - } - return false; -} - -function toEthAddress( value, defValue ) { - try { - value = "" + ( value ? ensure_starts_with_0x( value.toString() ) : "" ); - defValue = defValue || ""; - if( !validateEthAddress( value ) ) - return defValue; - } catch ( err ) { - } - return value; -} - -function toEthPrivateKey( value, defValue ) { - try { - value = "" + ( value ? value.toString() : "" ); - defValue = defValue || ""; - if( !validateEthPrivateKey( value ) ) - return defValue; - } catch ( err ) { - } - return value; -} - -function verifyArgumentWithNonEmptyValue( joArg ) { - if( ( !joArg.value ) || ( typeof joArg.value === "string" && joArg.value.length === 0 ) ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must not be empty" ) ); - process.exit( 126 ); - } - return joArg; -} - -function verifyArgumentIsURL( joArg ) { - try { - verifyArgumentWithNonEmptyValue( joArg ); - const u = toURL( joArg.value ); - if( u == null ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid URL" ) ); - process.exit( 126 ); - } - if( u.hostname.length <= 0 ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid URL" ) ); - process.exit( 126 ); - } - return joArg; - } catch ( err ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid URL" ) ); - process.exit( 126 ); - } -} - -function verifyArgumentIsInteger( joArg ) { - try { - verifyArgumentWithNonEmptyValue( joArg ); - if( !validateInteger( joArg.value ) ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid integer" ) ); - process.exit( 126 ); - } - joArg.value = toInteger( joArg.value ); - return joArg; - } catch ( err ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid integer" ) ); - process.exit( 126 ); - } -} - -function verifyArgumentIsIntegerIpPortNumber( joArg ) { - try { - verifyArgumentIsInteger( joArg ); - if( joArg.value < 0 ) - throw new Error( "Port number " + joArg.value + " cannot be negative" ); - if( joArg.value < 1 ) - throw new Error( "Port number " + joArg.value + " too small" ); - if( joArg.value > 65535 ) - throw new Error( "Port number " + joArg.value + " too big" ); - } catch ( err ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid integer IP port number" ) ); - process.exit( 126 ); - } -} - -function verifyArgumentIsPathToExistingFile( joArg ) { - try { - verifyArgumentWithNonEmptyValue( joArg ); - const stats = fs.lstatSync( joArg.value ); - if( stats.isDirectory() ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be path to existing file, path to folder provided" ) ); - process.exit( 126 ); - } - if( !stats.isFile() ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be path to existing file, bad path provided" ) ); - process.exit( 126 ); - } - return joArg; - } catch ( err ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be path to existing file" ) ); - process.exit( 126 ); - } -} - -function verifyArgumentIsPathToExistingFolder( joArg ) { - try { - verifyArgumentWithNonEmptyValue( joArg ); - const stats = fs.lstatSync( joArg.value ); - if( stats.isFile() ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be path to existing folder, path to file provided" ) ); - process.exit( 126 ); - } - if( !stats.isDirectory() ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be path to existing folder, bad path provided" ) ); - process.exit( 126 ); - } - return joArg; - } catch ( err ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be path to existing folder" ) ); - process.exit( 126 ); - } -} - -function verifyArgumentIsArrayOfIntegers( joArg ) { - try { - verifyArgumentWithNonEmptyValue( joArg ); - if( joArg.value.length < 3 ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " length " ) + cc.warning( joArg.value.length ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be bigger than 2" ) ); - process.exit( 126 ); - } - if( joArg.value[0] !== "[" || joArg.value[joArg.value.length - 1] !== "]" ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " first and last symbol " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be brackets" ) ); - process.exit( 126 ); - } - const newValue = joArg.value.replace( "[", "" ).replace( "]", "" ).split( "," ); - for( let index = 0; index < newValue.length; index++ ) { - if( !newValue[index] || ( typeof newValue[index] === "string" && newValue[index].length === 0 ) ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( newValue[index] ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must not be empty" ) ); - process.exit( 126 ); - } - if( !validateInteger( newValue[index] ) ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( newValue[index] ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid integer" ) ); - process.exit( 126 ); - } - newValue[index] = toInteger( newValue[index] ); - } - return newValue; - } catch ( err ) { - console.log( cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + cc.error( " must be valid integer array" ) ); - process.exit( 126 ); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function ensure_starts_with_0x( s ) { - if( s == null || s == undefined || typeof s !== "string" ) - return s; - if( s.length < 2 ) - return "0x" + s; - if( s[0] == "0" && s[1] == "x" ) - return s; - return "0x" + s; -} - -function remove_starting_0x( s ) { - if( s == null || s == undefined || typeof s !== "string" ) - return s; - if( s.length < 2 ) - return s; - if( s[0] == "0" && s[1] == "x" ) - return s.substr( 2 ); - return s; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function inet_ntoa( n ) { - const a = ( ( n >> 24 ) & 0xFF ) >>> 0; - const b = ( ( n >> 16 ) & 0xFF ) >>> 0; - const c = ( ( n >> 8 ) & 0xFF ) >>> 0; - const d = ( n & 0xFF ) >>> 0; - return ( a + "." + b + "." + c + "." + d ); -} - -function ip_from_hex( hex ) { - return inet_ntoa( parseInt( remove_starting_0x( hex ), 16 ) ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function private_key_2_public_key( w3, keyPrivate ) { - if( w3 == null || w3 == undefined || keyPrivate == null || keyPrivate == undefined ) - return ""; - // get a wallet instance from a private key - const privateKeyBuffer = ethereumjs_util.toBuffer( ensure_starts_with_0x( keyPrivate ) ); - const wallet = ethereumjs_wallet.fromPrivateKey( privateKeyBuffer ); - // get a public key - const keyPublic = wallet.getPublicKeyString(); - return remove_starting_0x( keyPublic ); -} - -function public_key_2_account_address( w3, keyPublic ) { - if( w3 == null || w3 == undefined || keyPublic == null || keyPublic == undefined ) - return ""; - const hash = w3.utils.sha3( ensure_starts_with_0x( keyPublic ) ); - const strAddress = ensure_starts_with_0x( hash.substr( hash.length - 40 ) ); - return strAddress; -} - -function private_key_2_account_address( w3, keyPrivate ) { - const keyPublic = private_key_2_public_key( w3, keyPrivate ); - const strAddress = public_key_2_account_address( w3, keyPublic ); - return strAddress; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// example: "1ether" -> "1000000000000000000" -// supported suffixes, lowercase -// const g_arrMoneyNameSuffixes = [ "ether", "finney", "szabo", "shannon", "lovelace", "babbage", "wei" ]; - -// supported suffix aliases, lowercase -const g_mapMoneyNameSuffixAliases = { - "ethe": "ether", - "ethr": "ether", - "eth": "ether", - "eter": "ether", - "ete": "ether", - "et": "ether", - "eh": "ether", - "er": "ether", - // "e": "ether", - "finne": "finney", - "finn": "finney", - "fin": "finney", - "fn": "finney", - "fi": "finney", - // "f": "finney", - "szab": "szabo", - "szb": "szabo", - "sza": "szabo", - "sz": "szabo", - "shanno": "shannon", - "shannn": "shannon", - "shann": "shannon", - "shan": "shannon", - "sha": "shannon", - "shn": "shannon", - "sh": "shannon", - "lovelac": "lovelace", - "lovela": "lovelace", - "lovel": "lovelace", - "love": "lovelace", - "lovl": "lovelace", - "lvl": "lovelace", - "lvla": "lovelace", - "lvlc": "lovelace", - "lvc": "lovelace", - "lv": "lovelace", - "lo": "lovelace", - "lc": "lovelace", - "ll": "lovelace", - // "l": "lovelace", - "babbag": "babbage", - "babba": "babbage", - "babbg": "babbage", - "babb": "babbage", - "bab": "babbage", - "bag": "babbage", - "bbb": "babbage", - "bb": "babbage", - "bg": "babbage", - "ba": "babbage", - "be": "babbage", - // "b": "babbage", - "we": "wei", - "wi": "wei", - // "w": "wei", - // - // next going as is because supported by wev3.utils.toWei() API - // - "noether": "noether", - "noeth": "noether", - "kwei": "kwei", - "femtoether": "femtoether", - "femto": "femtoether", - "mwei": "mwei", - "picoether": "picoether", - "pico": "picoether", - "gwei": "gwei", - "nanoether": "nanoether", - "nano": "nanoether", - "microether": "microether", - "micro": "microether", - "milliether": "milliether", - "milli": "milliether", - "kether": "kether", - "mether": "mether", - "gether": "gether", - "tether": "tether" -}; - -function parseMoneyUnitName( s ) { - s = s.trim().toLowerCase(); - if( s == "" ) - return "wei"; - if( s in g_mapMoneyNameSuffixAliases ) { - s = g_mapMoneyNameSuffixAliases[s]; - return s; - } - // if( g_arrMoneyNameSuffixes.indexOf( s ) >= 0 ) - // return s; - // throw new Error( "\"" + s + "\" is unknown money unit name" ); - return s; -} - -function is_numeric( s ) { - return /^\d+$/.test( s ); -} - -function parseMoneySpecToWei( w3, s, isThrowException ) { - try { - w3 = w3 || global.w3mod; - isThrowException = isThrowException ? true : false; - if( s == null || s == undefined ) { - if( isThrowException ) - throw new Error( "no parse-able value provided" ); - return "0"; - } - s = s.toString().trim(); - let strNumber = ""; - while( s.length > 0 ) { - const chr = s[0]; - if( is_numeric( chr ) || chr == "." ) { - strNumber += chr; - s = s.substr( 1 ); // remove first character - continue; - } - if( chr == " " || chr == "\t" || chr == "\r" || chr == "\n" ) - s = s.substr( 1 ); // remove first character - s = s.trim().toLowerCase(); - break; - } - // here s is rest suffix string, number is number as string or empty string - if( strNumber == "" ) - throw new Error( "no number or float value found" ); - s = parseMoneyUnitName( s ); - s = w3.utils.toWei( strNumber, s ); - s = s.toString( 10 ); - return s; - } catch ( err ) { - if( isThrowException ) - throw new Error( "Parse error in parseMoneySpecToWei(\"" + s + "\"), error is: " + err.toString() ); - } - return "0"; -} - -function fn_address_impl_( w3 ) { - if( this.address_ == undefined || this.address_ == null ) - this.address_ = "" + owaspUtils.private_key_2_account_address( w3, this.privateKey ); - return this.address_; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function compute_chain_id_from_schain_name( w3, strName ) { - let h = w3.utils.soliditySha3( strName ); - h = remove_starting_0x( h ).toLowerCase(); - while( h.length < 64 ) - h = "0" + h; - h = h.substr( 0, 14 ); - return "0x" + h; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function w3provider_2_url( provider ) { - if( ! provider ) - return null; - if( "host" in provider ) { - const u = provider.host.toString(); - if( u && cc.safeURL( u ) ) - return u; - } - if( "url" in provider ) { - const u = provider.url.toString(); - if( u && cc.safeURL( u ) ) - return u; - } - return null; -} - -function w3_2_url( w3 ) { - if( ! w3 ) - return null; - if( !( "currentProvider" in w3 ) ) - return null; - return w3provider_2_url( w3.currentProvider ); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -module.exports = { - cc: cc, - w3mod: w3mod, - ethereumjs_tx: ethereumjs_tx, - ethereumjs_wallet: ethereumjs_wallet, - ethereumjs_util: ethereumjs_util, - owaspAddUsageRef: function() { }, - rxIsInt: rxIsInt, - rxIsFloat: rxIsFloat, - validateRadix: validateRadix, - validateInteger: validateInteger, - toInteger: toInteger, - validateFloat: validateFloat, - toFloat: toFloat, - validateURL: validateURL, - toURL: toURL, - toStringURL: toStringURL, - toBoolean: toBoolean, - validateEthAddress: validateEthAddress, - validateEthPrivateKey: validateEthPrivateKey, - toEthAddress: toEthAddress, - toEthPrivateKey: toEthPrivateKey, - verifyArgumentWithNonEmptyValue: verifyArgumentWithNonEmptyValue, - verifyArgumentIsURL: verifyArgumentIsURL, - verifyArgumentIsInteger: verifyArgumentIsInteger, - verifyArgumentIsIntegerIpPortNumber: verifyArgumentIsIntegerIpPortNumber, - verifyArgumentIsPathToExistingFile: verifyArgumentIsPathToExistingFile, - verifyArgumentIsPathToExistingFolder: verifyArgumentIsPathToExistingFolder, - verifyArgumentIsArrayOfIntegers: verifyArgumentIsArrayOfIntegers, - ensure_starts_with_0x: ensure_starts_with_0x, - remove_starting_0x: remove_starting_0x, - inet_ntoa: inet_ntoa, - ip_from_hex: ip_from_hex, - private_key_2_public_key: private_key_2_public_key, - public_key_2_account_address: public_key_2_account_address, - private_key_2_account_address: private_key_2_account_address, - is_numeric: is_numeric, - parseMoneyUnitName: parseMoneyUnitName, - parseMoneySpecToWei: parseMoneySpecToWei, - fn_address_impl_: fn_address_impl_, - compute_chain_id_from_schain_name: compute_chain_id_from_schain_name, - w3provider_2_url: w3provider_2_url, - w3_2_url: w3_2_url -}; // module.exports diff --git a/npms/skale-owasp/owaspUtils.mjs b/npms/skale-owasp/owaspUtils.mjs new file mode 100644 index 000000000..8ceb80536 --- /dev/null +++ b/npms/skale-owasp/owaspUtils.mjs @@ -0,0 +1,814 @@ + +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + +/** + * @file owaspUtils.mjs + * @copyright SKALE Labs 2019-Present + */ + +// introduction: https://github.com/Checkmarx/JS-SCP +// main PDF with rules to follow: +// https://www.gitbook.com/download/pdf/book/checkmarx/JS-SCP +// top 10 hit parade: https://owasp.org/www-project-top-ten/ + +import * as ethersMod from "ethers"; +import * as fs from "fs"; +import * as cc from "../skale-cc/cc.mjs"; +import * as ethereumJsUtilModule from "ethereumjs-util"; +import * as ethereumJsWalletModule from "ethereumjs-wallet"; +const Wallet = ethereumJsWalletModule.default.default; + +const safeURL = cc.safeURL; +const replaceAll = cc.replaceAll; + +export { ethersMod, safeURL, replaceAll }; + +export function rxIsInt( val ) { + try { + const intRegex = /^-?\d+$/; + if( !intRegex.test( val ) ) + return false; + const intVal = parseInt( val, 10 ); + if( parseFloat( val ) == intVal && ( !isNaN( intVal ) ) ) + return true; + } catch ( err ) { + } + return false; +} + +export function rxIsFloat( val ) { + try { + const floatRegex = /^-?\d+(?:[.,]\d*?)?$/; + if( !floatRegex.test( val ) ) + return false; + val = parseFloat( val ); + if( isNaN( val ) ) + return false; + return true; + } catch ( err ) { + } + return false; +} + +export function parseIntOrHex( s ) { + if( typeof s != "string" ) + return parseInt( s ); + s = s.trim(); + if( s.length > 2 && s[0] == "0" && ( s[1] == "x" || s[1] == "X" ) ) + return parseInt( s, 16 ); + return parseInt( s, 10 ); +} + +export function validateRadix( value, radix ) { + value = "" + ( value ? value.toString() : "10" ); + value = value.trim(); + radix = ( radix == null || radix == undefined ) + ? ( ( value.length > 2 && value[0] == "0" && ( value[1] == "x" || value[1] == "X" ) ) + ? 16 : 10 ) + : parseInt( radix, 10 ); + return radix; +} + +export function validateInteger( value, radix ) { + try { + value = "" + value; + value = value.trim(); + if( value.length < 1 ) + return false; + radix = validateRadix( value, radix ); + if( ( !isNaN( value ) ) && + ( parseInt( Number( value ), radix ) == value || radix !== 10 ) && + ( !isNaN( parseInt( value, radix ) ) ) + ) + return true; + } catch ( err ) { + } + return false; +} + +export function toInteger( value, radix ) { + try { + radix = validateRadix( value, radix ); + if( !validateInteger( value, radix ) ) + return NaN; + return parseInt( value, radix ); + } catch ( err ) { + } + return false; +} + +export function validateFloat( value ) { + try { + const f = parseFloat( value ); + if( isNaN( f ) ) + return false; + return true; + } catch ( err ) { + } + return false; +} + +export function toFloat( value ) { + try { + const f = parseFloat( value ); + return f; + } catch ( err ) { + } + return false; +} + +export function validateURL( s ) { + const u = toURL( s ); + if( u == null ) + return false; + return true; +} + +export function toURL( s ) { + try { + if( s == null || s == undefined ) + return null; + if( typeof s !== "string" ) + return null; + s = s.trim(); + if( s.length <= 0 ) + return null; + const sc = s[0]; + if( sc == "\"" || sc == "'" ) { + const cnt = s.length; + if( s[cnt - 1] == sc ) { + const ss = s.substring( 1, cnt - 1 ); + const u = toURL( ss ); + if( u != null && u != undefined ) + u.strStrippedStringComma = sc; + return u; + } + return null; + } + const u = new URL( s ); + if( !u.hostname ) + return null; + if( u.hostname.length === 0 ) + return null; + u.strStrippedStringComma = null; + return u; + } catch ( err ) { + return null; + } +} + +export function toStringURL( s, defValue ) { + defValue = defValue || ""; + try { + const u = toURL( s ); + if( u == null || u == undefined ) + return defValue; + return u.toString(); + } catch ( err ) { + return defValue; + } +} + +export function isUrlHTTP( strURL ) { + try { + if( !validateURL( strURL ) ) + return false; + const u = new URL( strURL ); + if( u.protocol == "http:" || u.protocol == "https:" ) + return true; + } catch ( err ) { + } + return false; +} + +export function isUrlWS( strURL ) { + try { + if( !validateURL( strURL ) ) + return false; + const u = new URL( strURL ); + if( u.protocol == "ws:" || u.protocol == "wss:" ) + return true; + } catch ( err ) { + } + return false; +} + +export function toBoolean( value ) { + let b = false; + try { + if( typeof value === "boolean" ) + return value; + if( typeof value === "string" ) { + const ch = value[0].toLowerCase(); + if( ch == "y" || ch == "t" ) + b = true; else if( validateInteger( value ) ) + b = !!toInteger( value ); else if( validateFloat( value ) ) + b = !!toFloat( value ); else + b = !!b; + } else + b = !!b; + } catch ( err ) { + b = false; + } + b = !!b; + return b; +} + +export function validateInputAddresses( address ) { + return ( /^(0x){1}[0-9a-fA-F]{40}$/i.test( address ) ); +} + +export function validateEthAddress( value ) { + try { + if( validateInputAddresses( ensureStartsWith0x( value ) ) ) + return true; + } catch ( err ) { + } + return false; +} + +export function validateEthPrivateKey( value ) { + try { + const ethersWallet = new ethersMod.ethers.Wallet( ensureStartsWith0x( value ) ); + if( ethersWallet.address ) + return true; + } catch ( err ) { + } + return false; +} + +export function toEthAddress( value, defValue ) { + try { + value = "" + ( value ? ensureStartsWith0x( value.toString() ) : "" ); + defValue = defValue || ""; + if( !validateEthAddress( value ) ) + return defValue; + } catch ( err ) { + } + return value; +} + +export function toEthPrivateKey( value, defValue ) { + try { + value = "" + ( value ? value.toString() : "" ); + defValue = defValue || ""; + if( !validateEthPrivateKey( value ) ) + return defValue; + } catch ( err ) { + } + return value; +} + +export function verifyArgumentWithNonEmptyValue( joArg ) { + if( ( !joArg.value ) || ( typeof joArg.value === "string" && joArg.value.length === 0 ) ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must not be empty" ) + ); + process.exit( 126 ); + } + return joArg; +} + +export function verifyArgumentIsURL( joArg ) { + try { + verifyArgumentWithNonEmptyValue( joArg ); + const u = toURL( joArg.value ); + if( u == null ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be valid URL" ) + ); + process.exit( 126 ); + } + if( u.hostname.length <= 0 ) { + console.log( cc.fatal( + "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + cc.warning( joArg.value ) + + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be valid URL" ) + ); + process.exit( 126 ); + } + return joArg; + } catch ( err ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be valid URL" ) + ); + process.exit( 126 ); + } +} + +export function verifyArgumentIsInteger( joArg ) { + try { + verifyArgumentWithNonEmptyValue( joArg ); + if( !validateInteger( joArg.value ) ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be valid integer" ) + ); + process.exit( 126 ); + } + joArg.value = toInteger( joArg.value ); + return joArg; + } catch ( err ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be valid integer" ) + ); + process.exit( 126 ); + } +} + +export function verifyArgumentIsIntegerIpPortNumber( joArg ) { + try { + verifyArgumentIsInteger( joArg ); + if( joArg.value < 0 ) + throw new Error( "Port number " + joArg.value + " cannot be negative" ); + if( joArg.value < 1 ) + throw new Error( "Port number " + joArg.value + " too small" ); + if( joArg.value > 65535 ) + throw new Error( "Port number " + joArg.value + " too big" ); + return joArg; + } catch ( err ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be valid integer IP port number" ) + ); + process.exit( 126 ); + } +} + +export function verifyArgumentIsPathToExistingFile( joArg ) { + try { + verifyArgumentWithNonEmptyValue( joArg ); + const stats = fs.lstatSync( joArg.value ); + if( stats.isDirectory() ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be path to existing file, path to folder provided" ) + ); + process.exit( 126 ); + } + if( !stats.isFile() ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be path to existing file, bad path provided" ) + ); + process.exit( 126 ); + } + return joArg; + } catch ( err ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be path to existing file" ) + ); + process.exit( 126 ); + } +} + +export function verifyArgumentIsPathToExistingFolder( joArg ) { + try { + verifyArgumentWithNonEmptyValue( joArg ); + const stats = fs.lstatSync( joArg.value ); + if( stats.isFile() ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + + cc.info( joArg.name ) + + cc.error( " must be path to existing folder, path to file provided" ) + ); + process.exit( 126 ); + } + if( !stats.isDirectory() ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be path to existing folder, bad path provided" ) + ); + process.exit( 126 ); + } + return joArg; + } catch ( err ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + + cc.info( joArg.name ) + cc.error( " must be path to existing folder" ) + ); + process.exit( 126 ); + } +} + +export function verifyArgumentIsArrayOfIntegers( joArg ) { + try { + verifyArgumentWithNonEmptyValue( joArg ); + if( joArg.value.length < 3 ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " length " ) + + cc.warning( joArg.value.length ) + cc.error( " of argument " ) + + cc.info( joArg.name ) + cc.error( " must be bigger than 2" ) + ); + process.exit( 126 ); + } + if( joArg.value[0] !== "[" || joArg.value[joArg.value.length - 1] !== "]" ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " first and last symbol " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + cc.info( joArg.name ) + + cc.error( " must be brackets" ) + ); + process.exit( 126 ); + } + const newValue = joArg.value.replace( "[", "" ).replace( "]", "" ).split( "," ); + for( let index = 0; index < newValue.length; index++ ) { + if( !newValue[index] || + ( typeof newValue[index] === "string" && newValue[index].length === 0 ) + ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( newValue[index] ) + cc.error( " of argument " ) + + cc.info( joArg.name ) + cc.error( " must not be empty" ) + ); + process.exit( 126 ); + } + if( !validateInteger( newValue[index] ) ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( newValue[index] ) + cc.error( " of argument " ) + + cc.info( joArg.name ) + cc.error( " must be valid integer" ) + ); + process.exit( 126 ); + } + newValue[index] = toInteger( newValue[index] ); + } + return newValue; + } catch ( err ) { + console.log( + cc.fatal( "(OWASP) CRITICAL ERROR:" ) + cc.error( " value " ) + + cc.warning( joArg.value ) + cc.error( " of argument " ) + + cc.info( joArg.name ) + cc.error( " must be valid integer array" ) + ); + process.exit( 126 ); + } +} + +export function ensureStartsWith0x( s ) { + if( s == null || s == undefined || typeof s !== "string" ) + return s; + if( s.length < 2 ) + return "0x" + s; + if( s[0] == "0" && s[1] == "x" ) + return s; + return "0x" + s; +} + +export function removeStarting0x( s ) { + if( s == null || s == undefined || typeof s !== "string" ) + return s; + if( s.length < 2 ) + return s; + if( s[0] == "0" && s[1] == "x" ) + return s.substr( 2 ); + return s; +} + +export function inetNtoA( n ) { + const a = ( ( n >> 24 ) & 0xFF ) >>> 0; + const b = ( ( n >> 16 ) & 0xFF ) >>> 0; + const c = ( ( n >> 8 ) & 0xFF ) >>> 0; + const d = ( n & 0xFF ) >>> 0; + return ( a + "." + b + "." + c + "." + d ); +} + +export function ipFromHex( hex ) { + return inetNtoA( parseInt( removeStarting0x( hex ), 16 ) ); +} + +export function cloneObjectByRootKeys( joIn ) { + const joOut = { }, arrKeys = Object.keys( joIn ); + for( let i = 0; i < arrKeys.length; ++ i ) { + const key = arrKeys[i]; + const value = joIn[key]; + joOut[key] = value; + } + return joOut; +} + +// example: "1ether" -> "1000000000000000000" +// supported suffix aliases, lowercase +const gMapMoneyNameSuffixAliases = { + "ethe": "ether", + "ethr": "ether", + "eth": "ether", + "eter": "ether", + "ete": "ether", + "et": "ether", + "eh": "ether", + "er": "ether", + "finne": "finney", + "finn": "finney", + "fin": "finney", + "fn": "finney", + "fi": "finney", + "szab": "szabo", + "szb": "szabo", + "sza": "szabo", + "sz": "szabo", + "shanno": "shannon", + "shannn": "shannon", + "shann": "shannon", + "shan": "shannon", + "sha": "shannon", + "shn": "shannon", + "sh": "shannon", + "lovelac": "lovelace", + "lovela": "lovelace", + "lovel": "lovelace", + "love": "lovelace", + "lovl": "lovelace", + "lvl": "lovelace", + "lvla": "lovelace", + "lvlc": "lovelace", + "lvc": "lovelace", + "lv": "lovelace", + "lo": "lovelace", + "lc": "lovelace", + "ll": "lovelace", + "babbag": "babbage", + "babba": "babbage", + "babbg": "babbage", + "babb": "babbage", + "bab": "babbage", + "bag": "babbage", + "bbb": "babbage", + "bb": "babbage", + "bg": "babbage", + "ba": "babbage", + "be": "babbage", + "we": "wei", + "wi": "wei", + + // next are advanced kind of + "noether": "noether", + "noeth": "noether", + "kwei": "kwei", + "femtoether": "femtoether", + "femto": "femtoether", + "mwei": "mwei", + "picoether": "picoether", + "pico": "picoether", + "gwei": "gwei", + "nanoether": "nanoether", + "nano": "nanoether", + "microether": "microether", + "micro": "microether", + "milliether": "milliether", + "milli": "milliether", + "kether": "kether", + "mether": "mether", + "gether": "gether", + "tether": "tether" +}; + +export function parseMoneyUnitName( s ) { + s = s.trim().toLowerCase(); + if( s == "" ) + return "wei"; + if( s in gMapMoneyNameSuffixAliases ) { + s = gMapMoneyNameSuffixAliases[s]; + return s; + } + return s; +} + +function moneyUnitNameToEthersParseSpec( s ) { + switch ( s.toString().trim().toLowerCase() ) { + case "shannon": return 9; + case "lovelace": return 6; + case "babbage": return 3; + case "femtoether": return "ether"; + case "picoether": return "ether"; + case "nanoether": return "ether"; + case "microether": return "ether"; + case "milliether": return "ether"; + case "kether": return "ether"; + case "mether": return "ether"; + case "gether": return "ether"; + case "tether": return "ether"; + } + return s; +} + +function moneyUnitNameToPostDivider( s ) { + switch ( s.toString().trim().toLowerCase() ) { + case "femtoether": return "1000000000000000"; + case "picoether": return "1000000000000"; + case "nanoether": return "1000000000"; + case "microether": return "1000000"; + case "milliether": return "1000"; + } + return null; +} +function moneyUnitNameToPostMultiplier( s ) { + switch ( s.toString().trim().toLowerCase() ) { + case "kether": return "1000"; + case "mether": return "1000000"; + case "gether": return "1000000000"; + case "tether": return "1000000000000"; + } + return null; +} + +export function parseMoneySpecToWei( s, isThrowException ) { + try { + isThrowException = isThrowException ? true : false; + if( s == null || s == undefined ) { + if( isThrowException ) + throw new Error( "no parse-able value provided" ); + return "0"; + } + s = s.toString().trim(); + let strNumber = ""; + while( s.length > 0 ) { + const chr = s[0]; + if( /^\d+$/.test( chr ) || // is numeric + chr == "." + ) { + strNumber += chr; + s = s.substr( 1 ); // remove first character + continue; + } + if( chr == " " || chr == "\t" || chr == "\r" || chr == "\n" ) + s = s.substr( 1 ); // remove first character + s = s.trim().toLowerCase(); + break; + } + // here s is rest suffix string, number is number as string or empty string + if( strNumber == "" ) + throw new Error( "no number or float value found" ); + s = parseMoneyUnitName( s ); + const ddr = moneyUnitNameToPostDivider( s ), + mlr = moneyUnitNameToPostMultiplier( s ); + s = moneyUnitNameToEthersParseSpec( s ); + s = ethersMod.ethers.utils.parseUnits( strNumber, s ); + if( ddr != null ) + s = s.div( toBN( ddr ) ); + if( mlr != null ) + s = s.mul( toBN( mlr ) ); + s = s.toString(); + return s; + } catch ( err ) { + if( isThrowException ) { + throw new Error( + "Parse error in parseMoneySpecToWei(\"" + s + + "\"), error is: " + err.toString() ); + } + } + return "0"; +} + +export function computeChainIdFromSChainName( strName ) { + let h = ethersMod.ethers.utils.id( strName ); + h = removeStarting0x( h ).toLowerCase(); + while( h.length < 64 ) + h = "0" + h; + h = h.substr( 0, 14 ); + return ensureStartsWith0x( h ); +} + +export function privateKeyToAccountAddress( keyPrivate ) { + return ethersMod.ethers.utils.computeAddress( + ensureStartsWith0x( keyPrivate ) ); +} + +export function privateKeyToPublicKey( keyPrivate ) { + const privateKeyBuffer = + ethereumJsUtilModule.toBuffer( ensureStartsWith0x( keyPrivate ) ); + const wallet = Wallet.fromPrivateKey( privateKeyBuffer ); + const publicKey = wallet.getPublicKeyString(); + return removeStarting0x( publicKey ); +} + +export function publicKeyToAccountAddress( keyPublic ) { + const hash = ethersMod.ethers.utils.keccak256( ensureStartsWith0x( keyPublic ) ); + const strAddress = ensureStartsWith0x( hash.substr( hash.length - 40 ) ); + return strAddress; +} + +export function fnAddressImpl_() { + if( this.address_ == undefined || this.address_ == null || this.address_ == "" ) { + if( this.privateKey ) + this.address_ = "" + privateKeyToAccountAddress( this.privateKey ); + } + return this.address_; +} + +export function getEthersProviderFromURL( strURL ) { + const joConnectionInfo = { // see https://docs.ethers.io/v5/api/utils/web/#ConnectionInfo + url: strURL, + allowInsecureAuthentication: true + }; + const ethersProvider = new ethersMod.ethers.providers.JsonRpcProvider( joConnectionInfo ); + return ethersProvider; +} + +export function ethersProviderToUrl( ethersProvider ) { + let strURL = null; + if( ethersProvider && + "connection" in ethersProvider && typeof ethersProvider.connection == "object" && + "url" in ethersProvider.connection && typeof ethersProvider.connection.url == "string" + ) + strURL = "" + ethersProvider.connection.url; + return strURL; +} + +export function ensureObserverOptionsInitialized( opts ) { + if( ! opts ) + throw new Error( "IMA observer options is not valid JS object" ); + if( ! ( "imaState" in opts && opts.imaState && typeof opts.imaState == "object" ) ) + throw new Error( "IMA observer options does not contain \"imaState\" instance" ); + if( ! ( "joAbiSkaleManager" in opts.imaState && + opts.imaState.joAbiSkaleManager && + typeof opts.imaState.joAbiSkaleManager == "object" ) + ) + throw new Error( "IMA observer options does not contain \"joAbiSkaleManager\" instance" ); + const arrContractNames = [ + { abiKey: "schains", nameKey: "SChains" }, + { abiKey: "schains_internal", nameKey: "SChainsInternal" }, + { abiKey: "nodes", nameKey: "Nodes" } + ]; + for( let i = 0; i < arrContractNames.length; ++ i ) { + const strAbiSuffixName = arrContractNames[i].abiKey; + const strPropertySuffixName = arrContractNames[i].nameKey; + const strPropertyName = "jo" + strPropertySuffixName; + const contractAddress = opts.imaState.joAbiSkaleManager[strAbiSuffixName + "_address"]; + const joContractABI = opts.imaState.joAbiSkaleManager[strAbiSuffixName + "_abi"]; + opts[strPropertyName] = + new ethersMod.ethers.Contract( + contractAddress, + joContractABI, + opts.imaState.chainProperties.mn.ethersProvider + ); + } +} + +export function extractErrorMessage( jo, strDefaultErrorText ) { + strDefaultErrorText = strDefaultErrorText || "unknown error or error without a description"; + try { + const isError = function( err ) { + return err && err.stack && err.message; + }; + if( ! isError( jo ) ) { + if( "error" in jo ) { + jo = jo.error; + if( typeof jo == "string" ) + return jo; + if( typeof jo != "object" ) + return strDefaultErrorText + "(" + jo.toString() + ")"; + } + if( typeof jo == "string" && jo ) + return strDefaultErrorText + "(" + jo.toString() + ")"; + return strDefaultErrorText; + } + if( typeof jo.message == "string" && jo.message.length > 0 ) + return jo.message; // + jo.stack; + strDefaultErrorText += "(" + jo.toString() + ")"; // + jo.stack; + } catch ( err ) { + } + return strDefaultErrorText; +} + +export function toBN( x ) { + const bn = ethersMod.ethers.BigNumber.from( x ); + return bn; +} + +export function isNumeric( s ) { + return /^\d+$/.test( s ); +} diff --git a/npms/skale-owasp/package.json b/npms/skale-owasp/package.json index 5629442de..616a7c789 100644 --- a/npms/skale-owasp/package.json +++ b/npms/skale-owasp/package.json @@ -3,14 +3,19 @@ "private": true, "license": "AGPL-3.0", "author": "SKALE Labs and contributors", - "scripts": {}, + "scripts": { + "check-outdated": "yarn outdated", + "upgrade-to-latest": "yarn upgrade --latest" + }, "dependencies": { - "ethereumjs-tx": "1.3.7", - "ethereumjs-wallet": "0.6.3", - "ethereumjs-util": "6.1.0", - "web3": "^1.6.1", - "uuid": "3.3.3", - "sha3": "2.1.4" + "number-to-bn": "^1.7.0", + "ethers": "^5.7.2", + "@ethersproject/experimental": "^5.7.0", + "solc": "0.8.6", + "uuid": "^9.0.0", + "sha3": "2.1.4", + "ethereumjs-util": "^7.1.5", + "ethereumjs-wallet": "^1.0.2" }, "devDependencies": {}, "resolutions": { diff --git a/npms/skale-owasp/yarn.lock b/npms/skale-owasp/yarn.lock index 963cd3539..c900a025d 100644 --- a/npms/skale-owasp/yarn.lock +++ b/npms/skale-owasp/yarn.lock @@ -2,241 +2,368 @@ # yarn lockfile v1 -"@ethereumjs/common@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" - integrity sha512-DEHjW6e38o+JmB/NO3GZBpW4lpaiBpkFgXF6jLcJ6gETBYpEyaA5nTimsWBUJR3Vmtm/didUEbNjajskugZORg== - dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.1" +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + 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" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/experimental@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" + integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== + dependencies: + "@ethersproject/web" "^5.7.0" + ethers "^5.7.0" + scrypt-js "3.0.1" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" -"@ethereumjs/common@^2.6.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348" - integrity sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA== +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.3" - -"@ethereumjs/tx@^3.3.2": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.4.0.tgz#7eb1947eefa55eb9cf05b3ca116fb7a3dbd0bce7" - integrity sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw== - dependencies: - "@ethereumjs/common" "^2.6.0" - ethereumjs-util "^7.1.3" - -"@ethersproject/abi@5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" - integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== - dependencies: - "@ethersproject/address" "^5.0.4" - "@ethersproject/bignumber" "^5.0.7" - "@ethersproject/bytes" "^5.0.4" - "@ethersproject/constants" "^5.0.4" - "@ethersproject/hash" "^5.0.4" - "@ethersproject/keccak256" "^5.0.3" - "@ethersproject/logger" "^5.0.5" - "@ethersproject/properties" "^5.0.3" - "@ethersproject/strings" "^5.0.4" - -"@ethersproject/abstract-provider@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e" - integrity sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/networks" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/web" "^5.4.0" - -"@ethersproject/abstract-signer@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz#e4e9abcf4dd4f1ba0db7dff9746a5f78f355ea81" - integrity sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA== - dependencies: - "@ethersproject/abstract-provider" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - -"@ethersproject/address@^5.0.4", "@ethersproject/address@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.4.0.tgz#ba2d00a0f8c4c0854933b963b9a3a9f6eb4a37a3" - integrity sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - -"@ethersproject/base64@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.4.0.tgz#7252bf65295954c9048c7ca5f43e5c86441b2a9a" - integrity sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ== - dependencies: - "@ethersproject/bytes" "^5.4.0" - -"@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.4.0": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.2.tgz#44232e015ae4ce82ac034de549eb3583c71283d8" - integrity sha512-oIBDhsKy5bs7j36JlaTzFgNPaZjiNDOXsdSgSpXRucUl+UA6L/1YLlFeI3cPAoodcenzF4nxNPV13pcy7XbWjA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - bn.js "^4.11.9" - -"@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.4.0.tgz#56fa32ce3bf67153756dbaefda921d1d4774404e" - integrity sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.4.0.tgz#ee0bdcb30bf1b532d2353c977bf2ef1ee117958a" - integrity sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - -"@ethersproject/hash@^5.0.4": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0" - integrity sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA== - dependencies: - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" - integrity sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - js-sha3 "0.5.7" - -"@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.4.1.tgz#503bd33683538b923c578c07d1c2c0dd18672054" - integrity sha512-DZ+bRinnYLPw1yAC64oRl0QyVZj43QeHIhVKfD/+YwSz4wsv1pfwb5SOFjz+r710YEWzU6LrhuSjpSO+6PeE4A== - -"@ethersproject/networks@^5.4.0": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.2.tgz#2247d977626e97e2c3b8ee73cd2457babde0ce35" - integrity sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.1.tgz#9f051f976ce790142c6261ccb7b826eaae1f2f36" - integrity sha512-cyCGlF8wWlIZyizsj2PpbJ9I7rIlUAfnHYwy/T90pdkSn/NFTa5YWZx2wTJBe9V7dD65dcrrEMisCRUJiq6n3w== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/rlp@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" - integrity sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/signing-key@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.4.0.tgz#2f05120984e81cf89a3d5f6dec5c68ee0894fbec" - integrity sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - bn.js "^4.11.9" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" - integrity sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.4.0.tgz#a159d035179334bd92f340ce0f77e83e9e1522e0" - integrity sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ== - dependencies: - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - "@ethersproject/signing-key" "^5.4.0" - -"@ethersproject/web@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" - integrity sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og== - dependencies: - "@ethersproject/base64" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" "@types/bn.js@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" - integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== dependencies: "@types/node" "*" "@types/node@*": - version "16.10.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.1.tgz#f3647623199ca920960006b3dccf633ea905f243" - integrity sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w== - -"@types/node@^12.12.6": - version "12.20.27" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.27.tgz#4141fcad57c332a120591de883e26fe4bb14aaea" - integrity sha512-qZdePUDSLAZRXXV234bLBEUM0nAQjoxbcSwp1rqSMUe1rZ47mwU6OjciR/JvF1Oo8mc0ys6GE0ks0HGgqAZoGg== + version "18.14.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.3.tgz#485070908df2e7b476ecaf83108e50b4d925a153" + integrity sha512-1y36CC5iL5CMyKALzwX9cwwxcWIxvIBe3gzs4GrXWXEQ8klQnCZ2U/WDGiNrXHmQcUhnaun17XG9TEIDlGj2RA== "@types/pbkdf2@^3.0.0": version "3.1.0" @@ -257,15 +384,12 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -aes-js@^3.1.1: +aes-js@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== @@ -283,12 +407,12 @@ ajv@^6.12.3: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +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: version "1.2.0" @@ -303,67 +427,42 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== 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== -base-x@^3.0.2, base-x@^3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" - integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== +base-x@^3.0.2: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== dependencies: safe-buffer "^5.0.1" @@ -375,76 +474,41 @@ base64-js@^1.3.1: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" -bignumber.js@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" - integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== - -bindings@^1.2.1, bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bip66@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= - dependencies: - safe-buffer "^5.0.1" +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== blakejs@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" - integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + integrity sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ== dependencies: inherits "~2.0.0" -bluebird@^3.5.0: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9: +bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -body-parser@1.19.0, body-parser@^1.16.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" +bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== brace-expansion@^1.1.7: version "1.1.11" @@ -454,12 +518,12 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brorand@^1.0.1, brorand@^1.1.0: +brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0: +browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -471,52 +535,10 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify- inherits "^2.0.1" safe-buffer "^5.0.1" -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== dependencies: base-x "^3.0.2" @@ -529,15 +551,10 @@ bs58check@^2.1.2: create-hash "^1.1.0" safe-buffer "^5.1.2" -buffer-to-arraybuffer@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== buffer@6.0.3: version "6.0.3" @@ -547,68 +564,16 @@ buffer@6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -bufferutil@^4.0.1: - version "4.0.4" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.4.tgz#ab81373d313a6ead0d734e98c448c722734ae7bb" - integrity sha512-VNxjXUCrF3LvbLgwfkTb5LsFvk6pGIn7OBb9x+3o+iJ6mKw0JTUp4chBFc88hi1aspeZGeZG9jAIbpFYPQSLZw== - dependencies: - node-gyp-build "^4.2.0" - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-bind@^1.0.0, call-bind@^1.0.2: - 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" - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -cids@^0.7.1: - version "0.7.5" - resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" - integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== - dependencies: - buffer "^5.5.0" - class-is "^1.1.0" - multibase "~0.6.0" - multicodec "^1.0.0" - multihashes "~0.4.15" - cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -617,22 +582,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -class-is@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" - integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -641,86 +594,36 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + 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 sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-hash@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" - integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== - dependencies: - cids "^0.7.1" - multicodec "^0.5.5" - multihashes "^0.4.15" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -cookiejar@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== 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== -cors@^2.8.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -crc-32@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" - integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" @@ -732,7 +635,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -744,45 +647,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -crypto-browserify@3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" -debug@2.6.9, debug@^2.2.0: - 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@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -790,110 +661,35 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dom-walk@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" - integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== - -drbg.js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= - dependencies: - browserify-aes "^1.0.6" - create-hash "^1.1.2" - create-hmac "^1.1.4" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: +elliptic@6.5.4, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -906,127 +702,10 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -es-abstract@^1.18.5: - version "1.18.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" - integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-string "^1.0.7" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eth-ens-namehash@2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - -eth-lib@0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" - integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -eth-lib@^0.1.26: - version "0.1.29" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" - integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -ethereum-bloom-filters@^1.0.6: - version "1.0.10" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" - integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== - dependencies: - js-sha3 "^0.8.0" - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= +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== ethereum-cryptography@^0.1.3: version "0.1.3" @@ -1049,69 +728,10 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereumjs-tx@1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-util@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" - integrity sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - ethjs-util "0.1.6" - keccak "^1.0.2" - rlp "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - -ethereumjs-util@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-util@^6.0.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.1.tgz#236ef435f46820f0c420a708c0559b5897952069" - integrity sha512-1CGBmCp3m8IMGHhAJF/icH8qjCJrfQtaZ9KW+cAVV8kyN5Lc1IRq3KjV77ILOutrCwiyf5y2gMyCrAUMoCf2Ag== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.4" - -ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23" - integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw== +ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== dependencies: "@types/bn.js" "^5.1.0" bn.js "^5.1.2" @@ -1119,43 +739,57 @@ ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.3: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethereumjs-wallet@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz#b0eae6f327637c2aeb9ccb9047b982ac542e6ab1" - integrity sha512-qiXPiZOsStem+Dj/CQHbn5qex+FVkuPmGH7SvSnA9F3tdRDt8dLMyvIj3+U05QzVZNPYh4HXEdnzoYI4dZkr9w== +ethereumjs-wallet@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz#2c000504b4c71e8f3782dabe1113d192522e99b6" + integrity sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA== dependencies: - aes-js "^3.1.1" + aes-js "^3.1.2" bs58check "^2.1.2" - ethereumjs-util "^6.0.0" - hdkey "^1.1.0" - randombytes "^2.0.6" - safe-buffer "^5.1.2" - scrypt.js "^0.3.0" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^7.1.2" + randombytes "^2.1.0" + scrypt-js "^3.0.1" utf8 "^3.0.0" - uuid "^3.3.2" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@0.1.6, ethjs-util@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + uuid "^8.3.2" + +ethers@^5.7.0, ethers@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== @@ -1163,54 +797,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" - integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== - -express@^4.14.0: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -ext@^1.1.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" - integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== - dependencies: - type "^2.5.0" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -1219,12 +805,12 @@ extend@~3.0.2: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== fast-deep-equal@^3.1.1: version "3.1.3" @@ -1236,33 +822,15 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +follow-redirects@^1.12.1: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== form-data@~2.3.2: version "2.3.3" @@ -1273,24 +841,16 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -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 sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== dependencies: graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" fs-minipass@^1.2.7: version "1.2.7" @@ -1302,7 +862,7 @@ fs-minipass@^1.2.7: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fstream@^1.0.0, fstream@^1.0.12: version "1.0.12" @@ -1314,15 +874,10 @@ fstream@^1.0.0, fstream@^1.0.12: mkdirp ">=0.5 0" rimraf "2" -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== - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -1333,115 +888,34 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" glob@^7.0.3, glob@^7.1.3: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + 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.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -global@~4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" - integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== - dependencies: - min-document "^2.19.0" - process "^0.11.10" - -got@9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -got@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" @@ -1451,46 +925,10 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -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" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== hash-base@^3.0.0: version "3.1.0" @@ -1509,80 +947,32 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hdkey@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.2.tgz#c60f9cf6f90fbf24a8a52ea06893f36a0108cd3e" - integrity sha512-PTQ4VKu0oRnCrYfLp04iQZ7T2Cxz0UsEXYauk2j8eh6PJXCpbXuCFhOmtIFtbET0i3PMWmHN9J11gU8LEgUljQ== - dependencies: - bs58check "^2.1.2" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@0.4.24, iconv-lite@^0.4.4: +iconv-lite@^0.4.4: 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" -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== - dependencies: - punycode "2.1.0" - -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -1597,203 +987,59 @@ ignore-walk@^3.0.1: inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + 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.4, inherits@~2.0.0, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, 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 sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -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== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - is-fullwidth-code-point@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-function@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" - integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= - -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - -is-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" - integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== - -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" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-stream@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: - has-tostringtag "^1.0.0" + number-is-nan "^1.0.0" -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-typed-array@^1.1.3, is-typed-array@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" - integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + 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 sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -js-sha3@0.5.7, js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= - -js-sha3@^0.8.0: +js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== @@ -1801,80 +1047,55 @@ js-sha3@^0.8.0: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== 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@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== optionalDependencies: graceful-fs "^4.1.6" jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: assert-plus "1.0.0" extsprintf "1.3.0" - json-schema "0.2.3" + json-schema "0.4.0" verror "1.10.0" -keccak@^1.0.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== - dependencies: - bindings "^1.2.1" - inherits "^2.0.3" - nan "^2.2.1" - safe-buffer "^5.1.0" - keccak@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + version "3.0.3" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== dependencies: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" readable-stream "^3.6.0" -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" md5.js@^1.3.4: version "1.3.5" @@ -1885,57 +1106,22 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.49.0: - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== - -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.32" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== - dependencies: - mime-db "1.49.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== +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= +mime-types@^2.1.12, mime-types@~2.1.19: + 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: - dom-walk "^0.1.0" + mime-db "1.52.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" @@ -1945,19 +1131,19 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@^3.0.4, 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" -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" @@ -1974,94 +1160,22 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= - dependencies: - mkdirp "*" - -mkdirp@*: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "^1.2.5" - -mock-fs@^4.1.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" - integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + minimist "^1.2.6" ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multibase@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" - integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multibase@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" - integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multicodec@^0.5.5: - version "0.5.7" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" - integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== - dependencies: - varint "^5.0.0" - -multicodec@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" - integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== - dependencies: - buffer "^5.6.0" - varint "^5.0.0" - -multihashes@^0.4.15, multihashes@~0.4.15: - version "0.4.21" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" - integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== - dependencies: - buffer "^5.5.0" - multibase "^0.7.0" - varint "^5.0.0" - -nan@^2.14.0, nan@^2.2.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= +nan@^2.14.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== needle@^2.2.1: version "2.9.1" @@ -2072,16 +1186,6 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -2093,9 +1197,9 @@ node-addon-api@^3.0.0: integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== node-gyp-build@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" - integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== node-gyp@3.x: version "3.8.0" @@ -2134,7 +1238,7 @@ node-pre-gyp@^0.11.0: "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== dependencies: abbrev "1" @@ -2146,11 +1250,6 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - npm-bundled@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -2185,12 +1284,12 @@ npm-packlist@^1.1.6: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== -number-to-bn@1.7.0: +number-to-bn@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -2200,61 +1299,27 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -oboe@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" - integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= - dependencies: - http-https "^1.0.0" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== -os-tmpdir@^1.0.0: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== osenv@0, osenv@^0.1.4: version "0.1.5" @@ -2264,60 +1329,12 @@ osenv@0, osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= - dependencies: - p-finally "^1.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-headers@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" - integrity sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw== - -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-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 sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -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 sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -pbkdf2@^3.0.17, pbkdf2@^3.0.3: +pbkdf2@^3.0.17: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -2331,125 +1348,35 @@ pbkdf2@^3.0.17, pbkdf2@^3.0.3: performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -printj@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" - integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== 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== -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -proxy-addr@~2.0.5: - 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" - psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: +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" -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -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.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -2474,15 +1401,15 @@ readable-stream@^2.0.6: util-deprecate "~1.0.1" readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.1" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62" + integrity sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -request@^2.79.0, request@^2.87.0: +request@^2.87.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -2508,14 +1435,12 @@ request@^2.79.0, request@^2.87.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" +require-from-string@^2.0.0: + 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== -rimraf@2, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -2530,23 +1455,23 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4: - version "2.2.6" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c" - integrity sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg== +rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: - bn.js "^4.11.1" - -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== + bn.js "^5.2.0" safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, 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== +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== + "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -2557,56 +1482,26 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -scrypt-js@^3.0.0, scrypt-js@^3.0.1: +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== -scrypt.js@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.3.0.tgz#6c62d61728ad533c8c376a2e5e3e86d41a95c4c0" - integrity sha512-42LTc1nyFsyv/o0gcHtDztrn+aqpkaCNt5Qh7ATBZfhEZU7IC/0oT/qbBH+uRNoAPvs2fwiOId68FDEoSRA8/A== - dependencies: - scryptsy "^1.2.1" - optionalDependencies: - scrypt "^6.0.2" - -scrypt@^6.0.2, "scrypt@file:../scrypt/node-scrypt": +"scrypt@file:../scrypt/node-scrypt": version "6.0.3" dependencies: nan "^2.14.0" -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= - dependencies: - pbkdf2 "^3.0.3" - -secp256k1@^3.0.1: - version "3.8.0" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" - integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== - dependencies: - bindings "^1.5.0" - bip66 "^1.1.5" - bn.js "^4.11.8" - create-hash "^1.2.0" - drbg.js "^1.0.1" - elliptic "^6.5.2" - nan "^2.14.0" - safe-buffer "^5.1.2" - secp256k1@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.2.tgz#15dd57d0f0b9fdb54ac1fa1694f40e5e9a54f4a1" - integrity sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== dependencies: - elliptic "^6.5.2" + elliptic "^6.5.4" node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -semver@^5.3.0: +semver@^5.3.0, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2614,62 +1509,17 @@ semver@^5.3.0: semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" + integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw== set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" @@ -2686,33 +1536,25 @@ sha3@2.1.4: dependencies: buffer "6.0.3" -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.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" - integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== - -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@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== - dependencies: - decompress-response "^3.3.0" - once "^1.3.1" - simple-concat "^1.0.0" + 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== + +solc@0.8.6: + version "0.8.6" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.6.tgz#e4341fa6780137df97b94a0cfbd59b3f2037d0e0" + integrity sha512-miiDaWdaUnD7A6Cktb/2ug9f+ajcOCDYRr7vgbPEsMoutSlBtp5rca57oMg8iHSuM7jilwdxePujWI/+rbNftQ== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" sqlite3@5.0.2: version "5.0.2" @@ -2725,9 +1567,9 @@ sqlite3@5.0.2: node-gyp "3.x" sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -2739,48 +1581,23 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +"string-width@^1.0.2 || 2 || 3 || 4": + 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: - call-bind "^1.0.2" - define-properties "^1.1.3" + 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" @@ -2799,45 +1616,28 @@ string_decoder@~1.1.1: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= +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 "^3.0.0" + ansi-regex "^5.0.1" strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== dependencies: is-hex-prefixed "1.0.0" strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -swarm-js@^0.1.40: - version "0.1.40" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" - integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== tar@^2.0.0: version "2.2.2" @@ -2848,7 +1648,7 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4, tar@^4.0.2: +tar@^4: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -2861,20 +1661,12 @@ tar@^4, tar@^4.0.2: safe-buffer "^5.2.1" yallist "^3.1.1" -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" tough-cookie@~2.5.0: version "2.5.0" @@ -2887,64 +1679,14 @@ tough-cookie@~2.5.0: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-is@~1.6.17, 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" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" - integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -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 sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== uri-js@^4.2.2: version "4.4.1" @@ -2953,38 +1695,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= - -utf-8-validate@^5.0.2: - version "5.0.6" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.6.tgz#e1b3e0a5cc8648a3b44c1799fbb170d1aaaffe80" - integrity sha512-hoY0gOf9EkCw+nimK21FVKHUIG1BMqSiRwxB/q3A9yKZOrOI99PP77BxmarDqWz6rG3vVYiBWfhG8z2Tl+7fZA== - dependencies: - node-gyp-build "^4.2.0" - -utf8@3.0.0, utf8@^3.0.0: +utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== @@ -2992,322 +1703,32 @@ utf8@3.0.0, utf8@^3.0.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 sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util@^0.12.0: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -uuid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -varint@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" - integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== +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, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -web3-bzz@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.1.tgz#8430eb3cbb69baaee4981d190b840748c37a9ec2" - integrity sha512-JbnFNbRlwwHJZPtVuCxo7rC4U4OTg+mPsyhjgPQJJhS0a6Y54OgVWYk9UA/95HqbmTJwTtX329gJoSsseEfrng== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - -web3-core-helpers@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.1.tgz#cb21047306871f4cf0fedfece7d47ea2aa96141b" - integrity sha512-om2PZvK1uoWcgMq6JfcSx3241LEIVF6qi2JuHz2SLKiKEW5UsBUaVx0mNCmcZaiuYQCyOsLS3r33q5AdM+v8ng== - dependencies: - web3-eth-iban "1.6.1" - web3-utils "1.6.1" - -web3-core-method@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.1.tgz#4ae91c639bf1da85ebfd8b99595da6a2235d7b98" - integrity sha512-szH5KyIWIaULQDBdDvevQUCHV9lsExJ/oV0ePqK+w015D2SdMPMuhii0WB+HCePaksWO+rr/GAypvV9g2T3N+w== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-utils "1.6.1" - -web3-core-promievent@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.1.tgz#f650dea9361e2edf02691015b213fcc8ea499992" - integrity sha512-byJ5s2MQxrWdXd27pWFmujfzsTZK4ik8rDgIV1RFDFc+rHZ2nZhq+VWk7t/Nkrj7EaVXncEgTdPEHc18nx+ocQ== - dependencies: - eventemitter3 "4.0.4" - -web3-core-requestmanager@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.1.tgz#d9c08b0716c9cda546a0c02767b7e08deb04448a" - integrity sha512-4y7etYEUtkfflyYVBfN1oJtCbVFNhNX1omlEYzezhTnPj3/dT7n+dhUXcqvIhx9iKA13unGfpFge80XNFfcB8A== - dependencies: - util "^0.12.0" - web3-core-helpers "1.6.1" - web3-providers-http "1.6.1" - web3-providers-ipc "1.6.1" - web3-providers-ws "1.6.1" - -web3-core-subscriptions@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.1.tgz#4dfc1f74137354d4ac9eaa628aa916c5e2cc8741" - integrity sha512-WZwxsYttIojyGQ5RqxuQcKg0IJdDCFpUe4EncS3QKZwxPqWzGmgyLwE0rm7tP+Ux1waJn5CUaaoSCBxWGSun1g== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - -web3-core@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.1.tgz#b41f08fdc9ea1082d15384a3d6fa93a47c3fc1b4" - integrity sha512-m+b7UfYvU5cQUAh6NRfxRzH/5B3to1AdEQi1HIQt570cDWlObOOmoO9tY6iJnI5w4acxIO19LqjDMqEJGBYyRQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-requestmanager "1.6.1" - web3-utils "1.6.1" - -web3-eth-abi@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.6.1.tgz#15b937e3188570754d50bbac51a4bb0578600d1d" - integrity sha512-svhYrAlXP9XQtV7poWKydwDJq2CaNLMtmKydNXoOBLcQec6yGMP+v20pgrxF2H6wyTK+Qy0E3/5ciPOqC/VuoQ== - dependencies: - "@ethersproject/abi" "5.0.7" - web3-utils "1.6.1" - -web3-eth-accounts@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.1.tgz#aeb0dfb52c4391773550569732975b471212583f" - integrity sha512-rGn3jwnuOKwaQRu4SiShz0YAQ87aVDBKs4HO43+XTCI1q1Y1jn3NOsG3BW9ZHaOckev4+zEyxze/Bsh2oEk24w== - dependencies: - "@ethereumjs/common" "^2.5.0" - "@ethereumjs/tx" "^3.3.2" - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-util "^7.0.10" - scrypt-js "^3.0.1" - uuid "3.3.2" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-eth-contract@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.1.tgz#4b0a2c0b37015d70146e54c7cb3f035a58fbeec0" - integrity sha512-GXqTe3mF6kpbOAakiNc7wtJ120/gpuKMTZjuGFKeeY8aobRLfbfgKzM9IpyqVZV2v5RLuGXDuurVN2KPgtu3hQ== - dependencies: - "@types/bn.js" "^4.11.5" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-promievent "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-utils "1.6.1" - -web3-eth-ens@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.1.tgz#801bd5fb5237377ec2ed8517a9fe4634f2269c7a" - integrity sha512-ngprtbnoRgxg8s1wXt9nXpD3h1P+p7XnKXrp/8GdFI9uDmrbSQPRfzBw86jdZgOmy78hAnWmrHI6pBInmgi2qQ== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-promievent "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-contract "1.6.1" - web3-utils "1.6.1" - -web3-eth-iban@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.1.tgz#20bbed75723e3e9ff98e624979629d26329462b6" - integrity sha512-91H0jXZnWlOoXmc13O9NuQzcjThnWyAHyDn5Yf7u6mmKOhpJSGF/OHlkbpXt1Y4v2eJdEPaVFa+6i8aRyagE7Q== - dependencies: - bn.js "^4.11.9" - web3-utils "1.6.1" - -web3-eth-personal@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.1.tgz#9b524fb9f92b51163f46920ee2663d34a4897c8d" - integrity sha512-ItsC89Ln02+irzJjK6ALcLrMZfbVUCqVbmb/ieDKJ+eLW3pNkBNwoUzaydh92d5NzxNZgNxuQWVdlFyYX2hkEw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-eth@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.1.tgz#a25aba1ac213d872ecf3f81c7b4ab8072ecae224" - integrity sha512-kOV1ZgCKypSo5BQyltRArS7ZC3bRpIKAxSgzl7pUFinUb/MxfbM9KGeNxUXoCfTSErcCQJaDjcS6bSre5EMKuQ== - dependencies: - web3-core "1.6.1" - web3-core-helpers "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-eth-abi "1.6.1" - web3-eth-accounts "1.6.1" - web3-eth-contract "1.6.1" - web3-eth-ens "1.6.1" - web3-eth-iban "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-utils "1.6.1" - -web3-net@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.1.tgz#7a630a804ec9f81908ae52ccbb4ebbb9530b3906" - integrity sha512-gpnqKEIwfUHh5ik7wsQFlCje1DfcmGv+Sk7LCh1hCqn++HEDQxJ/mZCrMo11ZZpZHCH7c87imdxTg96GJnRxDw== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-utils "1.6.1" - -web3-providers-http@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.1.tgz#b59b14eefef23b98c327806f5f566303a73bd435" - integrity sha512-xBoKOJxu10+kO3ikamXmBfrWZ/xpQOGy0ocdp7Y81B17En5TXELwlmMXt1UlIgWiyYDhjq4OwlH/VODYqHXy3A== - dependencies: - web3-core-helpers "1.6.1" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.1.tgz#7ba460589d46896bb3d124288deed1b6a72d517e" - integrity sha512-anyoIZlpMzwEQI4lwylTzDrHsVp20v0QUtSTp2B5jInBinmQtyCE7vnbX20jEQ4j5uPwfJabKNtoJsk6a3O4WQ== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.6.1" - -web3-providers-ws@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.1.tgz#f7ee71f158971102b865e99ea7911f483e0507e9" - integrity sha512-FWMEFYb4rYFYRgSFBf/O1Ex4p/YKSlN+JydCtdlJwRimd89qm95CTfs4xGjCskwvXMjV2sarH+f1NPwJXicYpg== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.6.1" - websocket "^1.0.32" - -web3-shh@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.1.tgz#eebaab2e5e6be80fe2585c6c094fa10a03349ca7" - integrity sha512-oP00HbAtybLCGlLOZUYXOdeB9xq88k2l0TtStvKBtmFqRt+zVk5TxEeuOnVPRxNhcA2Un8RUw6FtvgZlWStu9A== - dependencies: - web3-core "1.6.1" - web3-core-method "1.6.1" - web3-core-subscriptions "1.6.1" - web3-net "1.6.1" - -web3-utils@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.6.1.tgz#befcb23922b00603ab56d8c5b4158468dc494aca" - integrity sha512-RidGKv5kOkcerI6jQqDFDoTllQQqV+rPhTzZHhmbqtFObbYpU93uc+yG1LHivRTQhA6llIx67iudc/vzisgO+w== - dependencies: - bn.js "^4.11.9" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - -web3@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.1.tgz#c9e68fe7b3073adddf35393441f950ec69b92735" - integrity sha512-c299lLiyb2/WOcxh7TinwvbATaMmrgNIeAzbLbmOKHI0LcwyfsB1eu2ReOIrfrCYDYRW2KAjYr7J7gHawqDNPQ== - dependencies: - web3-bzz "1.6.1" - web3-core "1.6.1" - web3-eth "1.6.1" - web3-eth-personal "1.6.1" - web3-net "1.6.1" - web3-shh "1.6.1" - web3-utils "1.6.1" - -websocket@^1.0.32: - version "1.0.34" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" - integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - 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" - -which-typed-array@^1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" - integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.7" - which@1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -3316,72 +1737,21 @@ which@1: isexe "^2.0.0" wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + 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" + 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 sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -xhr-request-promise@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" - integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== - dependencies: - xhr-request "^1.1.0" - -xhr-request@^1.0.1, xhr-request@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== - dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= - dependencies: - cookiejar "^2.1.1" - -xhr@^2.0.4, xhr@^2.3.3: - version "2.6.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" - integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== - dependencies: - global "~4.4.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== yallist@^3.0.0, yallist@^3.1.1: version "3.1.1" diff --git a/package.json b/package.json index 1cc410608..a0c7f4cf8 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,12 @@ "license": "AGPL-3.0", "author": "SKALE Labs and contributors", "scripts": { - "lint-check": "eslint ./agent/*.js ./npms/skale-*/*.js ./test/*.js", - "lint-fix": "eslint ./agent/*.js ./npms/skale-*/*.js ./test/*.js --fix", + "lint-check": "eslint ./agent/*.*js ./npms/skale-*/*.*js ./test/*.*js ./agent/test/*.*js", + "lint-fix": "eslint ./agent/*.*js ./npms/skale-*/*.*js ./test/*.*js ./agent/test/*.*js --fix", "preinstall": "./npms/scrypt/get_scrypt_npm.sh", - "postinstall": "echo \"----- installing in agent\n\" && cd ./agent && yarn install && cd .. && echo \"----- installing in test\n\" && cd ./test && yarn install && cd .. && echo \"----- installing in proxy\n\" && cd ./proxy && yarn install && cd .. && echo \"----- installing in test-tokens\n\" && cd ./test-tokens && yarn install && cd .." + "postinstall": "./postinstall.sh", + "check-outdated": "yarn outdated", + "upgrade-to-latest": "yarn upgrade --latest" }, "dependencies": {}, "devDependencies": { diff --git a/postinstall.sh b/postinstall.sh new file mode 100755 index 000000000..687710920 --- /dev/null +++ b/postinstall.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +echo " " +echo "----- installing in agent ------------------------------------------------------------------" +echo " " +cd ./agent +yarn install +cd .. + +echo " " +echo "----- installing in test -------------------------------------------------------------------" +echo " " +cd ./test +yarn install +cd .. + +echo " " +echo "----- installing in proxy ------------------------------------------------------------------" +echo " " +cd ./proxy +yarn install +cd .. + +echo " " +echo "----- installing in test-tokens ------------------------------------------------------------" +echo " " +cd ./test-tokens +yarn install +cd .. diff --git a/proxy/migrations/deploySkaleManagerComponents.ts b/proxy/migrations/deploySkaleManagerComponents.ts index 943d947da..0c35041e1 100644 --- a/proxy/migrations/deploySkaleManagerComponents.ts +++ b/proxy/migrations/deploySkaleManagerComponents.ts @@ -185,7 +185,7 @@ async function main() { }; await keyStorage.setBlsCommonPublicKeyForSchain( ethers.utils.solidityKeccak256(['string'], [schainName]), BLSPublicKey ); console.log("Set common public key in KeyStorage contract", keyStorage.address, "\n"); - await wallets.rechargeSchainWallet( web3.utils.soliditySha3( schainName ), { value: "1000000000000000000" } ); + await wallets.rechargeSchainWallet( web3.utils.soliditySha3( schainName ), { value: "10000000000000000000" } ); // originally it was 1000000000000000000 = 1ETH console.log("Recharge schain wallet in Wallets contract", wallets.address, "\n"); const jsonObject = { diff --git a/proxy/migrations/upgrade.ts b/proxy/migrations/upgrade.ts deleted file mode 100644 index ac5c1d5ec..000000000 --- a/proxy/migrations/upgrade.ts +++ /dev/null @@ -1,254 +0,0 @@ -import { ethers, network, upgrades, artifacts } from "hardhat"; -import hre from "hardhat"; -import { promises as fs } from "fs"; -import { getImplementationAddress, hashBytecode, Manifest } from "@openzeppelin/upgrades-core"; -import { deployLibraries, getLinkedContractFactory } from "./tools/factory"; -import { getAbi } from "./tools/abi"; -import { getManifestAdmin } from "@openzeppelin/hardhat-upgrades/dist/admin"; -import { SafeMock } from "../typechain/SafeMock"; -import { encodeTransaction } from "./tools/multiSend"; -import { createMultiSendTransaction, sendSafeTransaction } from "./tools/gnosis-safe"; -import chalk from "chalk"; -import { verify } from "./tools/verification"; -import { MessageProxy, MessageProxyForMainnet, MessageProxyForSchain } from "../typechain"; -import { getVersion } from "./tools/version"; - -function getContractKeyInAbiFile(contract: string) { - if (contract === "MessageProxyForMainnet") { - return "message_proxy_mainnet"; - } else if (contract === "MessageProxyForSchain") { - return "message_proxy_chain"; - } - return contract.replace(/([a-z0-9])(?=[A-Z])/g, '$1_').toLowerCase(); -} - -async function getManifestFile(): Promise { - return (await Manifest.forNetwork(ethers.provider)).file;; -} - -export async function getContractFactoryAndUpdateManifest(contract: string) { - const manifest = JSON.parse(await fs.readFile(await getManifestFile(), "utf-8")); - const { linkReferences } = await artifacts.readArtifact(contract); - if (!Object.keys(linkReferences).length) - return await ethers.getContractFactory(contract); - - const librariesToUpgrade = []; - const oldLibraries: {[k: string]: string} = {}; - if (manifest.libraries === undefined) { - Object.assign(manifest, {libraries: {}}); - } - for (const key of Object.keys(linkReferences)) { - const libraryName = Object.keys(linkReferences[key])[0]; - const { bytecode } = await artifacts.readArtifact(libraryName); - if (manifest.libraries[libraryName] === undefined) { - librariesToUpgrade.push(libraryName); - continue; - } - const libraryBytecodeHash = manifest.libraries[libraryName].bytecodeHash; - if (hashBytecode(bytecode) !== libraryBytecodeHash) { - librariesToUpgrade.push(libraryName); - } else { - oldLibraries[libraryName] = manifest.libraries[libraryName].address; - } - } - const libraries = await deployLibraries(librariesToUpgrade); - for (const libraryName of Object.keys(libraries)) { - const { bytecode } = await artifacts.readArtifact(libraryName); - manifest.libraries[libraryName] = {"address": libraries[libraryName], "bytecodeHash": hashBytecode(bytecode)}; - } - Object.assign(libraries, oldLibraries); - await fs.writeFile(await getManifestFile(), JSON.stringify(manifest, null, 4)); - return await getLinkedContractFactory(contract, libraries); -} - -async function checkDeployedVersion(version: string, targetVersion: string, messageProxy: MessageProxyForMainnet | MessageProxyForSchain) { - let deployedVersion = ""; - try { - deployedVersion = await messageProxy.version(); - } catch { - console.log("Can't read deployed version"); - }; - - if (deployedVersion) { - if (deployedVersion !== targetVersion) { - console.log(chalk.red(`This script can't upgrade version ${deployedVersion} to ${version}`)); - process.exit(1); - } - } else { - console.log(chalk.yellow("Can't check currently deployed version of skale-manager")); - } - console.log(`Will mark updated version as ${version}`); -} - -async function getMessageProxyName(fileName: string) { - if (fileName === "proxyMainnet") { - return "MessageProxyForMainnet"; - } else if (fileName === "proxySchain") { - return "MessageProxyForSchain"; - } - console.log(chalk.red("Invalid filename")); - process.exit(1); -} - -async function getMessageProxyInstance(fileName: string, abi: any) : Promise { - const messageProxyName = await getMessageProxyName(fileName); - const messageProxyFactory = await ethers.getContractFactory(messageProxyName); - const messageProxy = (messageProxyFactory.attach(abi[getContractKeyInAbiFile(messageProxyName) + "_address"])); - if (messageProxyName === "MessageProxyForMainnet") { - return messageProxy as MessageProxyForMainnet; - } else if (messageProxyName === "MessageProxyForSchain") { - return messageProxy as MessageProxyForSchain; - } else { - throw Error("Unknown MessageProxy"); - } -} - -type DeploymentAction = (safeTransactions: string[], abi: any) => Promise; - -export async function upgrade( - targetVersion: string, - contractNamesToUpgrade: string[], - deployNewContracts: DeploymentAction, - initialize: DeploymentAction, - fileName: string) -{ - if (!process.env.ABI) { - console.log(chalk.red("Set path to file with ABI and addresses to ABI environment variables")); - return; - } - - const abiFilename = process.env.ABI; - const abi = JSON.parse(await fs.readFile(abiFilename, "utf-8")); - - const proxyAdmin = await getManifestAdmin(hre); - const version = await getVersion(); - const messageProxy = await getMessageProxyInstance(fileName, abi); - await checkDeployedVersion(version, targetVersion, messageProxy); - - const [ deployer ] = await ethers.getSigners(); - let safe = await proxyAdmin.owner(); - const safeTransactions: string[] = []; - let safeMock; - if (await ethers.provider.getCode(safe) === "0x") { - console.log("Owner is not a contract"); - if (deployer.address !== safe) { - console.log(chalk.red("Used address does not have permissions to upgrade skale-manager")); - process.exit(1); - } - console.log(chalk.blue("Deploy SafeMock to simulate upgrade via multisig")); - const safeMockFactory = await ethers.getContractFactory("SafeMock"); - safeMock = (await safeMockFactory.deploy()) as SafeMock; - await safeMock.deployTransaction.wait(); - - console.log(chalk.blue("Transfer ownership to SafeMock")); - safe = safeMock.address; - await (await proxyAdmin.transferOwnership(safe)).wait(); - for (const contractName of contractNamesToUpgrade) { - const contractFactory = await getContractFactoryAndUpdateManifest(contractName); - const _contract = contractName; - const contractAddress = abi[getContractKeyInAbiFile(_contract) + "_address"]; - const contract = contractFactory.attach(contractAddress); - console.log(chalk.blue(`Grant access to ${contractName}`)); - await (await contract.grantRole(await contract.DEFAULT_ADMIN_ROLE(), safe)).wait(); - } - } else { - try { - const safeMockFactory = await ethers.getContractFactory("SafeMock"); - const checkSafeMock = (safeMockFactory.attach(safe)) as SafeMock; - if (await checkSafeMock.IS_SAFE_MOCK()) { - safeMock = checkSafeMock; - } - } catch (e: any) { - console.log(chalk.yellow("Owner is not SafeMock")); - } - } - - // Deploy new contracts - await deployNewContracts(safeTransactions, abi); - - // deploy new implementations - const contractsToUpgrade: {proxyAddress: string, implementationAddress: string, name: string, abi: any}[] = []; - for (const contract of contractNamesToUpgrade) { - const contractFactory = await getContractFactoryAndUpdateManifest(contract); - const _contract = contract; - const proxyAddress = abi[getContractKeyInAbiFile(_contract) + "_address"]; - - console.log(`Prepare upgrade of ${contract}`); - const newImplementationAddress = await upgrades.prepareUpgrade(proxyAddress, contractFactory, { unsafeAllowRenames: true }); - const currentImplementationAddress = await getImplementationAddress(network.provider, proxyAddress); - if (newImplementationAddress !== currentImplementationAddress) - { - contractsToUpgrade.push({ - proxyAddress, - implementationAddress: newImplementationAddress, - name: contract, - abi: getAbi(contractFactory.interface) - }); - await verify(contract, newImplementationAddress, []); - } else { - console.log(chalk.gray(`Contract ${contract} is up to date`)); - } - } - - // Switch proxies to new implementations - for (const contract of contractsToUpgrade) { - console.log(chalk.yellowBright(`Prepare transaction to upgrade ${contract.name} at ${contract.proxyAddress} to ${contract.implementationAddress}`)); - safeTransactions.push(encodeTransaction( - 0, - proxyAdmin.address, - 0, - proxyAdmin.interface.encodeFunctionData("upgrade", [contract.proxyAddress, contract.implementationAddress]))); - abi[getContractKeyInAbiFile(contract.name) + "_abi"] = contract.abi; - } - - await initialize(safeTransactions, abi); - - // write version - if (safeMock) { - console.log(chalk.blue("Grant access to set version")); - await (await messageProxy.grantRole(await messageProxy.DEFAULT_ADMIN_ROLE(), safe)).wait(); - } - safeTransactions.push(encodeTransaction( - 0, - messageProxy.address, - 0, - messageProxy.interface.encodeFunctionData("setVersion", [version]), - )); - - await fs.writeFile(`data/transactions-${version}-${network.name}.json`, JSON.stringify(safeTransactions, null, 4)); - - let privateKey = (network.config.accounts as string[])[0]; - if (network.config.accounts === "remote") { - // Don't have an information about private key - // Use random one because we most probable run tests - privateKey = ethers.Wallet.createRandom().privateKey; - } - - const safeTx = await createMultiSendTransaction(ethers, safe, privateKey, safeTransactions, safeMock !== undefined); - if (!safeMock) { - const chainId = (await ethers.provider.getNetwork()).chainId; - await sendSafeTransaction(safe, chainId, safeTx); - } else { - console.log(chalk.blue("Send upgrade transactions to safe mock")); - try { - await (await deployer.sendTransaction({ - to: safeMock.address, - value: safeTx.value, - data: safeTx.data, - })).wait(); - } finally { - console.log(chalk.blue("Return ownership to wallet")); - await (await safeMock.transferProxyAdminOwnership(proxyAdmin.address, deployer.address)).wait(); - if (await proxyAdmin.owner() === deployer.address) { - await (await safeMock.destroy({gasLimit: 1000000})).wait(); - } else { - console.log(chalk.blue("Something went wrong with ownership transfer")); - process.exit(1); - } - } - } - - await fs.writeFile(`data/${fileName}-${version}-${network.name}-abi.json`, JSON.stringify(abi, null, 4)); - - console.log("Done"); -} diff --git a/proxy/migrations/upgradeMainnet.ts b/proxy/migrations/upgradeMainnet.ts index 3ca1967c1..b453d7482 100644 --- a/proxy/migrations/upgradeMainnet.ts +++ b/proxy/migrations/upgradeMainnet.ts @@ -1,27 +1,69 @@ -import { getManifestAdmin } from "@openzeppelin/hardhat-upgrades/dist/admin"; -import { CommunityPool, MessageProxyForMainnet } from "../typechain"; -import { contracts, getContractKeyInAbiFile } from "./deployMainnet"; -import { encodeTransaction } from "./tools/multiSend"; -import { upgrade } from "./upgrade"; import chalk from "chalk"; import { ethers } from "hardhat"; -import hre from "hardhat"; +import { promises as fs } from "fs"; +import { Upgrader } from "@skalenetwork/upgrade-tools"; +import { SkaleABIFile } from "@skalenetwork/upgrade-tools/dist/src/types/SkaleABIFile"; +import { contracts } from "./deployMainnet"; +import { manifestSetup } from "./generateManifest"; +import { MessageProxyForMainnet } from "../typechain"; + +class ImaMainnetUpgrader extends Upgrader { + + async getMessageProxyForMainnet() { + return await ethers.getContractAt("MessageProxyForMainnet", this.abi.message_proxy_mainnet_address as string) as MessageProxyForMainnet; + } + + getDeployedVersion = async () => { + const messageProxyForMainnet = await this.getMessageProxyForMainnet(); + try { + return await messageProxyForMainnet.version(); + } catch { + console.log(chalk.red("Can't read deployed version")); + } + } + + setVersion = async (newVersion: string) => { + const messageProxyForMainnet = await this.getMessageProxyForMainnet(); + this.transactions.push({ + to: messageProxyForMainnet.address, + data: messageProxyForMainnet.interface.encodeFunctionData("setVersion", [newVersion]) + }); + } + + _getContractKeyInAbiFile(contract: string) { + if (contract === "MessageProxyForMainnet") { + return "message_proxy_mainnet"; + } + return contract.replace(/([a-z0-9])(?=[A-Z])/g, '$1_').toLowerCase(); + } +} + +async function getImaMainnetAbiAndAddress(): Promise { + if (!process.env.ABI) { + console.log(chalk.red("Set path to file with ABI and addresses to ABI environment variables")); + process.exit(1); + } + const abiFilename = process.env.ABI; + return JSON.parse(await fs.readFile(abiFilename, "utf-8")); +} async function main() { - await upgrade( + const pathToManifest: string = process.env.MANIFEST || ""; + await manifestSetup(pathToManifest); + const upgrader = new ImaMainnetUpgrader( + "proxyMainnet", "1.3.4", - contracts, - async (safeTransactions, abi) => undefined, - async (safeTransactions, abi) => undefined, - "proxyMainnet" + await getImaMainnetAbiAndAddress(), + contracts ); + await upgrader.upgrade(); } -if( require.main === module ) { +if (require.main === module) { main() - .then( () => process.exit( 0 ) ) - .catch( error => { - console.error( error ); - process.exit( 1 ); - } ); + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); } diff --git a/proxy/migrations/upgradeSchain.ts b/proxy/migrations/upgradeSchain.ts index 72ac293fc..a7419340a 100644 --- a/proxy/migrations/upgradeSchain.ts +++ b/proxy/migrations/upgradeSchain.ts @@ -1,58 +1,89 @@ -import { getManifestAdmin } from "@openzeppelin/hardhat-upgrades/dist/admin"; -import { CommunityLocker } from "../typechain/CommunityLocker"; -import { contracts, getContractKeyInAbiFile } from "./deploySchain"; -import { manifestSetup } from "./generateManifest"; -import { encodeTransaction } from "./tools/multiSend"; -import { upgrade } from "./upgrade"; import chalk from "chalk"; import { ethers } from "hardhat"; +import { promises as fs } from "fs"; +import { Upgrader } from "@skalenetwork/upgrade-tools"; +import { SkaleABIFile } from "@skalenetwork/upgrade-tools/dist/src/types/SkaleABIFile"; +import { contracts, getContractKeyInAbiFile } from "./deploySchain"; +import { manifestSetup } from "./generateManifest"; +import { CommunityLocker } from "../typechain/CommunityLocker"; +import { MessageProxyForSchain } from "../typechain"; + +class ImaSchainUpgrader extends Upgrader { + + async getMessageProxyForSchain() { + return await ethers.getContractAt("MessageProxyForSchain", this.abi.message_proxy_chain_address as string) as MessageProxyForSchain; + } + + getDeployedVersion = async () => { + const messageProxyForSchain = await this.getMessageProxyForSchain(); + try { + return await messageProxyForSchain.version(); + } catch { + console.log(chalk.red("Can't read deployed version")); + } + } + + setVersion = async (newVersion: string) => { + const messageProxyForSchain = await this.getMessageProxyForSchain(); + this.transactions.push({ + to: messageProxyForSchain.address, + data: messageProxyForSchain.interface.encodeFunctionData("setVersion", [newVersion]) + }); + } + + initialize = async () => { + const communityLockerName = "CommunityLocker"; + const communityLockerFactory = await ethers.getContractFactory(communityLockerName); + const communityLockerAddress = this.abi[getContractKeyInAbiFile(communityLockerName) + "_address"] as string; + let communityLocker; + if (communityLockerAddress) { + communityLocker = communityLockerFactory.attach(communityLockerAddress) as CommunityLocker; + console.log(chalk.yellow("Prepare transaction to initialize timestamp")); + this.transactions.push({ + to: communityLockerAddress, + data: communityLocker.interface.encodeFunctionData("initializeTimestamp") + }); + } else { + console.log(chalk.red("CommunityLocker was not found!")); + console.log(chalk.red("Check your abi!!!")); + process.exit(1); + } + } + + _getContractKeyInAbiFile(contract: string) { + if (contract === "MessageProxyForSchain") { + return "message_proxy_chain"; + } + return contract.replace(/([a-z0-9])(?=[A-Z])/g, '$1_').toLowerCase(); + } +} -function stringValue(value: string | undefined) { - if (value) { - return value; - } else { - return ""; +async function getImaSchainAbiAndAddress(): Promise { + if (!process.env.ABI) { + console.log(chalk.red("Set path to file with ABI and addresses to ABI environment variables")); + process.exit(1); } + const abiFilename = process.env.ABI; + return JSON.parse(await fs.readFile(abiFilename, "utf-8")); } async function main() { - const pathToManifest: string = stringValue(process.env.MANIFEST); - await manifestSetup( pathToManifest ); - await upgrade( + const pathToManifest: string = process.env.MANIFEST || ""; + await manifestSetup(pathToManifest); + const upgrader = new ImaSchainUpgrader( + "proxySchain", "1.3.4", - contracts, - async (safeTransactions, abi) => { - // deploying of new contracts - }, - async( safeTransactions, abi ) => { - const communityLockerName = "CommunityLocker"; - const communityLockerFactory = await ethers.getContractFactory(communityLockerName); - const communityLockerAddress = abi[getContractKeyInAbiFile(communityLockerName) + "_address"]; - let communityLocker; - if (communityLockerAddress) { - communityLocker = communityLockerFactory.attach(communityLockerAddress) as CommunityLocker; - console.log(chalk.yellow("Prepare transaction to initialize timestamp")); - safeTransactions.push(encodeTransaction( - 0, - communityLockerAddress, - 0, - communityLocker.interface.encodeFunctionData("initializeTimestamp") - )); - } else { - console.log(chalk.red("CommunityLocker was not found!")); - console.log(chalk.red("Check your abi!!!")); - process.exit(1); - } - }, - "proxySchain" + await getImaSchainAbiAndAddress(), + contracts ); + await upgrader.upgrade(); } -if( require.main === module ) { +if (require.main === module) { main() - .then( () => process.exit( 0 ) ) - .catch( error => { - console.error( error ); - process.exit( 1 ); - } ); + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); } diff --git a/proxy/package.json b/proxy/package.json index 0f94cda51..19a2ea24d 100644 --- a/proxy/package.json +++ b/proxy/package.json @@ -28,6 +28,7 @@ "@skalenetwork/etherbase-interfaces": "^0.0.1-develop.20", "@skalenetwork/ima-interfaces": "^1.1.0-develop.0", "@skalenetwork/skale-manager-interfaces": "1.0.0-develop.1", + "@skalenetwork/upgrade-tools": "2.0.0-refactor.15", "axios": "^0.21.4", "dotenv": "^10.0.0", "ethereumjs-tx": "2.1.2", diff --git a/proxy/predeployed/setup.cfg b/proxy/predeployed/setup.cfg index f25ca27aa..69f559606 100644 --- a/proxy/predeployed/setup.cfg +++ b/proxy/predeployed/setup.cfg @@ -19,7 +19,8 @@ packages = find: include_package_data = True python_requires = >=3.6 install_requires = - predeployed-generator >= 1.1.0a0 + predeployed-generator >= 1.1.0 + web3 >= 6.0.0 [options.packages.find] -where = src \ No newline at end of file +where = src diff --git a/proxy/predeployed/src/ima_predeployed/contract_generator.py b/proxy/predeployed/src/ima_predeployed/contract_generator.py index 50ce53af1..cc4568eae 100644 --- a/proxy/predeployed/src/ima_predeployed/contract_generator.py +++ b/proxy/predeployed/src/ima_predeployed/contract_generator.py @@ -4,7 +4,9 @@ def to_even_length(hex_string: str) -> str: - assert hex_string.startswith('0x') + a_res = hex_string.startswith('0x') + if __debug__: + if not a_res: raise AssertionError if len(hex_string) % 2 != 0: return "0x0" + hex_string[2:] else: @@ -22,11 +24,11 @@ def calculate_mapping_value_slot(slot: int, key: any, key_type: str) -> int: if key_type == 'address': return calculate_mapping_value_slot(slot, int(key, 16).to_bytes(32, 'big'), 'bytes32') else: - return int.from_bytes(Web3.solidityKeccak([key_type, 'uint256'], [key, slot]), 'big') + return int.from_bytes(Web3.solidity_keccak([key_type, 'uint256'], [key, slot]), 'big') def calculate_array_value_slot(slot: int, index: int) -> int: - return int.from_bytes(Web3.solidityKeccak(['uint256'], [slot]), 'big') + index + return int.from_bytes(Web3.solidity_keccak(['uint256'], [slot]), 'big') + index def next_slot(previous_slot: int) -> int: @@ -44,8 +46,12 @@ def __init__(self, artifact_filename: str): self.storage = {} def generate_contract(self, balance: int = 0, nonce: int = 0) -> dict: - assert isinstance(self.bytecode, str) - assert isinstance(self.storage, dict) + a_res = isinstance(self.bytecode, str) + if __debug__: + if not a_res: raise AssertionError + a_res = isinstance(self.storage, dict) + if __debug__: + if not a_res: raise AssertionError return { 'code': self.bytecode, 'balance': str(balance), @@ -59,7 +65,9 @@ def _write_address(self, slot: int, address: str) -> None: self.storage[to_even_length(hex(slot))] = address.lower() def _write_bytes32(self, slot: int, data: bytes) -> None: - assert len(data) <= 32 + data_length = len(data) + if __debug__: + if not ( data_length <= 32 ): raise AssertionError self.storage[to_even_length(hex(slot))] = to_even_length(add_0x(data.hex())) def _write_uint256(self, slot: int, value: int) -> None: diff --git a/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py b/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py index 9dff37b2c..bff2e5861 100644 --- a/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py +++ b/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py @@ -15,7 +15,7 @@ class CommunityLockerGenerator(AccessControlEnumerableGenerator): META_FILENAME = 'CommunityLocker.meta.json' DEFAULT_ADMIN_ROLE = (0).to_bytes(32, 'big') DEFAULT_TIME_LIMIT_SEC = 5 * 60 - MAINNET_HASH = Web3.solidityKeccak(['string'], ['Mainnet']) + MAINNET_HASH = Web3.solidity_keccak(['string'], ['Mainnet']) # ---------- storage ---------- # --------Initializable-------- @@ -81,7 +81,7 @@ def generate_storage(cls, **kwargs) -> Dict[str, str]: cls._write_address(storage, cls.TOKEN_MANAGER_LINKER_SLOT, TOKEN_MANAGER_LINKER_ADDRESS) cls._write_address(storage, cls.COMMUNITY_POOL_SLOT, community_pool_address) - cls._write_bytes32(storage, cls.SCHAIN_HASH_SLOT, Web3.solidityKeccak(['string'], [schain_name])) + cls._write_bytes32(storage, cls.SCHAIN_HASH_SLOT, Web3.solidity_keccak(['string'], [schain_name])) time_limit_per_message_slot = AccessControlEnumerableGenerator.calculate_mapping_value_slot( cls.TIME_LIMIT_PER_MESSAGE_SLOT, cls.MAINNET_HASH, 'bytes32') cls._write_uint256(storage, time_limit_per_message_slot, cls.DEFAULT_TIME_LIMIT_SEC) diff --git a/proxy/predeployed/src/ima_predeployed/contracts/eth_erc20.py b/proxy/predeployed/src/ima_predeployed/contracts/eth_erc20.py index 9127825da..c4180512f 100644 --- a/proxy/predeployed/src/ima_predeployed/contracts/eth_erc20.py +++ b/proxy/predeployed/src/ima_predeployed/contracts/eth_erc20.py @@ -14,8 +14,8 @@ class EthErc20Generator(AccessControlEnumerableGenerator): ARTIFACT_FILENAME = "EthErc20.json" META_FILENAME = "EthErc20.meta.json" DEFAULT_ADMIN_ROLE = (0).to_bytes(32, 'big') - MINTER_ROLE = Web3.solidityKeccak(['string'], ['MINTER_ROLE']) - BURNER_ROLE = Web3.solidityKeccak(['string'], ['BURNER_ROLE']) + MINTER_ROLE = Web3.solidity_keccak(['string'], ['MINTER_ROLE']) + BURNER_ROLE = Web3.solidity_keccak(['string'], ['BURNER_ROLE']) NAME = 'ERC20 Ether Clone' SYMBOL = 'ETHC' DECIMALS = 18 diff --git a/proxy/predeployed/src/ima_predeployed/contracts/message_proxy_for_schain.py b/proxy/predeployed/src/ima_predeployed/contracts/message_proxy_for_schain.py index e5ab5a50e..23d2dac2a 100644 --- a/proxy/predeployed/src/ima_predeployed/contracts/message_proxy_for_schain.py +++ b/proxy/predeployed/src/ima_predeployed/contracts/message_proxy_for_schain.py @@ -17,8 +17,8 @@ class MessageProxyForSchainGenerator(Generator): ARTIFACT_FILENAME = "MessageProxyForSchain.json" META_FILENAME = "MessageProxyForSchain.meta.json" DEFAULT_ADMIN_ROLE = (0).to_bytes(32, 'big') - CHAIN_CONNECTOR_ROLE = Web3.solidityKeccak(['string'], ['CHAIN_CONNECTOR_ROLE']) - MAINNET_HASH = Web3.solidityKeccak(['string'], ['Mainnet']) + CHAIN_CONNECTOR_ROLE = Web3.solidity_keccak(['string'], ['CHAIN_CONNECTOR_ROLE']) + MAINNET_HASH = Web3.solidity_keccak(['string'], ['Mainnet']) GAS_LIMIT = 3000000 ANY_SCHAIN = (0).to_bytes(32, 'big') @@ -89,7 +89,7 @@ def generate_storage(cls, **kwargs) -> Dict[str, str]: [TOKEN_MANAGER_LINKER_ADDRESS]) cls._write_address(storage, cls.KEY_STORAGE_SLOT, KEY_STORAGE_ADDRESS) cls._write_bytes32(storage, cls.SCHAIN_HASH_SLOT, - Web3.solidityKeccak(['string'], [schain_name])) + Web3.solidity_keccak(['string'], [schain_name])) connected_chain_info_slot = Generator.calculate_mapping_value_slot( cls.CONNECTED_CHAINS_SLOT, cls.MAINNET_HASH, 'bytes32') diff --git a/proxy/predeployed/src/ima_predeployed/contracts/token_manager.py b/proxy/predeployed/src/ima_predeployed/contracts/token_manager.py index 317e5e05c..c5acb698e 100644 --- a/proxy/predeployed/src/ima_predeployed/contracts/token_manager.py +++ b/proxy/predeployed/src/ima_predeployed/contracts/token_manager.py @@ -15,8 +15,8 @@ class TokenManagerGenerator(Generator): ARTIFACT_FILENAME = "TokenManager.json" META_FILENAME = "TokenManager.meta.json" DEFAULT_ADMIN_ROLE = (0).to_bytes(32, 'big') - AUTOMATIC_DEPLOY_ROLE = Web3.solidityKeccak(['string'], ['AUTOMATIC_DEPLOY_ROLE']) - TOKEN_REGISTRAR_ROLE = Web3.solidityKeccak(['string'], ['TOKEN_REGISTRAR_ROLE']) + AUTOMATIC_DEPLOY_ROLE = Web3.solidity_keccak(['string'], ['AUTOMATIC_DEPLOY_ROLE']) + TOKEN_REGISTRAR_ROLE = Web3.solidity_keccak(['string'], ['TOKEN_REGISTRAR_ROLE']) # ---------- storage ---------- # --------Initializable-------- @@ -79,7 +79,7 @@ def generate_storage(cls, **kwargs) -> Dict[str, str]: cls._write_address(storage, cls.MESSAGE_PROXY_SLOT, MESSAGE_PROXY_FOR_SCHAIN_ADDRESS) cls._write_address(storage, cls.TOKEN_MANAGER_LINKER_SLOT, TOKEN_MANAGER_LINKER_ADDRESS) cls._write_address(storage, cls.COMMUNITY_LOCKER_SLOT, COMMUNITY_LOCKER_ADDRESS) - cls._write_bytes32(storage, cls.SCHAIN_HASH_SLOT, Web3.solidityKeccak(['string'], [schain_name])) + cls._write_bytes32(storage, cls.SCHAIN_HASH_SLOT, Web3.solidity_keccak(['string'], [schain_name])) cls._write_address(storage, cls.DEPOSIT_BOX_SLOT, deposit_box_address) return storage diff --git a/proxy/predeployed/src/ima_predeployed/contracts/token_manager_linker.py b/proxy/predeployed/src/ima_predeployed/contracts/token_manager_linker.py index 9f10b54af..80ce135ee 100644 --- a/proxy/predeployed/src/ima_predeployed/contracts/token_manager_linker.py +++ b/proxy/predeployed/src/ima_predeployed/contracts/token_manager_linker.py @@ -17,7 +17,7 @@ class TokenManagerLinkerGenerator(Generator): ARTIFACT_FILENAME = "TokenManagerLinker.json" META_FILENAME = "TokenManagerLinker.meta.json" DEFAULT_ADMIN_ROLE = (0).to_bytes(32, 'big') - REGISTRAR_ROLE = Web3.solidityKeccak(['string'], ['REGISTRAR_ROLE']) + REGISTRAR_ROLE = Web3.solidity_keccak(['string'], ['REGISTRAR_ROLE']) # ---------- storage ---------- # --------Initializable-------- diff --git a/proxy/predeployed/test/base_genesis.json b/proxy/predeployed/test/base_genesis.json index e7ecdb5ed..35414dd46 100644 --- a/proxy/predeployed/test/base_genesis.json +++ b/proxy/predeployed/test/base_genesis.json @@ -5,19 +5,22 @@ "eip150Block": 0, "eip155Block": 0, "eip158Block": 0, - "istanbulBlock": 0, - "petersburgBlock": 0, "byzantiumBlock": 0, "constantinopleBlock": 0, - "berlinBlock": 0 + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "clique": { + "period": 5, + "epoch": 30000 + } }, "nonce": "0x0000000000000033", "timestamp": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x8000000", "difficulty": "0x100", - "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0xd2001DAb6898127Be2F167B548691C87251D13C3", + "extradata": "0x0000000000000000000000000000000000000000000000000000000000000000d2001DAb6898127Be2F167B548691C87251D13C30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "alloc": { "0xd2001DAb6898127Be2F167B548691C87251D13C3": { "balance": "1000000000000000000" diff --git a/proxy/predeployed/test/contracts/community_locker.py b/proxy/predeployed/test/contracts/community_locker.py index a1707e98b..5da08bf43 100644 --- a/proxy/predeployed/test/contracts/community_locker.py +++ b/proxy/predeployed/test/contracts/community_locker.py @@ -13,5 +13,5 @@ def check_community_locker(deployer_address: str, schain_name: str, community_po if not community_locker.functions.messageProxy().call() == MESSAGE_PROXY_FOR_SCHAIN_ADDRESS: raise AssertionError if not community_locker.functions.tokenManagerLinker().call() == TOKEN_MANAGER_LINKER_ADDRESS: raise AssertionError if not community_locker.functions.communityPool().call() == community_pool_address: raise AssertionError - if not community_locker.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): raise AssertionError + if not community_locker.functions.schainHash().call() == w3.solidity_keccak(['string'], [schain_name]): raise AssertionError if not community_locker.functions.timeLimitPerMessage(CommunityLockerGenerator.MAINNET_HASH).call() == CommunityLockerGenerator.DEFAULT_TIME_LIMIT_SEC: raise AssertionError diff --git a/proxy/predeployed/test/contracts/message_proxy_for_schain.py b/proxy/predeployed/test/contracts/message_proxy_for_schain.py index 98220db76..e7afa643a 100644 --- a/proxy/predeployed/test/contracts/message_proxy_for_schain.py +++ b/proxy/predeployed/test/contracts/message_proxy_for_schain.py @@ -23,7 +23,7 @@ def check_message_proxy_for_schain(owner_address, schain_name): raise AssertionError if not message_proxy_for_schain.functions.keyStorage().call() == KEY_STORAGE_ADDRESS: raise AssertionError - if not message_proxy_for_schain.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): + if not message_proxy_for_schain.functions.schainHash().call() == w3.solidity_keccak(['string'], [schain_name]): raise AssertionError if not message_proxy_for_schain.functions.getIncomingMessagesCounter('Mainnet').call() == 0: raise AssertionError diff --git a/proxy/predeployed/test/contracts/token_manager_erc1155.py b/proxy/predeployed/test/contracts/token_manager_erc1155.py index 011aefd3b..6338df414 100644 --- a/proxy/predeployed/test/contracts/token_manager_erc1155.py +++ b/proxy/predeployed/test/contracts/token_manager_erc1155.py @@ -22,6 +22,6 @@ def check_token_manager_erc1155(deployer_address, deposit_box_address, schain_na if not token_manager_erc1155.functions.messageProxy().call() == MESSAGE_PROXY_FOR_SCHAIN_ADDRESS: raise AssertionError if not token_manager_erc1155.functions.tokenManagerLinker().call() == TOKEN_MANAGER_LINKER_ADDRESS: raise AssertionError if not token_manager_erc1155.functions.communityLocker().call() == COMMUNITY_LOCKER_ADDRESS: raise AssertionError - if not token_manager_erc1155.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): raise AssertionError + if not token_manager_erc1155.functions.schainHash().call() == w3.solidity_keccak(['string'], [schain_name]): raise AssertionError if not token_manager_erc1155.functions.depositBox().call() == deposit_box_address: raise AssertionError if token_manager_erc1155.functions.automaticDeploy().call(): raise AssertionError diff --git a/proxy/predeployed/test/contracts/token_manager_erc20.py b/proxy/predeployed/test/contracts/token_manager_erc20.py index 189f4c6b5..1ea041293 100644 --- a/proxy/predeployed/test/contracts/token_manager_erc20.py +++ b/proxy/predeployed/test/contracts/token_manager_erc20.py @@ -22,6 +22,6 @@ def check_token_manager_erc20(deployer_address, deposit_box_address, schain_name if not token_manager_erc20.functions.messageProxy().call() == MESSAGE_PROXY_FOR_SCHAIN_ADDRESS: raise AssertionError if not token_manager_erc20.functions.tokenManagerLinker().call() == TOKEN_MANAGER_LINKER_ADDRESS: raise AssertionError if not token_manager_erc20.functions.communityLocker().call() == COMMUNITY_LOCKER_ADDRESS: raise AssertionError - if not token_manager_erc20.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): raise AssertionError + if not token_manager_erc20.functions.schainHash().call() == w3.solidity_keccak(['string'], [schain_name]): raise AssertionError if not token_manager_erc20.functions.depositBox().call() == deposit_box_address: raise AssertionError if token_manager_erc20.functions.automaticDeploy().call(): raise AssertionError diff --git a/proxy/predeployed/test/contracts/token_manager_erc721.py b/proxy/predeployed/test/contracts/token_manager_erc721.py index 3ab3b4600..1ec3cf6cf 100644 --- a/proxy/predeployed/test/contracts/token_manager_erc721.py +++ b/proxy/predeployed/test/contracts/token_manager_erc721.py @@ -22,6 +22,6 @@ def check_token_manager_erc721(deployer_address, deposit_box_address, schain_nam if not token_manager_erc721.functions.messageProxy().call() == MESSAGE_PROXY_FOR_SCHAIN_ADDRESS: raise AssertionError if not token_manager_erc721.functions.tokenManagerLinker().call() == TOKEN_MANAGER_LINKER_ADDRESS: raise AssertionError if not token_manager_erc721.functions.communityLocker().call() == COMMUNITY_LOCKER_ADDRESS: raise AssertionError - if not token_manager_erc721.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): raise AssertionError + if not token_manager_erc721.functions.schainHash().call() == w3.solidity_keccak(['string'], [schain_name]): raise AssertionError if not token_manager_erc721.functions.depositBox().call() == deposit_box_address: raise AssertionError if token_manager_erc721.functions.automaticDeploy().call(): raise AssertionError diff --git a/proxy/predeployed/test/contracts/token_manager_erc721_with_metadata.py b/proxy/predeployed/test/contracts/token_manager_erc721_with_metadata.py index d615e82cf..4746c16fc 100644 --- a/proxy/predeployed/test/contracts/token_manager_erc721_with_metadata.py +++ b/proxy/predeployed/test/contracts/token_manager_erc721_with_metadata.py @@ -22,6 +22,6 @@ def check_token_manager_erc721_with_metadata(deployer_address, deposit_box_addre if not token_manager_erc721_with_metadata.functions.messageProxy().call() == MESSAGE_PROXY_FOR_SCHAIN_ADDRESS: raise AssertionError if not token_manager_erc721_with_metadata.functions.tokenManagerLinker().call() == TOKEN_MANAGER_LINKER_ADDRESS: raise AssertionError if not token_manager_erc721_with_metadata.functions.communityLocker().call() == COMMUNITY_LOCKER_ADDRESS: raise AssertionError - if not token_manager_erc721_with_metadata.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): raise AssertionError + if not token_manager_erc721_with_metadata.functions.schainHash().call() == w3.solidity_keccak(['string'], [schain_name]): raise AssertionError if not token_manager_erc721_with_metadata.functions.depositBox().call() == deposit_box_address: raise AssertionError if token_manager_erc721_with_metadata.functions.automaticDeploy().call(): raise AssertionError diff --git a/proxy/predeployed/test/contracts/token_manager_eth.py b/proxy/predeployed/test/contracts/token_manager_eth.py index 95a9202ff..8e8a5c294 100644 --- a/proxy/predeployed/test/contracts/token_manager_eth.py +++ b/proxy/predeployed/test/contracts/token_manager_eth.py @@ -22,7 +22,7 @@ def check_token_manager_eth(deployer_address, deposit_box_address, schain_name): if not token_manager_eth.functions.messageProxy().call() == MESSAGE_PROXY_FOR_SCHAIN_ADDRESS: raise AssertionError if not token_manager_eth.functions.tokenManagerLinker().call() == TOKEN_MANAGER_LINKER_ADDRESS: raise AssertionError if not token_manager_eth.functions.communityLocker().call() == COMMUNITY_LOCKER_ADDRESS: raise AssertionError - if not token_manager_eth.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): raise AssertionError + if not token_manager_eth.functions.schainHash().call() == w3.solidity_keccak(['string'], [schain_name]): raise AssertionError if not token_manager_eth.functions.depositBox().call() == deposit_box_address: raise AssertionError if token_manager_eth.functions.automaticDeploy().call(): raise AssertionError if not token_manager_eth.functions.ethErc20().call() == ETH_ERC20_ADDRESS: raise AssertionError diff --git a/proxy/predeployed/test/requirements.txt b/proxy/predeployed/test/requirements.txt index 2172ac648..94e6bb1b6 100644 --- a/proxy/predeployed/test/requirements.txt +++ b/proxy/predeployed/test/requirements.txt @@ -1 +1 @@ -predeployed-generator>=1.1.0a1 \ No newline at end of file +predeployed-generator>=1.1.0 \ No newline at end of file diff --git a/proxy/predeployed/test/tools.py b/proxy/predeployed/test/tools.py index 0cd4dfccc..50195d485 100644 --- a/proxy/predeployed/test/tools.py +++ b/proxy/predeployed/test/tools.py @@ -6,9 +6,9 @@ w3 = Web3() wait_connection_seconds = 20 -while not w3.isConnected(): +while not w3.is_connected(): if wait_connection_seconds > 0: - sleep(1) + sleep( 1 ) wait_connection_seconds -= 1 else: raise ConnectionError("Can't connect to geth") diff --git a/proxy/scripts/prepare-docs.sh b/proxy/scripts/prepare-docs.sh new file mode 100755 index 000000000..db99f5079 --- /dev/null +++ b/proxy/scripts/prepare-docs.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# cSpell:words adoc + +set -o errexit + +OUTDIR=../docs/modules/api/pages/ + +if [ ! -d node_modules ]; then + yarn install --frozen-lockfile +fi + + +if [ "$(npm list | grep -c solidity-docgen)" -eq 0 ]; then + echo "Installing solidity-docgen..." + yarn add solidity-docgen@0.5.16 + else + echo "Solidity-docgen already installed." +fi + +if [ "$(npm list | grep -c lodash.startcase)" -eq 0 ]; then + echo "Installing lodash.startcase..." + yarn add lodash.startcase@4.4.0 + else + echo "Lodash.startcase already installed." +fi + +rm -rf "$OUTDIR" + +solidity-docgen \ + -i contracts/ \ + -e contracts/test/ \ + -H ../docs/helpers.js \ + --solc-module=./scripts/prepare-docs-solc.js \ + -t ../docs \ + -o "$OUTDIR" \ + --extension=adoc + +node scripts/gen-nav.js "$OUTDIR" > "$OUTDIR/../nav.adoc" diff --git a/proxy/scripts/test_upgrade.sh b/proxy/scripts/test_upgrade.sh old mode 100644 new mode 100755 index fd01cba5f..b6cbbd30b --- a/proxy/scripts/test_upgrade.sh +++ b/proxy/scripts/test_upgrade.sh @@ -2,10 +2,21 @@ set -e +if [ -z "$GITHUB_WORKSPACE" ] +then + GITHUB_WORKSPACE="$(dirname "$(dirname "$(dirname "$(realpath "$0")")")")" +fi + +if [ -z "$GITHUB_REPOSITORY" ] +then + GITHUB_REPOSITORY="skalenetwork/IMA" +fi + + DEPLOYED_TAG="$(cat "$GITHUB_WORKSPACE"/proxy/DEPLOYED)" VERSION_TAG="$(cat "$GITHUB_WORKSPACE"/VERSION)" DEPLOYED_VERSION="$(echo "$DEPLOYED_TAG" | cut -d '-' -f 1)" -DEPLOYED_DIR=$GITHUB_WORKSPACE/deployed-proxy/ +DEPLOYED_DIR=$GITHUB_WORKSPACE/deployed-IMA/ git clone --branch "$DEPLOYED_TAG" "https://github.com/$GITHUB_REPOSITORY.git" "$DEPLOYED_DIR" @@ -24,8 +35,12 @@ CHAIN_NAME_SCHAIN="Test" VERSION="$DEPLOYED_VERSION" npx hardhat run migrations/ cp "$GITHUB_WORKSPACE/proxy/migrations/generateManifest.ts" ./migrations/generateManifest.ts cp "$GITHUB_WORKSPACE/proxy/migrations/changeManifest.ts" ./migrations/changeManifest.ts cp "$GITHUB_WORKSPACE/proxy/migrations/tools/version.ts" ./migrations/tools/version.ts + ABI_FILENAME_SCHAIN="proxySchain_Test.json" -ABI="data/$ABI_FILENAME_SCHAIN" MANIFEST=".openzeppelin/unknown-1337.json" VERSION="$DEPLOYED_VERSION" npx hardhat run migrations/changeManifest.ts --network localhost +ABI="data/$ABI_FILENAME_SCHAIN" \ +MANIFEST=".openzeppelin/unknown-1337.json" \ +VERSION="$DEPLOYED_VERSION" \ +npx hardhat run migrations/changeManifest.ts --network localhost cp .openzeppelin/unknown-*.json "$GITHUB_WORKSPACE/proxy/.openzeppelin" cp ./data/skaleManagerComponents.json "$GITHUB_WORKSPACE/proxy/data/" @@ -37,16 +52,21 @@ cd "$GITHUB_WORKSPACE" rm -r --interactive=never "$DEPLOYED_DIR" cd proxy -# TODO: remove updateManifest script after upgrade from 1.3.0-stable.0 -./scripts/updateManifest.py ".openzeppelin/unknown-1337.json" -./scripts/updateManifest.py "data/ima-schain-$DEPLOYED_VERSION-manifest.json" - -ABI="data/$ABI_FILENAME_MAINNET" TEST_UPGRADE=true npx hardhat run migrations/upgradeMainnet.ts --network localhost +ABI="data/$ABI_FILENAME_MAINNET" \ +TEST_UPGRADE=true \ +ALLOW_NOT_ATOMIC_UPGRADE="OK" \ +VERSION=$VERSION_TAG \ +npx hardhat run migrations/upgradeMainnet.ts --network localhost VERSION="$(git describe --tags | echo "$VERSION_TAG")" echo "$VERSION" mv "data/proxyMainnet-$VERSION-localhost-abi.json" "data/proxyMainnet.json" -ABI="data/$ABI_FILENAME_SCHAIN" MANIFEST="data/ima-schain-$DEPLOYED_VERSION-manifest.json" CHAIN_NAME_SCHAIN="Test" npx hardhat run migrations/upgradeSchain.ts --network localhost +ABI="data/$ABI_FILENAME_SCHAIN" \ +MANIFEST="data/ima-schain-$DEPLOYED_VERSION-manifest.json" \ +CHAIN_NAME_SCHAIN="Test" \ +ALLOW_NOT_ATOMIC_UPGRADE="OK" \ +VERSION=$VERSION_TAG \ +npx hardhat run migrations/upgradeSchain.ts --network localhost npx kill-port 8545 diff --git a/proxy/yarn.lock b/proxy/yarn.lock index 4646476f0..a7c087d95 100644 --- a/proxy/yarn.lock +++ b/proxy/yarn.lock @@ -602,6 +602,11 @@ dependencies: "@types/bignumber.js" "^5.0.0" +"@openzeppelin/contracts-upgradeable@^4.4.2": + version "4.8.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.0.tgz#26688982f46969018e3ed3199e72a07c8d114275" + integrity sha512-5GeFgqMiDlqGT8EdORadp1ntGF0qzWZLmEY7Wbp/yVhN7/B3NNzCxujuI77ktlyG81N3CUZP8cZe3ZAQ/cW10w== + "@openzeppelin/contracts-upgradeable@^4.7.1": version "4.7.1" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.1.tgz#f63fc384255d6ac139e0a2561aa207fd7c14183c" @@ -774,6 +779,15 @@ resolved "https://registry.yarnpkg.com/@skalenetwork/skale-manager-interfaces/-/skale-manager-interfaces-0.1.2.tgz#88e543c8cc298cd0cc9559892d746d2d74786da8" integrity sha512-gapSQJahwWMlTB/xp/kMzB6k+9+Skx/N0fvEloiW4CUrkGkSa8+fj16YmUXX45p1hOc45W+JydiJPNgZtx32Dg== +"@skalenetwork/upgrade-tools@2.0.0-refactor.15": + version "2.0.0-refactor.15" + resolved "https://registry.yarnpkg.com/@skalenetwork/upgrade-tools/-/upgrade-tools-2.0.0-refactor.15.tgz#1699469da5067ab63a1671d97ed039f3f36cf50b" + integrity sha512-yrg1YjD4rilu/Hmcj54mcwD/tgi1f5OSBUYWZ9NGjqAAD6aitlQ0FewXoFAbWvwCgoB6t01X5IOO3Fy1gM6UNA== + dependencies: + "@openzeppelin/contracts-upgradeable" "^4.4.2" + axios "^0.27.2" + ethereumjs-util "^7.1.4" + "@solidity-parser/parser@^0.11.0": version "0.11.1" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.11.1.tgz#fa840af64840c930f24a9c82c08d4a092a068add" @@ -1411,6 +1425,14 @@ axios@^0.21.4: dependencies: follow-redirects "^1.14.0" +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -4190,6 +4212,11 @@ follow-redirects@^1.12.1, follow-redirects@^1.14.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== +follow-redirects@^1.14.9: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + for-each@^0.3.3, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -4221,6 +4248,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" diff --git a/test-tokens/hardhat.config.ts b/test-tokens/hardhat.config.ts index f7f7bf6bb..bfb12379e 100644 --- a/test-tokens/hardhat.config.ts +++ b/test-tokens/hardhat.config.ts @@ -2,12 +2,84 @@ import { task, HardhatUserConfig } from "hardhat/config"; import "@nomiclabs/hardhat-etherscan"; import "@nomiclabs/hardhat-web3"; import "@nomiclabs/hardhat-ethers"; -import * as owasp from "../npms/skale-owasp/owasp-util"; import * as dotenv from "dotenv" import { promises as fs } from "fs"; dotenv.config(); +function verifyArgumentWithNonEmptyValue( joArg ) { + if( ( !joArg.value ) || ( typeof joArg.value === "string" && joArg.value.length === 0 ) ) { + console.log( "CRITICAL ERROR: value " + joArg.value + " of argument " + joArg.name + " must not be empty" ); + process.exit( 126 ); + } + return joArg; +} + +function validateRadix( value, radix ) { + value = "" + ( value ? value.toString() : "10" ); + value = value.trim(); + radix = ( radix == null || radix == undefined ) + ? ( ( value.length > 2 && value[0] == "0" && ( value[1] == "x" || value[1] == "X" ) ) ? 16 : 10 ) + : parseInt( radix, 10 ); + return radix; +} +function validateInteger( value, radix ) { + try { + value = "" + value; + value = value.trim(); + if( value.length < 1 ) + return false; + radix = validateRadix( value, radix ); + if( ( !isNaN( value ) ) && + ( parseInt( value, radix ) == value || radix !== 10 ) && + ( !isNaN( parseInt( value, radix ) ) ) + ) + return true; + } catch ( err ) { + } + return false; +} + +function toInteger( value, radix ) { + try { + radix = validateRadix( value, radix ); + if( !validateInteger( value, radix ) ) + return NaN; + return parseInt( value, radix ); + } catch ( err ) { + } + return false; +} + +function verifyArgumentIsArrayOfIntegers( joArg ) { + try { + verifyArgumentWithNonEmptyValue( joArg ); + if( joArg.value.length < 3 ) { + console.log( "CRITICAL ERROR: length " + joArg.value.length + " of argument " + joArg.name + " must be bigger than 2" ); + process.exit( 126 ); + } + if( joArg.value[0] !== "[" || joArg.value[joArg.value.length - 1] !== "]" ) { + console.log( "CRITICAL ERROR: first and last symbol " + joArg.value + " of argument " + joArg.name + " must be brackets" ); + process.exit( 126 ); + } + const newValue = joArg.value.replace( "[", "" ).replace( "]", "" ).split( "," ); + for( let index = 0; index < newValue.length; index++ ) { + if( !newValue[index] || ( typeof newValue[index] === "string" && newValue[index].length === 0 ) ) { + console.log( "CRITICAL ERROR: value " + newValue[index] + " of argument " + joArg.name + " must not be empty" ); + process.exit( 126 ); + } + if( !validateInteger( newValue[index], undefined ) ) { + console.log( "CRITICAL ERROR: value " + newValue[index] + " of argument " + joArg.name + " must be valid integer" ); + process.exit( 126 ); + } + newValue[index] = toInteger( newValue[index], undefined ); + } + return newValue; + } catch ( err ) { + console.log( "(OWASP) CRITICAL ERROR: value " + joArg.value + " of argument " + joArg.name + " must be valid integer array" ); + process.exit( 126 ); + } +} task("erc20", "Deploy ERC20 Token sample to chain") .addOptionalParam("contract", "ERC20 Token contract") @@ -105,8 +177,8 @@ task("mint-erc1155", "Mint ERC1155 Token") const data = taskArgs.data ? taskArgs.data : "0x"; let res = null; if (batch) { - const tokenIds = owasp.verifyArgumentIsArrayOfIntegers({value: taskArgs.tokenId}); - const amounts = owasp.verifyArgumentIsArrayOfIntegers({value: taskArgs.amount}); + const tokenIds = verifyArgumentIsArrayOfIntegers({value: taskArgs.tokenId}); + const amounts = verifyArgumentIsArrayOfIntegers({value: taskArgs.amount}); if (tokenIds.length !== amounts.length) { console.log("\n\n!!! Length of arrays should be equal !!!\n\n"); return; @@ -117,7 +189,7 @@ task("mint-erc1155", "Mint ERC1155 Token") } console.log("ERC1155 Token at address:", taskArgs.tokenAddress); console.log("Minted tokenId:", taskArgs.tokenId, "and amount:", taskArgs.amount, "with data:", data, "to address", taskArgs.receiverAddress); - console.log("Gas spent:", res.gasUsed.toNumber()); + console.log("Gas spent:", res ? res.gasUsed.toNumber() : 0); } ); diff --git a/test-tokens/package.json b/test-tokens/package.json index 92f80a7c8..277c53142 100644 --- a/test-tokens/package.json +++ b/test-tokens/package.json @@ -9,7 +9,7 @@ "scripts": { "compile": "npx hardhat clean && npx hardhat compile", "prepare": "yarn compile", - "postinstall": "cd ../npms/skale-owasp && yarn install && cd ../../test-tokens" + "postinstall": "./postinstall.sh" }, "dependencies": { "@nomiclabs/hardhat-ethers": "^2.0.2", diff --git a/test-tokens/postinstall.sh b/test-tokens/postinstall.sh new file mode 100755 index 000000000..61b8f76af --- /dev/null +++ b/test-tokens/postinstall.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo " " +echo "----- installing in OWASP ------------------------------------------------------------------" +echo " " +cd ../npms/skale-owasp +yarn install +cd ../../test-tokens diff --git a/test/agent-test.js b/test/agent-test.js deleted file mode 100644 index 2ff55e927..000000000 --- a/test/agent-test.js +++ /dev/null @@ -1,909 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only - -/** - * @license - * SKALE IMA - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -/** - * @file agent-test.js - * @copyright SKALE Labs 2019-Present - */ - -const assert = require( "assert" ); -const fs = require( "fs" ); -const os = require( "os" ); -const path = require( "path" ); - -process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; // allow self-signed wss and https - -global.IMA = require( "../npms/skale-ima" ); -global.w3mod = IMA.w3mod; -global.ethereumjs_tx = IMA.ethereumjs_tx; -global.ethereumjs_wallet = IMA.ethereumjs_wallet; -global.ethereumjs_util = IMA.ethereumjs_util; -global.compose_tx_instance = IMA.compose_tx_instance; -global.owaspUtils = IMA.owaspUtils; -global.imaUtils = require( "../agent/utils.js" ); -IMA.expose_details_set( false ); -IMA.verbose_set( IMA.verbose_parse( "info" ) ); -global.log = global.imaUtils.log; -global.cc = global.imaUtils.cc; -global.imaCLI = require( "../agent/cli.js" ); -global.imaBLS = require( "../agent/bls.js" ); -global.rpcCall = require( "../agent/rpc-call.js" ); -global.rpcCall.init(); - -log.removeAll(); -// log.addStdout(); -// log.addMemory(); // console.log( log.getStreamWithFilePath( "memory" ).strAccumulatedLogText ); - -global.imaState = { - "strLogFilePath": "", - "nLogMaxSizeBeforeRotation": -1, - "nLogMaxFilesCount": -1, - "isPrintGathered": true, - "isPrintSecurityValues": true, - - "bIsNeededCommonInit": true, - "bSignMessages": false, // use BLS message signing, turned on with --sign-messages - "joSChainNetworkInfo": null, // scanned S-Chain network description - "strPathBlsGlue": "", // path to bls_glue app, must have if --sign-messages specified - "strPathHashG1": "", // path to hash_g1 app, must have if --sign-messages specified - "strPathBlsVerify": "", // path to verify_bls app, optional, if specified then we will verify gathered BLS signature - - "joAbiPublishResult_skale_manager": { }, - "joAbiPublishResult_main_net": { }, - "joAbiPublishResult_s_chain": { }, - "joAbiPublishResult_t_chain": { }, - "bHaveSkaleManagerABI": false, - "bHaveImaAbiMainNet": false, - "bHaveImaAbiSchain": false, - "bHaveImaAbiSchainTarget": false, - - "joErc20_main_net": null, - "joErc20_s_chain": null, - "joErc20_t_chain": null, - "strAddrErc20_explicit": "", - "strAddrErc20_explicit_target": "", // S<->S target - "strCoinNameErc20_main_net": "", // in-JSON coin name - "strCoinNameErc20_s_chain": "", // in-JSON coin name - "strCoinNameErc20_t_chain": "", // in-JSON coin name - - "joErc721_main_net": null, - "joErc721_s_chain": null, - "joErc721_t_chain": null, - "strAddrErc721_explicit": "", - "strAddrErc721_explicit_target": "", // S<->S target - "strCoinNameErc721_main_net": "", // in-JSON coin name - "strCoinNameErc721_s_chain": "", // in-JSON coin name - "strCoinNameErc721_t_chain": "", // in-JSON coin name - - "joErc1155_main_net": null, - "joErc1155_s_chain": null, - "joErc1155_t_chain": null, - "strAddrErc1155_explicit": "", - "strAddrErc1155_explicit_target": "", // S<->S target - "strCoinNameErc1155_main_net": "", // in-JSON coin name - "strCoinNameErc1155_s_chain": "", // in-JSON coin name - "strCoinNameErc1155_t_chain": "", // in-JSON coin name - - "strPathAbiJson_skale_manager": null, // "", // imaUtils.normalizePath( "../proxy/data/skaleManager.json" ), // "./abi_skale_manager.json" - "strPathAbiJson_main_net": imaUtils.normalizePath( "./agent-test-data/proxyMainnet.json" ), - "strPathAbiJson_s_chain": imaUtils.normalizePath( "./agent-test-data/proxySchain_Bob.json" ), - "strPathAbiJson_t_chain": null, - - "bShowConfigMode": false, // true - just show configuration values and exit - - "bNoWaitSChainStarted": false, - "nMaxWaitSChainAttempts": 0 + Number.MAX_SAFE_INTEGER, // 20 - "isPreventExitAfterLastAction": false, - - "strURL_main_net": owaspUtils.toStringURL( process.env.URL_W3_ETHEREUM || "http://127.0.0.1:8545" ), // example: "http://127.0.0.1:8545 - "strURL_s_chain": owaspUtils.toStringURL( process.env.URL_W3_S_CHAIN || "http://127.0.0.1:15000" ), - - "strChainName_main_net": ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), - "strChainName_s_chain": ( process.env.CHAIN_NAME_SCHAIN || "Bob" ).toString().trim(), - "strChainName_origin_chain": ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), - "strChainName_t_chain": ( process.env.CHAIN_NAME_SCHAIN_TARGET || "Alice" ).toString().trim(), - "cid_main_net": owaspUtils.toInteger( process.env.CID_ETHEREUM ) || -4, - "cid_s_chain": owaspUtils.toInteger( process.env.CID_SCHAIN ) || -4, - "cid_t_chain": owaspUtils.toInteger( process.env.CID_SCHAIN_TARGET ) || -4, - - "strPathJsonErc20_main_net": "", - "strPathJsonErc20_s_chain": "", - "strPathJsonErc20_t_chain": "", - "strPathJsonErc721_main_net": "", - "strPathJsonErc721_s_chain": "", - "strPathJsonErc721_t_chain": "", - "strPathJsonErc1155_main_net": "", - "strPathJsonErc1155_s_chain": "", - "strPathJsonErc1155_t_chain": "", - - "nAmountOfWei": 0, - "nAmountOfToken": 0, - "arrAmountsOfTokens": null, - "idToken": 0, - "idTokens": [], - "have_idToken": false, - "have_idTokens": false, - - "nTransferBlockSizeM2S": 4, // 10 - "nTransferBlockSizeS2M": 4, // 10 - "nTransferBlockSizeS2S": 4, // 10 - "nMaxTransactionsM2S": 0, - "nMaxTransactionsS2M": 0, - "nMaxTransactionsS2S": 0, - - "nBlockAwaitDepthM2S": 0, - "nBlockAwaitDepthS2M": 0, - "nBlockAwaitDepthS2S": 0, - "nBlockAgeM2S": 0, - "nBlockAgeS2M": 0, - "nBlockAgeS2S": 0, - - "nLoopPeriodSeconds": 10, - - "nNodeNumber": 0, // S-Chain node number(zero based) - "nNodesCount": 1, - "nTimeFrameSeconds": 0, // 0-disable, 60-recommended - "nNextFrameGap": 10, - - "nAutoExitAfterSeconds": 0, // 0-disable - - "w3_main_net": null, - "w3_s_chain": null, - "w3_t_chain": null, - - "jo_deposit_box_eth": null, // only main net - "jo_deposit_box_erc20": null, // only main net - "jo_deposit_box_erc721": null, // only main net - "jo_deposit_box_erc1155": null, // only main net - "jo_token_manager": null, // only s-chain - "jo_message_proxy_main_net": null, - "jo_message_proxy_s_chain": null, - "jo_linker": null, - "jo_lock_and_data_s_chain": null, - // "eth_erc721": null, // only s-chain - "eth_erc20": null, // only s-chain - - "joAccount_main_net": { - "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_ETHEREUM ), - "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_ETHEREUM ), - "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_ETHEREUM ), - "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_ETHEREUM ), - "strPathSslKey": ( process.env.SGX_SSL_KEY_FILE_ETHEREUM || "" ).toString().trim(), - "strPathSslCert": ( process.env.SGX_SSL_CERT_FILE_ETHEREUM || "" ).toString().trim() - }, - "joAccount_s_chain": { - "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN ), - "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_S_CHAIN ), - "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN ), - "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN ), - "strPathSslKey": ( process.env.SGX_SSL_KEY_FILE_S_CHAIN || "" ).toString().trim(), - "strPathSslCert": ( process.env.SGX_SSL_CERT_FILE_S_CHAIN || "" ).toString().trim() - }, - "joAccount_t_chain": { - "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN_TARGET ), - "address": IMA.owaspUtils.fn_address_impl_, - "strTransactionManagerURL": owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_S_CHAIN_TARGET ), - "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN_TARGET ), - "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN_TARGET ), - "strPathSslKey": ( process.env.SGX_SSL_KEY_FILE_S_CHAIN_TARGET || "" ).toString().trim(), - "strPathSslCert": ( process.env.SGX_SSL_CERT_FILE_S_CHAIN_TARGET || "" ).toString().trim() - }, - - // - "tc_main_net": IMA.tc_main_net, - "tc_s_chain": IMA.tc_s_chain, - "tc_t_chain": IMA.tc_t_chain, - // - - "doEnableDryRun": function( isEnable ) { return IMA.dry_run_enable( isEnable ); }, - "doIgnoreDryRun": function( isIgnore ) { return IMA.dry_run_ignore( isIgnore ); }, - - optsPendingTxAnalysis: { - isEnabled: true - }, - - "s2s_opts": { // S-Chain to S-Chain transfer options - "isEnabled": false, // is S-Chain to S-Chain transfers enabled - "secondsToReDiscoverSkaleNetwork": 10 * 60 // seconts to re-discover SKALE network, 0 to disable - }, - - "arrActions": [] // array of actions to run -}; - -imaCLI.ima_common_init(); - -describe( "OWASP", function() { - - describe( "Parsing utilities", function() { - - it( "Integer basic validation", function() { - assert.equal( owaspUtils.is_numeric( "0" ), true ); - assert.equal( owaspUtils.is_numeric( "123" ), true ); - } ); - - it( "Integer RegEx validation", function() { - assert.equal( owaspUtils.rxIsInt( "0" ), true ); - assert.equal( owaspUtils.rxIsInt( "123" ), true ); - assert.equal( owaspUtils.rxIsInt( "-456" ), true ); - assert.equal( owaspUtils.rxIsInt( "a012" ), false ); - } ); - - it( "Floating point RegEx validation", function() { - assert.equal( owaspUtils.rxIsFloat( "0" ), true ); - assert.equal( owaspUtils.rxIsFloat( "0.0" ), true ); - assert.equal( owaspUtils.rxIsFloat( "123.456" ), true ); - assert.equal( owaspUtils.rxIsFloat( "-123.456" ), true ); - assert.equal( owaspUtils.rxIsFloat( "a012" ), false ); - } ); - - it( "Radix validation", function() { - assert.equal( owaspUtils.validateRadix( "123", "10" ), 10 ); - assert.equal( owaspUtils.validateRadix( "0x20", "16" ), 16 ); - } ); - - it( "Integer conversion", function() { - assert.equal( owaspUtils.toInteger( "12345", 10 ), 12345 ); - assert.equal( owaspUtils.toInteger( "0x20", 16 ), 0x20 ); - } ); - - it( "Floating point validation", function() { - assert.equal( owaspUtils.validateFloat( "123.456" ), true ); - assert.equal( owaspUtils.validateFloat( "hello 123.456" ), false ); - } ); - - it( "Floating point conversion", function() { - assert.equal( owaspUtils.toFloat( "123.456" ), 123.456 ); - assert.equal( owaspUtils.rxIsFloat( owaspUtils.toFloat( "hello 123.456" ) ), false ); - } ); - - it( "Boolean conversion", function() { - assert.equal( owaspUtils.toBoolean( "true" ), true ); - assert.equal( owaspUtils.toBoolean( "false" ), false ); - assert.equal( owaspUtils.toBoolean( true ), true ); - assert.equal( owaspUtils.toBoolean( false ), false ); - assert.equal( owaspUtils.toBoolean( "True" ), true ); - assert.equal( owaspUtils.toBoolean( "False" ), false ); - assert.equal( owaspUtils.toBoolean( "TRUE" ), true ); - assert.equal( owaspUtils.toBoolean( "FALSE" ), false ); - assert.equal( owaspUtils.toBoolean( "t" ), true ); - assert.equal( owaspUtils.toBoolean( "f" ), false ); - assert.equal( owaspUtils.toBoolean( "T" ), true ); - assert.equal( owaspUtils.toBoolean( "F" ), false ); - assert.equal( owaspUtils.toBoolean( "1" ), true ); - assert.equal( owaspUtils.toBoolean( "-1" ), true ); - assert.equal( owaspUtils.toBoolean( "0" ), false ); - assert.equal( owaspUtils.toBoolean( "0.123" ), true ); - assert.equal( owaspUtils.toBoolean( "" ), false ); - } ); - - it( "URL validation", function() { - assert.equal( owaspUtils.validateURL( "http://127.0.0.1" ), true ); - assert.equal( owaspUtils.validateURL( "http://127.0.0.1/" ), true ); - assert.equal( owaspUtils.validateURL( "https://127.0.0.1:3344" ), true ); - assert.equal( owaspUtils.validateURL( "https://127.0.0.1:3344/" ), true ); - assert.equal( owaspUtils.validateURL( "ws://[::1]" ), true ); - assert.equal( owaspUtils.validateURL( "ws://[::1]/" ), true ); - assert.equal( owaspUtils.validateURL( "wss://[::1]:3344" ), true ); - assert.equal( owaspUtils.validateURL( "wss://[::1]:3344/" ), true ); - assert.equal( owaspUtils.validateURL( "http://some.domain.org" ), true ); - assert.equal( owaspUtils.validateURL( "http://some.domain.org/" ), true ); - assert.equal( owaspUtils.validateURL( "https://some.domain.org:3344" ), true ); - assert.equal( owaspUtils.validateURL( "https://some.domain.org:3344/" ), true ); - assert.equal( owaspUtils.validateURL( "hello ws://[::1]" ), false ); - assert.equal( owaspUtils.validateURL( "hello ws://[::1]/" ), false ); - assert.equal( owaspUtils.validateURL( "hello wss://[::1]:3344" ), false ); - assert.equal( owaspUtils.validateURL( "hello wss://[::1]:3344/" ), false ); - } ); - - it( "URL conversion", function() { - assert.equal( owaspUtils.toURL( "http://127.0.0.1" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "https://127.0.0.1:3344" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "https://127.0.0.1:3344/" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "ws://[::1]" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "ws://[::1]/" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "wss://[::1]:3344" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "wss://[::1]:3344/" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "http://some.domain.org" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "http://some.domain.org/" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "https://some.domain.org3344" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "https://some.domain.org:3344/" ).constructor.name, "URL" ); - assert.equal( owaspUtils.toURL( "http://127.0.0.1" ).toString(), "http://127.0.0.1/" ); - assert.equal( owaspUtils.toURL( "http://127.0.0.1/" ).toString(), "http://127.0.0.1/" ); - assert.equal( owaspUtils.toURL( "https://127.0.0.1:3344" ).toString(), "https://127.0.0.1:3344/" ); - assert.equal( owaspUtils.toURL( "https://127.0.0.1:3344/" ).toString(), "https://127.0.0.1:3344/" ); - assert.equal( owaspUtils.toURL( "ws://[::1]" ).toString(), "ws://[::1]/" ); - assert.equal( owaspUtils.toURL( "ws://[::1]/" ).toString(), "ws://[::1]/" ); - assert.equal( owaspUtils.toURL( "wss://[::1]:3344" ).toString(), "wss://[::1]:3344/" ); - assert.equal( owaspUtils.toURL( "wss://[::1]:3344/" ).toString(), "wss://[::1]:3344/" ); - assert.equal( owaspUtils.toURL( "http://some.domain.org" ).toString(), "http://some.domain.org/" ); - assert.equal( owaspUtils.toURL( "http://some.domain.org/" ).toString(), "http://some.domain.org/" ); - assert.equal( owaspUtils.toURL( "https://some.domain.org:3344" ).toString(), "https://some.domain.org:3344/" ); - assert.equal( owaspUtils.toURL( "https://some.domain.org:3344/" ).toString(), "https://some.domain.org:3344/" ); - assert.equal( owaspUtils.toStringURL( "http://127.0.0.1" ), "http://127.0.0.1/" ); - assert.equal( owaspUtils.toStringURL( "http://127.0.0.1/" ), "http://127.0.0.1/" ); - assert.equal( owaspUtils.toStringURL( "https://127.0.0.1:3344" ), "https://127.0.0.1:3344/" ); - assert.equal( owaspUtils.toStringURL( "https://127.0.0.1:3344/" ), "https://127.0.0.1:3344/" ); - assert.equal( owaspUtils.toStringURL( "ws://[::1]" ), "ws://[::1]/" ); - assert.equal( owaspUtils.toStringURL( "ws://[::1]/" ), "ws://[::1]/" ); - assert.equal( owaspUtils.toStringURL( "wss://[::1]:3344" ), "wss://[::1]:3344/" ); - assert.equal( owaspUtils.toStringURL( "wss://[::1]:3344/" ), "wss://[::1]:3344/" ); - assert.equal( owaspUtils.toStringURL( "http://some.domain.org" ), "http://some.domain.org/" ); - assert.equal( owaspUtils.toStringURL( "http://some.domain.org/" ), "http://some.domain.org/" ); - assert.equal( owaspUtils.toStringURL( "https://some.domain.org:3344" ), "https://some.domain.org:3344/" ); - assert.equal( owaspUtils.toStringURL( "https://some.domain.org:3344/" ), "https://some.domain.org:3344/" ); - } ); - - const strAddressValid0 = "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5F"; - const strAddressValid1 = "7aa5E36AA15E93D10F4F26357C30F052DacDde5F"; - const strAddressInvalid0 = "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5"; - const strAddressInvalid1 = "hello"; - const strAddressInvalid2 = ""; - - it( "Validate Ethereum address", function() { - assert.equal( owaspUtils.validateEthAddress( strAddressValid0 ), true ); - assert.equal( owaspUtils.validateEthAddress( strAddressValid1 ), true ); - assert.equal( owaspUtils.validateEthAddress( strAddressInvalid0 ), false ); - assert.equal( owaspUtils.validateEthAddress( strAddressInvalid1 ), false ); - assert.equal( owaspUtils.validateEthAddress( strAddressInvalid2 ), false ); - } ); - - it( "Parse Ethereum address", function() { - assert.equal( owaspUtils.toEthAddress( strAddressValid0 ), strAddressValid0 ); - assert.equal( owaspUtils.toEthAddress( strAddressValid1 ), strAddressValid0 ); - assert.equal( owaspUtils.toEthAddress( strAddressInvalid0, strAddressValid0 ), strAddressValid0 ); - assert.equal( owaspUtils.toEthAddress( strAddressInvalid0, "invalid value" ), "invalid value" ); - assert.equal( owaspUtils.toEthAddress( strAddressInvalid1, strAddressValid0 ), strAddressValid0 ); - assert.equal( owaspUtils.toEthAddress( strAddressInvalid1, "invalid value" ), "invalid value" ); - assert.equal( owaspUtils.toEthAddress( strAddressInvalid2, strAddressValid0 ), strAddressValid0 ); - assert.equal( owaspUtils.toEthAddress( strAddressInvalid2, "invalid value" ), "invalid value" ); - } ); - - const strPrivateKeyValid0 = "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC"; - const strPrivateKeyValid1 = "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC"; - const strPrivateKeyInvalid0 = "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1F"; - const strPrivateKeyInvalid1 = "hello"; - const strPrivateKeyInvalid2 = ""; - - it( "Validate Ethereum private key", function() { - assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyValid0 ), true ); - assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyValid1 ), true ); - assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyInvalid0 ), false ); - assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyInvalid1 ), false ); - assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyInvalid2 ), false ); - } ); - - it( "Parse Ethereum private key", function() { - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyValid0 ), strPrivateKeyValid0 ); - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyValid1 ), strPrivateKeyValid0 ); - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyInvalid0, strPrivateKeyValid0 ), strPrivateKeyValid0 ); - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyInvalid0, "invalid value" ), "invalid value" ); - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyInvalid1, strPrivateKeyValid0 ), strPrivateKeyValid0 ); - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyInvalid1, "invalid value" ), "invalid value" ); - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyInvalid2, strPrivateKeyValid0 ), strPrivateKeyValid0 ); - assert.equal( owaspUtils.toEthPrivateKey( strPrivateKeyInvalid2, "invalid value" ), "invalid value" ); - } ); - - it( "Byte sequence utilities", function() { - assert.equal( owaspUtils.ensure_starts_with_0x( "0x123" ), "0x123" ); - assert.equal( owaspUtils.ensure_starts_with_0x( "123" ), "0x123" ); - assert.equal( owaspUtils.remove_starting_0x( "0x123" ), "123" ); - assert.equal( owaspUtils.remove_starting_0x( "123" ), "123" ); - } ); - - } ); - - describe( "Command line argument utilities", function() { - - it( "Basic verification", function() { - assert.equal( typeof owaspUtils.verifyArgumentWithNonEmptyValue( { name: "path", value: "/tmp/file.name.here" } ), "object" ); - assert.equal( typeof owaspUtils.verifyArgumentIsURL( { name: "url", value: "http://127.0.0.1" } ), "object" ); - assert.equal( typeof owaspUtils.verifyArgumentIsInteger( { name: "url", value: "123" } ), "object" ); - } ); - - it( "Paths verification", function() { - assert.equal( typeof owaspUtils.verifyArgumentIsPathToExistingFile( { name: "url", value: __filename } ), "object" ); - assert.equal( typeof owaspUtils.verifyArgumentIsPathToExistingFolder( { name: "url", value: __dirname } ), "object" ); - } ); - - } ); - - describe( "Key/address utilities", function() { - const joAccount_test = { - "privateKey": owaspUtils.toEthPrivateKey( "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC" ), - "address": IMA.owaspUtils.fn_address_impl_ - }; - - it( "Extract address from private key", function() { - const address = joAccount_test.address( imaState.w3_main_net ); - const address2 = owaspUtils.private_key_2_account_address( imaState.w3_main_net, joAccount_test.privateKey ); - // console.log( "private key is", joAccount_test.privateKey ); - // console.log( "computed address is", joAccount_test.address( imaState.w3_main_net ) ); - assert.equal( address.toLowerCase(), "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5F".toLowerCase() ); - assert.equal( address2.toLowerCase(), "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5F".toLowerCase() ); - } ); - - it( "Extract public key from private key", function() { - // const address = joAccount_test.address( imaState.w3_main_net ); - const publicKey = owaspUtils.private_key_2_public_key( imaState.w3_main_net, joAccount_test.privateKey ); - // console.log( "private key is", joAccount_test.privateKey ); - // console.log( "extracted public is", publicKey ); - assert.equal( publicKey.toLowerCase(), "5dd431d36ce6b88f27d351051b31a26848c4a886f0dd0bc87a7d5a9d821417c9e807e8589f680ab0f2ab29831231ad7b3d6659990ee830582fede785fc3c33c4".toLowerCase() ); - } ); - - it( "Extract address from public key", function() { - const address = joAccount_test.address( imaState.w3_main_net ); - const publicKey = owaspUtils.private_key_2_public_key( imaState.w3_main_net, joAccount_test.privateKey ); - const address2 = owaspUtils.public_key_2_account_address( imaState.w3_main_net, publicKey ); - // console.log( "computed address is", joAccount_test.address( imaState.w3_main_net ) ); - // console.log( "private key is", joAccount_test.privateKey ); - // console.log( "extracted address is", publicKey ); - assert.equal( address.toLowerCase(), address2.toLowerCase() ); - } ); - } ); - - describe( "Ethereum value of money utilities", function() { - - it( "Parse money unit name", function() { - assert.equal( owaspUtils.parseMoneyUnitName( "ethe" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "ethr" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "eth" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "eter" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "ete" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "et" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "eh" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "er" ), "ether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "finne" ), "finney" ); - assert.equal( owaspUtils.parseMoneyUnitName( "finn" ), "finney" ); - assert.equal( owaspUtils.parseMoneyUnitName( "fin" ), "finney" ); - assert.equal( owaspUtils.parseMoneyUnitName( "fn" ), "finney" ); - assert.equal( owaspUtils.parseMoneyUnitName( "fi" ), "finney" ); - assert.equal( owaspUtils.parseMoneyUnitName( "szab" ), "szabo" ); - assert.equal( owaspUtils.parseMoneyUnitName( "szb" ), "szabo" ); - assert.equal( owaspUtils.parseMoneyUnitName( "sza" ), "szabo" ); - assert.equal( owaspUtils.parseMoneyUnitName( "sz" ), "szabo" ); - assert.equal( owaspUtils.parseMoneyUnitName( "shanno" ), "shannon" ); - assert.equal( owaspUtils.parseMoneyUnitName( "shannn" ), "shannon" ); - assert.equal( owaspUtils.parseMoneyUnitName( "shann" ), "shannon" ); - assert.equal( owaspUtils.parseMoneyUnitName( "shan" ), "shannon" ); - assert.equal( owaspUtils.parseMoneyUnitName( "sha" ), "shannon" ); - assert.equal( owaspUtils.parseMoneyUnitName( "shn" ), "shannon" ); - assert.equal( owaspUtils.parseMoneyUnitName( "sh" ), "shannon" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lovelac" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lovela" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lovel" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "love" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lovl" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lvl" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lvla" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lvlc" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lvc" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lv" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lo" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "lc" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "ll" ), "lovelace" ); - assert.equal( owaspUtils.parseMoneyUnitName( "babbag" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "babba" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "babbg" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "babb" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "bab" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "bag" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "bbb" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "bb" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "bg" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "ba" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "be" ), "babbage" ); - assert.equal( owaspUtils.parseMoneyUnitName( "we" ), "wei" ); - assert.equal( owaspUtils.parseMoneyUnitName( "wi" ), "wei" ); - assert.equal( owaspUtils.parseMoneyUnitName( "noether" ), "noether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "noeth" ), "noether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "kwei" ), "kwei" ); - assert.equal( owaspUtils.parseMoneyUnitName( "femtoether" ), "femtoether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "femto" ), "femtoether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "mwei" ), "mwei" ); - assert.equal( owaspUtils.parseMoneyUnitName( "picoether" ), "picoether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "pico" ), "picoether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "gwei" ), "gwei" ); - assert.equal( owaspUtils.parseMoneyUnitName( "nanoether" ), "nanoether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "nano" ), "nanoether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "microether" ), "microether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "micro" ), "microether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "milliether" ), "milliether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "milli" ), "milliether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "kether" ), "kether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "mether" ), "mether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "gether" ), "gether" ); - assert.equal( owaspUtils.parseMoneyUnitName( "tether" ), "tether" ); - } ); - - it( "Parse money value specification", function() { - const w3 = null; - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1ether" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1ethe" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1ethr" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1eth" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1eter" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1ete" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1et" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1eh" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1er" ), "1000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1finney" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1finne" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1finn" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1fin" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1fn" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1fi" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1szab" ), "1000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1szb" ), "1000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1sza" ), "1000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1sz" ), "1000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1shanno" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1shannn" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1shann" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1shan" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1sha" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1shn" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1sh" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lovelac" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lovela" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lovel" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1love" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lovl" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lvl" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lvla" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lvlc" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lvc" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lv" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lo" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1lc" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1ll" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1babbag" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1babba" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1babbg" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1babb" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1bab" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1bag" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1bbb" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1bb" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1bg" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1ba" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1be" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1we" ), "1" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1wi" ), "1" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1noether" ), "0" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1noeth" ), "0" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1kwei" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1femtoether" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1femto" ), "1000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1mwei" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1picoether" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1pico" ), "1000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1gwei" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1nanoether" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1nano" ), "1000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1microether" ), "1000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1micro" ), "1000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1milliether" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1milli" ), "1000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1kether" ), "1000000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1mether" ), "1000000000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1gether" ), "1000000000000000000000000000" ); - assert.equal( owaspUtils.parseMoneySpecToWei( w3, "1tether" ), "1000000000000000000000000000000" ); - } ); - - } ); - -} ); - -describe( "CLI", function() { - - describe( "IMA Agent command line helpers", function() { - - it( "About", function() { - assert.equal( imaCLI.print_about( true ), true ); - } ); - - it( "Parse and collect CLI argument", function() { - let joArg = imaCLI.parse_command_line_argument( "--help" ); - assert.equal( joArg.name, "help" ); - assert.equal( joArg.value, "" ); - joArg = imaCLI.parse_command_line_argument( "--test-url=http://127.0.0.1:3456" ); - assert.equal( joArg.name, "test-url" ); - assert.equal( joArg.value, "http://127.0.0.1:3456" ); - const isExitIfEmpty = false; - const isPrintValue = true; - const fnNameColorizer = null; - const fnValueColorizer = null; - assert.equal( imaCLI.ensure_have_value( "test-url", "http://127.0.0.1:3456", isExitIfEmpty, isPrintValue, fnNameColorizer, fnValueColorizer ), true ); - const joAccount_test = { - "privateKey": owaspUtils.toEthPrivateKey( "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC" ), - "address": IMA.owaspUtils.fn_address_impl_ - }; - assert.equal( imaCLI.ensure_have_chain_credentials( imaState.strChainName_s_chain, joAccount_test, isExitIfEmpty, isPrintValue ), true ); - } ); - - } ); - - // TO-DO: imaCLI.find_node_index - // TO-DO: imaCLI.load_node_config - - describe( "IMA Agent command line parser", function() { - - it( "Minimal command line parse", function() { - const joExternalHandlers = {}; - const argv = []; - assert.equal( imaCLI.parse( joExternalHandlers, argv ), 0 ); - } ); - - it( "Basic command line parse", function() { - const joExternalHandlers = {}; - const argv = [ - "--verbose=9", - "--s2s-disable", - "--url-main-net=" + imaState.strURL_main_net, - "--url-s-chain=" + imaState.strURL_s_chain, - "--id-main-net=" + imaState.strChainName_main_net, - "--id-s-chain=" + imaState.strChainName_s_chain, - "--id-origin-chain=" + imaState.strChainName_origin_chain, - "--cid-main-net=" + imaState.cid_main_net, - "--cid-s-chain=" + imaState.cid_s_chain, - "--address-main-net=" + imaState.joAccount_main_net.address(), - "--address-s-chain=" + imaState.joAccount_s_chain.address(), - "--key-main-net=" + imaState.joAccount_main_net.privateKey, - "--key-s-chain=" + imaState.joAccount_s_chain.privateKey, - //"--abi-skale-manager=" + imaState.strPathAbiJson_skale_manager, - "--abi-main-net=" + imaState.strPathAbiJson_main_net, - "--abi-s-chain=" + imaState.strPathAbiJson_s_chain, - // --erc721-main-net --erc721-s-chain --addr-erc721-s-chain - // --erc20-main-net --erc20-s-chain --addr-erc20-s-chain - // --erc1155-main-net --erc1155-s-chain --addr-erc1155-s-chain - "--sleep-between-tx=5000", - "--wait-next-block=true", - // --value... - "--gas-price-multiplier-mn=2", - "--gas-price-multiplier-sc=2", - "--gas-price-multiplier=2", - // --no-wait-s-chain --max-wait-attempts - "--skip-dry-run", // --skip-dry-run --ignore-dry-run --dry-run - "--m2s-transfer-block-size=4", - "--s2m-transfer-block-size=4", - "--s2s-transfer-block-size=4", - "--transfer-block-size=4", - "--m2s-max-transactions=0", - "--s2m-max-transactions=0", - "--s2s-max-transactions=0", - "--max-transactions=0", - "--m2s-await-blocks=0", - "--s2m-await-blocks=0", - "--s2s-await-blocks=0", - "--await-blocks=0", - "--m2s-await-time=0", - "--s2m-await-time=0", - "--s2s-await-time=0", - "--await-time=0", - "--period=300", - "--node-number=0", - "--nodes-count=1", - "--time-framing=0", - "--time-gap=10", - "--no-ptx" - // --log-size --log-files --log - // --sign-messages --bls-glue --hash-g1 --bls-verify - ]; - assert.equal( imaCLI.parse( joExternalHandlers, argv ), 0 ); - } ); - - } ); - -} ); - -describe( "Agent Utils Module", function() { - - describe( "String helpers", function() { - - it( "Text replacement", function() { - assert.equal( imaUtils.replaceAll( "abc123abcdef456abc", "abc", "" ), "123def456" ); - } ); - - it( "Random file name", function() { - const strPathTmpFolder = os.tmpdir(); - const strPathTmpFile = path.join( strPathTmpFolder, imaUtils.getRandomFileName() + ".txt" ); - // console.log( "Tmp file is", strPathTmpFile ); - assert.equal( strPathTmpFile ? true : false, true ); - } ); - - it( "UTF8 encode/decode", function() { - const strSrc = "Test string 123, Тестовая строка 123, 테스트 문자열 123, Cadena de prueba 123, テスト文字列123, Chaîne de test 123, Testzeichenfolge 123, 測試字符串123"; - const arrBytes = imaUtils.encodeUTF8( strSrc ); - const strDst = imaUtils.decodeUTF8( arrBytes ); - assert.equal( strSrc, strDst ); - } ); - - it( "Compose S-Chain URL", function() { - assert.equal( imaUtils.compose_schain_node_url( { ip: "127.0.0.1", httpRpcPort: 3456 } ), "http://127.0.0.1:3456" ); - assert.equal( imaUtils.compose_schain_node_url( { ip: "127.0.0.1", httpsRpcPort: 3456 } ), "https://127.0.0.1:3456" ); - assert.equal( imaUtils.compose_schain_node_url( { ip: "127.0.0.1", wsRpcPort: 3456 } ), "ws://127.0.0.1:3456" ); - assert.equal( imaUtils.compose_schain_node_url( { ip: "127.0.0.1", wssRpcPort: 3456 } ), "wss://127.0.0.1:3456" ); - assert.equal( imaUtils.compose_schain_node_url( { ip6: "::1", httpRpcPort6: 3456 } ), "http://[::1]:3456" ); - assert.equal( imaUtils.compose_schain_node_url( { ip6: "::1", httpsRpcPort6: 3456 } ), "https://[::1]:3456" ); - assert.equal( imaUtils.compose_schain_node_url( { ip6: "::1", wsRpcPort6: 3456 } ), "ws://[::1]:3456" ); - assert.equal( imaUtils.compose_schain_node_url( { ip6: "::1", wssRpcPort6: 3456 } ), "wss://[::1]:3456" ); - } ); - - } ); - - describe( "Byte array manipulation helpers", function() { - - it( "HEX encode/decode raw", function() { - const strSrc = "5465737420737472696e6720313233"; - const arrBytes = imaUtils.hexToBytes( strSrc, false ); - const strDst = imaUtils.bytesToHex( arrBytes, false ); - assert.equal( strSrc, strDst ); - } ); - - it( "HEX encode/decode 0x-prefixed", function() { - const strSrc = "0x5465737420737472696e6720313233"; - const arrBytes = imaUtils.hexToBytes( strSrc, false ); - const strDst = imaUtils.bytesToHex( arrBytes, false ); - assert.equal( strSrc, "0x" + strDst ); - } ); - - it( "HEX encode/decode with inversive order raw", function() { - const strSrc = "5465737420737472696e6720313233"; - const arrBytes = imaUtils.hexToBytes( strSrc, true ); - const strDst = imaUtils.bytesToHex( arrBytes, true ); - assert.equal( strSrc, strDst ); - } ); - - it( "HEX encode/decode with inversive order 0x-prefixed", function() { - const strSrc = "0x5465737420737472696e6720313233"; - const arrBytes = imaUtils.hexToBytes( strSrc, true ); - const strDst = imaUtils.bytesToHex( arrBytes, true ); - assert.equal( strSrc, "0x" + strDst ); - } ); - - it( "Array padding with zeroes at left", function() { - const strSrc = "123"; - const arrBytes = imaUtils.bytesAlignLeftWithZeroes( imaUtils.hexToBytes( strSrc, false ), 4 ); - const strDst = imaUtils.bytesToHex( arrBytes, false ); - assert.equal( strDst, "00000123" ); - } ); - - it( "Array padding with zeroes at right", function() { - const strSrc = "123"; - const arrBytes = imaUtils.bytesAlignRightWithZeroes( imaUtils.hexToBytes( strSrc, false ), 4 ); - const strDst = imaUtils.bytesToHex( arrBytes, false ); - assert.equal( strDst, "01230000" ); - } ); - - it( "Typed array concatenation", function() { - const strSrcLeft = "0xbaad", strSrcRight = "0xf00d"; - const arrBytesLeft = imaUtils.hexToBytes( strSrcLeft, false ); - const arrBytesRight = imaUtils.hexToBytes( strSrcRight, false ); - const arrBytes = imaUtils.concatTypedArrays( arrBytesLeft, arrBytesRight ); - const strDst = imaUtils.bytesToHex( arrBytes, false ); - assert.equal( strDst, "baadf00d" ); - } ); - - it( "Byte array concatenation", function() { - const strSrcLeft = "0xbaad", strSrcRight = "0xf00d"; - const arrBytesLeft = imaUtils.hexToBytes( strSrcLeft, false ); - const arrBytesRight = imaUtils.hexToBytes( strSrcRight, false ); - const arrBytes = imaUtils.bytesConcat( arrBytesLeft, arrBytesRight ); - const strDst = imaUtils.bytesToHex( arrBytes, false ); - assert.equal( strDst, "baadf00d" ); - } ); - - it( "Single Byte concatenation", function() { - const strSrcLeft = "0xbaadf0", nSrcRight = 0x0d; - const arrBytesLeft = imaUtils.hexToBytes( strSrcLeft, false ); - const arrBytes = imaUtils.concatByte( arrBytesLeft, nSrcRight ); - const strDst = imaUtils.bytesToHex( arrBytes, false ); - assert.equal( strDst, "baadf00d" ); - } ); - - it( "Array/buffer conversion", function() { - const strSrc = "baadf00d"; - const arrBytes = imaUtils.toBuffer( imaUtils.toArrayBuffer( imaUtils.hexToBytes( strSrc, true ) ) ); - const strDst = imaUtils.bytesToHex( arrBytes, true ); - assert.equal( strDst, "baadf00d" ); - } ); - - } ); - - describe( "Path/file/JSON helpers", function() { - - it( "Home directory and path normalization", function() { - const strPathHomeFolder = imaUtils.normalizePath( "~" ); - const strPathSrc = "~/some/file/path/here"; - const strPathDst = strPathHomeFolder + "/some/file/path/here"; - assert.equal( imaUtils.normalizePath( strPathSrc ), strPathDst ); - } ); - - it( "File existence and text loading/saving", function() { - const strPathTmpFolder = os.tmpdir(); - const strPathTmpFile = path.join( strPathTmpFolder, imaUtils.getRandomFileName() + ".txt" ); - // console.log( "Tmp file is", strPathTmpFile ); - try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; - assert.equal( imaUtils.fileExists( strPathTmpFile ), false ); - const strContentSaved = "Text file content"; - assert.equal( imaUtils.fileSave( strPathTmpFile, strContentSaved ), true ); - assert.equal( imaUtils.fileExists( strPathTmpFile ), true ); - const strContentLoaded = imaUtils.fileLoad( strPathTmpFile, "file \"" + strPathTmpFile + "\"was not loaded" ); - assert.equal( strContentLoaded, strContentSaved ); - try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; - } ); - - it( "File existence and JSON loading/saving", function() { - const strPathTmpFolder = os.tmpdir(); - const strPathTmpFile = path.join( strPathTmpFolder, imaUtils.getRandomFileName() + ".json" ); - // console.log( "Tmp file is", strPathTmpFile ); - try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; - assert.equal( imaUtils.fileExists( strPathTmpFile ), false ); - const joContentSaved = { a: 123, b: 456 }; - assert.equal( imaUtils.jsonFileSave( strPathTmpFile, joContentSaved ), true ); - assert.equal( imaUtils.fileExists( strPathTmpFile ), true ); - const joContentLoaded = imaUtils.jsonFileLoad( strPathTmpFile, { error: "file \"" + strPathTmpFile + "\"was not loaded" } ); - assert.equal( JSON.stringify( joContentSaved ), JSON.stringify( joContentLoaded ) ); - try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; - } ); - - } ); - - describe( "ABI JSON Helpers", function() { - - it( "Find ABI entries", function() { - const strName = imaState.strChainName_s_chain; - const strFile = imaState.strPathAbiJson_s_chain; - const joABI = imaUtils.jsonFileLoad( strFile, { error: "file \"" + strFile + "\"was not loaded" } ); - const strKey = "token_manager_linker_address"; - const arrKeys = [ - "token_manager_linker_address", - "token_manager_linker_abi", - "eth_erc20_address", - "eth_erc20_abi", - "token_manager_eth_address", - "token_manager_eth_abi", - "token_manager_erc20_address", - "token_manager_erc20_abi", - "token_manager_erc721_address", - "token_manager_erc721_abi", - "token_manager_erc1155_address", - "token_manager_erc1155_abi", - "message_proxy_chain_address", - "message_proxy_chain_abi" - ]; - const isExitOnError = false; - assert.equal( imaUtils.check_key_exist_in_abi( strName, strFile, joABI, strKey, isExitOnError ), true ); - assert.equal( imaUtils.check_keys_exist_in_abi( strName, strFile, joABI, arrKeys, isExitOnError ), true ); - } ); - - it( "Discover coin name", function() { - const strFile = imaState.strPathAbiJson_s_chain; - const joABI = imaUtils.jsonFileLoad( strFile, { error: "file \"" + strFile + "\"was not loaded" } ); - const strCoinName = imaUtils.discover_in_json_coin_name( joABI ); - // console.log( "strCoinName is", strCoinName ); - assert.equal( strCoinName.length > 0, true ); - } ); - - } ); - -} ); diff --git a/test/agent-test.mjs b/test/agent-test.mjs new file mode 100644 index 000000000..4b00d00c6 --- /dev/null +++ b/test/agent-test.mjs @@ -0,0 +1,1276 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * @license + * SKALE IMA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @file agent-test.mjs + * @copyright SKALE Labs 2019-Present + */ + +import * as assert from "assert"; +import * as fs from "fs"; +import * as os from "os"; +import * as path from "path"; +import * as url from "url"; + +import * as owaspUtils from "../npms/skale-owasp/owaspUtils.mjs"; +import * as imaTx from "../npms/skale-ima/imaTx.mjs"; +import * as log from "../npms/skale-log/log.mjs"; +import * as imaUtils from "../agent/utils.mjs"; +import * as imaCLI from "../agent/cli.mjs"; + +import * as state from "../agent/state.mjs"; + +const __dirname = path.dirname( url.fileURLToPath( import.meta.url ) ); +const __filename = new URL( "", import.meta.url ).pathname; + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; + +log.exposeDetailsSet( false ); +log.verboseSet( log.verboseParse( "info" ) ); + +log.removeAll(); +const imaState = { + "loopState": { + "oracle": { + "isInProgress": false, + "wasInProgress": false + }, + "m2s": { + "isInProgress": false, + "wasInProgress": false + }, + "s2m": { + "isInProgress": false, + "wasInProgress": false + }, + "s2s": { + "isInProgress": false, + "wasInProgress": false + } + }, + + "strLogFilePath": "", + "nLogMaxSizeBeforeRotation": -1, + "nLogMaxFilesCount": -1, + "isPrintGathered": true, + "isPrintSecurityValues": true, + "isPrintPWA": false, + "isDynamicLogInDoTransfer": true, + "isDynamicLogInBlsSigner": false, + + "bIsNeededCommonInit": true, + "bSignMessages": false, + "joSChainNetworkInfo": null, + "strPathBlsGlue": "", + "strPathHashG1": "", + "strPathBlsVerify": "", + + "bShowConfigMode": false, + + "isEnabledMultiCall": true, + + "bNoWaitSChainStarted": false, + "nMaxWaitSChainAttempts": 0 + Number.MAX_SAFE_INTEGER, // 20 + + "nAmountOfWei": 0, + "nAmountOfToken": 0, + "arrAmountsOfTokens": null, + "idToken": 0, + "idTokens": [], + "haveOneTokenIdentifier": false, + "haveArrayOfTokenIdentifiers": false, + + "nTransferBlockSizeM2S": 4, + "nTransferBlockSizeS2M": 4, + "nTransferBlockSizeS2S": 4, + "nTransferStepsM2S": 8, + "nTransferStepsS2M": 8, + "nTransferStepsS2S": 8, + "nMaxTransactionsM2S": 0, + "nMaxTransactionsS2M": 0, + "nMaxTransactionsS2S": 0, + + "nBlockAwaitDepthM2S": 0, + "nBlockAwaitDepthS2M": 0, + "nBlockAwaitDepthS2S": 0, + "nBlockAgeM2S": 0, + "nBlockAgeS2M": 0, + "nBlockAgeS2S": 0, + + "nLoopPeriodSeconds": 10, + + "nNodeNumber": 0, // S-Chain node number(zero based) + "nNodesCount": 1, + "nTimeFrameSeconds": 0, // 0-disable, 60-recommended + "nNextFrameGap": 10, + + "nAutoExitAfterSeconds": 0, // 0-disable + + "joDepositBoxETH": null, // only main net + "joDepositBoxERC20": null, // only main net + "joDepositBoxERC721": null, // only main net + "joDepositBoxERC1155": null, // only main net + "joTokenManager": null, // only s-chain + "joMessageProxyMainNet": null, + "joMessageProxySChain": null, + "joLinker": null, + "joLockAndDataSChain": null, + "joEthErc20": null, // only s-chain + + "chainProperties": { + "mn": { + "joAccount": { + "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_ETHEREUM ), + "address": owaspUtils.fnAddressImpl_, + "strTransactionManagerURL": + owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_ETHEREUM ), + "nTmPriority": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_PRIORITY_ETHEREUM ) || 5, + "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_ETHEREUM ), + "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_ETHEREUM ), + "strPathSslKey": + ( process.env.SGX_SSL_KEY_FILE_ETHEREUM || "" ).toString().trim(), + "strPathSslCert": + ( process.env.SGX_SSL_CERT_FILE_ETHEREUM || "" ).toString().trim(), + "strBlsKeyName": owaspUtils.toStringURL( process.env.BLS_KEY_ETHEREUM ) + }, + "transactionCustomizer": imaTx.getTransactionCustomizerForMainNet(), + "ethersProvider": null, + "strURL": + owaspUtils.toStringURL( process.env.URL_W3_ETHEREUM || "http://127.0.0.1:8545" ), + "strChainName": ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), + "chainId": owaspUtils.toInteger( process.env.CID_ETHEREUM ) || -4, + "strPathAbiJson": imaUtils.normalizePath( "./agent-test-data/proxyMainnet.json" ), + "joAbiIMA": { }, + "bHaveAbiIMA": false, + "joErc20": null, + "joErc721": null, + "joErc1155": null, + "strCoinNameErc20": "", // in-JSON coin name + "strCoinNameErc721": "", // in-JSON coin name + "strCoinNameErc1155": "", // in-JSON coin name + "strPathJsonErc20": "", + "strPathJsonErc721": "", + "strPathJsonErc1155": "" + }, + "sc": { + "joAccount": { + "privateKey": owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN ), + "address": owaspUtils.fnAddressImpl_, + "strTransactionManagerURL": + owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_S_CHAIN ), + "nTmPriority": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_PRIORITY_S_CHAIN ) || 5, + "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN ), + "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN ), + "strPathSslKey": + ( process.env.SGX_SSL_KEY_FILE_S_CHAIN || "" ).toString().trim(), + "strPathSslCert": + ( process.env.SGX_SSL_CERT_FILE_S_CHAIN || "" ).toString().trim(), + "strBlsKeyName": owaspUtils.toStringURL( process.env.BLS_KEY_S_CHAIN ) + }, + "transactionCustomizer": imaTx.getTransactionCustomizerForSChain(), + "ethersProvider": null, + "strURL": + owaspUtils.toStringURL( process.env.URL_W3_S_CHAIN || "http://127.0.0.1:15000" ), + "strChainName": ( process.env.CHAIN_NAME_SCHAIN || "Bob" ).toString().trim(), + "chainId": owaspUtils.toInteger( process.env.CID_SCHAIN ) || -4, + "strPathAbiJson": imaUtils.normalizePath( "./agent-test-data/proxySchain_Bob.json" ), + "joAbiIMA": { }, + "bHaveAbiIMA": false, + "joErc20": null, + "joErc721": null, + "joErc1155": null, + "strCoinNameErc20": "", // in-JSON coin name + "strCoinNameErc721": "", // in-JSON coin name + "strCoinNameErc1155": "", // in-JSON coin name + "strPathJsonErc20": "", + "strPathJsonErc721": "", + "strPathJsonErc1155": "" + }, + "tc": { + "joAccount": { + "privateKey": + owaspUtils.toEthPrivateKey( process.env.PRIVATE_KEY_FOR_SCHAIN_TARGET ), + "address": owaspUtils.fnAddressImpl_, + "strTransactionManagerURL": + owaspUtils.toStringURL( process.env.TRANSACTION_MANAGER_URL_S_CHAIN_TARGET ), + "nTmPriority": + owaspUtils.toStringURL( + process.env.TRANSACTION_MANAGER_PRIORITY_S_CHAIN_TARGET ) || 5, + "strSgxURL": owaspUtils.toStringURL( process.env.SGX_URL_S_CHAIN_TARGET ), + "strSgxKeyName": owaspUtils.toStringURL( process.env.SGX_KEY_S_CHAIN_TARGET ), + "strPathSslKey": + ( process.env.SGX_SSL_KEY_FILE_S_CHAIN_TARGET || "" ).toString().trim(), + "strPathSslCert": + ( process.env.SGX_SSL_CERT_FILE_S_CHAIN_TARGET || "" ).toString().trim(), + "strBlsKeyName": owaspUtils.toStringURL( process.env.BLS_KEY_T_CHAIN ) + }, + "transactionCustomizer": imaTx.getTransactionCustomizerForSChainTarget(), + "ethersProvider": null, + "strURL": owaspUtils.toStringURL( process.env.URL_W3_S_CHAIN_TARGET ), + "strChainName": + ( process.env.CHAIN_NAME_SCHAIN_TARGET || "Alice" ).toString().trim(), + "chainId": owaspUtils.toInteger( process.env.CID_SCHAIN_TARGET ) || -4, + "strPathAbiJson": null, + "joAbiIMA": { }, + "bHaveAbiIMA": false, + "joErc20": null, + "joErc721": null, + "joErc1155": null, + "strCoinNameErc20": "", // in-JSON coin name + "strCoinNameErc721": "", // in-JSON coin name + "strCoinNameErc1155": "", // in-JSON coin name + "strPathJsonErc20": "", + "strPathJsonErc721": "", + "strPathJsonErc1155": "" + } + }, + + "strPathAbiJsonSkaleManager": null, + "joAbiSkaleManager": { }, + "bHaveSkaleManagerABI": false, + + "strChainNameOriginChain": + ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), + + "strAddrErc20Explicit": "", + "strAddrErc20ExplicitTarget": "", // S<->S target + "strAddrErc721Explicit": "", + "strAddrErc721ExplicitTarget": "", // S<->S target + "strAddrErc1155Explicit": "", + "strAddrErc1155ExplicitTarget": "", // S<->S target + + "isPWA": true, + "nTimeoutSecondsPWA": 60, + + "optsS2S": { + "isEnabled": false, + "secondsToReDiscoverSkaleNetwork": 10 * 60 + }, + + "nJsonRpcPort": 14999, // 0 to disable + "isCrossImaBlsMode": true, + + "arrActions": [] // array of actions to run +}; +state.set( imaState ); + +imaCLI.commonInit(); +imaCLI.initContracts(); + +describe( "OWASP-1", function() { + + describe( "Parsing utilities", function() { + + it( "Integer basic validation", function() { + assert.equal( owaspUtils.isNumeric( "0" ), true ); + assert.equal( owaspUtils.isNumeric( "123" ), true ); + } ); + + it( "Integer RegEx validation", function() { + assert.equal( owaspUtils.rxIsInt( "0" ), true ); + assert.equal( owaspUtils.rxIsInt( "123" ), true ); + assert.equal( owaspUtils.rxIsInt( "-456" ), true ); + assert.equal( owaspUtils.rxIsInt( "a012" ), false ); + } ); + + it( "Floating point RegEx validation", function() { + assert.equal( owaspUtils.rxIsFloat( "0" ), true ); + assert.equal( owaspUtils.rxIsFloat( "0.0" ), true ); + assert.equal( owaspUtils.rxIsFloat( "123.456" ), true ); + assert.equal( owaspUtils.rxIsFloat( "-123.456" ), true ); + assert.equal( owaspUtils.rxIsFloat( "a012" ), false ); + } ); + + it( "Radix validation", function() { + assert.equal( owaspUtils.validateRadix( "123", "10" ), 10 ); + assert.equal( owaspUtils.validateRadix( "0x20", "16" ), 16 ); + } ); + + it( "Integer conversion", function() { + assert.equal( owaspUtils.toInteger( "12345", 10 ), 12345 ); + assert.equal( owaspUtils.toInteger( "0x20", 16 ), 0x20 ); + } ); + + it( "Integer automatic conversion", function() { + assert.equal( owaspUtils.parseIntOrHex( 12345, 10 ), 12345 ); + assert.equal( owaspUtils.parseIntOrHex( "12345", 10 ), 12345 ); + assert.equal( owaspUtils.parseIntOrHex( 0x20, 16 ), 0x20 ); + assert.equal( owaspUtils.parseIntOrHex( "0x20", 16 ), 0x20 ); + } ); + + it( "Integer advanced validation", function() { + assert.equal( owaspUtils.validateInteger( "12345", 10 ), true ); + assert.equal( owaspUtils.validateInteger( "0x20", 16 ), true ); + assert.equal( owaspUtils.validateInteger( "hello 12345", 10 ), false ); + assert.equal( owaspUtils.validateInteger( "hello 0x20", 16 ), false ); + } ); + + it( "Floating point advanced validation", function() { + assert.equal( owaspUtils.validateFloat( "123.456" ), true ); + assert.equal( owaspUtils.validateFloat( "hello 123.456" ), false ); + } ); + + it( "Floating point conversion", function() { + assert.equal( owaspUtils.toFloat( "123.456" ), 123.456 ); + assert.equal( owaspUtils.rxIsFloat( owaspUtils.toFloat( "hello 123.456" ) ), false ); + } ); + + it( "Boolean conversion", function() { + assert.equal( owaspUtils.toBoolean( "true" ), true ); + assert.equal( owaspUtils.toBoolean( "false" ), false ); + assert.equal( owaspUtils.toBoolean( true ), true ); + assert.equal( owaspUtils.toBoolean( false ), false ); + assert.equal( owaspUtils.toBoolean( "True" ), true ); + assert.equal( owaspUtils.toBoolean( "False" ), false ); + assert.equal( owaspUtils.toBoolean( "TRUE" ), true ); + assert.equal( owaspUtils.toBoolean( "FALSE" ), false ); + assert.equal( owaspUtils.toBoolean( "t" ), true ); + assert.equal( owaspUtils.toBoolean( "f" ), false ); + assert.equal( owaspUtils.toBoolean( "T" ), true ); + assert.equal( owaspUtils.toBoolean( "F" ), false ); + assert.equal( owaspUtils.toBoolean( "1" ), true ); + assert.equal( owaspUtils.toBoolean( "-1" ), true ); + assert.equal( owaspUtils.toBoolean( "0" ), false ); + assert.equal( owaspUtils.toBoolean( "0.123" ), true ); + assert.equal( owaspUtils.toBoolean( "" ), false ); + } ); + + } ); +} ); + +describe( "OWASP-2", function() { + + describe( "Parsing utilities", function() { + + it( "URL validation", function() { + assert.equal( owaspUtils.validateURL( "http://127.0.0.1" ), true ); + assert.equal( owaspUtils.validateURL( "http://127.0.0.1/" ), true ); + assert.equal( owaspUtils.validateURL( "https://127.0.0.1:3344" ), true ); + assert.equal( owaspUtils.validateURL( "https://127.0.0.1:3344/" ), true ); + assert.equal( owaspUtils.validateURL( "ws://[::1]" ), true ); + assert.equal( owaspUtils.validateURL( "ws://[::1]/" ), true ); + assert.equal( owaspUtils.validateURL( "wss://[::1]:3344" ), true ); + assert.equal( owaspUtils.validateURL( "wss://[::1]:3344/" ), true ); + assert.equal( owaspUtils.validateURL( "http://some.domain.org" ), true ); + assert.equal( owaspUtils.validateURL( "http://some.domain.org/" ), true ); + assert.equal( owaspUtils.validateURL( "https://some.domain.org:3344" ), true ); + assert.equal( owaspUtils.validateURL( "https://some.domain.org:3344/" ), true ); + assert.equal( owaspUtils.validateURL( "hello ws://[::1]" ), false ); + assert.equal( owaspUtils.validateURL( "hello ws://[::1]/" ), false ); + assert.equal( owaspUtils.validateURL( "hello wss://[::1]:3344" ), false ); + assert.equal( owaspUtils.validateURL( "hello wss://[::1]:3344/" ), false ); + } ); + + it( "URL conversion", function() { + assert.equal( owaspUtils.toURL( "http://127.0.0.1" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "https://127.0.0.1:3344" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "https://127.0.0.1:3344/" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "ws://[::1]" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "ws://[::1]/" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "wss://[::1]:3344" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "wss://[::1]:3344/" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "http://some.domain.org" ).constructor.name, "URL" ); + assert.equal( owaspUtils.toURL( "http://some.domain.org/" ).constructor.name, "URL" ); + assert.equal( + owaspUtils.toURL( "https://some.domain.org3344" ).constructor.name, "URL" ); + assert.equal( + owaspUtils.toURL( "https://some.domain.org:3344/" ).constructor.name, "URL" ); + assert.equal( + owaspUtils.toURL( "http://127.0.0.1" ).toString(), "http://127.0.0.1/" ); + assert.equal( + owaspUtils.toURL( "http://127.0.0.1/" ).toString(), "http://127.0.0.1/" ); + assert.equal( + owaspUtils.toURL( + "https://127.0.0.1:3344" ).toString(), "https://127.0.0.1:3344/" ); + assert.equal( + owaspUtils.toURL( + "https://127.0.0.1:3344/" ).toString(), "https://127.0.0.1:3344/" ); + assert.equal( owaspUtils.toURL( "ws://[::1]" ).toString(), "ws://[::1]/" ); + assert.equal( owaspUtils.toURL( "ws://[::1]/" ).toString(), "ws://[::1]/" ); + assert.equal( + owaspUtils.toURL( "wss://[::1]:3344" ).toString(), "wss://[::1]:3344/" ); + assert.equal( + owaspUtils.toURL( "wss://[::1]:3344/" ).toString(), "wss://[::1]:3344/" ); + assert.equal( + owaspUtils.toURL( + "http://some.domain.org" ).toString(), "http://some.domain.org/" ); + assert.equal( + owaspUtils.toURL( + "http://some.domain.org/" ).toString(), "http://some.domain.org/" ); + assert.equal( + owaspUtils.toURL( + "https://some.domain.org:3344" ).toString(), + "https://some.domain.org:3344/" ); + assert.equal( + owaspUtils.toURL( + "https://some.domain.org:3344/" ).toString(), + "https://some.domain.org:3344/" ); + assert.equal( + owaspUtils.toStringURL( "http://127.0.0.1" ), "http://127.0.0.1/" ); + assert.equal( + owaspUtils.toStringURL( "http://127.0.0.1/" ), "http://127.0.0.1/" ); + assert.equal( + owaspUtils.toStringURL( "https://127.0.0.1:3344" ), "https://127.0.0.1:3344/" ); + assert.equal( + owaspUtils.toStringURL( "https://127.0.0.1:3344/" ), "https://127.0.0.1:3344/" ); + assert.equal( owaspUtils.toStringURL( "ws://[::1]" ), "ws://[::1]/" ); + assert.equal( owaspUtils.toStringURL( "ws://[::1]/" ), "ws://[::1]/" ); + assert.equal( owaspUtils.toStringURL( "wss://[::1]:3344" ), "wss://[::1]:3344/" ); + assert.equal( owaspUtils.toStringURL( "wss://[::1]:3344/" ), "wss://[::1]:3344/" ); + assert.equal( + owaspUtils.toStringURL( + "http://some.domain.org" ), "http://some.domain.org/" ); + assert.equal( + owaspUtils.toStringURL( + "http://some.domain.org/" ), "http://some.domain.org/" ); + assert.equal( + owaspUtils.toStringURL( + "https://some.domain.org:3344" ), "https://some.domain.org:3344/" ); + assert.equal( + owaspUtils.toStringURL( + "https://some.domain.org:3344/" ), "https://some.domain.org:3344/" ); + } ); + + it( "Check URL is HTTP(S)", function() { + assert.equal( owaspUtils.isUrlHTTP( "http://127.0.0.1" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "http://localhost" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "http://[::1]" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "http://127.0.0.1:1234" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "http://localhost:1234" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "http://[::1]:1234" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "https://127.0.0.1" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "https://localhost" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "https://[::1]" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "https://127.0.0.1:1234" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "https://localhost:1234" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "https://[::1]:1234" ), true ); + assert.equal( owaspUtils.isUrlHTTP( "ws://127.0.0.1" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "ws://localhost" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "ws://[::1]" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "ws://127.0.0.1:1234" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "ws://localhost:1234" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "ws://[::1]:1234" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "wss://127.0.0.1" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "wss://localhost" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "wss://[::1]" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "wss://127.0.0.1:1234" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "wss://localhost:1234" ), false ); + assert.equal( owaspUtils.isUrlHTTP( "wss://[::1]:1234" ), false ); + } ); + + it( "Check URL is WS(S)", function() { + assert.equal( owaspUtils.isUrlWS( "http://127.0.0.1" ), false ); + assert.equal( owaspUtils.isUrlWS( "http://localhost" ), false ); + assert.equal( owaspUtils.isUrlWS( "http://[::1]" ), false ); + assert.equal( owaspUtils.isUrlWS( "http://127.0.0.1:1234" ), false ); + assert.equal( owaspUtils.isUrlWS( "http://localhost:1234" ), false ); + assert.equal( owaspUtils.isUrlWS( "http://[::1]:1234" ), false ); + assert.equal( owaspUtils.isUrlWS( "https://127.0.0.1" ), false ); + assert.equal( owaspUtils.isUrlWS( "https://localhost" ), false ); + assert.equal( owaspUtils.isUrlWS( "https://[::1]" ), false ); + assert.equal( owaspUtils.isUrlWS( "https://127.0.0.1:1234" ), false ); + assert.equal( owaspUtils.isUrlWS( "https://localhost:1234" ), false ); + assert.equal( owaspUtils.isUrlWS( "https://[::1]:1234" ), false ); + assert.equal( owaspUtils.isUrlWS( "ws://127.0.0.1" ), true ); + assert.equal( owaspUtils.isUrlWS( "ws://localhost" ), true ); + assert.equal( owaspUtils.isUrlWS( "ws://[::1]" ), true ); + assert.equal( owaspUtils.isUrlWS( "ws://127.0.0.1:1234" ), true ); + assert.equal( owaspUtils.isUrlWS( "ws://localhost:1234" ), true ); + assert.equal( owaspUtils.isUrlWS( "ws://[::1]:1234" ), true ); + assert.equal( owaspUtils.isUrlWS( "wss://127.0.0.1" ), true ); + assert.equal( owaspUtils.isUrlWS( "wss://localhost" ), true ); + assert.equal( owaspUtils.isUrlWS( "wss://[::1]" ), true ); + assert.equal( owaspUtils.isUrlWS( "wss://127.0.0.1:1234" ), true ); + assert.equal( owaspUtils.isUrlWS( "wss://localhost:1234" ), true ); + assert.equal( owaspUtils.isUrlWS( "wss://[::1]:1234" ), true ); + } ); + } ); +} ); + +describe( "OWASP-3", function() { + + describe( "Parsing utilities", function() { + + const strAddressValid0 = "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5F"; + const strAddressValid1 = "7aa5E36AA15E93D10F4F26357C30F052DacDde5F"; + const strAddressInvalid0 = "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5"; + const strAddressInvalid1 = "hello"; + const strAddressInvalid2 = ""; + + it( "Validate Ethereum address", function() { + assert.equal( owaspUtils.validateEthAddress( strAddressValid0 ), true ); + assert.equal( owaspUtils.validateEthAddress( strAddressValid1 ), true ); + assert.equal( owaspUtils.validateEthAddress( strAddressInvalid0 ), false ); + assert.equal( owaspUtils.validateEthAddress( strAddressInvalid1 ), false ); + assert.equal( owaspUtils.validateEthAddress( strAddressInvalid2 ), false ); + } ); + + it( "Parse Ethereum address", function() { + assert.equal( owaspUtils.toEthAddress( strAddressValid0 ), strAddressValid0 ); + assert.equal( owaspUtils.toEthAddress( strAddressValid1 ), strAddressValid0 ); + assert.equal( + owaspUtils.toEthAddress( + strAddressInvalid0, strAddressValid0 ), strAddressValid0 ); + assert.equal( + owaspUtils.toEthAddress( + strAddressInvalid0, "invalid value" ), "invalid value" ); + assert.equal( + owaspUtils.toEthAddress( + strAddressInvalid1, strAddressValid0 ), strAddressValid0 ); + assert.equal( + owaspUtils.toEthAddress( + strAddressInvalid1, "invalid value" ), "invalid value" ); + assert.equal( + owaspUtils.toEthAddress( + strAddressInvalid2, strAddressValid0 ), strAddressValid0 ); + assert.equal( + owaspUtils.toEthAddress( + strAddressInvalid2, "invalid value" ), "invalid value" ); + } ); + + const strPrivateKeyValid0 = + "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC"; + const strPrivateKeyValid1 = + "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC"; + const strPrivateKeyInvalid0 = + "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1F"; + const strPrivateKeyInvalid1 = "hello"; + const strPrivateKeyInvalid2 = ""; + + it( "Validate Ethereum private key", function() { + assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyValid0 ), true ); + assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyValid1 ), true ); + assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyInvalid0 ), false ); + assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyInvalid1 ), false ); + assert.equal( owaspUtils.validateEthPrivateKey( strPrivateKeyInvalid2 ), false ); + } ); + + it( "Parse Ethereum private key", function() { + assert.equal( + owaspUtils.toEthPrivateKey( strPrivateKeyValid0 ), strPrivateKeyValid0 ); + assert.equal( + owaspUtils.toEthPrivateKey( strPrivateKeyValid1 ), strPrivateKeyValid0 ); + assert.equal( + owaspUtils.toEthPrivateKey( + strPrivateKeyInvalid0, strPrivateKeyValid0 ), strPrivateKeyValid0 ); + assert.equal( + owaspUtils.toEthPrivateKey( + strPrivateKeyInvalid0, "invalid value" ), "invalid value" ); + assert.equal( + owaspUtils.toEthPrivateKey( + strPrivateKeyInvalid1, strPrivateKeyValid0 ), strPrivateKeyValid0 ); + assert.equal( + owaspUtils.toEthPrivateKey( + strPrivateKeyInvalid1, "invalid value" ), "invalid value" ); + assert.equal( + owaspUtils.toEthPrivateKey( + strPrivateKeyInvalid2, strPrivateKeyValid0 ), strPrivateKeyValid0 ); + assert.equal( + owaspUtils.toEthPrivateKey( + strPrivateKeyInvalid2, "invalid value" ), "invalid value" ); + } ); + + it( "Byte sequence utilities", function() { + assert.equal( owaspUtils.ensureStartsWith0x( "0x123" ), "0x123" ); + assert.equal( owaspUtils.ensureStartsWith0x( "123" ), "0x123" ); + assert.equal( owaspUtils.removeStarting0x( "0x123" ), "123" ); + assert.equal( owaspUtils.removeStarting0x( "123" ), "123" ); + } ); + + } ); +} ); + +describe( "OWASP-4", function() { + + describe( "Command line argument utilities", function() { + + it( "Basic verification", function() { + assert.equal( + typeof owaspUtils.verifyArgumentWithNonEmptyValue( + { name: "path", value: "/tmp/file.name.here" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsURL( + { name: "url", value: "http://127.0.0.1" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsURL( + { name: "url", value: "http://[::1]" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsURL( + { name: "url", value: "http://localhost" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsURL( + { name: "url", value: "http://127.0.0.1:1234" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsURL( + { name: "url", value: "http://[::1]:1234" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsURL( + { name: "url", value: "http://localhost:1234" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsInteger( + { name: "url", value: "123" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsInteger( + { name: "url", value: "0x123" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsIntegerIpPortNumber( + { name: "port", value: "1" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsIntegerIpPortNumber( + { name: "port", value: "123" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsIntegerIpPortNumber( + { name: "port", value: "1024" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsIntegerIpPortNumber( + { name: "port", value: "65535" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsArrayOfIntegers( + { name: "some_array", value: "[1]" } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsArrayOfIntegers( + { name: "some_array", value: "[1,2,3]" } ), "object" ); + } ); + + it( "Paths verification", function() { + assert.equal( + typeof owaspUtils.verifyArgumentIsPathToExistingFile( + { name: "url", value: __filename } ), "object" ); + assert.equal( + typeof owaspUtils.verifyArgumentIsPathToExistingFolder( + { name: "url", value: __dirname } ), "object" ); + } ); + + } ); +} ); + +describe( "OWASP-5", function() { + + describe( "Other utilities", function() { + + it( "IP from her", function() { + assert.equal( owaspUtils.ipFromHex( "0x0a0b0c0d" ), "10.11.12.13" ); + } ); + + it( "Clone object by root keys", function() { + const joIn = { "a": 1, "2": 2, "c": { "d": 3, "e": 4 } }; + const joOut = owaspUtils.cloneObjectByRootKeys( joIn ); + assert.equal( JSON.stringify( joIn ), JSON.stringify( joOut ) ); + } ); + + it( "ID from chain name", function() { + assert.equal( + owaspUtils.computeChainIdFromSChainName( "Hello World" ), + "0x592fa743889fc7" ); + } ); + + it( "Extract error message", function() { + const not_extracted = "error message was not extracted"; + assert.equal( + owaspUtils.extractErrorMessage( + null, not_extracted ), not_extracted ); + assert.equal( + owaspUtils.extractErrorMessage( + undefined, not_extracted ), not_extracted ); + assert.equal( + owaspUtils.extractErrorMessage( + 123, not_extracted ), not_extracted ); + assert.equal( + owaspUtils.extractErrorMessage( + "123", not_extracted ), not_extracted ); + assert.equal( + owaspUtils.extractErrorMessage( + "", not_extracted ), not_extracted ); + assert.equal( + owaspUtils.extractErrorMessage( + {}, not_extracted ), not_extracted ); + assert.equal( + owaspUtils.extractErrorMessage( + { "err": "something" }, not_extracted ), not_extracted ); + assert.equal( + owaspUtils.extractErrorMessage( + new Error( "Hello World" ), not_extracted ), "Hello World" ); + } ); + + } ); + + describe( "Key/address utilities", function() { + const joTestAccount = { + "privateKey": + owaspUtils.toEthPrivateKey( + "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC" ), + "address": owaspUtils.fnAddressImpl_ + }; + + it( "Extract address from private key", function() { + const address = joTestAccount.address(); + const address2 = + owaspUtils.privateKeyToAccountAddress( joTestAccount.privateKey ); + assert.equal( + address.toLowerCase(), + "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5F".toLowerCase() ); + assert.equal( + address2.toLowerCase(), + "0x7aa5E36AA15E93D10F4F26357C30F052DacDde5F".toLowerCase() ); + } ); + + it( "Extract public key from private key", function() { + const publicKey = owaspUtils.privateKeyToPublicKey( joTestAccount.privateKey ); + assert.equal( + publicKey.toLowerCase(), + ( "5dd431d36ce6b88f27d351051b31a26848c4a886f0dd0bc87a7d5a9d82" + + "1417c9e807e8589f680ab0f2ab29831231ad" + + "7b3d6659990ee830582fede785fc3c33c4" ).toLowerCase() ); + } ); + + it( "Extract address from public key", function() { + const address = joTestAccount.address(); + const publicKey = owaspUtils.privateKeyToPublicKey( joTestAccount.privateKey ); + const address2 = owaspUtils.publicKeyToAccountAddress( publicKey ); + assert.equal( address.toLowerCase(), address2.toLowerCase() ); + } ); + } ); +} ); + +describe( "OWASP-6", function() { + + describe( "Ethereum value of money utilities", function() { + + it( "Parse money unit name", function() { + assert.equal( owaspUtils.parseMoneyUnitName( "ethe" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "ethr" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "eth" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "eter" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "ete" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "et" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "eh" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "er" ), "ether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "finne" ), "finney" ); + assert.equal( owaspUtils.parseMoneyUnitName( "finn" ), "finney" ); + assert.equal( owaspUtils.parseMoneyUnitName( "fin" ), "finney" ); + assert.equal( owaspUtils.parseMoneyUnitName( "fn" ), "finney" ); + assert.equal( owaspUtils.parseMoneyUnitName( "fi" ), "finney" ); + assert.equal( owaspUtils.parseMoneyUnitName( "szab" ), "szabo" ); + assert.equal( owaspUtils.parseMoneyUnitName( "szb" ), "szabo" ); + assert.equal( owaspUtils.parseMoneyUnitName( "sza" ), "szabo" ); + assert.equal( owaspUtils.parseMoneyUnitName( "sz" ), "szabo" ); + assert.equal( owaspUtils.parseMoneyUnitName( "shanno" ), "shannon" ); + assert.equal( owaspUtils.parseMoneyUnitName( "shannn" ), "shannon" ); + assert.equal( owaspUtils.parseMoneyUnitName( "shann" ), "shannon" ); + assert.equal( owaspUtils.parseMoneyUnitName( "shan" ), "shannon" ); + assert.equal( owaspUtils.parseMoneyUnitName( "sha" ), "shannon" ); + assert.equal( owaspUtils.parseMoneyUnitName( "shn" ), "shannon" ); + assert.equal( owaspUtils.parseMoneyUnitName( "sh" ), "shannon" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lovelac" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lovela" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lovel" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "love" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lovl" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lvl" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lvla" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lvlc" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lvc" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lv" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lo" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "lc" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "ll" ), "lovelace" ); + assert.equal( owaspUtils.parseMoneyUnitName( "babbag" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "babba" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "babbg" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "babb" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "bab" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "bag" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "bbb" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "bb" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "bg" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "ba" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "be" ), "babbage" ); + assert.equal( owaspUtils.parseMoneyUnitName( "we" ), "wei" ); + assert.equal( owaspUtils.parseMoneyUnitName( "wi" ), "wei" ); + assert.equal( owaspUtils.parseMoneyUnitName( "noether" ), "noether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "noeth" ), "noether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "kwei" ), "kwei" ); + assert.equal( owaspUtils.parseMoneyUnitName( "femtoether" ), "femtoether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "femto" ), "femtoether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "mwei" ), "mwei" ); + assert.equal( owaspUtils.parseMoneyUnitName( "picoether" ), "picoether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "pico" ), "picoether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "gwei" ), "gwei" ); + assert.equal( owaspUtils.parseMoneyUnitName( "nanoether" ), "nanoether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "nano" ), "nanoether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "microether" ), "microether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "micro" ), "microether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "milliether" ), "milliether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "milli" ), "milliether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "kether" ), "kether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "mether" ), "mether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "gether" ), "gether" ); + assert.equal( owaspUtils.parseMoneyUnitName( "tether" ), "tether" ); + } ); + + it( "Parse money value specification", function() { + assert.equal( owaspUtils.parseMoneySpecToWei( "1ether" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1ethe" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1ethr" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1eth" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1eter" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1ete" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1et" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1eh" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1er" ), "1000000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1finney" ), "1000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1finne" ), "1000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1finn" ), "1000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1fin" ), "1000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1fn" ), "1000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1fi" ), "1000000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1szab" ), "1000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1szb" ), "1000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1sza" ), "1000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1sz" ), "1000000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1shanno" ), "1000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1shannn" ), "1000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1shann" ), "1000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1shan" ), "1000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1sha" ), "1000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1shn" ), "1000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1sh" ), "1000000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lovelac" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lovela" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lovel" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1love" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lovl" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lvl" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lvla" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lvlc" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lvc" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lv" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lo" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1lc" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1ll" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1babbag" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1babba" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1babbg" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1babb" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1bab" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1bag" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1bbb" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1bb" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1bg" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1ba" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1be" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1we" ), "1" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1wi" ), "1" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1noether" ), "0" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1noeth" ), "0" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1kwei" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1femtoether" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1femto" ), "1000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1mwei" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1picoether" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1pico" ), "1000000" ); + assert.equal( owaspUtils.parseMoneySpecToWei( "1gwei" ), "1000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1nanoether" ), "1000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1nano" ), "1000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1microether" ), "1000000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1micro" ), "1000000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1milliether" ), "1000000000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1milli" ), "1000000000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1kether" ), "1000000000000000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1mether" ), "1000000000000000000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1gether" ), "1000000000000000000000000000" ); + assert.equal( + owaspUtils.parseMoneySpecToWei( "1tether" ), "1000000000000000000000000000000" ); + } ); + + } ); + +} ); + +describe( "CLI", function() { + + describe( "IMA Agent command line helpers", function() { + + it( "About", function() { + assert.equal( imaCLI.printAbout( true ), true ); + } ); + + it( "Parse and collect CLI argument", function() { + let joArg = imaCLI.parseCommandLineArgument( "--help" ); + assert.equal( joArg.name, "help" ); + assert.equal( joArg.value, "" ); + joArg = imaCLI.parseCommandLineArgument( "--test-url=http://127.0.0.1:3456" ); + assert.equal( joArg.name, "test-url" ); + assert.equal( joArg.value, "http://127.0.0.1:3456" ); + const isExitIfEmpty = false; + const isPrintValue = true; + const fnNameColorizer = null; + const fnValueColorizer = null; + assert.equal( + imaCLI.ensureHaveValue( + "test-url", + "http://127.0.0.1:3456", + isExitIfEmpty, + isPrintValue, + fnNameColorizer, + fnValueColorizer + ), + true ); + const joTestAccount = { + "privateKey": + owaspUtils.toEthPrivateKey( + "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC" ), + "address": owaspUtils.fnAddressImpl_ + }; + assert.equal( + imaCLI.ensureHaveCredentials( + imaState.chainProperties.sc.strChainName, + joTestAccount, + isExitIfEmpty, + isPrintValue ), + true ); + } ); + + } ); + + // TO-DO: imaCLI.findNodeIndex + + describe( "IMA Agent command line parser", function() { + + it( "Minimal command line parse", function() { + const joExternalHandlers = {}; + const argv = []; + assert.equal( imaCLI.parse( joExternalHandlers, argv ), 0 ); + } ); + + it( "Basic command line parse", function() { + const joExternalHandlers = {}; + const argv = [ + "--verbose=9", + "--s2s-disable", + "--url-main-net=" + imaState.chainProperties.mn.strURL, + "--url-s-chain=" + imaState.chainProperties.sc.strURL, + "--id-main-net=" + imaState.chainProperties.mn.strChainName, + "--id-s-chain=" + imaState.chainProperties.sc.strChainName, + "--id-origin-chain=" + imaState.strChainNameOriginChain, + "--cid-main-net=" + imaState.chainProperties.mn.chainId, + "--cid-s-chain=" + imaState.chainProperties.sc.chainId, + "--address-main-net=" + + ( imaState.chainProperties.mn.joAccount.address() || + "0x7aa5e36aa15e93d10f4f26357c30f052dacdde5f" ), + "--address-s-chain=" + + ( imaState.chainProperties.sc.joAccount.address() || + "0x66c5a87f4a49DD75e970055A265E8dd5C3F8f852" ), + "--key-main-net=" + + ( imaState.chainProperties.mn.joAccount.privateKey || + "23ABDBD3C61B5330AF61EBE8BEF582F4E5CC08E554053A718BDCE7813B9DC1FC" ), + "--key-s-chain=" + ( imaState.chainProperties.sc.joAccount.privateKey || + "80ebc2e00b8f13c5e2622b5694ab63ee80f7c5399554d2a12feeb0212eb8c69e" ), + //"--abi-skale-manager=" + imaState.strPathAbiJsonSkaleManager, + "--abi-main-net=" + imaState.chainProperties.mn.strPathAbiJson, + "--abi-s-chain=" + imaState.chainProperties.sc.strPathAbiJson, + // --erc721-main-net --erc721-s-chain --addr-erc721-s-chain + // --erc20-main-net --erc20-s-chain --addr-erc20-s-chain + // --erc1155-main-net --erc1155-s-chain --addr-erc1155-s-chain + "--sleep-between-tx=5000", + "--wait-next-block=true", + // --value... + "--gas-price-multiplier-mn=2", + "--gas-price-multiplier-sc=2", + "--gas-price-multiplier=2", + // --no-wait-s-chain --max-wait-attempts + "--skip-dry-run", // --skip-dry-run --ignore-dry-run --dry-run + "--m2s-transfer-block-size=4", + "--s2m-transfer-block-size=4", + "--s2s-transfer-block-size=4", + "--transfer-block-size=4", + "--m2s-max-transactions=0", + "--s2m-max-transactions=0", + "--s2s-max-transactions=0", + "--max-transactions=0", + "--m2s-await-blocks=0", + "--s2m-await-blocks=0", + "--s2s-await-blocks=0", + "--await-blocks=0", + "--m2s-await-time=0", + "--s2m-await-time=0", + "--s2s-await-time=0", + "--await-time=0", + "--period=300", + "--node-number=0", + "--nodes-count=1", + "--time-framing=0", + "--time-gap=10", + "--no-pwa" + // --log-size --log-files --log + // --sign-messages --bls-glue --hash-g1 --bls-verify + ]; + assert.equal( imaCLI.parse( joExternalHandlers, argv ), 0 ); + } ); + + } ); + +} ); + +describe( "Agent Utils Module-1", function() { + + describe( "String helpers", function() { + + it( "Text replacement", function() { + assert.equal( imaUtils.replaceAll( "abc123abcdef456abc", "abc", "" ), "123def456" ); + } ); + + it( "Random file name", function() { + const strPathTmpFolder = os.tmpdir(); + const strPathTmpFile = + path.join( strPathTmpFolder, imaUtils.getRandomFileName() + ".txt" ); + assert.equal( strPathTmpFile ? true : false, true ); + } ); + + it( "Compose S-Chain URL", function() { + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip: "127.0.0.1", httpRpcPort: 3456 } ), "http://127.0.0.1:3456" ); + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip: "127.0.0.1", httpsRpcPort: 3456 } ), "https://127.0.0.1:3456" ); + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip: "127.0.0.1", wsRpcPort: 3456 } ), "ws://127.0.0.1:3456" ); + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip: "127.0.0.1", wssRpcPort: 3456 } ), "wss://127.0.0.1:3456" ); + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip6: "::1", httpRpcPort6: 3456 } ), "http://[::1]:3456" ); + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip6: "::1", httpsRpcPort6: 3456 } ), "https://[::1]:3456" ); + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip6: "::1", wsRpcPort6: 3456 } ), "ws://[::1]:3456" ); + assert.equal( + imaUtils.composeSChainNodeUrl( + { ip6: "::1", wssRpcPort6: 3456 } ), "wss://[::1]:3456" ); + } ); + + it( "Compose IMA Agent URL", function() { + // HTTP_JSON = 3 + // IMA_AGENT_JSON = 10 + // so... distance is 10 - 3 = 7 + // as result, 14999 + 7 = 15006 + assert.equal( + imaUtils.composeImaAgentNodeUrl( + { ip: "127.0.0.1", httpRpcPort: 14999 } ), "http://127.0.0.1:15006" ); + } ); + + } ); + +} ); + +describe( "Agent Utils Module-2", function() { + + describe( "Byte array manipulation helpers", function() { + + it( "HEX encode/decode raw", function() { + const strSrc = "5465737420737472696e6720313233"; + const arrBytes = imaUtils.hexToBytes( strSrc, false ); + const strDst = imaUtils.bytesToHex( arrBytes, false ); + assert.equal( strSrc, strDst ); + } ); + + it( "HEX encode/decode 0x-prefixed", function() { + const strSrc = "0x5465737420737472696e6720313233"; + const arrBytes = imaUtils.hexToBytes( strSrc, false ); + const strDst = imaUtils.bytesToHex( arrBytes, false ); + assert.equal( strSrc, "0x" + strDst ); + } ); + + it( "HEX encode/decode with inversive order raw", function() { + const strSrc = "5465737420737472696e6720313233"; + const arrBytes = imaUtils.hexToBytes( strSrc, true ); + const strDst = imaUtils.bytesToHex( arrBytes, true ); + assert.equal( strSrc, strDst ); + } ); + + it( "HEX encode/decode with inversive order 0x-prefixed", function() { + const strSrc = "0x5465737420737472696e6720313233"; + const arrBytes = imaUtils.hexToBytes( strSrc, true ); + const strDst = imaUtils.bytesToHex( arrBytes, true ); + assert.equal( strSrc, "0x" + strDst ); + } ); + + it( "Array padding with zeroes at left", function() { + const strSrc = "123"; + const arrBytes = + imaUtils.bytesAlignLeftWithZeroes( + imaUtils.hexToBytes( strSrc, false ), 4 ); + const strDst = imaUtils.bytesToHex( arrBytes, false ); + assert.equal( strDst, "00000123" ); + } ); + + it( "Array padding with zeroes at right", function() { + const strSrc = "123"; + const arrBytes = + imaUtils.bytesAlignRightWithZeroes( + imaUtils.hexToBytes( strSrc, false ), 4 ); + const strDst = imaUtils.bytesToHex( arrBytes, false ); + assert.equal( strDst, "01230000" ); + } ); + + it( "Typed array concatenation", function() { + const strSrcLeft = "0xbaad", strSrcRight = "0xf00d"; + const arrBytesLeft = imaUtils.hexToBytes( strSrcLeft, false ); + const arrBytesRight = imaUtils.hexToBytes( strSrcRight, false ); + const arrBytes = imaUtils.concatTypedArrays( arrBytesLeft, arrBytesRight ); + const strDst = imaUtils.bytesToHex( arrBytes, false ); + assert.equal( strDst, "baadf00d" ); + } ); + + it( "Byte array concatenation", function() { + const strSrcLeft = "0xbaad", strSrcRight = "0xf00d"; + const arrBytesLeft = imaUtils.hexToBytes( strSrcLeft, false ); + const arrBytesRight = imaUtils.hexToBytes( strSrcRight, false ); + const arrBytes = imaUtils.bytesConcat( arrBytesLeft, arrBytesRight ); + const strDst = imaUtils.bytesToHex( arrBytes, false ); + assert.equal( strDst, "baadf00d" ); + } ); + + it( "Single Byte concatenation", function() { + const strSrcLeft = "0xbaadf0", nSrcRight = 0x0d; + const arrBytesLeft = imaUtils.hexToBytes( strSrcLeft, false ); + const arrBytes = imaUtils.concatByte( arrBytesLeft, nSrcRight ); + const strDst = imaUtils.bytesToHex( arrBytes, false ); + assert.equal( strDst, "baadf00d" ); + } ); + + } ); + +} ); + +describe( "Agent Utils Module-3", function() { + + describe( "Path/file/JSON helpers", function() { + + it( "Home directory and path normalization", function() { + const strPathHomeFolder = imaUtils.normalizePath( "~" ); + const strPathSrc = "~/some/file/path/here"; + const strPathDst = strPathHomeFolder + "/some/file/path/here"; + assert.equal( imaUtils.normalizePath( strPathSrc ), strPathDst ); + } ); + + it( "File existence and text loading/saving", function() { + const strPathTmpFolder = os.tmpdir(); + const strPathTmpFile = + path.join( strPathTmpFolder, imaUtils.getRandomFileName() + ".txt" ); + try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; + assert.equal( imaUtils.fileExists( strPathTmpFile ), false ); + const strContentSaved = "Text file content"; + assert.equal( imaUtils.fileSave( strPathTmpFile, strContentSaved ), true ); + assert.equal( imaUtils.fileExists( strPathTmpFile ), true ); + const strContentLoaded = + imaUtils.fileLoad( + strPathTmpFile, "file \"" + strPathTmpFile + "\"was not loaded" ); + assert.equal( strContentLoaded, strContentSaved ); + try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; + } ); + + it( "File existence and JSON loading/saving", function() { + const strPathTmpFolder = os.tmpdir(); + const strPathTmpFile = + path.join( strPathTmpFolder, imaUtils.getRandomFileName() + ".json" ); + try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; + assert.equal( imaUtils.fileExists( strPathTmpFile ), false ); + const joContentSaved = { a: 123, b: 456 }; + assert.equal( imaUtils.jsonFileSave( strPathTmpFile, joContentSaved ), true ); + assert.equal( imaUtils.fileExists( strPathTmpFile ), true ); + const joContentLoaded = + imaUtils.jsonFileLoad( + strPathTmpFile, + { error: "file \"" + strPathTmpFile + "\"was not loaded" } ); + assert.equal( + JSON.stringify( joContentSaved ), JSON.stringify( joContentLoaded ) ); + try { fs.unlinkSync( strPathTmpFile ); } catch ( err ) { }; + } ); + + } ); + + describe( "ABI JSON Helpers", function() { + + it( "Find ABI entries", function() { + const strName = imaState.chainProperties.sc.strChainName; + const strFile = imaState.chainProperties.sc.strPathAbiJson; + const joABI = + imaUtils.jsonFileLoad( + strFile, + { error: "file \"" + strFile + "\"was not loaded" } ); + const strKey = "token_manager_linker_address"; + const arrKeys = [ + "token_manager_linker_address", + "token_manager_linker_abi", + "eth_erc20_address", + "eth_erc20_abi", + "token_manager_eth_address", + "token_manager_eth_abi", + "token_manager_erc20_address", + "token_manager_erc20_abi", + "token_manager_erc721_address", + "token_manager_erc721_abi", + "token_manager_erc1155_address", + "token_manager_erc1155_abi", + "message_proxy_chain_address", + "message_proxy_chain_abi" + ]; + const isExitOnError = false; + assert.equal( + imaUtils.checkKeyExistInABI( + strName, strFile, joABI, strKey, isExitOnError ), true ); + assert.equal( + imaUtils.checkKeysExistInABI( + strName, strFile, joABI, arrKeys, isExitOnError ), true ); + } ); + + it( "Discover coin name", function() { + const strFile = imaState.chainProperties.sc.strPathAbiJson; + const joABI = + imaUtils.jsonFileLoad( + strFile, + { error: "file \"" + strFile + "\"was not loaded" } ); + const strCoinName = + imaUtils.discoverCoinNameInJSON( joABI ); + assert.equal( strCoinName.length > 0, true ); + } ); + + } ); + +} ); diff --git a/test/agent/agent.py b/test/agent/agent.py index d75958ea0..68c5d3462 100644 --- a/test/agent/agent.py +++ b/test/agent/agent.py @@ -40,7 +40,12 @@ def __init__(self, config): self.blockchain = BlockChain(config) def register(self): - self._execute_command('register') + self._execute_command( + 'register', + { + 'colors': None + } + ) def start(self): if self.agent_service is None: @@ -64,7 +69,8 @@ def transfer_eth_from_mainnet_to_schain(self, from_key, to_key, amount_wei, time 'm2s-payment', { **self._wei_to_bigger(amount_wei), - 'key-main-net': from_key + 'key-main-net': from_key, + 'colors': None } ) @@ -75,7 +81,7 @@ def transfer_eth_from_mainnet_to_schain(self, from_key, to_key, amount_wei, time if time() > start + timeout: return else: - sleep(1) + sleep( 1 ) def transfer_eth_from_schain_to_mainnet(self, from_key, to_key, amount_wei, timeout=0): destination_address = self.blockchain.key_to_address(from_key) @@ -90,7 +96,8 @@ def transfer_eth_from_schain_to_mainnet(self, from_key, to_key, amount_wei, time { **self._wei_to_bigger(amount_wei), 'key-s-chain': from_key, - 'key-main-net': to_key + 'key-main-net': to_key, + 'colors': None } ) @@ -102,13 +109,19 @@ def transfer_eth_from_schain_to_mainnet(self, from_key, to_key, amount_wei, time if time() > start + timeout: return else: - sleep(1) + sleep( 1 ) balance = self.blockchain.get_balance_on_mainnet(destination_address) initial_balance = balance start = time() debug(f'Initial balance: {initial_balance}') - self._execute_command('s2m-receive', {'key-main-net': from_key}) + self._execute_command( + 's2m-receive', + { + 'key-main-net': from_key, + 'colors': None + } + ) if timeout > 0: approximate_gas_spends = 3 * 10 ** 15 @@ -119,7 +132,7 @@ def transfer_eth_from_schain_to_mainnet(self, from_key, to_key, amount_wei, time if time() > start + timeout: return else: - sleep(1) + sleep( 1 ) def transfer_erc20_from_mainnet_to_schain(self, token_contract, from_key, to_key, amount, amount_wei, timeout=0): config_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -135,7 +148,8 @@ def transfer_erc20_from_mainnet_to_schain(self, token_contract, from_key, to_key 'amount': amount, 'key-main-net': from_key, 'key-s-chain': to_key, - 'erc20-main-net': erc20_config_filename + 'erc20-main-net': erc20_config_filename, + 'colors': None } ) @@ -146,7 +160,7 @@ def transfer_erc20_from_mainnet_to_schain(self, token_contract, from_key, to_key return except ValueError: debug('Wait for erc20 deployment') - sleep(1) + sleep( 1 ) def transfer_erc721_from_mainnet_to_schain(self, token_contract, from_key, to_key, token_id, amount_wei, timeout=0): config_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -154,7 +168,7 @@ def transfer_erc721_from_mainnet_to_schain(self, token_contract, from_key, to_ke self._create_path(erc721_config_filename) with open(erc721_config_filename, 'w') as erc721_file: json.dump(config_json, erc721_file) - sleep(5) + sleep( 5 ) self._execute_command( 'm2s-payment', @@ -163,7 +177,8 @@ def transfer_erc721_from_mainnet_to_schain(self, token_contract, from_key, to_ke 'tid': token_id, 'key-main-net': from_key, 'key-s-chain': to_key, - 'erc721-main-net': erc721_config_filename + 'erc721-main-net': erc721_config_filename, + 'colors': None } ) @@ -174,7 +189,7 @@ def transfer_erc721_from_mainnet_to_schain(self, token_contract, from_key, to_ke return except ValueError: debug('Wait for erc721 deployment') - sleep(1) + sleep( 1 ) def transfer_erc1155_from_mainnet_to_schain(self, token_contract, from_key, to_key, token_id, token_amount, amount_wei, timeout=0): config_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -182,7 +197,7 @@ def transfer_erc1155_from_mainnet_to_schain(self, token_contract, from_key, to_k self._create_path(erc1155_config_filename) with open(erc1155_config_filename, 'w') as erc1155_file: json.dump(config_json, erc1155_file) - sleep(5) + sleep( 5 ) self._execute_command( 'm2s-payment', @@ -192,7 +207,8 @@ def transfer_erc1155_from_mainnet_to_schain(self, token_contract, from_key, to_k 'amount': token_amount, 'key-main-net': from_key, 'key-s-chain': to_key, - 'erc1155-main-net': erc1155_config_filename + 'erc1155-main-net': erc1155_config_filename, + 'colors': None } ) @@ -203,7 +219,7 @@ def transfer_erc1155_from_mainnet_to_schain(self, token_contract, from_key, to_k return except ValueError: debug('Wait for erc1155 deployment') - sleep(1) + sleep( 1 ) def transfer_erc1155_batch_from_mainnet_to_schain(self, token_contract, from_key, to_key, token_ids, token_amounts, amount_wei, timeout=0): config_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -211,7 +227,7 @@ def transfer_erc1155_batch_from_mainnet_to_schain(self, token_contract, from_key self._create_path(erc1155_config_filename) with open(erc1155_config_filename, 'w') as erc1155_file: json.dump(config_json, erc1155_file) - sleep(5) + sleep( 5 ) self._execute_command( 'm2s-payment', @@ -221,7 +237,8 @@ def transfer_erc1155_batch_from_mainnet_to_schain(self, token_contract, from_key 'amounts': str(token_amounts).replace(' ', ''), 'key-main-net': from_key, 'key-s-chain': to_key, - 'erc1155-main-net': erc1155_config_filename + 'erc1155-main-net': erc1155_config_filename, + 'colors': None } ) @@ -232,7 +249,7 @@ def transfer_erc1155_batch_from_mainnet_to_schain(self, token_contract, from_key return except ValueError: debug('Wait for erc1155 deployment') - sleep(1) + sleep( 1 ) def transfer_erc20_from_schain_to_mainnet(self, token_contract, token_contract_on_mainnet, from_key, to_key, amount, amount_wei, timeout=0): config_schain_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -249,7 +266,6 @@ def transfer_erc20_from_schain_to_mainnet(self, token_contract, token_contract_o destination_address = self.blockchain.key_to_address(from_key) erc20 = token_contract_on_mainnet balance = erc20.functions.balanceOf(destination_address).call() - # balance = erc20.functions.balanceOf(destination_address) tx_count = self.blockchain.get_transactions_count_on_mainnet(destination_address) @@ -261,21 +277,16 @@ def transfer_erc20_from_schain_to_mainnet(self, token_contract, token_contract_o 'key-main-net': to_key, 'key-s-chain': from_key, 'erc20-main-net': erc20_config_filename, - 'erc20-s-chain': erc20_clone_config_filename + 'erc20-s-chain': erc20_clone_config_filename, + 'colors': None } ) - # sleep(30) start = time() while (time() < start + timeout if timeout > 0 else True) and \ balance == erc20.functions.balanceOf(destination_address).call(): debug('Wait for erc20 payment') - sleep(1) - # start = time() - # while (time() < start + timeout if timeout > 0 else True) and \ - # self.blockchain.get_transactions_count_on_mainnet(destination_address) == tx_count: - # debug('Wait for erc20 payment') - # sleep(1) + sleep( 1 ) def transfer_erc721_from_schain_to_mainnet(self, token_contract, token_contract_on_mainnet, from_key, to_key, token_id, amount_wei, timeout=0): config_schain_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -291,9 +302,8 @@ def transfer_erc721_from_schain_to_mainnet(self, token_contract, token_contract_ erc721 = token_contract_on_mainnet destination_address = erc721.functions.ownerOf(token_id).call() - # destination_address = self.blockchain.key_to_address(to_key) tx_count = self.blockchain.get_transactions_count_on_mainnet(destination_address) - sleep(10) + sleep( 10 ) self._execute_command( 's2m-payment', { @@ -302,7 +312,8 @@ def transfer_erc721_from_schain_to_mainnet(self, token_contract, token_contract_ 'key-main-net': to_key, 'key-s-chain': from_key, 'erc721-main-net': erc721_config_filename, - 'erc721-s-chain': erc721_clone_config_filename + 'erc721-s-chain': erc721_clone_config_filename, + 'colors': None } ) @@ -310,12 +321,7 @@ def transfer_erc721_from_schain_to_mainnet(self, token_contract, token_contract_ while (time() < start + timeout if timeout > 0 else True) and \ destination_address == erc721.functions.ownerOf(token_id).call(): debug('Wait for erc721 payment') - sleep(1) - # start = time() - # while (time() < start + timeout if timeout > 0 else True) and \ - # self.blockchain.get_transactions_count_on_mainnet(destination_address) == tx_count: - # debug('Wait for erc721 payment') - # sleep(1) + sleep( 1 ) def transfer_erc1155_from_schain_to_mainnet(self, token_contract, token_contract_on_mainnet, from_key, to_key, token_id, token_amount, amount_wei, timeout=0): config_schain_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -331,10 +337,7 @@ def transfer_erc1155_from_schain_to_mainnet(self, token_contract, token_contract erc1155 = token_contract_on_mainnet destination_address = self.blockchain.key_to_address(from_key) - # destination_address = erc1155.functions.balanceOf(token_id).call() - # destination_address = self.blockchain.key_to_address(to_key) - # tx_count = self.blockchain.get_transactions_count_on_mainnet(destination_address) - sleep(10) + sleep( 10 ) self._execute_command( 's2m-payment', { @@ -344,7 +347,8 @@ def transfer_erc1155_from_schain_to_mainnet(self, token_contract, token_contract 'key-main-net': to_key, 'key-s-chain': from_key, 'erc1155-main-net': erc1155_config_filename, - 'erc1155-s-chain': erc1155_clone_config_filename + 'erc1155-s-chain': erc1155_clone_config_filename, + 'colors': None } ) @@ -352,12 +356,7 @@ def transfer_erc1155_from_schain_to_mainnet(self, token_contract, token_contract while (time() < start + timeout if timeout > 0 else True) and \ token_amount != erc1155.functions.balanceOf(destination_address, token_id).call(): debug('Wait for erc1155 payment') - sleep(1) - # start = time() - # while (time() < start + timeout if timeout > 0 else True) and \ - # self.blockchain.get_transactions_count_on_mainnet(destination_address) == tx_count: - # debug('Wait for erc1155 payment') - # sleep(1) + sleep( 1 ) def transfer_erc1155_batch_from_schain_to_mainnet(self, token_contract, token_contract_on_mainnet, from_key, to_key, token_ids, token_amounts, amount_wei, timeout=0): config_schain_json = {'token_address': token_contract.address, 'token_abi': token_contract.abi} @@ -373,10 +372,7 @@ def transfer_erc1155_batch_from_schain_to_mainnet(self, token_contract, token_co erc1155 = token_contract_on_mainnet destination_address = self.blockchain.key_to_address(from_key) - # destination_address = erc1155.functions.balanceOf(token_id).call() - # destination_address = self.blockchain.key_to_address(to_key) - # tx_count = self.blockchain.get_transactions_count_on_mainnet(destination_address) - sleep(10) + sleep( 10 ) self._execute_command( 's2m-payment', { @@ -386,7 +382,8 @@ def transfer_erc1155_batch_from_schain_to_mainnet(self, token_contract, token_co 'key-main-net': to_key, 'key-s-chain': from_key, 'erc1155-main-net': erc1155_config_filename, - 'erc1155-s-chain': erc1155_clone_config_filename + 'erc1155-s-chain': erc1155_clone_config_filename, + 'colors': None } ) @@ -394,12 +391,7 @@ def transfer_erc1155_batch_from_schain_to_mainnet(self, token_contract, token_co while (time() < start + timeout if timeout > 0 else True) and \ token_amounts != erc1155.functions.balanceOfBatch([destination_address]*len(token_ids), token_ids).call(): debug('Wait for erc1155 payment') - sleep(1) - # start = time() - # while (time() < start + timeout if timeout > 0 else True) and \ - # self.blockchain.get_transactions_count_on_mainnet(destination_address) == tx_count: - # debug('Wait for erc1155 payment') - # sleep(1) + sleep( 1 ) # private @@ -414,7 +406,7 @@ def _construct_command(self, command, flags=None): flags = {**self._get_default_flags(), command: None, **flags} return ['node', - f'{self.config.agent_root}/main.js'] + \ + f'{self.config.agent_root}/main.mjs'] + \ [f'--{key}' + (f'={str(value)}' if value is not None else '') for key, value in flags.items() ] def _format_command(self, command, flags=None): @@ -435,7 +427,16 @@ def _get_default_flags(self): 'key-main-net': self.config.mainnet_key, 'key-s-chain': self.config.schain_key, 'no-wait-s-chain': None, - 'no-ptx': None + 'no-pwa': None, + 'gas-price-multiplier': '2.0', + 'gas-multiplier': '2.0', + 'colors': None, + 'no-expose': None, + 'no-expose-pwa': None, + 'no-expose-security-info': None, + 'no-gathered': None, + 'dynamic-log-in-transfer': None, + 'accumulated-log-in-bls-signer': None } def _wei_to_bigger(self, amount): diff --git a/test/package.json b/test/package.json index 7cc26cf11..992428507 100644 --- a/test/package.json +++ b/test/package.json @@ -4,9 +4,9 @@ "license": "AGPL-3.0", "author": "SKALE Labs and contributors", "scripts": { - "lint-check": "eslint ./*.js", - "lint-fix": "eslint ./*.js --fix", - "test": "npx mocha ./agent-test.js" + "lint-check": "eslint ./*.*js", + "lint-fix": "eslint ./*.*js --fix", + "test": "npx mocha ./agent-test.mjs" }, "dependencies": {}, "devDependencies": { diff --git a/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py b/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py index 92d57d664..51839fe91 100644 --- a/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py +++ b/test/test_cases/load_send_ether_from_mainnet_to_schain_and_back.py @@ -22,7 +22,7 @@ from tools.test_case import TestCase from tools.test_pool import test_pool -import time +from time import sleep class SendEtherFromSchainToMainnetAndBack(TestCase): @@ -31,19 +31,19 @@ def __init__(self, config): super().__init__('load_send_ether_from_mainnet_to_schain_and_back', config) def _execute(self): - amount = 2 * 10 ** 18 - self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amount) - # + amountRecharge = 2 * 10 ** 18 + self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amountRecharge) + sleep( 5 ) range_int = 5 # ETH eth_amount = 12 * 10 ** 18 - # address = self.blockchain.key_to_address(self.config.mainnet_key) # transfer to schain self.agent.transfer_eth_from_mainnet_to_schain(self.config.mainnet_key, self.config.schain_key, eth_amount, self.timeout) + sleep( 5 ) # balance = self.blockchain.get_balance_on_schain(address) initial_balance = balance @@ -59,19 +59,27 @@ def _execute(self): self.config.schain_key, amount, self.timeout) - time.sleep(2) + sleep( 5 ) # back to mainnet self.agent.transfer_eth_from_schain_to_mainnet(self.config.mainnet_key, self.config.schain_key, amount_from_schain, self.timeout) + sleep( 5 ) self.blockchain.get_balance_on_schain(address) a = 0 # balance = self.blockchain.get_balance_on_schain(address) + print( 'Real balance.......', balance ) + needed_balance = initial_balance + range_int * amount - range_int * amount_from_schain + print( 'Needed balance.....', needed_balance ) + res = initial_balance - range_int * amount - if balance == initial_balance + range_int * amount - range_int * amount_from_schain: + if balance == needed_balance: + print( 'Passed.............', 'YES!' ) self._mark_passed() + else: + print( 'Passed.............', 'NO(' ) test_pool.register_test(SendEtherFromSchainToMainnetAndBack) diff --git a/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py b/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py index e415cdbe4..e7da44e81 100644 --- a/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py +++ b/test/test_cases/send_erc1155_batch_from_mainnet_to_schain.py @@ -33,10 +33,9 @@ def __init__(self, config): super().__init__('Send ERC1155 Batch to schain', config) def _prepare(self): - sleep(5) - + sleep( 5 ) self.erc1155 = self.blockchain.deploy_erc1155_on_mainnet(self.config.mainnet_key, 'elv1155') - sleep(5) + address = self.blockchain.key_to_address(self.config.mainnet_key) mint_txn = self.erc1155.functions.mintBatch(address, self.tokenIds, self.tokenAmounts, "0x")\ .buildTransaction({ @@ -51,8 +50,6 @@ def _prepare(self): def _execute(self): - sleep(5) - self.agent.transfer_erc1155_batch_from_mainnet_to_schain( self.erc1155, self.config.mainnet_key, diff --git a/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py b/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py index 13104ff38..c8fc21f13 100644 --- a/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py +++ b/test/test_cases/send_erc1155_batch_from_schain_to_mainnet.py @@ -35,8 +35,10 @@ def __init__(self, config): super().__init__('Send ERC1155 Batch from schain to mainnet', config) def _prepare(self): - amount = 2 * 10 ** 18 - self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amount) + sleep( 5 ) + amountRecharge = 2 * 10 ** 18 + self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amountRecharge) + sleep( 5 ) # deploy token self.erc1155 = self.blockchain.deploy_erc1155_on_mainnet(self.config.mainnet_key, 'elv1155') # mint @@ -45,18 +47,11 @@ def _prepare(self): .buildTransaction({ 'gas': 8000000, 'nonce': self.blockchain.get_transactions_count_on_mainnet(address)}) - # - sleep(5) - signed_txn = self.blockchain.web3_mainnet.eth.account\ .signTransaction(mint_txn, private_key=self.config.mainnet_key) - # - sleep(5) self.blockchain.web3_mainnet.eth.sendRawTransaction(signed_txn.rawTransaction) - self.blockchain.disableWhitelistERC1155(self.config.mainnet_key, self.config.schain_name) self.blockchain.enableAutomaticDeployERC1155(self.config.schain_key, "Mainnet") - sleep(5) # send to schain self.agent.transfer_erc1155_batch_from_mainnet_to_schain(self.erc1155, self.config.mainnet_key, @@ -64,20 +59,13 @@ def _prepare(self): self.token_ids, self.token_amounts, self.timeout) - sleep(5) - # + sleep( 5 ) amount_eth = 90 * 10 ** 15 - # self.agent.transfer_eth_from_mainnet_to_schain(self.config.mainnet_key, self.config.schain_key, amount_eth, self.timeout) - - # - sleep(5) - - # - sleep(5) + sleep( 5 ) self.erc1155_clone = self.blockchain.get_erc1155_on_schain("Mainnet", self.erc1155.address) def _execute(self): @@ -87,8 +75,7 @@ def _execute(self): if self.erc1155_clone.functions.balanceOfBatch([source_address] * len(self.token_ids), self.token_ids).call() != self.token_amounts: error("Token was not send") return - # - sleep(5) + sleep( 5 ) self.agent.transfer_erc1155_batch_from_schain_to_mainnet( self.erc1155_clone, self.erc1155, diff --git a/test/test_cases/send_erc1155_from_mainnet_to_schain.py b/test/test_cases/send_erc1155_from_mainnet_to_schain.py index 2184e4ceb..5283fee6c 100644 --- a/test/test_cases/send_erc1155_from_mainnet_to_schain.py +++ b/test/test_cases/send_erc1155_from_mainnet_to_schain.py @@ -33,10 +33,9 @@ def __init__(self, config): super().__init__('Send ERC1155 to schain', config) def _prepare(self): - sleep(5) - + sleep( 5 ) self.erc1155 = self.blockchain.deploy_erc1155_on_mainnet(self.config.mainnet_key, 'elv1155') - sleep(5) + address = self.blockchain.key_to_address(self.config.mainnet_key) mint_txn = self.erc1155.functions.mint(address, self.tokenId, self.tokenAmount, "0x")\ .buildTransaction({ @@ -51,8 +50,6 @@ def _prepare(self): def _execute(self): - sleep(5) - self.agent.transfer_erc1155_from_mainnet_to_schain( self.erc1155, self.config.mainnet_key, diff --git a/test/test_cases/send_erc1155_from_schain_to_mainnet.py b/test/test_cases/send_erc1155_from_schain_to_mainnet.py index 9c4de177a..cd609e57e 100644 --- a/test/test_cases/send_erc1155_from_schain_to_mainnet.py +++ b/test/test_cases/send_erc1155_from_schain_to_mainnet.py @@ -35,8 +35,10 @@ def __init__(self, config): super().__init__('Send ERC1155 from schain to mainnet', config) def _prepare(self): - amount = 2 * 10 ** 18 - self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amount) + sleep( 5 ) + amountRecharge = 2 * 10 ** 18 + self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amountRecharge) + sleep( 5 ) # deploy token self.erc1155 = self.blockchain.deploy_erc1155_on_mainnet(self.config.mainnet_key, 'elv1155') # mint @@ -45,18 +47,11 @@ def _prepare(self): .buildTransaction({ 'gas': 8000000, 'nonce': self.blockchain.get_transactions_count_on_mainnet(address)}) - # - sleep(5) - signed_txn = self.blockchain.web3_mainnet.eth.account\ .signTransaction(mint_txn, private_key=self.config.mainnet_key) - # - sleep(5) self.blockchain.web3_mainnet.eth.sendRawTransaction(signed_txn.rawTransaction) - self.blockchain.disableWhitelistERC1155(self.config.mainnet_key, self.config.schain_name) self.blockchain.enableAutomaticDeployERC1155(self.config.schain_key, "Mainnet") - sleep(5) # send to schain self.agent.transfer_erc1155_from_mainnet_to_schain(self.erc1155, self.config.mainnet_key, @@ -64,20 +59,13 @@ def _prepare(self): self.token_id, self.token_amount, self.timeout) - sleep(5) - # + sleep( 5 ) amount_eth = 90 * 10 ** 15 - # self.agent.transfer_eth_from_mainnet_to_schain(self.config.mainnet_key, self.config.schain_key, amount_eth, self.timeout) - - # - sleep(5) - - # - sleep(5) + sleep( 5 ) self.erc1155_clone = self.blockchain.get_erc1155_on_schain("Mainnet", self.erc1155.address) def _execute(self): @@ -87,8 +75,7 @@ def _execute(self): if self.erc1155_clone.functions.balanceOf(source_address, self.token_id).call() != self.token_amount: error("Token was not send") return - # - sleep(5) + sleep( 5 ) self.agent.transfer_erc1155_from_schain_to_mainnet( self.erc1155_clone, self.erc1155, diff --git a/test/test_cases/send_erc20_from_mainnet_to_schain.py b/test/test_cases/send_erc20_from_mainnet_to_schain.py index 20c248293..0459cb4bf 100644 --- a/test/test_cases/send_erc20_from_mainnet_to_schain.py +++ b/test/test_cases/send_erc20_from_mainnet_to_schain.py @@ -18,8 +18,7 @@ # You should have received a copy of the GNU Affero General Public License # along with SKALE IMA. If not, see . -from time import sleep, time -from logging import debug +from time import sleep from tools.test_case import TestCase from tools.test_pool import test_pool @@ -32,6 +31,7 @@ def __init__(self, config): super().__init__('Send ERC20 to schain', config) def _prepare(self): + sleep( 5 ) self.erc20 = self.blockchain.deploy_erc20_on_mainnet(self.config.mainnet_key, 'D2-Token', 'D2', 100) address = self.blockchain.key_to_address(self.config.mainnet_key) diff --git a/test/test_cases/send_erc20_from_schain_to_mainnet.py b/test/test_cases/send_erc20_from_schain_to_mainnet.py index 2b059e2c5..48e216c80 100644 --- a/test/test_cases/send_erc20_from_schain_to_mainnet.py +++ b/test/test_cases/send_erc20_from_schain_to_mainnet.py @@ -18,7 +18,7 @@ # You should have received a copy of the GNU Affero General Public License # along with SKALE IMA. If not, see . -from time import sleep, time +from time import sleep from logging import debug, error from tools.test_case import TestCase @@ -36,8 +36,10 @@ def __init__(self, config): super().__init__('Send ERC20 from schain to mainnet', config) def _prepare(self): - amount = 2 * 10 ** 18 - self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amount) + sleep( 5 ) + amountRecharge = 2 * 10 ** 18 + self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amountRecharge) + sleep( 5 ) # deploy token @@ -54,7 +56,6 @@ def _prepare(self): signed_txn = self.blockchain.web3_mainnet.eth.account.signTransaction(mint_txn, private_key=self.config.mainnet_key) self.blockchain.web3_mainnet.eth.sendRawTransaction(signed_txn.rawTransaction) - self.blockchain.disableWhitelistERC20(self.config.mainnet_key, self.config.schain_name) self.blockchain.enableAutomaticDeployERC20(self.config.schain_key, "Mainnet") @@ -65,6 +66,7 @@ def _prepare(self): self.config.schain_key, self.amount, self.timeout) + sleep( 5 ) amount_of_eth = 90 * 10 ** 15 @@ -72,9 +74,7 @@ def _prepare(self): self.config.schain_key, amount_of_eth, self.timeout) - - # self.blockchain.add_eth_cost(self.config.schain_key, - # amount_of_eth) + sleep( 5 ) self.erc20_clone = self.blockchain.get_erc20_on_schain("Mainnet", self.erc20.address) diff --git a/test/test_cases/send_erc721_from_mainnet_to_schain.py b/test/test_cases/send_erc721_from_mainnet_to_schain.py index 4ab36eb52..cb610ff5f 100644 --- a/test/test_cases/send_erc721_from_mainnet_to_schain.py +++ b/test/test_cases/send_erc721_from_mainnet_to_schain.py @@ -18,7 +18,7 @@ # You should have received a copy of the GNU Affero General Public License # along with SKALE IMA. If not, see . -from time import sleep, time +from time import sleep from logging import debug from tools.test_case import TestCase @@ -33,10 +33,9 @@ def __init__(self, config): super().__init__('Send ERC721 to schain', config) def _prepare(self): - sleep(5) - + sleep( 5 ) self.erc721 = self.blockchain.deploy_erc721_on_mainnet(self.config.mainnet_key, 'elv721', 'ELV') - sleep(5) + address = self.blockchain.key_to_address(self.config.mainnet_key) mint_txn = self.erc721.functions.mint(address, self.tokenId)\ .buildTransaction({ @@ -51,8 +50,6 @@ def _prepare(self): def _execute(self): - sleep(5) - self.agent.transfer_erc721_from_mainnet_to_schain( self.erc721, self.config.mainnet_key, diff --git a/test/test_cases/send_erc721_from_schain_to_mainnet.py b/test/test_cases/send_erc721_from_schain_to_mainnet.py index 67c7ea2b2..957ac7c4e 100644 --- a/test/test_cases/send_erc721_from_schain_to_mainnet.py +++ b/test/test_cases/send_erc721_from_schain_to_mainnet.py @@ -18,7 +18,7 @@ # You should have received a copy of the GNU Affero General Public License # along with SKALE IMA. If not, see . -from time import sleep, time +from time import sleep from logging import debug, error from tools.test_case import TestCase @@ -34,8 +34,10 @@ def __init__(self, config): super().__init__('Send ERC721 from schain to mainnet', config) def _prepare(self): - amount = 2 * 10 ** 18 - self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amount) + sleep( 5 ) + amountRecharge = 2 * 10 ** 18 + self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amountRecharge) + sleep( 5 ) # deploy token self.erc721 = self.blockchain.deploy_erc721_on_mainnet(self.config.mainnet_key, 'elv721', 'ELV') # mint @@ -44,25 +46,18 @@ def _prepare(self): .buildTransaction({ 'gas': 8000000, 'nonce': self.blockchain.get_transactions_count_on_mainnet(address)}) - # - sleep(5) - signed_txn = self.blockchain.web3_mainnet.eth.account\ .signTransaction(mint_txn, private_key=self.config.mainnet_key) - # - sleep(5) self.blockchain.web3_mainnet.eth.sendRawTransaction(signed_txn.rawTransaction) - self.blockchain.disableWhitelistERC721(self.config.mainnet_key, self.config.schain_name) self.blockchain.enableAutomaticDeployERC721(self.config.schain_key, "Mainnet") - sleep(5) # send to schain self.agent.transfer_erc721_from_mainnet_to_schain(self.erc721, self.config.mainnet_key, self.config.schain_key, self.token_id, self.timeout) - sleep(5) + sleep( 5 ) # amount_eth = 90 * 10 ** 15 # @@ -72,10 +67,7 @@ def _prepare(self): self.timeout) # - sleep(5) - - # - sleep(5) + sleep( 5 ) self.erc721_clone = self.blockchain.get_erc721_on_schain("Mainnet", self.erc721.address) def _execute(self): @@ -86,7 +78,7 @@ def _execute(self): error("Token was not send") return # - sleep(5) + sleep( 5 ) self.agent.transfer_erc721_from_schain_to_mainnet( self.erc721_clone, self.erc721, diff --git a/test/test_cases/send_ether_from_schain_to_mainnet.py b/test/test_cases/send_ether_from_schain_to_mainnet.py index c390a98c7..84b1e1732 100644 --- a/test/test_cases/send_ether_from_schain_to_mainnet.py +++ b/test/test_cases/send_ether_from_schain_to_mainnet.py @@ -23,6 +23,7 @@ from tools.test_case import TestCase from tools.test_pool import test_pool +from time import sleep class SendEtherToMainnet(TestCase): amount = 7 * 10 ** 16 # 60 finney @@ -33,8 +34,10 @@ def __init__(self, config): super().__init__('Send ether from schain to mainnet', config) def _prepare(self): - amount = 2 * 10 ** 18 - self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amount) + sleep( 5 ) + amountRecharge = 2 * 10 ** 18 + self.blockchain.recharge_user_wallet(self.config.mainnet_key, self.config.schain_name, amountRecharge) + sleep( 5 ) source_address = self.blockchain.key_to_address(self.config.schain_key) if self.blockchain.get_balance_on_schain(source_address) < self.amount: @@ -46,6 +49,7 @@ def _prepare(self): destination_address = self.blockchain.key_to_address(self.config.mainnet_key) if self.blockchain.get_balance_on_mainnet(destination_address) < min_transaction_fee: self.blockchain.send_ether_on_mainnet(self.config.mainnet_key, self.config.mainnet_key, min_transaction_fee) + sleep( 5 ) def _execute(self): source_address = self.blockchain.key_to_address(self.config.mainnet_key) @@ -64,12 +68,22 @@ def _execute(self): self.config.schain_key, self.amount, self.timeout) + sleep( 5 ) transaction_fee = 6 * 10 ** 16 approximate_gas_spends = 3 * 10 ** 15 - if self.blockchain.get_balance_on_mainnet(destination_address) > ( - balance + self.amount - transaction_fee - approximate_gas_spends): + extra_subtract_value = 1 * 10 ** 17 + + real_balance = self.blockchain.get_balance_on_mainnet(destination_address) + print( 'Real balance.......', real_balance ) + expected_balance = balance + self.amount - transaction_fee - approximate_gas_spends - extra_subtract_value + print( 'Expected balance...', expected_balance ) + + if real_balance > expected_balance: + print( 'Passed.............', 'YES!' ) self._mark_passed() + else: + print( 'Passed.............', 'NO(' ) -test_pool.register_test(SendEtherToMainnet) \ No newline at end of file +test_pool.register_test(SendEtherToMainnet) diff --git a/test/tools/blockchain.py b/test/tools/blockchain.py index 16f7c2147..4b0da570f 100644 --- a/test/tools/blockchain.py +++ b/test/tools/blockchain.py @@ -21,7 +21,7 @@ from web3 import Web3, HTTPProvider import json from eth_account import Account -import time +from time import sleep class BlockChain: config = None @@ -384,7 +384,7 @@ def await_receipt(web3, tx, retries=10, timeout=5): receipt = BlockChain.get_receipt(web3, tx) if (receipt != None): return receipt - time.sleep(timeout) + sleep( timeout ) return None @staticmethod diff --git a/test/tools/test_case.py b/test/tools/test_case.py index 6d4205577..cdf973e79 100644 --- a/test/tools/test_case.py +++ b/test/tools/test_case.py @@ -22,6 +22,7 @@ from proxy.deployer import Deployer from agent.agent import Agent from time import time +from logging import error class TestCase: name = None @@ -32,14 +33,16 @@ class TestCase: config = None time_started = time() timeout = None + timeout_of_entire_test = None - def __init__(self, name, config, timeout=80000): + def __init__(self, name, config, timeout=10, timeout_of_entire_test=80000): self.name = name self.deployer = Deployer(config) self.agent = Agent(config) self.blockchain = BlockChain(config) self.config = config self.timeout = timeout + self.timeout_of_entire_test = timeout_of_entire_test def prepare(self): @@ -52,6 +55,7 @@ def execute(self): self.time_started = time() self._execute() if self._timeout(): + error(f'CRITICAL INTEGRATION TEST ERROR: Test "{self.name}" will be marked failed due to timeout') self.passed = False def clean_up(self): @@ -79,7 +83,8 @@ def _mark_passed(self): self.passed = True def _timeout(self): - if self.timeout is not None and time() > self.time_started + self.timeout: + if self.timeout is not None and time() > self.time_started + self.timeout_of_entire_test: return True else: return False + return False diff --git a/test/tools/test_runner.py b/test/tools/test_runner.py index a8075a452..638ca0d36 100644 --- a/test/tools/test_runner.py +++ b/test/tools/test_runner.py @@ -57,6 +57,6 @@ def run(self): if test.is_passed(): info(f'Test "{test_name}" passed') else: - error(f'Test "{test_name}" failed') + error(f'CRITICAL INTEGRATION TEST ERROR: Test "{test_name}" failed') exit(1) info('All tests passed') diff --git a/test/tools/utils.py b/test/tools/utils.py index 87332b016..40d04a4df 100644 --- a/test/tools/utils.py +++ b/test/tools/utils.py @@ -27,5 +27,5 @@ def execute(command: str, print_command=False): print('Execute:', command) exit_code = system(command) if exit_code: - error(f'Command "{command}" failed with exit code {exit_code}') + error(f'CRITICAL INTEGRATION TEST ERROR: Command "{command}" failed with exit code {exit_code}') exit(1) diff --git a/yarn.lock b/yarn.lock index acb94225b..c6c30c9f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,23 +3,23 @@ "@babel/code-frame@^7.0.0": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" - integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: - "@babel/highlight" "^7.14.5" + "@babel/highlight" "^7.18.6" -"@babel/helper-validator-identifier@^7.14.5": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== +"@babel/helper-validator-identifier@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== -"@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== dependencies: - "@babel/helper-validator-identifier" "^7.14.5" + "@babel/helper-validator-identifier" "^7.18.6" chalk "^2.0.0" js-tokens "^4.0.0" @@ -56,9 +56,9 @@ ansi-escapes@^4.2.1: type-fest "^0.21.3" ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== ansi-regex@^5.0.1: version "5.0.1" @@ -86,31 +86,47 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -array-includes@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a" - integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A== +array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - get-intrinsic "^1.1.1" - is-string "^1.0.5" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + is-string "^1.0.7" -array.prototype.flat@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" - integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== +array.prototype.flat@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" + integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -188,7 +204,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" @@ -211,13 +227,6 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -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@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -226,9 +235,9 @@ debug@^3.2.7: ms "^2.1.1" debug@^4.0.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + 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" @@ -244,6 +253,14 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -268,36 +285,60 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2: - version "1.18.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" - integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" + integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== dependencies: + available-typed-arrays "^1.0.5" call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" function-bind "^1.1.1" - get-intrinsic "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.3" get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.4" + is-array-buffer "^3.0.1" + 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" - object-inspect "^1.11.0" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.2" object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" es-to-primitive@^1.2.1: version "1.2.1" @@ -311,28 +352,28 @@ es-to-primitive@^1.2.1: escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== eslint-config-standard@^14.1.1: version "14.1.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg== -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== +eslint-import-resolver-node@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" + integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== dependencies: debug "^3.2.7" - resolve "^1.20.0" + is-core-module "^2.11.0" + resolve "^1.22.1" -eslint-module-utils@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534" - integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q== +eslint-module-utils@^2.7.4: + version "2.7.4" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" + integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== dependencies: debug "^3.2.7" - pkg-dir "^2.0.0" eslint-plugin-es@^3.0.0: version "3.0.1" @@ -343,25 +384,25 @@ eslint-plugin-es@^3.0.0: regexpp "^3.0.0" eslint-plugin-import@^2.20.2: - version "2.24.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz#2c8cd2e341f3885918ee27d18479910ade7bb4da" - integrity sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q== + version "2.27.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" + integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== dependencies: - array-includes "^3.1.3" - array.prototype.flat "^1.2.4" - debug "^2.6.9" + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.6.2" - find-up "^2.0.0" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.7.4" has "^1.0.3" - is-core-module "^2.6.0" - minimatch "^3.0.4" - object.values "^1.1.4" - pkg-up "^2.0.0" - read-pkg-up "^3.0.0" - resolve "^1.20.0" - tsconfig-paths "^3.11.0" + is-core-module "^2.11.0" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.values "^1.1.6" + resolve "^1.22.1" + semver "^6.3.0" + tsconfig-paths "^3.14.1" eslint-plugin-node@^11.1.0: version "11.1.0" @@ -520,7 +561,7 @@ fast-json-stable-stringify@^2.0.0: fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== figures@^3.0.0: version "3.2.0" @@ -536,13 +577,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -557,6 +591,13 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -567,12 +608,27 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -581,6 +637,15 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.1.3: + 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-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -615,31 +680,62 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -graceful-fs@^4.1.2: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +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-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -654,11 +750,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -721,19 +812,23 @@ inquirer@^7.0.0: strip-ansi "^6.0.0" through "^2.3.6" -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +internal-slot@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" + integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== dependencies: - get-intrinsic "^1.1.0" + get-intrinsic "^1.1.3" has "^1.0.3" side-channel "^1.0.4" -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-array-buffer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" + integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-typed-array "^1.1.10" is-bigint@^1.0.1: version "1.0.4" @@ -750,12 +845,24 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-callable@^1.1.4, is-callable@^1.2.4: +is-callable@^1.1.3, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-callable@^1.1.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-core-module@^2.2.0, is-core-module@^2.6.0: +is-core-module@^2.11.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-core-module@^2.2.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== @@ -777,24 +884,31 @@ is-extglob@^2.1.1: is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== 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-glob@^4.0.0, is-glob@^4.0.1: +is-glob@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.2.tgz#859fc2e731e58c902f99fcabccb75a7dd07d29d8" integrity sha512-ZZTOjRcDjuAAAv2cTBQP/lL59ZTArx77+7UzHdWW/XB1mrfp7DEaVpKmZ0XIzx+M7AxfhKcqV+nMetUQmFifwg== dependencies: is-extglob "^2.1.1" -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-glob@^4.0.1, is-glob@^4.0.3: + 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-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-number-object@^1.0.4: version "1.0.6" @@ -811,6 +925,13 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -825,6 +946,24 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + 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" + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -843,11 +982,6 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - 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" @@ -868,29 +1002,11 @@ json5@^1.0.1: levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - lodash@^4.17.14, lodash@^4.17.19: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -908,22 +1024,29 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0, minimist@^1.2.5: +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + mkdirp@^0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "^1.2.5" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + minimist "^1.2.6" ms@2.1.2: version "2.1.2" @@ -950,17 +1073,12 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" +object-inspect@^1.12.2: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -object-inspect@^1.11.0, object-inspect@^1.9.0: +object-inspect@^1.9.0: version "1.11.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== @@ -970,24 +1088,24 @@ object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" object-keys "^1.1.1" -object.values@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" - integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg== +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" once@^1.3.0: version "1.4.0" @@ -1018,26 +1136,7 @@ optionator@^0.8.3: os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^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" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== parent-module@^1.0.0: version "1.0.1" @@ -1046,19 +1145,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - 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" @@ -1067,43 +1153,17 @@ path-is-absolute@^1.0.0: path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== -path-parse@^1.0.6: +path-parse@^1.0.6, 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-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== progress@^2.0.0: version "2.0.3" @@ -1115,22 +1175,14 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" regexpp@^2.0.1: version "2.0.1" @@ -1147,7 +1199,7 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.20.0: +resolve@^1.10.1: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -1155,6 +1207,15 @@ resolve@^1.10.0, resolve@^1.10.1, resolve@^1.20.0: is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^1.22.1: + 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" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -1182,17 +1243,26 @@ rxjs@^6.6.0: dependencies: tslib "^1.9.0" +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + "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== -"semver@2 || 3 || 4 || 5", semver@^5.5.0: +semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.1.0, semver@^6.1.2: +semver@^6.1.0, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -1200,14 +1270,14 @@ semver@^6.1.0, semver@^6.1.2: shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== side-channel@^1.0.4: version "1.0.4" @@ -1219,9 +1289,9 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" - integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== + 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== slice-ansi@^2.1.0: version "2.1.0" @@ -1232,36 +1302,10 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.10" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" - integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== string-width@^3.0.0: version "3.1.0" @@ -1281,21 +1325,23 @@ string-width@^4.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.20.4" strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" @@ -1335,6 +1381,11 @@ supports-color@^7.1.0: 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== + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -1353,7 +1404,7 @@ text-table@^0.2.0: through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== tmp@^0.0.33: version "0.0.33" @@ -1362,14 +1413,14 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tsconfig-paths@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" - integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA== +tsconfig-paths@^3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" + integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.1" - minimist "^1.2.0" + minimist "^1.2.6" strip-bom "^3.0.0" tslib@^1.9.0: @@ -1380,7 +1431,7 @@ tslib@^1.9.0: type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" @@ -1394,14 +1445,23 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" uri-js@^4.2.2: @@ -1416,14 +1476,6 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -1435,6 +1487,18 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + 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" + is-typed-array "^1.1.10" + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"