Repository: skalenetwork/IMA (language: python)

Issue:
Contracts release
The release of version `1.3.2` of smart contracts.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 74fb0a3e9..1347cef38 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -56,7 +56,9 @@ jobs:
         echo "Branch $BRANCH"
         export VERSION=$(bash ./scripts/calculate_version.sh)
         echo "VERSION=$VERSION" >> $GITHUB_ENV
-        echo "Version $VERSION"    
+        echo "Version $VERSION"
+        ( test $BRANCH = "stable" || test $BRANCH = "master" && export PRERELEASE=false ) || export PRERELEASE=true
+        echo "PRERELEASE=$PRERELEASE" >> $GITHUB_ENV
         echo ------------ download binaries
         LIB_BLS_RELEASE_TAG=${{ secrets.LIB_BLS_RELEASE_TAG }} bash ./scripts/download_binaries.sh
         export RELEASE=true
@@ -116,7 +118,7 @@ jobs:
         tag_name: ${{ env.VERSION }}
         release_name: ${{ env.VERSION }}
         draft: false
-        prerelease: true
+        prerelease: ${{ env.PRERELEASE }}
     
     - name: Upload Release Assets
       id: upload-release-assets
diff --git a/.gitignore b/.gitignore
index d6174759c..7b0773a12 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,7 +63,6 @@ npms/skale-ima/node_modules
 npms/skale-log/node_modules
 npms/skale-observer/node_modules
 npms/skale-owasp/node_modules
-npms/skale-cool-socket/node_modules
 
 # TypeScript v1 declaration files
 typings/
diff --git a/VERSION b/VERSION
index 3a3cd8cc8..1892b9267 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-1.3.1
+1.3.2
diff --git a/agent/CLI.md b/agent/CLI.md
deleted file mode 100644
index 9993fed6a..000000000
--- a/agent/CLI.md
+++ /dev/null
@@ -1,293 +0,0 @@
-<!-- SPDX-License-Identifier: (AGPL-3.0-only OR CC-BY-4.0) -->
-
-# IMA Command Line Interface
-
-**IMA** runs message transfer loop between **Ethereum(Main Net)** and **S-Chain**, also between assigned **S-Chain** and all connected to it other **S-Chains**. IMA also offers set of test tasks in its CLI.
-
-IMA operates with 3 types of chains:
-
-- **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.
-
-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.
-```
-
-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.
-
-**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.
-```
-
-**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.
-```
-
-**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.
-```
-
-**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 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.
-```
-
-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.
-```
-
-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:
-
-```
---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.
-```
-
-**Gas reumbursement** 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.
-```
-
-**Gas reumbursement** 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.
-
-**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).
-```
-
-**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.
-```
-
-**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.
-```
-
-**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.
-```
-
-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.
-```
diff --git a/agent/bls.js b/agent/bls.js
index 70541339a..72cb45352 100644
--- a/agent/bls.js
+++ b/agent/bls.js
@@ -864,15 +864,8 @@ async function do_sign_messages_impl(
         //     }
         // }
         //
-        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" );
+        details.write( strLogPrefix + cc.debug( "Will sign " ) + cc.info( jarrMessages.length ) + cc.debug( " message(s)..." ) + "\n" );
+        log.write( strLogPrefix + cc.debug( "Will sign " ) + cc.j( jarrMessages ) + cc.debug( " message(s)..." ) + "\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 );
@@ -891,32 +884,22 @@ async function do_sign_messages_impl(
         //     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" );
+        log.write( strLogPrefix + cc.debug( "Will collect " ) + cc.info( nCountOfBlsPartsToCollect ) + cc.debug( " signature(s)" ) + "\n" );
+        details.write( strLogPrefix + cc.debug( "Will 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( ")" ) +
-                cc.normal( ", " ) + cc.notice( "sequence ID" ) + cc.normal( " is " ) + cc.attention( sequence_id );
+                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 ) {
+            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";
+                        cc.error( " failed, RPC call was not created, error: " ) + cc.warning( err ) + "\n";
                     log.write( strErrorMessage );
                     details.write( strErrorMessage );
                     return;
@@ -953,21 +936,14 @@ async function do_sign_messages_impl(
                     // targetChainURL: targetChainURL
                 };
                 details.write(
-                    strLogPrefix + log.generate_timestamp_string( null, true ) + " " +
-                    cc.debug( "Will invoke " ) + cc.info( "skale_imaVerifyAndSign" ) +
+                    strLogPrefix + 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( {
+                await joCall.call( {
                     method: "skale_imaVerifyAndSign",
-                    params: joParams,
-                    qa: {
-                        skaled_no: 0 + i,
-                        sequence_id: "" + sequence_id,
-                        ts: "" + log.generate_timestamp_string( null, false )
-                    }
+                    params: joParams
                 }, async function( joIn, joOut, err ) {
                     ++joGatheringTracker.nCountReceived; // including errors
                     if( err ) {
@@ -975,21 +951,17 @@ async function do_sign_messages_impl(
                         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";
+                            cc.error( " failed, RPC call reported error: " ) + cc.warning( err ) + "\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" ) +
+                        strLogPrefix + 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;
@@ -997,18 +969,14 @@ async function do_sign_messages_impl(
                             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";
+                                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" ) +
-                                cc.error( ", " ) + cc.notice( "sequence ID" ) + cc.error( " is " ) + cc.attention( sequence_id ) +
-                                "\n";
+                                cc.error( " failed with " ) + cc.warning( "unknown wallet error" ) + "\n";
                             log.write( strErrorMessage );
                             details.write( strErrorMessage );
                         }
@@ -1062,9 +1030,7 @@ async function do_sign_messages_impl(
                                 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";
+                                    cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n";
                                 log.write( strErrorMessage );
                                 details.write( strErrorMessage );
                             }
@@ -1093,9 +1059,7 @@ async function do_sign_messages_impl(
                         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";
+                            cc.error( ", error is " ) + cc.warning( err.toString() ) + "\n";
                         log.write( strErrorMessage );
                         details.write( strErrorMessage );
                     }
@@ -1107,7 +1071,7 @@ async function do_sign_messages_impl(
         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() {
+            const iv = setInterval( async function() {
                 ++ joGatheringTracker.nWaitIntervalStepsDone;
                 cntSuccess = joGatheringTracker.nCountReceived - joGatheringTracker.nCountErrors;
                 if( cntSuccess >= nCountOfBlsPartsToCollect ) {
@@ -1166,7 +1130,7 @@ async function do_sign_messages_impl(
                 }
                 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 ) => {
+                    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() ) +
@@ -1183,7 +1147,7 @@ async function do_sign_messages_impl(
                 }
                 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 ) => {
+                    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: " ) +
@@ -1518,7 +1482,7 @@ async function do_sign_u256( u256, details, fn ) {
     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() {
+        const iv = setInterval( async function() {
             ++ joGatheringTracker.nWaitIntervalStepsDone;
             const cntSuccess = joGatheringTracker.nCountReceived - joGatheringTracker.nCountErrors;
             if( cntSuccess >= nCountOfBlsPartsToCollect ) {
@@ -1549,7 +1513,7 @@ async function do_sign_u256( u256, details, fn ) {
                 }
                 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 ) => {
+                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 );
@@ -1564,7 +1528,7 @@ async function do_sign_u256( u256, details, fn ) {
             }
             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 ) => {
+                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() ) +
@@ -1580,7 +1544,7 @@ async function do_sign_u256( u256, details, fn ) {
             }
             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 ) => {
+                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: " ) +
diff --git a/agent/cli.js b/agent/cli.js
index 1f7abf696..c999c74b2 100644
--- a/agent/cli.js
+++ b/agent/cli.js
@@ -405,9 +405,8 @@ function parse( joExternalHandlers, argv ) {
             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( "ORACLE GAS PRICE MANAGEMENT" ) + cc.info( " options:" ) );
+            console.log( soi + cc.debug( "--" ) + cc.bright( "ogp-mode" ) + cc.sunny( "=" ) + cc.note( "number" ) + cc.debug( "..............." ) + cc.notice( "Oracle gas price mode: " ) + cc.sunny( "0" ) + cc.notice( " - " ) + cc.error( "disable" ) + cc.debug( "(default)" ) + cc.notice( ", " ) + cc.sunny( "1" ) + cc.notice( " - " ) + cc.success( "enable" ) + cc.notice( " and invoke before message transfer loop." ) );
             //
             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." ) );
@@ -423,10 +422,8 @@ function parse( joExternalHandlers, argv ) {
             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( "gathered" ) + cc.debug( "......................" ) + cc.notice( "Print details of gathering data from command line arguments. " ) + cc.debug( "Default mode." ) );
             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 );
         }
@@ -1098,14 +1095,6 @@ function parse( joExternalHandlers, argv ) {
             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;
@@ -1181,12 +1170,9 @@ function parse( joExternalHandlers, argv ) {
             IMA.setEnabledProgressiveEventsScan( false );
             continue;
         }
-        if( joArg.name == "enable-oracle" ) {
-            IMA.setEnabledOracle( true );
-            continue;
-        }
-        if( joArg.name == "disable-oracle" ) {
-            IMA.setEnabledOracle( false );
+        if( joArg.name == "ogp-mode" ) {
+            owaspUtils.verifyArgumentIsInteger( joArg );
+            IMA.setOracleGasPriceMode( owaspUtils.toInteger( joArg.value ) );
             continue;
         }
         if( joArg.name == "s2s-forward" ) {
@@ -1234,9 +1220,8 @@ function parse( joExternalHandlers, argv ) {
     return 0;
 }
 
-function getWeb3FromURL( strURL, log ) {
+function getWeb3FromURL( strURL ) {
     let w3 = null;
-    log = log || { write: console.log };
     try {
         const u = cc.safeURL( strURL );
         const strProtocol = u.protocol.trim().toLowerCase().replace( ":", "" ).replace( "/", "" );
@@ -1488,7 +1473,7 @@ function ima_common_init() {
     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 );
+        imaState.w3_main_net = getWeb3FromURL( u );
     } else {
         log.write(
             cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "Main-net" ) +
@@ -1500,7 +1485,7 @@ function ima_common_init() {
     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 );
+        imaState.w3_s_chain = getWeb3FromURL( u );
     } else {
         log.write(
             cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S-Chain" ) +
@@ -1512,7 +1497,7 @@ function ima_common_init() {
     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 );
+        imaState.w3_t_chain = getWeb3FromURL( u );
     } else {
         log.write(
             cc.error( "WARNING:" ) + cc.warning( " No " ) + cc.note( "S<->S Target S-Chain" ) +
@@ -2004,7 +1989,6 @@ function ima_common_init() {
 
     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" );
@@ -2057,33 +2041,33 @@ function ima_common_init() {
         //
         //
         try {
-            ensure_have_value( "Main-net user account address", imaState.joAccount_main_net.address( imaState.w3_main_net ), false, isPrintGathered && isPrintSecurityValues );
+            ensure_have_value( "Main-net user account address", imaState.joAccount_main_net.address( imaState.w3_main_net ), false, isPrintGathered );
         } catch ( err ) {}
         try {
-            ensure_have_value( "S-chain user account address", imaState.joAccount_s_chain.address( imaState.w3_s_chain ), false, isPrintGathered && isPrintSecurityValues );
+            ensure_have_value( "S-chain user account address", imaState.joAccount_s_chain.address( imaState.w3_s_chain ), false, isPrintGathered );
         } 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 ) => {
+        // ensure_have_value( "Private key for main-net user account address", imaState.joAccount_main_net.privateKey, false, isPrintGathered, 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 ) => {
+        // ensure_have_value( "Private key for S-Chain user account address", imaState.joAccount_s_chain.privateKey, false, isPrintGathered, 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 ) => {
+        // ensure_have_value( "Private key for S<->S Target S-Chain user account address", imaState.joAccount_t_chain.privateKey, false, isPrintGathered, null, ( x ) => {
         //     return cc.attention( x );
         // } );
         //
         try {
-            ensure_have_chain_credentials( "Main Net", imaState.joAccount_main_net, false, isPrintGathered && isPrintSecurityValues );
+            ensure_have_chain_credentials( "Main Net", imaState.joAccount_main_net, false, isPrintGathered );
         } catch ( err ) {}
         try {
-            ensure_have_chain_credentials( "S-Chain", imaState.joAccount_s_chain, false, isPrintGathered && isPrintSecurityValues );
+            ensure_have_chain_credentials( "S-Chain", imaState.joAccount_s_chain, false, isPrintGathered );
         } catch ( err ) {}
         try {
-            ensure_have_chain_credentials( "S<->S Target S-Chain", imaState.joAccount_t_chain, false, isPrintGathered && isPrintSecurityValues );
+            ensure_have_chain_credentials( "S<->S Target S-Chain", imaState.joAccount_t_chain, false, isPrintGathered );
         } catch ( err ) {}
         //
         //
@@ -2149,7 +2133,7 @@ function ima_common_init() {
             return cc.info( x );
         } );
 
-        ensure_have_value( "Automatic exit(seconds)", imaState.nAutoExitAfterSeconds, false, isPrintGathered && isPrintSecurityValues );
+        ensure_have_value( "Automatic exit(seconds)", imaState.nAutoExitAfterSeconds, false, isPrintGathered );
 
         if( imaState.strLogFilePath.length > 0 ) {
             ensure_have_value( "Log file path", imaState.strLogFilePath, false, isPrintGathered, null, ( x ) => {
@@ -2246,7 +2230,7 @@ function ima_common_init() {
             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( "Oracle gas price mode is" ) + cc.debug( "............................." ) + cc.info( IMA.getOracleGasPriceMode() ) + "\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" );
diff --git a/agent/main.js b/agent/main.js
index 0b37c7ea9..1f3c13916 100644
--- a/agent/main.js
+++ b/agent/main.js
@@ -47,8 +47,6 @@ 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();
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -58,7 +56,6 @@ global.imaState = {
     "nLogMaxSizeBeforeRotation": -1,
     "nLogMaxFilesCount": -1,
     "isPrintGathered": true,
-    "isPrintSecurityValues": false,
 
     "bIsNeededCommonInit": true,
     "bSignMessages": false, // use BLS message signing, turned on with --sign-messages
@@ -257,7 +254,7 @@ global.imaState = {
 
     "optsPendingTxAnalysis": {
         "isEnabled": false, // disable bv default
-        "nTimeoutSecondsBeforeSecondAttempt": 3, // 0 - disable 2nd attempt
+        "nTimeoutSecondsBeforeSecondAttempt": 30, // 0 - disable 2nd attempt
         "isIgnore": false, // ignore PTX result
         "isIgnore2": true // ignore secondary PTX result
     },
@@ -314,7 +311,7 @@ const fnInitActionSkaleNetworkScanForS2S = function() {
                 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
+            log.write( strLogPrefix + cc.normal( "Downloading SKALE network information " ) + cc.normal( "..." ) + "\n" ); // just print value
             const opts = {
                 imaState: imaState,
                 "details": log,
@@ -322,26 +319,24 @@ const fnInitActionSkaleNetworkScanForS2S = function() {
                 "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,
-            //     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" );
+            const strError = await skale_observer.cache_schains(
+                imaState.strChainName_s_chain, // strChainNameConnectedTo
+                imaState.w3_main_net,
+                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" );
             await skale_observer.periodic_caching_start(
                 imaState.strChainName_s_chain, // strChainNameConnectedTo
                 imaState.w3_main_net,
                 addressFrom,
                 opts
             );
-            log.write( strLogPrefix + cc.success( "Done, did started periodic S-Chains caching." ) + "\n" );
             return true;
         }
     } );
@@ -1457,7 +1452,7 @@ imaCLI.parse( {
                     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
+                log.write( strLogPrefix + cc.normal( "Downloading SKALE network information " ) + cc.normal( "..." ) + "\n" ); // just print value
                 const opts = {
                     imaState: imaState,
                     "details": log,
@@ -1480,7 +1475,7 @@ imaCLI.parse( {
                     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
+                log.write( strLogPrefix + cc.normal( "Downloading SKALE network information " ) + cc.normal( "..." ) + "\n" ); // just print value
 
                 const opts = {
                     imaState: imaState,
@@ -1754,11 +1749,8 @@ async function continue_schain_discovery_in_background_if_needed( isSilent ) {
         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;
+    g_timer_s_chain_discovery = setInterval( async function() {
         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;
@@ -1768,7 +1760,7 @@ async function continue_schain_discovery_in_background_if_needed( isSilent ) {
             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" );
+                    cc.notice( cntDiscovered ) + cc.info( " node(s) already discovered..." ) + "\n" );
             }
             await discover_s_chain_network( function( err, joSChainNetworkInfo ) {
                 if( ! err ) {
@@ -1776,14 +1768,14 @@ async function continue_schain_discovery_in_background_if_needed( isSilent ) {
                     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( ")" );
+                            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 (" );
+                                cc.info( cntStillUnknown ) + cc.success( " of " ) + cc.info( cntNodes ) +
+                                cc.success( " still unknown (" );
                             try {
                                 const jarrNodes = joSChainNetworkInfo.network;
                                 let cntBad = 0;
@@ -1791,13 +1783,13 @@ async function continue_schain_discovery_in_background_if_needed( isSilent ) {
                                     const joNode = jarrNodes[i];
                                     try {
                                         if( ! ( joNode && "imaInfo" in joNode && typeof joNode.imaInfo === "object" &&
-                                                "t" in joNode.imaInfo && typeof joNode.imaInfo.t === "number" ) ) {
+                                            "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( ")" );
+                                                cc.notice( "#" ) + cc.info( i ) +
+                                                cc.attention( "(" ) + cc.u( strNodeURL ) + cc.attention( ")" );
                                             strMessage += strNodeDescColorized;
                                             ++ cntBad;
                                         }
@@ -1808,8 +1800,8 @@ async function continue_schain_discovery_in_background_if_needed( isSilent ) {
                         }
                         if( ! isSilent ) {
                             strMessage +=
-                                    cc.success( ", complete re-discovered S-Chain network info: " ) +
-                                    cc.j( joSChainNetworkInfo );
+                                cc.success( ", complete re-discovered S-Chain network info: " ) +
+                                cc.j( joSChainNetworkInfo );
                         }
                         log.write( strMessage + "\n" );
                     }
@@ -1819,17 +1811,12 @@ async function 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"
+                    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 );
 }
 
@@ -2186,8 +2173,8 @@ if( imaState.nMonitoringPort > 0 ) {
                     } 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 );
+                    // answer: { "id": 1, "method": "get_last_transfer_errors", "error": null, "last_transfer_errors": [ { ts: ..., textLog: ... }, ... ] }
+                    joAnswer.last_transfer_errors = IMA.get_last_transfer_errors();
                     joAnswer.last_error_categories = IMA.get_last_error_categories();
                     break;
                 default:
@@ -2454,10 +2441,10 @@ async function single_transfer_loop() {
             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" );
+        if( IMA.getOracleGasPriceMode() == 1 ) {
             b0 = IMA.do_oracle_gas_price_setup(
                 imaState.w3_main_net,
                 imaState.w3_s_chain,
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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @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/package.json b/agent/package.json
index c0f40499b..a6ce83b34 100644
--- a/agent/package.json
+++ b/agent/package.json
@@ -4,17 +4,15 @@
     "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": "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"
     },
     "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",
+        "ethereumjs-util": "^7.1.3",
         "web3": "^1.6.1",
         "uuid": "8.3.2",
-        "ws": "^8.6.0",
+        "ws": "^8.4.0",
         "urllib": "2.38.0",
         "sha3": "2.1.4",
         "shelljs": "^0.8.5"
diff --git a/agent/rpc-call.js b/agent/rpc-call.js
index 2b83e2ae5..f6bcfe98d 100644
--- a/agent/rpc-call.js
+++ b/agent/rpc-call.js
@@ -62,11 +62,7 @@ async function wait_web_socket_is_open( socket, fnDone, fnStep ) {
     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;
+        const iv = setInterval( async function() {
             if( socket.readyState === 1 ) {
                 // console.log( "Connection is made" )
                 clearInterval( iv );
@@ -78,15 +74,6 @@ async function wait_web_socket_is_open( socket, fnDone, fnStep ) {
                     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 ] );
@@ -121,10 +108,7 @@ async function do_connect( joCall, opts, fn ) {
                 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 );
                 }
             } );
@@ -185,9 +169,7 @@ async function do_call( joCall, joIn, fn ) {
             out: null
         };
         joCall.mapPendingByCallID[joIn.id] = entry;
-        entry.iv = setTimeout( function() {
-            clearTimeout( entry.iv );
-            entry.iv = null;
+        entry.out = setTimeout( function() {
             delete joCall.mapPendingByCallID[joIn.id];
         }, 20 * 1000 );
         joCall.wsConn.send( JSON.stringify( joIn ) );
diff --git a/agent/run.sh b/agent/run.sh
index 56c190205..4149381b5 100644
--- a/agent/run.sh
+++ b/agent/run.sh
@@ -109,9 +109,7 @@ BASE_OPTIONS="--gas-price-multiplier=$GAS_PRICE_MULTIPLIER \
 --time-framing=$TIME_FRAMING \
 --tm-url-main-net=$TM_URL_MAIN_NET \
 --time-gap=$TIME_GAP \
---monitoring-port=$MONITORING_PORT \
---ptx \
---ptx-attempt=3 "
+--monitoring-port=$MONITORING_PORT"
 
 echo "Base options:"
 echo "$BASE_OPTIONS"
diff --git a/agent/yarn.lock b/agent/yarn.lock
index 47f6d1b9e..0e786c078 100644
--- a/agent/yarn.lock
+++ b/agent/yarn.lock
@@ -1192,17 +1192,6 @@ ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3:
     ethereum-cryptography "^0.1.3"
     rlp "^2.2.4"
 
-ethereumjs-util@^7.1.4:
-  version "7.1.4"
-  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458"
-  integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==
-  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"
@@ -2407,7 +2396,7 @@ 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:
+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=
@@ -3803,10 +3792,10 @@ ws@^3.0.0:
     safe-buffer "~5.1.0"
     ultron "~1.1.0"
 
-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.4.0:
+  version "8.4.0"
+  resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.0.tgz#f05e982a0a88c604080e8581576e2a063802bed6"
+  integrity sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==
 
 xhr-request-promise@^0.1.2:
   version "0.1.3"
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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @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/event_dispatcher.js
deleted file mode 100644
index 43e9e5f30..000000000
--- a/npms/skale-cool-socket/event_dispatcher.js
+++ /dev/null
@@ -1,115 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @file event_dispatcher.js
- * @copyright SKALE Labs 2019-Present
- */
-
-class UniversalDispatcherEvent {
-    constructor( type, jo ) {
-        this.type = type;
-        for( const [ key, value ] of Object.entries( jo ) ) {
-            if( key in this ) {
-                console.warn( "UniversalDispatcherEvent will skip", key, "data field" );
-                continue;
-            }
-            this[key] = value;
-        }
-    }
-};
-
-class EventDispatcher {
-    // see https://stackoverflow.com/questions/36675693/eventtarget-interface-in-safari
-    constructor() {
-        this._listeners = [];
-        this.isDisposed = false;
-        this.isDisposing = false;
-    }
-    dispose() {
-        if( this.isDisposed )
-            return;
-        this.isDisposing = true;
-        this.isDisposed = true;
-        this.dispatchEvent( new UniversalDispatcherEvent( "dispose", { detail: { ref: this } } ) );
-        this.removeAllEventListeners();
-    }
-    hasEventListener( type, listener ) {
-        return this._listeners.some( item => item.type === type && item.listener === listener );
-    }
-    addEventListener( type, listener ) {
-        if( ! this.hasEventListener( type, listener ) ) {
-            this._listeners.push( {
-                type,
-                listener,
-                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 );
-            if( index >= 0 ) {
-                this._listeners.splice( index, 1 );
-                continue;
-            }
-            break;
-        }
-        // console.log( `${this}-listeners:`, this._listeners );
-        return this;
-    }
-    removeAllEventListeners() {
-        this._listeners = [];
-        return this;
-    }
-    on( type, listener ) {
-        return this.addEventListener( type, listener );
-    }
-    off( type, listener ) {
-        return this.removeEventListener( type, listener );
-    }
-    offAll() {
-        return this.removeAllEventListeners();
-    }
-    dispatchEvent( evt ) {
-        const a = this._listeners.filter( item => item.type === evt.type );
-        for( const item of a ) {
-            const {
-                type,
-                listener,
-                options: { once }
-            } = item;
-            listener.call( this, evt );
-            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
deleted file mode 100644
index e05e2f54a..000000000
--- a/npms/skale-cool-socket/package.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
-    "name": "skale-cool-socket",
-    "version": "1.2.3",
-    "description": "Cool socket implementation for direct, local, worker thread, web socket, web RTC connections",
-    "main": "test.js",
-    "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"
-    },
-    "keywords": [
-        "cool",
-        "socket",
-        "worker",
-        "thread",
-        "ws",
-        "wss",
-        "webrtc"
-    ],
-    "dependencies": {
-        "connect": "^3.7.0",
-        "serve-static": "^1.14.1",
-        "ws": "^8.6.0"
-    },
-    "devDependencies": {
-        "eslint": "^6.8.0",
-        "eslint-config-standard": "^14.1.1",
-        "eslint-plugin-import": "^2.20.2",
-        "eslint-plugin-node": "^11.1.0",
-        "eslint-plugin-promise": "^4.2.1",
-        "eslint-plugin-standard": "^4.0.1"
-    }
-}
diff --git a/npms/skale-cool-socket/server.js b/npms/skale-cool-socket/server.js
deleted file mode 100644
index d4335a472..000000000
--- a/npms/skale-cool-socket/server.js
+++ /dev/null
@@ -1,141 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @file server.js
- * @copyright SKALE Labs 2019-Present
- */
-
-const { EventDispatcher, UniversalDispatcherEvent } = require( "./event_dispatcher.js" );
-const utils = require( "./utils.js" );
-
-class Server extends EventDispatcher {
-    constructor( acceptor ) {
-        super();
-        if( acceptor == null || acceptor == undefined || typeof acceptor != "object" )
-            throw new Error( "Cannot create server on bad acceptor" );
-        const self = this;
-        self.log = console.log;
-        self.acceptor = acceptor;
-        self.mapApiHandlers = {};
-        self.mapAcceptedPipes = { };
-        self.isLogAcceptedSocket = false;
-        self.isLogSocketErrors = true;
-        self.isLogSocketTraffic = false;
-        self.isLogSocketTrafficRaw = false;
-        acceptor.on( "connection", function( eventData ) {
-            const socket = eventData.socket;
-            if( ( ! ( "remoteAddress" in eventData ) ) || eventData.remoteAddress == null || eventData.remoteAddress == undefined )
-                socket.strSavedRemoteAddress = socket.constructor.name;
-            else
-                socket.strSavedRemoteAddress = "" + eventData.remoteAddress;
-            if( self.isLogAcceptedSocket )
-                self.log( "New server connection \"" + socket.strSavedRemoteAddress + "\"" );
-            self.mapAcceptedPipes[socket] = { };
-            let _offAllPipeEventListeners = null;
-            let _onPipeClose = function() {
-                if( self.isLogAcceptedSocket )
-                    self.log( "Accepted socket closed \"" + socket.strSavedRemoteAddress + "\"" );
-                if( _offAllPipeEventListeners ) {
-                    _offAllPipeEventListeners();
-                    _offAllPipeEventListeners = null;
-                }
-                delete self.mapAcceptedPipes[socket];
-            };
-            let _onPipeError = function( eventData ) {
-                if( self.isLogSocketErrors )
-                    self.log( "Socket error \"" + socket.strSavedRemoteAddress + "\"" );
-                if( _offAllPipeEventListeners ) {
-                    _offAllPipeEventListeners();
-                    _offAllPipeEventListeners = null;
-                }
-                delete self.mapAcceptedPipes[socket];
-            };
-            let _onPipeMessage = function( 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 );
-                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 );
-                        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 );
-                        isFlush = true;
-                    }
-                } catch ( err ) {
-                    if( self.isLogSocketErrors )
-                        self.log( "Server method", joMessage.method, "RPC exception:", err );
-                    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 );
-                    } else {
-                        if( self.isLogSocketTraffic )
-                            self.log( "Accepted socket \"" + socket.strSavedRemoteAddress + " answer", joAnswer );
-                    }
-                    socket.send( joAnswer, isFlush );
-                }
-            };
-            _offAllPipeEventListeners = function() {
-                if( _onPipeClose ) {
-                    socket.off( "close", _onPipeClose );
-                    _onPipeClose = null;
-                }
-                if( _onPipeError ) {
-                    socket.off( "error", _onPipeError );
-                    _onPipeError = null;
-                }
-                if( _onPipeMessage ) {
-                    socket.off( "message", _onPipeMessage );
-                    _onPipeMessage = null;
-                }
-                socket.disposeImpersonatedEntries();
-            };
-            socket.on( "close", _onPipeClose );
-            socket.on( "error", _onPipeError );
-            socket.on( "message", _onPipeMessage );
-        } );
-        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/settings.js
deleted file mode 100644
index ca1e6215c..000000000
--- a/npms/skale-cool-socket/settings.js
+++ /dev/null
@@ -1,197 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @file settings.js
- * @copyright SKALE Labs 2019-Present
- */
-
-const settings = {
-    rtcSpace: {
-        defaultSpaceName: "default space",
-        defaultSpaceCategory: "default category"
-    },
-    net: {
-        hostname: "localhost",
-        secure: false,
-        ports: {
-            http: 8080, // 80, 443, 8080
-            ws: 17171,
-            signaling: 17172
-        },
-        pipe: {
-            maxAccumulatedMessagesCount: 30
-        },
-        ws: {
-            client: {
-                reconnectAfterMilliseconds: 100
-            }
-        },
-        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/yetithefoot/7592580
-                // 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",
-                "stun:stun.4.google.com:19302",
-                "stun:stun.5.google.com:19302", // where is the end?
-                "stun:stun.l.google.com:19302",
-                "stun:stun1.l.google.com:19302",
-                "stun:stun2.l.google.com:19302",
-                "stun:stun3.l.google.com:19302",
-                "stun:stun4.l.google.com:19302",
-                "stun:stun5.l.google.com:19302", // where is the end?
-                "stun:stun.gmx.net",
-                "stun:stun.sipgate.net",
-                "stun:stun.sipgate.net:10000",
-                "stun:stun.phoneserve.com",
-                "stun:stun.counterpath.net",
-                "stun:stun.12connect.com:3478",
-                "stun:stun.xten.com",
-                "stun:stun01.sipphone.com",
-                "stun:stun.ekiga.net",
-                "stun:stun.fwdnet.net",
-                "stun:stun.ideasip.com",
-                "stun:stun.iptel.org",
-                "stun:stun.schlund.de",
-                "stun:stun.voiparound.com",
-                "stun:stun.voipbuster.com",
-                "stun:stun.voipstunt.com",
-                "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).
-            },
-            peerAdditionalOptions: {
-                optional: [ { DtlsSrtpKeyAgreement: true } ]
-            },
-            dataChannel: {
-                label: "genericDataChannel",
-                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
-            offerDiscovery: {
-                periodMilliseconds: 1000,
-                stepCount: 20
-            },
-            fastPublishMode: {
-                serverPeer: true,
-                joiner: true
-            }
-        }
-    },
-    logging: {
-        net: {
-            socket: {
-                flush: false,
-                flushOne: false,
-                flushBlock: false,
-                flushCount: false,
-                flushMethodStats: false,
-                accumulate: false,
-                send: false,
-                receive: false,
-                receiveBlock: false,
-                receiveCount: false,
-                receiveMethodStats: false
-            },
-            signaling: {
-                generic: false,
-                connect: true,
-                disconnect: true,
-                error: true,
-                rawMessage: false,
-                message: false,
-                impersonate: false,
-                publishOffer: false,
-                objectLifetime: true,
-                offer: false,
-                answer: false,
-                localDescription: false,
-                remoteDescription: false,
-                candidate: false,
-                candidateWalk: false,
-                publishTimeout: true,
-                signalingNegotiationTimeout: true,
-                offerDiscoveryStepFail: true,
-                offerRegister: false,
-                offerUnregister: false,
-                offerSkipPublishedAnswer: false,
-                creatorImpersonationComplete: false
-            },
-            rtc: {
-                generic: false,
-                error: true,
-                closePeer: true,
-                closeDataChannel: true,
-                iceConnectionStateChange: false,
-                iceConnectionStateName: false,
-                iceGatheringStateChange: false,
-                iceGatheringStateName: false,
-                iceIceIdentifyResult: false,
-                iceSignalingStateChange: false,
-                iceNegotiationNeeded: false
-            },
-            server: {
-                connect: true,
-                disconnect: true,
-                error: true,
-                rawMessage: false,
-                message: false,
-                impersonate: true,
-                weaponShot: false,
-                collisionDetection: true
-            },
-            client: {
-                space: { attach: true, detach: true },
-                connect: true,
-                disconnect: true,
-                error: true,
-                rawMessage: false,
-                message: false,
-                impersonate: true
-            },
-            relay: {
-                connect: true,
-                disconnect: true,
-                error: true,
-                rawMessage: false,
-                message: false
-            }
-        }
-    }
-};
-
-module.exports = {
-    settings: settings
-};
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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @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/utils.js b/npms/skale-cool-socket/utils.js
deleted file mode 100644
index 270b57c68..000000000
--- a/npms/skale-cool-socket/utils.js
+++ /dev/null
@@ -1,253 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @file utils.js
- * @copyright SKALE Labs 2019-Present
- */
-
-const { settings } = require( "./settings.js" );
-
-const uuid_v4 = 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 ) {
-    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 ) );
-};
-
-const randomStringABC = function( length, arrCharacters ) {
-    length = parseInt( length, 10 );
-    if( length <= 0 || arrCharacters.length == 0 )
-        return "";
-    let s = "";
-    for( let i = 0; i < length; ++i )
-        s += arrCharacters.charAt( Math.floor( Math.random() * arrCharacters.length ) );
-    return s;
-};
-
-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 );
-    let arrCharacters = "";
-    if( isABC )
-        arrCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-    if( isDigits )
-        arrCharacters += "0123456789";
-    if( isSpecChr )
-        arrCharacters += "(){}[]~!?@#$%^&*_+-='\"/\\";
-    if( isPunctuation )
-        arrCharacters += ",.:;";
-    if( arrCharacters.length == 0 )
-        return "";
-    return randomStringABC( length, arrCharacters );
-};
-
-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 ) {
-    return str.replace( new RegExp( find, "g" ), replace );
-};
-
-const simpleEscapeString = function( s ) {
-    if( s == null || s == undefined || typeof s != "string" )
-        return s;
-    s = replaceAll( s, "&", "&amp;" );
-    s = replaceAll( s, "<", "&lt;" );
-    s = replaceAll( s, ">", "&gt;" );
-    s = replaceAll( s, " ", "&nbsp;" );
-    return s;
-};
-
-const abstractUniqueID = function() {
-    const id = replaceAll( uuid_v4(), "-", "" ).toLowerCase();
-    return id;
-};
-
-const isEven = function( n ) {
-    return n % 2 == 0;
-};
-const isOdd = function( n ) {
-    return Math.abs( n % 2 ) == 1;
-};
-
-const g_nCallIdDigits = 10;
-const randomCallID = function() {
-    const id = randomHexString( g_nCallIdDigits );
-    return id;
-};
-
-const g_nDirectPipeIdDigits = 10;
-const randomDirectPipeID = function() {
-    const id = randomHexString( g_nDirectPipeIdDigits );
-    return id;
-};
-
-const bind_scope_to_function = function( scope, fn ) {
-    return function() {
-        fn.apply( scope, arguments );
-    };
-};
-
-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
-    };
-    return joAnswer;
-};
-
-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
-    );
-};
-
-const zero_padding_left = function( val, cntCharsNeeded ) {
-    if( val == null || val == undefined )
-        return val;
-    let s = "" + val;
-    while( s.length < cntCharsNeeded )
-        s = "0" + s;
-    return s;
-};
-const zero_padding_right = function( val, cntCharsNeeded ) {
-    if( val == null || val == undefined )
-        return val;
-    let s = "" + val;
-    while( s.length < cntCharsNeeded )
-        s = s + "0";
-    return s;
-};
-
-const parse_date_time = function( ts ) {
-    if( ts === null || ts === undefined )
-        return ts;
-    if( typeof ts != "string" )
-        return null;
-    // example:
-    //  0----|----1----|----2----|----
-    //  012345678901234567890123456789
-    // "2020/03/19-19:42:55.663"
-    const year = parseInt( ts.substring( 0, 4 ), 10 );
-    const month = parseInt( ts.substring( 5, 7 ), 10 ) + 1;
-    const day = parseInt( ts.substring( 8, 10 ), 10 );
-    const hour = parseInt( ts.substring( 11, 13 ), 10 );
-    const minute = parseInt( ts.substring( 14, 16 ), 10 );
-    const second = parseInt( ts.substring( 17, 19 ), 10 );
-    let millisecond = ts.substring( 20 );
-    if( millisecond.length > 3 )
-        millisecond = millisecond.substring( 0, 3 );
-    else {
-        while( millisecond.length < 3 )
-            millisecond = "0" + millisecond;
-    }
-    millisecond = parseInt( millisecond, 10 );
-    const u = Date.UTC( year, month, day, hour, minute, second, millisecond );
-    const d = new Date( u );
-    d.setMilliseconds( millisecond );
-    return d;
-};
-const format_date_time = function( dt, isDate, isTime, isMilliseconds, sepDate, sepTime, sepBetween, sepMilliseconds ) {
-    if( dt === null )
-        return "null-date-time";
-    if( dt === undefined )
-        return "undefined-date-time";
-    if( ! ( dt instanceof Date ) )
-        return "not-a-date-time";
-    isDate = ( isDate == null || isDate == undefined ) ? true : ( isDate ? true : false );
-    isTime = ( isTime == null || isTime == undefined ) ? true : ( isTime ? true : false );
-    if( ( !isDate ) && ( !isTime ) )
-        return "";
-    let s = "";
-    if( isDate ) {
-        sepDate = ( sepDate == null || sepDate == undefined || ( typeof sepDate != "string" ) ) ? "/" : sepDate;
-        const strDate = "" +
-            zero_padding_left( dt.getFullYear(), 4 ) +
-            sepDate +
-            zero_padding_left( dt.getMonth() + 1, 2 ) +
-            sepDate +
-            zero_padding_left( dt.getDate(), 2 );
-        s += strDate;
-    }
-    if( isTime ) {
-        sepTime = ( sepTime == null || sepTime == undefined || ( typeof sepTime != "string" ) ) ? ":" : sepTime;
-        if( isDate ) {
-            sepBetween = ( sepBetween == null || sepBetween == undefined || ( typeof sepBetween != "string" ) ) ? "-" : sepBetween;
-            s += sepBetween;
-        }
-        let strTime = "" +
-            zero_padding_left( dt.getHours(), 2 ) +
-            sepDate +
-            zero_padding_left( dt.getMinutes(), 2 ) +
-            sepDate +
-            zero_padding_left( 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 );
-        }
-        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/yarn.lock b/npms/skale-cool-socket/yarn.lock
deleted file mode 100644
index 71b02d8b2..000000000
--- a/npms/skale-cool-socket/yarn.lock
+++ /dev/null
@@ -1,1510 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@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==
-  dependencies:
-    "@babel/highlight" "^7.16.7"
-
-"@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/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==
-  dependencies:
-    "@babel/helper-validator-identifier" "^7.16.7"
-    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=
-
-acorn-jsx@^5.2.0:
-  version "5.3.2"
-  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
-  integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-
-acorn@^7.1.1:
-  version "7.4.1"
-  resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
-  integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
-
-ajv@^6.10.0, ajv@^6.10.2:
-  version "6.12.6"
-  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
-  integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
-  dependencies:
-    fast-deep-equal "^3.1.1"
-    fast-json-stable-stringify "^2.0.0"
-    json-schema-traverse "^0.4.1"
-    uri-js "^4.2.2"
-
-ansi-escapes@^4.2.1:
-  version "4.3.2"
-  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
-  integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
-  dependencies:
-    type-fest "^0.21.3"
-
-ansi-regex@^4.1.0:
-  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"
-  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
-  integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-
-ansi-styles@^3.2.0, ansi-styles@^3.2.1:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
-  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
-  dependencies:
-    color-convert "^1.9.0"
-
-ansi-styles@^4.1.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
-  integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
-  dependencies:
-    color-convert "^2.0.1"
-
-argparse@^1.0.7:
-  version "1.0.10"
-  resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
-  integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
-  dependencies:
-    sprintf-js "~1.0.2"
-
-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==
-  dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.1.3"
-    es-abstract "^1.19.1"
-    get-intrinsic "^1.1.1"
-    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==
-  dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.1.3"
-    es-abstract "^1.19.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==
-
-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==
-
-brace-expansion@^1.1.7:
-  version "1.1.11"
-  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
-  integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
-  dependencies:
-    balanced-match "^1.0.0"
-    concat-map "0.0.1"
-
-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"
-
-callsites@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
-  integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-
-chalk@^2.0.0, chalk@^2.1.0:
-  version "2.4.2"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
-  integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
-  dependencies:
-    ansi-styles "^3.2.1"
-    escape-string-regexp "^1.0.5"
-    supports-color "^5.3.0"
-
-chalk@^4.1.0:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
-  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
-  dependencies:
-    ansi-styles "^4.1.0"
-    supports-color "^7.1.0"
-
-chardet@^0.7.0:
-  version "0.7.0"
-  resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
-  integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
-
-cli-cursor@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
-  integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
-  dependencies:
-    restore-cursor "^3.1.0"
-
-cli-width@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
-  integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
-
-color-convert@^1.9.0:
-  version "1.9.3"
-  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
-  integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
-  dependencies:
-    color-name "1.1.3"
-
-color-convert@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
-  integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
-  dependencies:
-    color-name "~1.1.4"
-
-color-name@1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
-  integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-
-color-name@~1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
-  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-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=
-
-connect@^3.7.0:
-  version "3.7.0"
-  resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
-  integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
-  dependencies:
-    debug "2.6.9"
-    finalhandler "1.1.2"
-    parseurl "~1.3.3"
-    utils-merge "1.0.1"
-
-cross-spawn@^6.0.5:
-  version "6.0.5"
-  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
-  integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
-  dependencies:
-    nice-try "^1.0.4"
-    path-key "^2.0.1"
-    semver "^5.5.0"
-    shebang-command "^1.2.0"
-    which "^1.2.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==
-  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"
-  integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
-  dependencies:
-    ms "^2.1.1"
-
-debug@^4.0.1:
-  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"
-
-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==
-
-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"
-
-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.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
-  integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
-
-doctrine@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
-  integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
-  dependencies:
-    esutils "^2.0.2"
-
-doctrine@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
-  integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
-  dependencies:
-    esutils "^2.0.2"
-
-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=
-
-emoji-regex@^7.0.1:
-  version "7.0.3"
-  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
-  integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-
-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=
-
-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==
-  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.3"
-    internal-slot "^1.0.3"
-    is-callable "^1.2.4"
-    is-negative-zero "^2.0.2"
-    is-regex "^1.1.4"
-    is-shared-array-buffer "^1.0.1"
-    is-string "^1.0.7"
-    is-weakref "^1.0.2"
-    object-inspect "^1.12.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"
-
-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=
-
-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=
-
-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==
-  dependencies:
-    debug "^3.2.7"
-    resolve "^1.20.0"
-
-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==
-  dependencies:
-    debug "^3.2.7"
-    find-up "^2.1.0"
-
-eslint-plugin-es@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893"
-  integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==
-  dependencies:
-    eslint-utils "^2.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==
-  dependencies:
-    array-includes "^3.1.4"
-    array.prototype.flat "^1.2.5"
-    debug "^2.6.9"
-    doctrine "^2.1.0"
-    eslint-import-resolver-node "^0.3.6"
-    eslint-module-utils "^2.7.3"
-    has "^1.0.3"
-    is-core-module "^2.8.1"
-    is-glob "^4.0.3"
-    minimatch "^3.1.2"
-    object.values "^1.1.5"
-    resolve "^1.22.0"
-    tsconfig-paths "^3.14.1"
-
-eslint-plugin-node@^11.1.0:
-  version "11.1.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d"
-  integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==
-  dependencies:
-    eslint-plugin-es "^3.0.0"
-    eslint-utils "^2.0.0"
-    ignore "^5.1.1"
-    minimatch "^3.0.4"
-    resolve "^1.10.1"
-    semver "^6.1.0"
-
-eslint-plugin-promise@^4.2.1:
-  version "4.3.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45"
-  integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ==
-
-eslint-plugin-standard@^4.0.1:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz#0c3bf3a67e853f8bbbc580fb4945fbf16f41b7c5"
-  integrity sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ==
-
-eslint-scope@^5.0.0:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
-  integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
-  dependencies:
-    esrecurse "^4.3.0"
-    estraverse "^4.1.1"
-
-eslint-utils@^1.4.3:
-  version "1.4.3"
-  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
-  integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
-  dependencies:
-    eslint-visitor-keys "^1.1.0"
-
-eslint-utils@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
-  integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
-  dependencies:
-    eslint-visitor-keys "^1.1.0"
-
-eslint-visitor-keys@^1.1.0:
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
-  integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
-
-eslint@^6.8.0:
-  version "6.8.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb"
-  integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==
-  dependencies:
-    "@babel/code-frame" "^7.0.0"
-    ajv "^6.10.0"
-    chalk "^2.1.0"
-    cross-spawn "^6.0.5"
-    debug "^4.0.1"
-    doctrine "^3.0.0"
-    eslint-scope "^5.0.0"
-    eslint-utils "^1.4.3"
-    eslint-visitor-keys "^1.1.0"
-    espree "^6.1.2"
-    esquery "^1.0.1"
-    esutils "^2.0.2"
-    file-entry-cache "^5.0.1"
-    functional-red-black-tree "^1.0.1"
-    glob-parent "^5.0.0"
-    globals "^12.1.0"
-    ignore "^4.0.6"
-    import-fresh "^3.0.0"
-    imurmurhash "^0.1.4"
-    inquirer "^7.0.0"
-    is-glob "^4.0.0"
-    js-yaml "^3.13.1"
-    json-stable-stringify-without-jsonify "^1.0.1"
-    levn "^0.3.0"
-    lodash "^4.17.14"
-    minimatch "^3.0.4"
-    mkdirp "^0.5.1"
-    natural-compare "^1.4.0"
-    optionator "^0.8.3"
-    progress "^2.0.0"
-    regexpp "^2.0.1"
-    semver "^6.1.2"
-    strip-ansi "^5.2.0"
-    strip-json-comments "^3.0.1"
-    table "^5.2.3"
-    text-table "^0.2.0"
-    v8-compile-cache "^2.0.3"
-
-espree@^6.1.2:
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
-  integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
-  dependencies:
-    acorn "^7.1.1"
-    acorn-jsx "^5.2.0"
-    eslint-visitor-keys "^1.1.0"
-
-esprima@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
-  integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-
-esquery@^1.0.1:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
-  integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
-  dependencies:
-    estraverse "^5.1.0"
-
-esrecurse@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
-  integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
-  dependencies:
-    estraverse "^5.2.0"
-
-estraverse@^4.1.1:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
-  integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
-
-estraverse@^5.1.0, estraverse@^5.2.0:
-  version "5.3.0"
-  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
-  integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
-
-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==
-
-etag@~1.8.1:
-  version "1.8.1"
-  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
-  integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
-
-external-editor@^3.0.3:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
-  integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
-  dependencies:
-    chardet "^0.7.0"
-    iconv-lite "^0.4.24"
-    tmp "^0.0.33"
-
-fast-deep-equal@^3.1.1:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
-  integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-json-stable-stringify@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
-  integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-
-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=
-
-figures@^3.0.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
-  integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
-  dependencies:
-    escape-string-regexp "^1.0.5"
-
-file-entry-cache@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
-  integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==
-  dependencies:
-    flat-cache "^2.0.1"
-
-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"
-
-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"
-  integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==
-  dependencies:
-    flatted "^2.0.0"
-    rimraf "2.6.3"
-    write "1.0.3"
-
-flatted@^2.0.0:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
-  integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
-
-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.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=
-
-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==
-
-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=
-
-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-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"
-
-glob-parent@^5.0.0:
-  version "5.1.2"
-  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
-  integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
-  dependencies:
-    is-glob "^4.0.1"
-
-glob@^7.1.3:
-  version "7.2.0"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
-  integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.0.4"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
-globals@^12.1.0:
-  version "12.4.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8"
-  integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==
-  dependencies:
-    type-fest "^0.8.1"
-
-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-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=
-
-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:
-  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"
-  integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
-  dependencies:
-    has-symbols "^1.0.2"
-
-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"
-
-http-errors@2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
-  integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
-  dependencies:
-    depd "2.0.0"
-    inherits "2.0.4"
-    setprototypeof "1.2.0"
-    statuses "2.0.1"
-    toidentifier "1.0.1"
-
-iconv-lite@^0.4.24:
-  version "0.4.24"
-  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
-  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
-  dependencies:
-    safer-buffer ">= 2.1.2 < 3"
-
-ignore@^4.0.6:
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
-  integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
-
-ignore@^5.1.1:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
-  integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
-
-import-fresh@^3.0.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
-  integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
-  dependencies:
-    parent-module "^1.0.0"
-    resolve-from "^4.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=
-
-inflight@^1.0.4:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
-  integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
-  dependencies:
-    once "^1.3.0"
-    wrappy "1"
-
-inherits@2, inherits@2.0.4:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
-  integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-inquirer@^7.0.0:
-  version "7.3.3"
-  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
-  integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==
-  dependencies:
-    ansi-escapes "^4.2.1"
-    chalk "^4.1.0"
-    cli-cursor "^3.1.0"
-    cli-width "^3.0.0"
-    external-editor "^3.0.3"
-    figures "^3.0.0"
-    lodash "^4.17.19"
-    mute-stream "0.0.8"
-    run-async "^2.4.0"
-    rxjs "^6.6.0"
-    string-width "^4.1.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==
-  dependencies:
-    get-intrinsic "^1.1.0"
-    has "^1.0.3"
-    side-channel "^1.0.4"
-
-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.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==
-  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-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=
-
-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-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.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.7"
-  resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
-  integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
-  dependencies:
-    has-tostringtag "^1.0.0"
-
-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-shared-array-buffer@^1.0.1:
-  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"
-  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-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"
-  integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-
-js-tokens@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
-  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
-js-yaml@^3.13.1:
-  version "3.14.1"
-  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
-  integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
-  dependencies:
-    argparse "^1.0.7"
-    esprima "^4.0.0"
-
-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-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=
-
-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==
-  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=
-  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"
-  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-
-mime@1.6.0:
-  version "1.6.0"
-  resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
-  integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
-
-mimic-fn@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
-  integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-
-minimatch@^3.0.4, 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, 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==
-
-mkdirp@^0.5.1:
-  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.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.2:
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
-  integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-
-ms@2.1.3, 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==
-
-mute-stream@0.0.8:
-  version "0.0.8"
-  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
-  integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
-
-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=
-
-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-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"
-
-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==
-  dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.1.3"
-    es-abstract "^1.19.1"
-
-on-finished@2.4.1:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
-  integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
-  dependencies:
-    ee-first "1.1.1"
-
-on-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:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
-  integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
-  dependencies:
-    wrappy "1"
-
-onetime@^5.1.0:
-  version "5.1.2"
-  resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
-  integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
-  dependencies:
-    mimic-fn "^2.1.0"
-
-optionator@^0.8.3:
-  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-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=
-
-parent-module@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
-  integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
-  dependencies:
-    callsites "^3.0.0"
-
-parseurl@~1.3.3:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
-  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-
-path-exists@^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=
-
-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=
-
-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==
-
-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=
-
-progress@^2.0.0:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
-  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==
-
-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==
-
-regexpp@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
-  integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
-
-regexpp@^3.0.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
-  integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
-
-resolve-from@^4.0.0:
-  version "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==
-  dependencies:
-    is-core-module "^2.8.1"
-    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"
-  integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
-  dependencies:
-    onetime "^5.1.0"
-    signal-exit "^3.0.2"
-
-rimraf@2.6.3:
-  version "2.6.3"
-  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
-  integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
-  dependencies:
-    glob "^7.1.3"
-
-run-async@^2.4.0:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
-  integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
-
-rxjs@^6.6.0:
-  version "6.6.7"
-  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
-  integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
-  dependencies:
-    tslib "^1.9.0"
-
-"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@^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:
-  version "6.3.0"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
-  integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-
-send@0.18.0:
-  version "0.18.0"
-  resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
-  integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
-  dependencies:
-    debug "2.6.9"
-    depd "2.0.0"
-    destroy "1.2.0"
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    etag "~1.8.1"
-    fresh "0.5.2"
-    http-errors "2.0.0"
-    mime "1.6.0"
-    ms "2.1.3"
-    on-finished "2.4.1"
-    range-parser "~1.2.1"
-    statuses "2.0.1"
-
-serve-static@^1.14.1:
-  version "1.15.0"
-  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
-  integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
-  dependencies:
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    parseurl "~1.3.3"
-    send "0.18.0"
-
-setprototypeof@1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
-  integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
-
-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=
-  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=
-
-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.2:
-  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"
-  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
-  integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
-  dependencies:
-    ansi-styles "^3.2.0"
-    astral-regex "^1.0.0"
-    is-fullwidth-code-point "^2.0.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=
-
-statuses@2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
-  integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
-
-statuses@~1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
-  integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-
-string-width@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
-  integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
-  dependencies:
-    emoji-regex "^7.0.1"
-    is-fullwidth-code-point "^2.0.0"
-    strip-ansi "^5.1.0"
-
-string-width@^4.1.0:
-  version "4.2.3"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
-  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
-  dependencies:
-    emoji-regex "^8.0.0"
-    is-fullwidth-code-point "^3.0.0"
-    strip-ansi "^6.0.1"
-
-string.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"
-
-strip-ansi@^5.1.0, strip-ansi@^5.2.0:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
-  integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
-  dependencies:
-    ansi-regex "^4.1.0"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
-  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
-  dependencies:
-    ansi-regex "^5.0.1"
-
-strip-bom@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
-  integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
-
-strip-json-comments@^3.0.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
-  integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-
-supports-color@^5.3.0:
-  version "5.5.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
-  integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
-  dependencies:
-    has-flag "^3.0.0"
-
-supports-color@^7.1.0:
-  version "7.2.0"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
-  integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
-  dependencies:
-    has-flag "^4.0.0"
-
-supports-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"
-  integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==
-  dependencies:
-    ajv "^6.10.2"
-    lodash "^4.17.14"
-    slice-ansi "^2.1.0"
-    string-width "^3.0.0"
-
-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=
-
-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=
-
-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"
-  resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
-  integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
-
-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.6"
-    strip-bom "^3.0.0"
-
-tslib@^1.9.0:
-  version "1.14.1"
-  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
-  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-
-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"
-
-type-fest@^0.21.3:
-  version "0.21.3"
-  resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
-  integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
-
-type-fest@^0.8.1:
-  version "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==
-  dependencies:
-    function-bind "^1.1.1"
-    has-bigints "^1.0.1"
-    has-symbols "^1.0.2"
-    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=
-
-uri-js@^4.2.2:
-  version "4.4.1"
-  resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
-  integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
-  dependencies:
-    punycode "^2.1.0"
-
-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=
-
-v8-compile-cache@^2.0.3:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
-  integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
-
-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@^1.2.9:
-  version "1.3.1"
-  resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
-  integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
-  dependencies:
-    isexe "^2.0.0"
-
-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=
-
-write@1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
-  integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==
-  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==
diff --git a/npms/skale-ima/index.js b/npms/skale-ima/index.js
index 835171808..022988471 100644
--- a/npms/skale-ima/index.js
+++ b/npms/skale-ima/index.js
@@ -599,18 +599,8 @@ 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_transfer_errors() {
+    return JSON.parse( JSON.stringify( g_arrLastTransferErrors ) );
 }
 
 function get_last_error_categories() {
@@ -632,14 +622,13 @@ function setEnabledProgressiveEventsScan( isEnabled ) {
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-let g_bIsEnabledOracle = false;
+let g_nOracleGasPriceMode = 0;
 
-function getEnabledOracle( isEnabled ) {
-    return g_bIsEnabledOracle ? true : false;
+function getOracleGasPriceMode() {
+    return 0 + g_nOracleGasPriceMode;
 }
-
-function setEnabledOracle( isEnabled ) {
-    g_bIsEnabledOracle = isEnabled ? true : false;
+function setOracleGasPriceMode( mode ) {
+    g_nOracleGasPriceMode = 0 + parseInt( mode ? mode.toString() : "0" );
 }
 
 async function do_oracle_gas_price_setup(
@@ -653,7 +642,7 @@ async function do_oracle_gas_price_setup(
     fn_sign_o_msg,
     optsPendingTxAnalysis
 ) {
-    if( ! getEnabledOracle() )
+    if( getOracleGasPriceMode() == 0 )
         return;
     const details = log.createMemoryStream();
     const jarrReceipts = [];
@@ -671,91 +660,15 @@ async function do_oracle_gas_price_setup(
         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()";
+        strActionName = "do_oracle_gas_price_setup.timestampOfBlock()";
         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" );
+        let timestampOfBlock = "0x" + w3_main_net.utils.toBN( latestBlock.timestamp ).toString( 16 );
+        details.write( cc.debug( "Timestamp on Main Net is " ) + cc.info( timestampOfBlock ) + cc.debug( " (original)" ) + "\n" );
+        timestampOfBlock -= 10;
+        details.write( cc.debug( "Timestamp on Main Net is " ) + cc.info( timestampOfBlock ) + 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;
-        }
+        const gasPriceOnMainNet = "0x" + w3_main_net.utils.toBN( await w3_main_net.eth.getGasPrice() ).toString( 16 );
+        details.write( cc.info( "Main Net gas price" ) + cc.debug( " is " ) + cc.bright( gasPriceOnMainNet ) + "\n" );
         //
         strActionName = "do_oracle_gas_price_setup.fn_sign_o_msg()";
         await fn_sign_o_msg( gasPriceOnMainNet, details, async function( strError, u256, joGlueResult ) {
@@ -790,7 +703,7 @@ async function do_oracle_gas_price_setup(
             const methodWithArguments_setGasPrice = jo_community_locker.methods.setGasPrice(
                 // call params
                 u256,
-                "0x" + bnTimestampOfBlock.toString( 16 ),
+                timestampOfBlock,
                 sign // bls signature components
             );
             const dataTx_setGasPrice = methodWithArguments_setGasPrice.encodeABI(); // the encoded ABI of the method
@@ -838,9 +751,11 @@ async function do_oracle_gas_price_setup(
             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 )
+            if( joSetGasPriceSR.joACI.isAutoSend ) {
+                if( optsPendingTxAnalysis && "isEnabled" in optsPendingTxAnalysis && optsPendingTxAnalysis.isEnabled )
+                    await async_pending_tx_start( details, w3_schain, w3_main_net, chain_id_schain, chain_id_mainnet, "" + joSetGasPriceSR.txHashSent );
                 joReceipt = await get_web3_transactionReceipt( details, 10, w3_schain, joSetGasPriceSR.txHashSent );
-            else {
+            } else {
                 const serializedTx_setGasPrice = tx_setGasPrice.serialize();
                 strActionName = "w3_schain.eth.sendSignedTransaction()";
                 // let joReceipt = await w3_schain.eth.sendSignedTransaction( "0x" + serializedTx_setGasPrice.toString( "hex" ) );
@@ -853,6 +768,8 @@ async function do_oracle_gas_price_setup(
                     "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" );
         } );
@@ -1335,8 +1252,8 @@ async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAcc
         /*
         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"
+            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 &&
@@ -1392,9 +1309,8 @@ async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAcc
         */
         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 )
-        ;
+            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
@@ -1425,8 +1341,8 @@ async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAcc
     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"
+            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 &&
@@ -1509,17 +1425,16 @@ async function safe_sign_transaction_with_account( details, w3, tx, rawTx, joAcc
     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"
+            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";
+            cc.error( " bad credentials information specified, no explicit SGX and no explicit private key found, account is: " ) +
+            cc.j( joAccount ) + "\n";
         details.write( s );
         log.write( s );
         if( isExitIfEmpty ) {
@@ -4806,6 +4721,7 @@ async function async_pending_tx_start( details, w3, w3_opposite, chain_id, chain
                     }
                 } );
             } );
+
         }
     } catch ( err ) {
         const s =
@@ -5566,7 +5482,7 @@ async function do_transfer(
                                 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 w3_node = getWeb3FromURL( jo_node.http_endpoint_ip );
                                 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 node_r = await get_web3_pastEventsProgressive(
                                     details,
@@ -5819,9 +5735,6 @@ async function do_transfer(
                         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 );
@@ -5832,6 +5745,7 @@ async function do_transfer(
                             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()",
@@ -5839,9 +5753,6 @@ async function do_transfer(
                                 "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 );
                         }
@@ -5981,7 +5892,7 @@ async function do_s2s_all( // s-chain --> s-chain
     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 w3_src = getWeb3FromURL( url_src );
         const joAccountSrc = joAccountDst; // ???
         const chain_id_src = "" + jo_schain.data.name;
         const cid_src = "" + jo_schain.data.computed.chainId;
@@ -6353,9 +6264,11 @@ async function mintERC20(
         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( 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 {
+        } else {
             const serializedTx_mint = tx_mint.serialize();
             strActionName = "w3.eth.sendSignedTransaction()";
             // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_mint.toString( "hex" ) );
@@ -6447,9 +6360,11 @@ async function mintERC721(
         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( 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 {
+        } else {
             const serializedTx_mint = tx_mint.serialize();
             strActionName = "w3.eth.sendSignedTransaction()";
             // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_mint.toString( "hex" ) );
@@ -6544,9 +6459,11 @@ async function mintERC1155(
         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( 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 {
+        } else {
             const serializedTx_mint = tx_mint.serialize();
             strActionName = "w3.eth.sendSignedTransaction()";
             // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_mint.toString( "hex" ) );
@@ -6638,9 +6555,11 @@ async function burnERC20(
         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( 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 {
+        } else {
             const serializedTx_burn = tx_burn.serialize();
             strActionName = "w3.eth.sendSignedTransaction()";
             // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_burn.toString( "hex" ) );
@@ -6732,9 +6651,11 @@ async function burnERC721(
         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( 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 {
+        } else {
             const serializedTx_burn = tx_burn.serialize();
             strActionName = "w3.eth.sendSignedTransaction()";
             // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_burn.toString( "hex" ) );
@@ -6828,9 +6749,11 @@ async function burnERC1155(
         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( 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 {
+        } else {
             const serializedTx_burn = tx_burn.serialize();
             strActionName = "w3.eth.sendSignedTransaction()";
             // let joReceipt = await w3.eth.sendSignedTransaction( "0x" + serializedTx_burn.toString( "hex" ) );
@@ -6953,8 +6876,8 @@ module.exports.getMaxIterationsInAllRangeEventsScan = getMaxIterationsInAllRange
 module.exports.setMaxIterationsInAllRangeEventsScan = setMaxIterationsInAllRangeEventsScan;
 module.exports.getEnabledProgressiveEventsScan = getEnabledProgressiveEventsScan;
 module.exports.setEnabledProgressiveEventsScan = setEnabledProgressiveEventsScan;
-module.exports.getEnabledOracle = getEnabledOracle;
-module.exports.setEnabledOracle = setEnabledOracle;
+module.exports.getOracleGasPriceMode = getOracleGasPriceMode;
+module.exports.setOracleGasPriceMode = setOracleGasPriceMode;
 module.exports.do_oracle_gas_price_setup = do_oracle_gas_price_setup;
 
 module.exports.get_S2S_transfer_mode_description = get_S2S_transfer_mode_description;
diff --git a/npms/skale-ima/package.json b/npms/skale-ima/package.json
index f425aa5d4..05aacded4 100644
--- a/npms/skale-ima/package.json
+++ b/npms/skale-ima/package.json
@@ -33,7 +33,7 @@
     "dependencies": {
         "ethereumjs-tx": "1.3.7",
         "ethereumjs-wallet": "^1.0.2",
-        "ethereumjs-util": "^7.1.4",
+        "ethereumjs-util": "^7.1.3",
         "web3": "^1.6.1",
         "ioredis": "^4.28.2"
     },
diff --git a/npms/skale-ima/yarn.lock b/npms/skale-ima/yarn.lock
index 53afa15c5..053271b48 100644
--- a/npms/skale-ima/yarn.lock
+++ b/npms/skale-ima/yarn.lock
@@ -1087,17 +1087,6 @@ ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3:
     ethereum-cryptography "^0.1.3"
     rlp "^2.2.4"
 
-ethereumjs-util@^7.1.4:
-  version "7.1.4"
-  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458"
-  integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==
-  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"
diff --git a/npms/skale-log/log.js b/npms/skale-log/log.js
index 5932b7012..0d2a1eb37 100644
--- a/npms/skale-log/log.js
+++ b/npms/skale-log/log.js
@@ -37,27 +37,22 @@ function n2s( n, sz ) {
     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; };
+function generateTimestamp() {
+    const ts = new Date();
     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 ) )
-        ;
+	"" + 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 generateTimestampPrefix() {
+    return generateTimestamp() + cc.bright( ":" ) + " ";
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -256,13 +251,12 @@ function insertFileOutput( strFilePath, nMaxSizeBeforeRotation, nMaxFilesCount )
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 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;
+	  write: function() {
+        let s = generateTimestampPrefix(); let i = 0; let cnt = 0;
         try {
-            for( i = 0; i < arguments.length; ++i ) {
+            cnt = arguments.length;
+            for( i = 0; i < cnt; ++i ) {
                 try {
                     s += arguments[i];
                 } catch ( err ) {
diff --git a/npms/skale-observer/observer.js b/npms/skale-observer/observer.js
index 821e66bc0..cfed1d786 100644
--- a/npms/skale-observer/observer.js
+++ b/npms/skale-observer/observer.js
@@ -24,58 +24,12 @@
  * @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 { getWeb3FromURL } = require( "../../agent/cli.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 ) {
@@ -244,6 +198,7 @@ async function check_connected_schains( strChainNameConnectedTo, arr_schains, ad
         if( jo_schain.data.name == strChainNameConnectedTo )
             continue;
         try {
+            //jo_schain.isConnected = await opts.imaState.jo_message_proxy_s_chain.methods.isConnectedChain( strChainNameConnectedTo ).call( { from: addressFrom } );
             const url = pick_random_schain_w3_url( jo_schain );
             if( opts && opts.details ) {
                 opts.details.write(
@@ -251,18 +206,16 @@ async function check_connected_schains( strChainNameConnectedTo, arr_schains, ad
                     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 );
+            const w3 = getWeb3FromURL( url );
+            const jo_message_proxy_s_chain = new w3.eth.Contract( imaState.joAbiPublishResult_s_chain.message_proxy_chain_abi, 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 ) {
+            if( opts && opts.details )
                 opts.details.write( cc.error( "Got error: " ) + cc.warning( err.toString() ) + "\n" );
-                opts.details.write( err.stack );
-            }
         }
     }
     return arr_schains;
@@ -345,7 +298,7 @@ function merge_schains_array_from_to( arrSrc, arrDst, arrNew, arrOld, opts ) {
         opts.details.write( cc.success( "Finally, have " ) + cc.info( arrDst.length ) + cc.success( " S-Chain(s)" ) + "\n" );
 }
 
-let g_arr_schains_cached = [];
+let g_arr_schains_cached = null;
 
 async function cache_schains( strChainNameConnectedTo, w3, addressFrom, opts ) {
     let strError = null;
@@ -366,7 +319,7 @@ async function cache_schains( strChainNameConnectedTo, w3, 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.debug( "Connected " ) + cc.attention( "S-Chains" ) + cc.debug( " cache was updated: " ) +
                 cc.j( g_arr_schains_cached ) + "\n" );
         }
         if( opts.fn_chache_changed )
@@ -377,10 +330,8 @@ async function cache_schains( strChainNameConnectedTo, w3, addressFrom, opts ) {
             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 ) {
+        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
 }
@@ -389,139 +340,33 @@ 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,
-                    "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
-                    },
-                    // "tc_main_net": IMA.tc_main_net,
-                    // "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 );
-}
-
-// let g_intervalPeriodicSchainsCaching = null;
-// let g_bIsPeriodicCachingStepInProgress = false;
+let g_intervalPeriodicSchainsCaching = null;
+let g_bIsPeriodicCachingStepInProgress = false;
 
 async function periodic_caching_start( strChainNameConnectedTo, w3, addressFrom, opts ) {
-    // await periodic_caching_stop();
-    // if( ! ( "secondsToReDiscoverSkaleNetwork" in opts ) )
-    //     return false;
-    // const secondsToReDiscoverSkaleNetwork = parseInt( opts.secondsToReDiscoverSkaleNetwork );
-    // if( secondsToReDiscoverSkaleNetwork <= 0 )
-    //     return false;
-    // const fn_async_handler = async function() {
-    //     if( g_bIsPeriodicCachingStepInProgress )
-    //         return;
-    //     g_bIsPeriodicCachingStepInProgress = true;
-    //     // const strError =
-    //     await cache_schains( strChainNameConnectedTo, w3, addressFrom, opts );
-    //     g_bIsPeriodicCachingStepInProgress = false;
-    // };
-    // g_intervalPeriodicSchainsCaching = setInterval( function() {
-    //     if( g_bIsPeriodicCachingStepInProgress )
-    //         return;
-    //     fn_async_handler()
-    //         .then( () => {
-    //         } ).catch( () => {
-    //         } );
-    // }, secondsToReDiscoverSkaleNetwork * 1000 );
-    // return true;
-    await ensure_have_worker( opts );
-    const jo = {
-        method: "periodic_caching_start",
-        message: {
-            secondsToReDiscoverSkaleNetwork: parseInt( opts.secondsToReDiscoverSkaleNetwork ),
-            strChainNameConnectedTo: strChainNameConnectedTo,
-            addressFrom: addressFrom
-        }
-    };
-    g_client.send( jo );
+    await periodic_caching_stop();
+    if( ! ( "secondsToReDiscoverSkaleNetwork" in opts ) )
+        return false;
+    const secondsToReDiscoverSkaleNetwork = parseInt( opts.secondsToReDiscoverSkaleNetwork );
+    if( secondsToReDiscoverSkaleNetwork <= 0 )
+        return false;
+    g_intervalPeriodicSchainsCaching = setInterval( async function() {
+        if( g_bIsPeriodicCachingStepInProgress )
+            return;
+        g_bIsPeriodicCachingStepInProgress = true;
+        // const strError =
+        await cache_schains( strChainNameConnectedTo, w3, addressFrom, opts );
+        g_bIsPeriodicCachingStepInProgress = false;
+    }, secondsToReDiscoverSkaleNetwork * 1000 );
+    return true;
 }
 async function periodic_caching_stop() {
-    // if( ! g_intervalPeriodicSchainsCaching )
-    //     return false;
-    // clearInterval( g_intervalPeriodicSchainsCaching );
-    // g_intervalPeriodicSchainsCaching = null;
-    // g_bIsPeriodicCachingStepInProgress = false;
-    // return true;
-    await ensure_have_worker( opts );
-    const jo = {
-        method: "periodic_caching_stop",
-        message: {
-        }
-    };
-    g_client.send( jo );
+    if( ! g_intervalPeriodicSchainsCaching )
+        return false;
+    clearInterval( g_intervalPeriodicSchainsCaching );
+    g_intervalPeriodicSchainsCaching = null;
+    g_bIsPeriodicCachingStepInProgress = false;
+    return true;
 }
 
 function pick_random_schain_node_index( jo_schain ) {
@@ -567,8 +412,6 @@ async function discover_chain_id( strURL ) {
     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;
diff --git a/npms/skale-observer/observer_worker.js b/npms/skale-observer/observer_worker.js
deleted file mode 100644
index 8f9ac3786..000000000
--- a/npms/skale-observer/observer_worker.js
+++ /dev/null
@@ -1,186 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @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_;
-            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" );
-            }
-            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 );
-            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, 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..c3575b4e1 100644
--- a/npms/skale-observer/package.json
+++ b/npms/skale-observer/package.json
@@ -5,9 +5,9 @@
     "author": "SKALE Labs and contributors",
     "scripts": {},
     "dependencies": {
-        "ethereumjs-tx": "2.1.2",
-        "ethereumjs-wallet": "^1.0.2",
-        "ethereumjs-util": "^7.1.4",
+        "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"
diff --git a/npms/skale-observer/yarn.lock b/npms/skale-observer/yarn.lock
index e63d0f7ee..a0ba805e4 100644
--- a/npms/skale-observer/yarn.lock
+++ b/npms/skale-observer/yarn.lock
@@ -257,7 +257,7 @@ accepts@~1.3.7:
     mime-types "~2.1.24"
     negotiator "0.6.2"
 
-aes-js@^3.1.2:
+aes-js@^3.1.1:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a"
   integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==
@@ -376,6 +376,20 @@ bignumber.js@^9.0.0:
   resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673"
   integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==
 
+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"
+
 blakejs@^1.1.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702"
@@ -398,7 +412,7 @@ bn.js@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.6, bn.js@^4.11.9:
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, 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==
@@ -437,7 +451,7 @@ brorand@^1.0.1, brorand@^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.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, 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==
@@ -844,6 +858,15 @@ dom-walk@^0.1.0:
   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"
@@ -999,6 +1022,11 @@ ethereum-bloom-filters@^1.0.6:
   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"
@@ -1020,18 +1048,39 @@ ethereum-cryptography@^0.1.3:
     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@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-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==
+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:
-    ethereumjs-common "^1.5.0"
-    ethereumjs-util "^6.0.0"
+    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"
@@ -1057,30 +1106,20 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.3:
     ethereum-cryptography "^0.1.3"
     rlp "^2.2.4"
 
-ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4:
-  version "7.1.4"
-  resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458"
-  integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==
-  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==
+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==
   dependencies:
-    aes-js "^3.1.2"
+    aes-js "^3.1.1"
     bs58check "^2.1.2"
-    ethereum-cryptography "^0.1.3"
-    ethereumjs-util "^7.1.2"
-    randombytes "^2.1.0"
-    scrypt-js "^3.0.1"
+    ethereumjs-util "^6.0.0"
+    hdkey "^1.1.0"
+    randombytes "^2.0.6"
+    safe-buffer "^5.1.2"
+    scrypt.js "^0.3.0"
     utf8 "^3.0.0"
-    uuid "^8.3.2"
+    uuid "^3.3.2"
 
 ethjs-unit@0.1.6:
   version "0.1.6"
@@ -1090,7 +1129,7 @@ ethjs-unit@0.1.6:
     bn.js "4.11.6"
     number-to-bn "1.7.0"
 
-ethjs-util@0.1.6:
+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==
@@ -1184,6 +1223,11 @@ 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"
@@ -1452,6 +1496,15 @@ 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"
@@ -1770,6 +1823,16 @@ jsprim@^1.2.2:
     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"
@@ -1968,7 +2031,7 @@ multihashes@^0.4.15, multihashes@~0.4.15:
     multibase "^0.7.0"
     varint "^5.0.0"
 
-nan@^2.14.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==
@@ -2335,7 +2398,7 @@ query-string@^5.0.1:
     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.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
   integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
@@ -2445,7 +2508,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
     hash-base "^3.0.0"
     inherits "^2.0.1"
 
-rlp@^2.2.3, rlp@^2.2.4:
+rlp@^2.0.0, 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==
@@ -2477,11 +2540,41 @@ scrypt-js@^3.0.0, scrypt-js@^3.0.1:
   resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312"
   integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==
 
-"scrypt@file:../scrypt/node-scrypt":
+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":
   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"
@@ -2912,11 +3005,6 @@ uuid@^3.3.2:
   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"
diff --git a/proxy/.openzeppelin/mainnet.json b/proxy/.openzeppelin/mainnet.json
index e92791986..ea0fda846 100644
--- a/proxy/.openzeppelin/mainnet.json
+++ b/proxy/.openzeppelin/mainnet.json
@@ -5894,6 +5894,1385 @@
           }
         }
       }
+    },
+    "1e516afa1c1b72e0b42ff6e87b93743fcfc100b644ed3e005fabfd265a063212": {
+      "address": "0x8BaC52833c7901182ED972Bfa4A56A2432D79170",
+      "txHash": "0x6e7b9f825829a6c8bebc01aafa19660f062a5ffc169b662f77e387335fca701e",
+      "layout": {
+        "storage": [
+          {
+            "contract": "Initializable",
+            "label": "_initialized",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21"
+          },
+          {
+            "contract": "Initializable",
+            "label": "_initializing",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:26"
+          },
+          {
+            "contract": "ContextUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:30"
+          },
+          {
+            "contract": "ERC165Upgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:35"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "_roles",
+            "type": "t_mapping(t_bytes32,t_struct(RoleData)253_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:63"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:219"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "_roleMembers",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:25"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:89"
+          },
+          {
+            "contract": "SkaleManagerClient",
+            "label": "contractManagerOfSkaleManager",
+            "type": "t_contract(IContractManager)6990",
+            "src": "contracts/mainnet/SkaleManagerClient.sol:37"
+          },
+          {
+            "contract": "MessageProxy",
+            "label": "connectedChains",
+            "type": "t_mapping(t_bytes32,t_struct(ConnectedChainInfo)7687_storage)",
+            "src": "contracts/MessageProxy.sol:58"
+          },
+          {
+            "contract": "MessageProxy",
+            "label": "deprecatedRegistryContracts",
+            "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))",
+            "src": "contracts/MessageProxy.sol:61"
+          },
+          {
+            "contract": "MessageProxy",
+            "label": "gasLimit",
+            "type": "t_uint256",
+            "src": "contracts/MessageProxy.sol:63"
+          },
+          {
+            "contract": "MessageProxyForMainnet",
+            "label": "communityPool",
+            "type": "t_contract(ICommunityPool)6276",
+            "src": "contracts/mainnet/MessageProxyForMainnet.sol:73"
+          },
+          {
+            "contract": "MessageProxyForMainnet",
+            "label": "headerMessageGasCost",
+            "type": "t_uint256",
+            "src": "contracts/mainnet/MessageProxyForMainnet.sol:75"
+          },
+          {
+            "contract": "MessageProxyForMainnet",
+            "label": "messageGasCost",
+            "type": "t_uint256",
+            "src": "contracts/mainnet/MessageProxyForMainnet.sol:76"
+          },
+          {
+            "contract": "MessageProxyForMainnet",
+            "label": "_registryContracts",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "contracts/mainnet/MessageProxyForMainnet.sol:77"
+          },
+          {
+            "contract": "MessageProxyForMainnet",
+            "label": "version",
+            "type": "t_string_storage",
+            "src": "contracts/mainnet/MessageProxyForMainnet.sol:78"
+          },
+          {
+            "contract": "MessageProxyForMainnet",
+            "label": "messageInProgress",
+            "type": "t_bool",
+            "src": "contracts/mainnet/MessageProxyForMainnet.sol:79"
+          }
+        ],
+        "types": {
+          "t_contract(ICommunityPool)6276": {
+            "label": "contract ICommunityPool"
+          },
+          "t_uint256": {
+            "label": "uint256"
+          },
+          "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)": {
+            "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)"
+          },
+          "t_bytes32": {
+            "label": "bytes32"
+          },
+          "t_struct(AddressSet)5413_storage": {
+            "label": "struct EnumerableSetUpgradeable.AddressSet",
+            "members": [
+              {
+                "label": "_inner",
+                "type": "t_struct(Set)5112_storage"
+              }
+            ]
+          },
+          "t_struct(Set)5112_storage": {
+            "label": "struct EnumerableSetUpgradeable.Set",
+            "members": [
+              {
+                "label": "_values",
+                "type": "t_array(t_bytes32)dyn_storage"
+              },
+              {
+                "label": "_indexes",
+                "type": "t_mapping(t_bytes32,t_uint256)"
+              }
+            ]
+          },
+          "t_array(t_bytes32)dyn_storage": {
+            "label": "bytes32[]"
+          },
+          "t_mapping(t_bytes32,t_uint256)": {
+            "label": "mapping(bytes32 => uint256)"
+          },
+          "t_string_storage": {
+            "label": "string"
+          },
+          "t_bool": {
+            "label": "bool"
+          },
+          "t_mapping(t_bytes32,t_struct(ConnectedChainInfo)7687_storage)": {
+            "label": "mapping(bytes32 => struct MessageProxy.ConnectedChainInfo)"
+          },
+          "t_struct(ConnectedChainInfo)7687_storage": {
+            "label": "struct MessageProxy.ConnectedChainInfo",
+            "members": [
+              {
+                "label": "incomingMessageCounter",
+                "type": "t_uint256"
+              },
+              {
+                "label": "outgoingMessageCounter",
+                "type": "t_uint256"
+              },
+              {
+                "label": "inited",
+                "type": "t_bool"
+              }
+            ]
+          },
+          "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": {
+            "label": "mapping(bytes32 => mapping(address => bool))"
+          },
+          "t_mapping(t_address,t_bool)": {
+            "label": "mapping(address => bool)"
+          },
+          "t_address": {
+            "label": "address"
+          },
+          "t_contract(IContractManager)6990": {
+            "label": "contract IContractManager"
+          },
+          "t_array(t_uint256)49_storage": {
+            "label": "uint256[49]"
+          },
+          "t_mapping(t_bytes32,t_struct(RoleData)253_storage)": {
+            "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)"
+          },
+          "t_struct(RoleData)253_storage": {
+            "label": "struct AccessControlUpgradeable.RoleData",
+            "members": [
+              {
+                "label": "members",
+                "type": "t_mapping(t_address,t_bool)"
+              },
+              {
+                "label": "adminRole",
+                "type": "t_bytes32"
+              }
+            ]
+          },
+          "t_array(t_uint256)50_storage": {
+            "label": "uint256[50]"
+          }
+        }
+      }
+    },
+    "2fdb12e0abe1b31b32c26071f9e12640ec6dc2d6408ad5335959a6be1e535ece": {
+      "address": "0xc107d8CCC84C391b0E66A6cE2460Ece69EF1ad26",
+      "txHash": "0x7eb4a7dc7f0b4331de35baca1d2c01909a56118afdfcb4c45406886e0ee62262",
+      "layout": {
+        "storage": [
+          {
+            "contract": "Initializable",
+            "label": "_initialized",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21"
+          },
+          {
+            "contract": "Initializable",
+            "label": "_initializing",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:26"
+          },
+          {
+            "contract": "ContextUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:30"
+          },
+          {
+            "contract": "ERC165Upgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:35"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "_roles",
+            "type": "t_mapping(t_bytes32,t_struct(RoleData)253_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:63"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:219"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "_roleMembers",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:25"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:89"
+          },
+          {
+            "contract": "SkaleManagerClient",
+            "label": "contractManagerOfSkaleManager",
+            "type": "t_contract(IContractManager)6990",
+            "src": "contracts/mainnet/SkaleManagerClient.sol:37"
+          },
+          {
+            "contract": "Twin",
+            "label": "messageProxy",
+            "type": "t_contract(IMessageProxyForMainnet)6403",
+            "src": "contracts/mainnet/Twin.sol:38"
+          },
+          {
+            "contract": "Twin",
+            "label": "schainLinks",
+            "type": "t_mapping(t_bytes32,t_address)",
+            "src": "contracts/mainnet/Twin.sol:39"
+          },
+          {
+            "contract": "Linker",
+            "label": "_mainnetContracts",
+            "type": "t_struct(AddressSet)5413_storage",
+            "src": "contracts/mainnet/Linker.sol:44"
+          },
+          {
+            "contract": "Linker",
+            "label": "_interchainConnections",
+            "type": "t_mapping(t_bytes32,t_bool)",
+            "src": "contracts/mainnet/Linker.sol:47"
+          },
+          {
+            "contract": "Linker",
+            "label": "statuses",
+            "type": "t_mapping(t_bytes32,t_enum(KillProcess)14639)",
+            "src": "contracts/mainnet/Linker.sol:51"
+          }
+        ],
+        "types": {
+          "t_struct(AddressSet)5413_storage": {
+            "label": "struct EnumerableSetUpgradeable.AddressSet",
+            "members": [
+              {
+                "label": "_inner",
+                "type": "t_struct(Set)5112_storage"
+              }
+            ]
+          },
+          "t_struct(Set)5112_storage": {
+            "label": "struct EnumerableSetUpgradeable.Set",
+            "members": [
+              {
+                "label": "_values",
+                "type": "t_array(t_bytes32)dyn_storage"
+              },
+              {
+                "label": "_indexes",
+                "type": "t_mapping(t_bytes32,t_uint256)"
+              }
+            ]
+          },
+          "t_array(t_bytes32)dyn_storage": {
+            "label": "bytes32[]"
+          },
+          "t_bytes32": {
+            "label": "bytes32"
+          },
+          "t_mapping(t_bytes32,t_uint256)": {
+            "label": "mapping(bytes32 => uint256)"
+          },
+          "t_uint256": {
+            "label": "uint256"
+          },
+          "t_mapping(t_bytes32,t_bool)": {
+            "label": "mapping(bytes32 => bool)"
+          },
+          "t_bool": {
+            "label": "bool"
+          },
+          "t_mapping(t_bytes32,t_enum(KillProcess)14639)": {
+            "label": "mapping(bytes32 => enum Linker.KillProcess)"
+          },
+          "t_enum(KillProcess)14639": {
+            "label": "enum Linker.KillProcess",
+            "members": [
+              "NotKilled",
+              "PartiallyKilledBySchainOwner",
+              "PartiallyKilledByContractOwner",
+              "Killed"
+            ]
+          },
+          "t_contract(IMessageProxyForMainnet)6403": {
+            "label": "contract IMessageProxyForMainnet"
+          },
+          "t_mapping(t_bytes32,t_address)": {
+            "label": "mapping(bytes32 => address)"
+          },
+          "t_address": {
+            "label": "address"
+          },
+          "t_contract(IContractManager)6990": {
+            "label": "contract IContractManager"
+          },
+          "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)": {
+            "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)"
+          },
+          "t_array(t_uint256)49_storage": {
+            "label": "uint256[49]"
+          },
+          "t_mapping(t_bytes32,t_struct(RoleData)253_storage)": {
+            "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)"
+          },
+          "t_struct(RoleData)253_storage": {
+            "label": "struct AccessControlUpgradeable.RoleData",
+            "members": [
+              {
+                "label": "members",
+                "type": "t_mapping(t_address,t_bool)"
+              },
+              {
+                "label": "adminRole",
+                "type": "t_bytes32"
+              }
+            ]
+          },
+          "t_mapping(t_address,t_bool)": {
+            "label": "mapping(address => bool)"
+          },
+          "t_array(t_uint256)50_storage": {
+            "label": "uint256[50]"
+          }
+        }
+      }
+    },
+    "f8d36e36cf2863e2c7b5b33d1c96a8a22e03c4e4d918eeec5eaa186e95bd7af8": {
+      "address": "0x59501EDE4441B566D43330938b01044168a4Af0C",
+      "txHash": "0x6540f141d47e3de9f5edc0c9c7f6ef16be8c52c2a6ff0d9ca94318dbb7145187",
+      "layout": {
+        "storage": [
+          {
+            "contract": "Initializable",
+            "label": "_initialized",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21"
+          },
+          {
+            "contract": "Initializable",
+            "label": "_initializing",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:26"
+          },
+          {
+            "contract": "ContextUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:30"
+          },
+          {
+            "contract": "ERC165Upgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:35"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "_roles",
+            "type": "t_mapping(t_bytes32,t_struct(RoleData)253_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:63"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:219"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "_roleMembers",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)1550_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:25"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:89"
+          },
+          {
+            "contract": "SkaleManagerClient",
+            "label": "contractManagerOfSkaleManager",
+            "type": "t_contract(IContractManager)2295",
+            "src": "contracts/mainnet/SkaleManagerClient.sol:37"
+          },
+          {
+            "contract": "Twin",
+            "label": "messageProxy",
+            "type": "t_contract(IMessageProxyForMainnet)2168",
+            "src": "contracts/mainnet/Twin.sol:38"
+          },
+          {
+            "contract": "Twin",
+            "label": "schainLinks",
+            "type": "t_mapping(t_bytes32,t_address)",
+            "src": "contracts/mainnet/Twin.sol:39"
+          },
+          {
+            "contract": "CommunityPool",
+            "label": "_userWallets",
+            "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))",
+            "src": "contracts/mainnet/CommunityPool.sol:44"
+          },
+          {
+            "contract": "CommunityPool",
+            "label": "activeUsers",
+            "type": "t_mapping(t_address,t_mapping(t_bytes32,t_bool))",
+            "src": "contracts/mainnet/CommunityPool.sol:47"
+          },
+          {
+            "contract": "CommunityPool",
+            "label": "minTransactionGas",
+            "type": "t_uint256",
+            "src": "contracts/mainnet/CommunityPool.sol:49"
+          }
+        ],
+        "types": {
+          "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))": {
+            "label": "mapping(address => mapping(bytes32 => uint256))"
+          },
+          "t_address": {
+            "label": "address"
+          },
+          "t_mapping(t_bytes32,t_uint256)": {
+            "label": "mapping(bytes32 => uint256)"
+          },
+          "t_bytes32": {
+            "label": "bytes32"
+          },
+          "t_uint256": {
+            "label": "uint256"
+          },
+          "t_mapping(t_address,t_mapping(t_bytes32,t_bool))": {
+            "label": "mapping(address => mapping(bytes32 => bool))"
+          },
+          "t_mapping(t_bytes32,t_bool)": {
+            "label": "mapping(bytes32 => bool)"
+          },
+          "t_bool": {
+            "label": "bool"
+          },
+          "t_contract(IMessageProxyForMainnet)2168": {
+            "label": "contract IMessageProxyForMainnet"
+          },
+          "t_mapping(t_bytes32,t_address)": {
+            "label": "mapping(bytes32 => address)"
+          },
+          "t_contract(IContractManager)2295": {
+            "label": "contract IContractManager"
+          },
+          "t_mapping(t_bytes32,t_struct(AddressSet)1550_storage)": {
+            "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)"
+          },
+          "t_struct(AddressSet)1550_storage": {
+            "label": "struct EnumerableSetUpgradeable.AddressSet",
+            "members": [
+              {
+                "label": "_inner",
+                "type": "t_struct(Set)1249_storage"
+              }
+            ]
+          },
+          "t_struct(Set)1249_storage": {
+            "label": "struct EnumerableSetUpgradeable.Set",
+            "members": [
+              {
+                "label": "_values",
+                "type": "t_array(t_bytes32)dyn_storage"
+              },
+              {
+                "label": "_indexes",
+                "type": "t_mapping(t_bytes32,t_uint256)"
+              }
+            ]
+          },
+          "t_array(t_bytes32)dyn_storage": {
+            "label": "bytes32[]"
+          },
+          "t_array(t_uint256)49_storage": {
+            "label": "uint256[49]"
+          },
+          "t_mapping(t_bytes32,t_struct(RoleData)253_storage)": {
+            "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)"
+          },
+          "t_struct(RoleData)253_storage": {
+            "label": "struct AccessControlUpgradeable.RoleData",
+            "members": [
+              {
+                "label": "members",
+                "type": "t_mapping(t_address,t_bool)"
+              },
+              {
+                "label": "adminRole",
+                "type": "t_bytes32"
+              }
+            ]
+          },
+          "t_mapping(t_address,t_bool)": {
+            "label": "mapping(address => bool)"
+          },
+          "t_array(t_uint256)50_storage": {
+            "label": "uint256[50]"
+          }
+        }
+      }
+    },
+    "f6018820ce7fbbe1ef233f211940e3c0906fbfcc4905961a2425f2a2cb73adc6": {
+      "address": "0x1d3c18a87DF66cc3F8e176f5bef4CDE0C40D50e7",
+      "txHash": "0x34d0a9e6e27f8833a12fb3cad6842ffe409dc6b49bd941e1b8cea7b2058feab5",
+      "layout": {
+        "storage": [
+          {
+            "contract": "Initializable",
+            "label": "_initialized",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21"
+          },
+          {
+            "contract": "Initializable",
+            "label": "_initializing",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:26"
+          },
+          {
+            "contract": "ContextUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:30"
+          },
+          {
+            "contract": "ERC165Upgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:35"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "_roles",
+            "type": "t_mapping(t_bytes32,t_struct(RoleData)253_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:63"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:219"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "_roleMembers",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:25"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:89"
+          },
+          {
+            "contract": "SkaleManagerClient",
+            "label": "contractManagerOfSkaleManager",
+            "type": "t_contract(IContractManager)6990",
+            "src": "contracts/mainnet/SkaleManagerClient.sol:37"
+          },
+          {
+            "contract": "Twin",
+            "label": "messageProxy",
+            "type": "t_contract(IMessageProxyForMainnet)6403",
+            "src": "contracts/mainnet/Twin.sol:38"
+          },
+          {
+            "contract": "Twin",
+            "label": "schainLinks",
+            "type": "t_mapping(t_bytes32,t_address)",
+            "src": "contracts/mainnet/Twin.sol:39"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "linker",
+            "type": "t_contract(ILinker)6375",
+            "src": "contracts/mainnet/DepositBox.sol:36"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "_automaticDeploy",
+            "type": "t_mapping(t_bytes32,t_bool)",
+            "src": "contracts/mainnet/DepositBox.sol:39"
+          },
+          {
+            "contract": "DepositBoxEth",
+            "label": "approveTransfers",
+            "type": "t_mapping(t_address,t_uint256)",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:39"
+          },
+          {
+            "contract": "DepositBoxEth",
+            "label": "transferredAmount",
+            "type": "t_mapping(t_bytes32,t_uint256)",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:41"
+          },
+          {
+            "contract": "DepositBoxEth",
+            "label": "activeEthTransfers",
+            "type": "t_mapping(t_bytes32,t_bool)",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:43"
+          }
+        ],
+        "types": {
+          "t_mapping(t_address,t_uint256)": {
+            "label": "mapping(address => uint256)"
+          },
+          "t_address": {
+            "label": "address"
+          },
+          "t_uint256": {
+            "label": "uint256"
+          },
+          "t_mapping(t_bytes32,t_uint256)": {
+            "label": "mapping(bytes32 => uint256)"
+          },
+          "t_bytes32": {
+            "label": "bytes32"
+          },
+          "t_mapping(t_bytes32,t_bool)": {
+            "label": "mapping(bytes32 => bool)"
+          },
+          "t_bool": {
+            "label": "bool"
+          },
+          "t_contract(ILinker)6375": {
+            "label": "contract ILinker"
+          },
+          "t_contract(IMessageProxyForMainnet)6403": {
+            "label": "contract IMessageProxyForMainnet"
+          },
+          "t_mapping(t_bytes32,t_address)": {
+            "label": "mapping(bytes32 => address)"
+          },
+          "t_contract(IContractManager)6990": {
+            "label": "contract IContractManager"
+          },
+          "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)": {
+            "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)"
+          },
+          "t_struct(AddressSet)5413_storage": {
+            "label": "struct EnumerableSetUpgradeable.AddressSet",
+            "members": [
+              {
+                "label": "_inner",
+                "type": "t_struct(Set)5112_storage"
+              }
+            ]
+          },
+          "t_struct(Set)5112_storage": {
+            "label": "struct EnumerableSetUpgradeable.Set",
+            "members": [
+              {
+                "label": "_values",
+                "type": "t_array(t_bytes32)dyn_storage"
+              },
+              {
+                "label": "_indexes",
+                "type": "t_mapping(t_bytes32,t_uint256)"
+              }
+            ]
+          },
+          "t_array(t_bytes32)dyn_storage": {
+            "label": "bytes32[]"
+          },
+          "t_array(t_uint256)49_storage": {
+            "label": "uint256[49]"
+          },
+          "t_mapping(t_bytes32,t_struct(RoleData)253_storage)": {
+            "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)"
+          },
+          "t_struct(RoleData)253_storage": {
+            "label": "struct AccessControlUpgradeable.RoleData",
+            "members": [
+              {
+                "label": "members",
+                "type": "t_mapping(t_address,t_bool)"
+              },
+              {
+                "label": "adminRole",
+                "type": "t_bytes32"
+              }
+            ]
+          },
+          "t_mapping(t_address,t_bool)": {
+            "label": "mapping(address => bool)"
+          },
+          "t_array(t_uint256)50_storage": {
+            "label": "uint256[50]"
+          }
+        }
+      }
+    },
+    "2d0379284247816c6b23a6a076ab3f219935512b957bb47be54f37fc2137c316": {
+      "address": "0x1419fE9A82741fe6d9Ab27Fd7e007810a3c1896b",
+      "txHash": "0x9a5753bc7dd5083a1028d47bfcc6a8d2c4614b52fb6c75e6775fcb2f578e398e",
+      "layout": {
+        "storage": [
+          {
+            "contract": "Initializable",
+            "label": "_initialized",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21"
+          },
+          {
+            "contract": "Initializable",
+            "label": "_initializing",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:26"
+          },
+          {
+            "contract": "ContextUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:30"
+          },
+          {
+            "contract": "ERC165Upgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:35"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "_roles",
+            "type": "t_mapping(t_bytes32,t_struct(RoleData)253_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:63"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:219"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "_roleMembers",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:25"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:89"
+          },
+          {
+            "contract": "SkaleManagerClient",
+            "label": "contractManagerOfSkaleManager",
+            "type": "t_contract(IContractManager)6990",
+            "src": "contracts/mainnet/SkaleManagerClient.sol:37"
+          },
+          {
+            "contract": "Twin",
+            "label": "messageProxy",
+            "type": "t_contract(IMessageProxyForMainnet)6403",
+            "src": "contracts/mainnet/Twin.sol:38"
+          },
+          {
+            "contract": "Twin",
+            "label": "schainLinks",
+            "type": "t_mapping(t_bytes32,t_address)",
+            "src": "contracts/mainnet/Twin.sol:39"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "linker",
+            "type": "t_contract(ILinker)6375",
+            "src": "contracts/mainnet/DepositBox.sol:36"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "_automaticDeploy",
+            "type": "t_mapping(t_bytes32,t_bool)",
+            "src": "contracts/mainnet/DepositBox.sol:39"
+          },
+          {
+            "contract": "DepositBoxERC20",
+            "label": "_deprecatedSchainToERC20",
+            "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:51"
+          },
+          {
+            "contract": "DepositBoxERC20",
+            "label": "transferredAmount",
+            "type": "t_mapping(t_bytes32,t_mapping(t_address,t_uint256))",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:52"
+          },
+          {
+            "contract": "DepositBoxERC20",
+            "label": "_schainToERC20",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:53"
+          }
+        ],
+        "types": {
+          "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": {
+            "label": "mapping(bytes32 => mapping(address => bool))"
+          },
+          "t_bytes32": {
+            "label": "bytes32"
+          },
+          "t_mapping(t_address,t_bool)": {
+            "label": "mapping(address => bool)"
+          },
+          "t_address": {
+            "label": "address"
+          },
+          "t_bool": {
+            "label": "bool"
+          },
+          "t_mapping(t_bytes32,t_mapping(t_address,t_uint256))": {
+            "label": "mapping(bytes32 => mapping(address => uint256))"
+          },
+          "t_mapping(t_address,t_uint256)": {
+            "label": "mapping(address => uint256)"
+          },
+          "t_uint256": {
+            "label": "uint256"
+          },
+          "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)": {
+            "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)"
+          },
+          "t_struct(AddressSet)5413_storage": {
+            "label": "struct EnumerableSetUpgradeable.AddressSet",
+            "members": [
+              {
+                "label": "_inner",
+                "type": "t_struct(Set)5112_storage"
+              }
+            ]
+          },
+          "t_struct(Set)5112_storage": {
+            "label": "struct EnumerableSetUpgradeable.Set",
+            "members": [
+              {
+                "label": "_values",
+                "type": "t_array(t_bytes32)dyn_storage"
+              },
+              {
+                "label": "_indexes",
+                "type": "t_mapping(t_bytes32,t_uint256)"
+              }
+            ]
+          },
+          "t_array(t_bytes32)dyn_storage": {
+            "label": "bytes32[]"
+          },
+          "t_mapping(t_bytes32,t_uint256)": {
+            "label": "mapping(bytes32 => uint256)"
+          },
+          "t_contract(ILinker)6375": {
+            "label": "contract ILinker"
+          },
+          "t_mapping(t_bytes32,t_bool)": {
+            "label": "mapping(bytes32 => bool)"
+          },
+          "t_contract(IMessageProxyForMainnet)6403": {
+            "label": "contract IMessageProxyForMainnet"
+          },
+          "t_mapping(t_bytes32,t_address)": {
+            "label": "mapping(bytes32 => address)"
+          },
+          "t_contract(IContractManager)6990": {
+            "label": "contract IContractManager"
+          },
+          "t_array(t_uint256)49_storage": {
+            "label": "uint256[49]"
+          },
+          "t_mapping(t_bytes32,t_struct(RoleData)253_storage)": {
+            "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)"
+          },
+          "t_struct(RoleData)253_storage": {
+            "label": "struct AccessControlUpgradeable.RoleData",
+            "members": [
+              {
+                "label": "members",
+                "type": "t_mapping(t_address,t_bool)"
+              },
+              {
+                "label": "adminRole",
+                "type": "t_bytes32"
+              }
+            ]
+          },
+          "t_array(t_uint256)50_storage": {
+            "label": "uint256[50]"
+          }
+        }
+      }
+    },
+    "68e72e32699694afe1325120cd744d12529260b738ae609394cb1b0791a00d69": {
+      "address": "0x5C6Cbec4dbDbb5176BbfbF68aA33AbF4b49a116c",
+      "txHash": "0xdbb9bff59832d263528c7d49d4fb6985150935b25e443000f2fddbf4920a857d",
+      "layout": {
+        "storage": [
+          {
+            "contract": "Initializable",
+            "label": "_initialized",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21"
+          },
+          {
+            "contract": "Initializable",
+            "label": "_initializing",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:26"
+          },
+          {
+            "contract": "ContextUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:30"
+          },
+          {
+            "contract": "ERC165Upgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:35"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "_roles",
+            "type": "t_mapping(t_bytes32,t_struct(RoleData)253_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:63"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:219"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "_roleMembers",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:25"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:89"
+          },
+          {
+            "contract": "SkaleManagerClient",
+            "label": "contractManagerOfSkaleManager",
+            "type": "t_contract(IContractManager)6990",
+            "src": "contracts/mainnet/SkaleManagerClient.sol:37"
+          },
+          {
+            "contract": "Twin",
+            "label": "messageProxy",
+            "type": "t_contract(IMessageProxyForMainnet)6403",
+            "src": "contracts/mainnet/Twin.sol:38"
+          },
+          {
+            "contract": "Twin",
+            "label": "schainLinks",
+            "type": "t_mapping(t_bytes32,t_address)",
+            "src": "contracts/mainnet/Twin.sol:39"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "linker",
+            "type": "t_contract(ILinker)6375",
+            "src": "contracts/mainnet/DepositBox.sol:36"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "_automaticDeploy",
+            "type": "t_mapping(t_bytes32,t_bool)",
+            "src": "contracts/mainnet/DepositBox.sol:39"
+          },
+          {
+            "contract": "DepositBoxERC721",
+            "label": "_deprecatedSchainToERC721",
+            "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:44"
+          },
+          {
+            "contract": "DepositBoxERC721",
+            "label": "transferredAmount",
+            "type": "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:45"
+          },
+          {
+            "contract": "DepositBoxERC721",
+            "label": "_schainToERC721",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:46"
+          }
+        ],
+        "types": {
+          "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": {
+            "label": "mapping(bytes32 => mapping(address => bool))"
+          },
+          "t_bytes32": {
+            "label": "bytes32"
+          },
+          "t_mapping(t_address,t_bool)": {
+            "label": "mapping(address => bool)"
+          },
+          "t_address": {
+            "label": "address"
+          },
+          "t_bool": {
+            "label": "bool"
+          },
+          "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))": {
+            "label": "mapping(address => mapping(uint256 => bytes32))"
+          },
+          "t_mapping(t_uint256,t_bytes32)": {
+            "label": "mapping(uint256 => bytes32)"
+          },
+          "t_uint256": {
+            "label": "uint256"
+          },
+          "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)": {
+            "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)"
+          },
+          "t_struct(AddressSet)5413_storage": {
+            "label": "struct EnumerableSetUpgradeable.AddressSet",
+            "members": [
+              {
+                "label": "_inner",
+                "type": "t_struct(Set)5112_storage"
+              }
+            ]
+          },
+          "t_struct(Set)5112_storage": {
+            "label": "struct EnumerableSetUpgradeable.Set",
+            "members": [
+              {
+                "label": "_values",
+                "type": "t_array(t_bytes32)dyn_storage"
+              },
+              {
+                "label": "_indexes",
+                "type": "t_mapping(t_bytes32,t_uint256)"
+              }
+            ]
+          },
+          "t_array(t_bytes32)dyn_storage": {
+            "label": "bytes32[]"
+          },
+          "t_mapping(t_bytes32,t_uint256)": {
+            "label": "mapping(bytes32 => uint256)"
+          },
+          "t_contract(ILinker)6375": {
+            "label": "contract ILinker"
+          },
+          "t_mapping(t_bytes32,t_bool)": {
+            "label": "mapping(bytes32 => bool)"
+          },
+          "t_contract(IMessageProxyForMainnet)6403": {
+            "label": "contract IMessageProxyForMainnet"
+          },
+          "t_mapping(t_bytes32,t_address)": {
+            "label": "mapping(bytes32 => address)"
+          },
+          "t_contract(IContractManager)6990": {
+            "label": "contract IContractManager"
+          },
+          "t_array(t_uint256)49_storage": {
+            "label": "uint256[49]"
+          },
+          "t_mapping(t_bytes32,t_struct(RoleData)253_storage)": {
+            "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)"
+          },
+          "t_struct(RoleData)253_storage": {
+            "label": "struct AccessControlUpgradeable.RoleData",
+            "members": [
+              {
+                "label": "members",
+                "type": "t_mapping(t_address,t_bool)"
+              },
+              {
+                "label": "adminRole",
+                "type": "t_bytes32"
+              }
+            ]
+          },
+          "t_array(t_uint256)50_storage": {
+            "label": "uint256[50]"
+          }
+        }
+      }
+    },
+    "a381826594fabffcf27c98e96cd4847c95a227f315ac3dabd70733a9a691890e": {
+      "address": "0xDdE9fC39471F1D119b9928994c555E7296752b9A",
+      "txHash": "0xa5ab5878caa087b86012bf0511d59586ee5bb31cabe24dd197678bdd9de3b87c",
+      "layout": {
+        "storage": [
+          {
+            "contract": "Initializable",
+            "label": "_initialized",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21"
+          },
+          {
+            "contract": "Initializable",
+            "label": "_initializing",
+            "type": "t_bool",
+            "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:26"
+          },
+          {
+            "contract": "ContextUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:30"
+          },
+          {
+            "contract": "ERC165Upgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:35"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "_roles",
+            "type": "t_mapping(t_bytes32,t_struct(RoleData)253_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:63"
+          },
+          {
+            "contract": "AccessControlUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:219"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "_roleMembers",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:25"
+          },
+          {
+            "contract": "AccessControlEnumerableUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)49_storage",
+            "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:89"
+          },
+          {
+            "contract": "SkaleManagerClient",
+            "label": "contractManagerOfSkaleManager",
+            "type": "t_contract(IContractManager)6990",
+            "src": "contracts/mainnet/SkaleManagerClient.sol:37"
+          },
+          {
+            "contract": "Twin",
+            "label": "messageProxy",
+            "type": "t_contract(IMessageProxyForMainnet)6403",
+            "src": "contracts/mainnet/Twin.sol:38"
+          },
+          {
+            "contract": "Twin",
+            "label": "schainLinks",
+            "type": "t_mapping(t_bytes32,t_address)",
+            "src": "contracts/mainnet/Twin.sol:39"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "linker",
+            "type": "t_contract(ILinker)6375",
+            "src": "contracts/mainnet/DepositBox.sol:36"
+          },
+          {
+            "contract": "DepositBox",
+            "label": "_automaticDeploy",
+            "type": "t_mapping(t_bytes32,t_bool)",
+            "src": "contracts/mainnet/DepositBox.sol:39"
+          },
+          {
+            "contract": "ERC1155ReceiverUpgradeable",
+            "label": "__gap",
+            "type": "t_array(t_uint256)50_storage",
+            "src": "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol:26"
+          },
+          {
+            "contract": "DepositBoxERC1155",
+            "label": "_deprecatedSchainToERC1155",
+            "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:47"
+          },
+          {
+            "contract": "DepositBoxERC1155",
+            "label": "transferredAmount",
+            "type": "t_mapping(t_bytes32,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:48"
+          },
+          {
+            "contract": "DepositBoxERC1155",
+            "label": "_schainToERC1155",
+            "type": "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)",
+            "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:49"
+          }
+        ],
+        "types": {
+          "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": {
+            "label": "mapping(bytes32 => mapping(address => bool))"
+          },
+          "t_bytes32": {
+            "label": "bytes32"
+          },
+          "t_mapping(t_address,t_bool)": {
+            "label": "mapping(address => bool)"
+          },
+          "t_address": {
+            "label": "address"
+          },
+          "t_bool": {
+            "label": "bool"
+          },
+          "t_mapping(t_bytes32,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))": {
+            "label": "mapping(bytes32 => mapping(address => mapping(uint256 => uint256)))"
+          },
+          "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": {
+            "label": "mapping(address => mapping(uint256 => uint256))"
+          },
+          "t_mapping(t_uint256,t_uint256)": {
+            "label": "mapping(uint256 => uint256)"
+          },
+          "t_uint256": {
+            "label": "uint256"
+          },
+          "t_mapping(t_bytes32,t_struct(AddressSet)5413_storage)": {
+            "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)"
+          },
+          "t_struct(AddressSet)5413_storage": {
+            "label": "struct EnumerableSetUpgradeable.AddressSet",
+            "members": [
+              {
+                "label": "_inner",
+                "type": "t_struct(Set)5112_storage"
+              }
+            ]
+          },
+          "t_struct(Set)5112_storage": {
+            "label": "struct EnumerableSetUpgradeable.Set",
+            "members": [
+              {
+                "label": "_values",
+                "type": "t_array(t_bytes32)dyn_storage"
+              },
+              {
+                "label": "_indexes",
+                "type": "t_mapping(t_bytes32,t_uint256)"
+              }
+            ]
+          },
+          "t_array(t_bytes32)dyn_storage": {
+            "label": "bytes32[]"
+          },
+          "t_mapping(t_bytes32,t_uint256)": {
+            "label": "mapping(bytes32 => uint256)"
+          },
+          "t_array(t_uint256)50_storage": {
+            "label": "uint256[50]"
+          },
+          "t_contract(ILinker)6375": {
+            "label": "contract ILinker"
+          },
+          "t_mapping(t_bytes32,t_bool)": {
+            "label": "mapping(bytes32 => bool)"
+          },
+          "t_contract(IMessageProxyForMainnet)6403": {
+            "label": "contract IMessageProxyForMainnet"
+          },
+          "t_mapping(t_bytes32,t_address)": {
+            "label": "mapping(bytes32 => address)"
+          },
+          "t_contract(IContractManager)6990": {
+            "label": "contract IContractManager"
+          },
+          "t_array(t_uint256)49_storage": {
+            "label": "uint256[49]"
+          },
+          "t_mapping(t_bytes32,t_struct(RoleData)253_storage)": {
+            "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)"
+          },
+          "t_struct(RoleData)253_storage": {
+            "label": "struct AccessControlUpgradeable.RoleData",
+            "members": [
+              {
+                "label": "members",
+                "type": "t_mapping(t_address,t_bool)"
+              },
+              {
+                "label": "adminRole",
+                "type": "t_bytes32"
+              }
+            ]
+          }
+        }
+      }
     }
   }
 }
diff --git a/proxy/DEPLOYED b/proxy/DEPLOYED
index 52f2c31b1..a939f53a1 100644
--- a/proxy/DEPLOYED
+++ b/proxy/DEPLOYED
@@ -1,1 +1,1 @@
-1.3.0-stable.0
\ No newline at end of file
+1.3.2-stable.1
\ No newline at end of file
diff --git a/proxy/migrations/deploySkaleManagerComponents.ts b/proxy/migrations/deploySkaleManagerComponents.ts
index 680e49e2f..943d947da 100644
--- a/proxy/migrations/deploySkaleManagerComponents.ts
+++ b/proxy/migrations/deploySkaleManagerComponents.ts
@@ -29,7 +29,7 @@ import { getAbi } from './tools/abi';
 import { Manifest, hashBytecode } from "@openzeppelin/upgrades-core";
 import { KeyStorageMock } from '../typechain/KeyStorageMock';
 import { Wallet } from 'ethers';
-import { getPublicKey, stringValue } from '../test/utils/helper';
+import { getPublicKey } from '../test/utils/helper';
 
 export function getContractKeyInAbiFile(contract: string) {
     return contract.replace(/([a-z0-9])(?=[A-Z])/g, '$1_').toLowerCase();
@@ -75,6 +75,16 @@ async function main() {
         process.exit( 126 );
     }
 
+    if ( process.env.PRIVATE_KEY_FOR_ETHEREUM === undefined || process.env.PRIVATE_KEY_FOR_ETHEREUM === "" ) {
+        console.log( "Please set PRIVATE_KEY_FOR_ETHEREUM to .env file" );
+        process.exit( 127 );
+    }
+
+    if ( process.env.PRIVATE_KEY_FOR_SCHAIN === undefined || process.env.PRIVATE_KEY_FOR_SCHAIN === "" ) {
+        console.log( "Please set PRIVATE_KEY_FOR_ETHEREUM to .env file" );
+        process.exit( 128 );
+    }
+
     const schainName = process.env.CHAIN_NAME_SCHAIN;
 
     console.log("Deploy ContractManager");
@@ -132,8 +142,8 @@ async function main() {
     console.log("Set KeyStorage", keyStorage.address, "to ContractManager", contractManager.address, "\n");
     await contractManager.setContractsAddress( "Nodes", nodes.address );
     console.log("Set Nodes", nodes.address, "to ContractManager", contractManager.address, "\n");
-    const nodeAddress1 = new Wallet(stringValue(process.env.PRIVATE_KEY_FOR_ETHEREUM)).connect(ethers.provider);
-    const nodeAddress2 = new Wallet(stringValue(process.env.PRIVATE_KEY_FOR_SCHAIN)).connect(ethers.provider);
+    const nodeAddress1 = new Wallet(process.env.PRIVATE_KEY_FOR_ETHEREUM).connect(ethers.provider);
+    const nodeAddress2 = new Wallet(process.env.PRIVATE_KEY_FOR_SCHAIN).connect(ethers.provider);
     await owner.sendTransaction({to: nodeAddress1.address, value: ethers.utils.parseEther("1")});
     await owner.sendTransaction({to: nodeAddress2.address, value: ethers.utils.parseEther("1")});
 
@@ -161,7 +171,7 @@ async function main() {
     console.log("Create Node 1 with address", nodeAddress2.address, "\n");
     await schainsInternal.initializeSchain( schainName, owner.address, 1, 1 );
     console.log("Initialize Schain", schainName, "with address", owner.address, "\n");
-    await schainsInternal.connect(owner).addNodesToSchainsGroups(stringValue(ethers.utils.id(schainName)), [0, 1]);
+    await schainsInternal.connect(owner).addNodesToSchainsGroups(ethers.utils.id(schainName), [0, 1]);
     console.log("Add Nodes 0 and 1 to schain", schainName, "\n");
     const BLSPublicKey = {
         x: {
diff --git a/proxy/migrations/upgradeMainnet.ts b/proxy/migrations/upgradeMainnet.ts
index 3a63275b3..a9951d8c3 100644
--- a/proxy/migrations/upgradeMainnet.ts
+++ b/proxy/migrations/upgradeMainnet.ts
@@ -3,7 +3,7 @@ import { upgrade } from "./upgrade";
 
 async function main() {
     await upgrade(
-        "1.3.0",
+        "1.3.2",
         contracts,
         async (safeTransactions, abi) => undefined,
         async (safeTransactions, abi) => undefined,
diff --git a/proxy/migrations/upgradeSchain.ts b/proxy/migrations/upgradeSchain.ts
index f54d9a7f7..f787263dd 100644
--- a/proxy/migrations/upgradeSchain.ts
+++ b/proxy/migrations/upgradeSchain.ts
@@ -14,7 +14,7 @@ async function main() {
     const pathToManifest: string = stringValue(process.env.MANIFEST);
     await manifestSetup( pathToManifest );
     await upgrade(
-        "1.3.0",
+        "1.3.2",
         contracts,
         async (safeTransactions, abi) => {
             // deploying of new contracts


Test patch:
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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @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 <https://github.com/coturn/coturn> and see <https://www.allerstorfer.at/install-coturn-on-ubuntu/>
-//     // Explanation for Mac OSX is <https://medium.com/@ittipon.bay/how-to-setup-coturn-for-mac-a3c4a6ba4db8>
-//     //
-//     // Install via **sudo apt-get install coturn** or **brew install coturn**.
-//     // Run **sudo nano /etc/turnserver.conf** and specify described in <https://www.allerstorfer.at/install-coturn-on-ubuntu/>,
-//     // 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/test_server.js
deleted file mode 100644
index 32283918d..000000000
--- a/npms/skale-cool-socket/test_server.js
+++ /dev/null
@@ -1,47 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @file test_server.js
- * @copyright SKALE Labs 2019-Present
- */
-
-const { Server } = require( "./server.js" );
-
-class TestServer extends Server {
-    constructor( acceptor ) {
-        super( acceptor );
-        const self = this;
-        self.mapApiHandlers.echo = function( joMessage, joAnswer, eventData, socket ) {
-            console.log( "SERVER <<<", JSON.stringify( joMessage ) );
-            joAnswer.message = joMessage.message ? joMessage.message : "<no message echo>";
-            console.log( "SERVER >>>", JSON.stringify( joAnswer ) );
-            return joAnswer;
-        };
-    }
-    dispose() {
-        this.isDisposing = true;
-        super.dispose();
-    }
-};
-
-module.exports = {
-    TestServer: TestServer
-};
diff --git a/npms/skale-cool-socket/test_signaling_server.js b/npms/skale-cool-socket/test_signaling_server.js
deleted file mode 100644
index 736839c19..000000000
--- a/npms/skale-cool-socket/test_signaling_server.js
+++ /dev/null
@@ -1,734 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @file test_signaling_server.js
- * @copyright SKALE Labs 2019-Present
- */
-
-const fs = require( "fs" );
-
-const https_loaded_mod = require( "https" );
-const ws_loaded_mod = require( "ws" );
-const wrtc_loaded_mod = require( "wrtc" );
-
-const network_layer = require( "./socket.js" );
-const { settings } = require( "./settings.js" );
-const { UniversalDispatcherEvent, EventDispatcher } = require( "./event_dispatcher.js" );
-const utils = require( "./utils.js" );
-
-// 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;
-
-network_layer.set_https_mod( https_mod );
-network_layer.set_ws_mod( ws_mod );
-network_layer.set_wrtc_mod( wrtc_mod );
-
-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.isCreator = ( strRole == "creator" ) ? true : false;
-        this.isJoiner = ( strRole == "joiner" ) ? true : false;
-        this.signalingSpace = signalingSpace;
-        this.socket = socket;
-        socket.signalingClient = this;
-        if( this.isCreator )
-            this.signalingSpace.idSomebodyCreator = "" + this.idRtcParticipant;
-        this.signalingSpace.map_clients[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 } } ) );
-    }
-    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 + "\"" );
-        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.idRtcParticipant = null;
-        }
-        if( this.isCreator ) {
-            if( this.signalingSpace )
-                this.signalingSpace.idSomebodyCreator = "";
-        }
-        this.isCreator = false;
-        this.isJoiner = false;
-        this.idSpace = null;
-        this.idCategory = null;
-        this.signalingSpace.autoDispose();
-        this.signalingSpace = null;
-        super.dispose();
-    }
-    disconnect() {
-        if( this.isDisposed || ( !this.socket ) )
-            return;
-        this.offerDiscoveryStop();
-        let bPass = false, anyError = null;
-        try {
-            this.socket.disconnect();
-            bPass = true;
-        } catch ( err ) {
-            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 );
-        }
-        //
-        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 + "\"" );
-    }
-    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 + "\"" );
-        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 + "\"" );
-        this.offerDiscoveryStop();
-        this.dispose();
-    }
-    offerDiscoveryStop() {
-        if( ! this.isFetchingOffer )
-            return;
-        if( this.timerFetchingOffer ) {
-            clearInterval( this.timerFetchingOffer );
-            this.timerFetchingOffer = null;
-        }
-        this.isFetchingOffer = false;
-        this.fetchingOfferStepNumber = 0;
-    }
-    offerDiscoveryStart( joMessage ) {
-        if( this.isFetchingOffer )
-            return;
-        this.isFetchingOffer = true;
-        this.offerDiscoveryStep( joMessage );
-    }
-    offerDiscoveryStep( joMessage ) {
-        if( ! this.isFetchingOffer )
-            return;
-        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( this.fetchingOfferStepNumber >= settings.net.rtc.offerDiscovery.stepCount ) {
-                    this.offerDiscoveryStop();
-                    throw new Error( "no offer found" );
-                }
-                if( ! this.timerFetchingOffer ) {
-                    const self = this;
-                    this.timerFetchingOffer = setInterval( function() {
-                        self.offerDiscoveryStep( joMessage );
-                    }, settings.net.rtc.offerDiscovery.periodMilliseconds );
-                }
-                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 );
-            }
-            joAnswer = utils.prepareAnswerJSON( joMessage ); // successful answer
-            joAnswer.offer = joOfferInfo.offer;
-            joAnswer.idOffer = 0 + joOfferInfo.idOffer;
-            joAnswer.idSomebodyCreator = joOfferInfo.idSomebodyCreator; // server holder
-        } catch ( err ) {
-            if( settings.logging.net.signaling.error )
-                console.warn( "Server method", joMessage.method, "RPC exception:", err );
-            joAnswer = utils.prepareAnswerJSON( joMessage );
-            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 );
-        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.idSomebodyCreator = "";
-        this.arr_published_offers = [];
-        this.signalingCategory = signalingCategory;
-        this.map_clients = {};
-        this.signalingCategory.map_spaces[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 } } ) );
-    }
-    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 ) )
-            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.idSpace = null;
-        }
-        this.idCategory = null;
-        this.signalingCategory.autoDispose();
-        this.signalingCategory = null;
-        this.arr_published_offers = [];
-        super.dispose();
-    }
-    autoDispose() {
-        if( this.isDisposed )
-            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 + "\"" );
-        this.dispose();
-    }
-    allSomebodyIDs() {
-        if( this.isDisposed )
-            return [];
-        return Object.keys( this.map_clients );
-    }
-    clientGet( idRtcParticipant ) {
-        if( this.isDisposed )
-            return null;
-        const signalingClient = this.map_clients[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];
-            signalingClient.dispose();
-            this.autoDispose();
-            return true;
-        }
-        return false;
-    }
-    fetchPublishedOffer() {
-        if( this.isDisposed || this.isDisposing ) {
-            if( settings.logging.net.signaling.offerDiscoveryStepFail )
-                console.warn( "Attempt to fetch offer in destroyed signaling space" );
-            return null;
-        }
-        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( 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 );
-        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.signalingManager = signalingManager;
-        this.map_spaces = {};
-        this.signalingManager.map_categories[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 } } ) );
-    }
-    dispose() {
-        if( this.isDisposed )
-            return;
-        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 ) )
-            signalingSpace.dispose();
-        if( this.signalingManager ) {
-            delete this.signalingManager.map_categories[this.idCategory];
-            this.signalingManager.dispatchEvent( new UniversalDispatcherEvent( "categoryRemoved", { detail: { signalingCategory: this } } ) );
-            this.signalingManager = null;
-        }
-        this.map_spaces = {};
-        this.idCategory = null;
-        super.dispose();
-    }
-    autoDispose() {
-        if( this.isDisposed )
-            return;
-        if( this.allCSpaceIDs().length > 0 )
-            return;
-        if( settings.logging.net.signaling.objectLifetime )
-            console.log( "Auto-dispose signaling category \"" + this.idCategory + "\"" );
-        this.dispose();
-    }
-    allCSpaceIDs() {
-        if( this.isDisposed )
-            return [];
-        return Object.keys( this.map_spaces );
-    }
-    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 );
-            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 );
-            return signalingSpace;
-        } catch ( err ) {
-            if( settings.logging.net.signaling.error )
-                console.warn( "Signaling space retrieval error:", err );
-            return null;
-        }
-    }
-    spaceRemove( idSpace ) {
-        if( this.isDisposed )
-            return false;
-        idSpace = "" + ( idSpace ? idSpace.toString() : idSpace.rtcSpace.defaultSpaceName );
-        if( idSpace in this.map_spaces ) {
-            const signalingSpace = this.map_spaces[idSpace];
-            signalingSpace.dispose();
-            this.autoDispose();
-            return true;
-        }
-        return false;
-    }
-    fetchPublishedOffer() {
-        if( this.isDisposed )
-            return null;
-        for( const [ /*idSpace*/, signalingSpace ] of Object.entries( this.map_spaces ) ) {
-            const joOfferInfo = signalingSpace.fetchPublishedOffer();
-            if( joOfferInfo )
-                return joOfferInfo;
-        }
-        return null;
-    }
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-class SignalingManager extends EventDispatcher {
-    constructor() {
-        super();
-        this.isDisposed = false;
-        this.map_categories = {};
-        if( settings.logging.net.signaling.objectLifetime )
-            console.log( "New signaling manager" );
-    }
-    dispose() {
-        if( this.isDisposed )
-            return;
-        this.isDisposing = true;
-        if( settings.logging.net.signaling.objectLifetime )
-            console.log( "Disposing signaling manager" );
-        for( const [ /*idCategory*/, signalingCategory ] of Object.entries( this.map_categories ) )
-            signalingCategory.dispose();
-        this.map_categories = {};
-        super.dispose();
-    }
-    allCategoryIDs() {
-        return Object.keys( this.map_categories );
-    }
-    categoryGet( idCategory, isAutoAlloc ) {
-        try {
-            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 );
-            return signalingCategory;
-        } catch ( err ) {
-            if( settings.logging.net.signaling.error )
-                console.warn( "Signaling category retrieval error:", err );
-            return null;
-        }
-    }
-    categoryRemove( idCategory ) {
-        idCategory = "" + ( idCategory ? idCategory.toString() : settings.rtcSpace.defaultSpaceName );
-        if( idCategory in this.map_categories ) {
-            const signalingCategory = this.map_categories[idCategory];
-            signalingCategory.dispose();
-            return true;
-        }
-        return false;
-    }
-};
-
-const g_default_signaling_manager = new SignalingManager();
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-class SignalingServer extends EventDispatcher {
-    constructor( acceptor, signalingManager ) {
-        super();
-        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;
-        const self = this;
-        acceptor.on( "connection", function( eventData ) {
-            const socket = eventData.socket;
-            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 + "\"" );
-            socket.signalingAuthInfo = {
-                isAuthorized: false,
-                idCategory: null,
-                idSpaceSpace: null,
-                idRtcParticipant: null
-            };
-            let _offAllPipeEventListeners = null;
-            let _onPipeClose = function() {
-                if( settings.logging.net.signaling.disconnect )
-                    console.warn( "Signaling client socket closed \"" + socket.strSavedRemoteAddress + "\"" );
-                if( _offAllPipeEventListeners ) {
-                    _offAllPipeEventListeners();
-                    _offAllPipeEventListeners = null;
-                }
-                if( socket.signalingClient ) {
-                    socket.signalingClient.onPipeClose( socket );
-                    socket.signalingClient = null;
-                }
-            };
-            let _onPipeError = function( eventData ) {
-                if( settings.logging.net.signaling.error )
-                    console.warn( "Socket error \"" + socket.strSavedRemoteAddress + "\"" );
-                if( _offAllPipeEventListeners ) {
-                    _offAllPipeEventListeners();
-                    _offAllPipeEventListeners = null;
-                }
-                if( socket.signalingClient ) {
-                    socket.signalingClient.onPipeError( socket );
-                    socket.signalingClient = null;
-                }
-            };
-            let _onPipeMessage = function( 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 );
-                let signalingCategory = null;
-                let signalingSpace = null;
-                let signalingClient = socket.signalingClient;
-                if( signalingClient ) {
-                    signalingSpace = signalingClient.signalingSpace;
-                    if( signalingSpace )
-                        signalingCategory = signalingSpace.signalingCategory;
-                }
-                let joAnswer = null;
-                let isForceDisconnect = false;
-                try {
-                    switch ( joMessage.method ) {
-                    case "signalingListSpaces": {
-                        joAnswer = utils.prepareAnswerJSON( joMessage );
-                        joAnswer.arrSpaces = self.gamingSpaceManager.allNames();
-                    } break;
-                    case "signalingImpersonate": {
-                        const idRtcParticipant = joMessage.idRtcParticipant;
-                        if( ( !idRtcParticipant ) || typeof idRtcParticipant != "string" || idRtcParticipant.length <= 0 ) {
-                            isForceDisconnect = true;
-                            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" ) ) ) {
-                            isForceDisconnect = true;
-                            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 ) {
-                            isForceDisconnect = true;
-                            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" );
-                        }
-                        //
-                        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" );
-                        }
-                        signalingSpace = signalingCategory.spaceGet( idSpace, true );
-                        if( ! signalingSpace ) {
-                            isForceDisconnect = true;
-                            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" );
-                        }
-                        //
-                        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 );
-                        if( settings.logging.net.signaling.impersonate ) {
-                            isForceDisconnect = true;
-                            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 ) );
-                    } break;
-                    case "signalingPublishOffer": {
-                        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
-                        };
-                        signalingSpace.arr_published_offers.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 );
-                        }
-                        joAnswer = utils.prepareAnswerJSON( joMessage ); // successful answer
-                    } break;
-                    case "signalingFetchOffer": {
-                        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 );
-                        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
-                        // 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 );
-                    } break;
-                    } // switch( joMessage.method )
-                } catch ( err ) {
-                    if( settings.logging.net.signaling.error )
-                        console.warn( "Server method", joMessage.method, "RPC exception:", err );
-                    joAnswer = utils.prepareAnswerJSON( joMessage );
-                    joAnswer.error = "" + err.toString();
-                }
-                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 );
-                    socket.send( joAnswer, true ); // isFlush=true always in signaling server
-                    if( isForceDisconnect )
-                        socket.disconnect();
-                }
-                if( signalingSpace )
-                    signalingSpace.autoDispose();
-                if( signalingCategory )
-                    signalingCategory.autoDispose();
-            };
-            _offAllPipeEventListeners = function() {
-                if( _onPipeClose ) {
-                    socket.off( "close", _onPipeClose );
-                    _onPipeClose = null;
-                }
-                if( _onPipeError ) {
-                    socket.off( "error", _onPipeError );
-                    _onPipeError = null;
-                }
-                if( _onPipeMessage ) {
-                    socket.off( "message", _onPipeMessage );
-                    _onPipeMessage = null;
-                }
-                let signalingSpace = null;
-                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( signalingSpace )
-                        signalingSpace.clientRemove( signalingClient.idRtcParticipant );
-
-                    signalingClient.dispose();
-                }
-                socket.signalingClient = null;
-            };
-            socket.on( "close", _onPipeClose );
-            socket.on( "error", _onPipeError );
-            socket.on( "message", _onPipeMessage );
-        } );
-        this.dispatchEvent( new UniversalDispatcherEvent( "initialized", { detail: { ref: this } } ) );
-    }
-    dispose() {
-        this.isDisposing = true;
-        super.dispose();
-    }
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-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 );
-let signalingServer = new SignalingServer( acceptor );
-signalingServer.on( "initialized", function() {
-    if( settings.logging.net.signaling.generic )
-        console.log( protoName + " signaling server did started" );
-} );
-signalingServer.on( "dispose", function() {
-    if( settings.logging.net.signaling.generic )
-        console.log( protoName + " signaling server did stopped" );
-} );
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-let g_bShouldExit = false, g_bProcessExitRequested = false;
-function exit_if_needed() {
-    if( ! g_bShouldExit )
-        return;
-    if( g_bProcessExitRequested )
-        return;
-    // ensure components stopped here, if needed
-    g_bProcessExitRequested = true;
-    console.log( "App will exit" );
-    process.exit( 0 );
-}
-
-process.on( "SIGINT", function() {
-    console.warn( "\nApp did caught interrupt signal " );
-    // stop components here, if needed
-    if( signalingServer ) {
-        console.log( "Will stop signaling server" );
-        signalingServer.dispose();
-        signalingServer = null;
-        console.log( "Did stopped signaling server" );
-    }
-    if( acceptor ) {
-        console.log( "Will stop signaling acceptor" );
-        acceptor.dispose();
-        acceptor = null;
-        console.log( "Did stopped signaling acceptor" );
-    }
-    g_bShouldExit = true;
-    //
-    exit_if_needed();
-    g_bShouldExit = true;
-} );
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/npms/skale-cool-socket/test_worker.js b/npms/skale-cool-socket/test_worker.js
deleted file mode 100644
index a315cf581..000000000
--- a/npms/skale-cool-socket/test_worker.js
+++ /dev/null
@@ -1,52 +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 <https://www.gnu.org/licenses/>.
- */
-
-/**
- * @file test_worker.js
- * @copyright SKALE Labs 2019-Present
- */
-
-const network_layer = require( "./socket.js" );
-const { TestServer } = require( "./test_server.js" );
-const {
-    parentPort
-    //, workerData
-} = require( "worker_threads" );
-
-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 ) );
-}
-
-const url = "local_worker_server";
-const acceptor = new network_layer.InWorkerSocketServerAcceptor( url, doSendMessage );
-const server = new TestServer( acceptor );
-server.on( "dispose", function() { console.log( "disposed in-worker server" ); } );
diff --git a/proxy/scripts/test_upgrade.sh b/proxy/scripts/test_upgrade.sh
index 5778acbd4..3945fbcc7 100644
--- a/proxy/scripts/test_upgrade.sh
+++ b/proxy/scripts/test_upgrade.sh
@@ -10,12 +10,15 @@ DEPLOYED_DIR=$GITHUB_WORKSPACE/deployed-proxy/
 
 git clone --branch "$DEPLOYED_TAG" "https://github.com/$GITHUB_REPOSITORY.git" "$DEPLOYED_DIR"
 
-npx ganache-cli --gasLimit 9000000 --quiet --allowUnlimitedContractSize &
+ACCOUNTS_FILENAME="$DEPLOYED_DIR/proxy/generatedAccounts.json"
+npx ganache-cli --gasLimit 9000000 --quiet --allowUnlimitedContractSize --account_keys_path "$ACCOUNTS_FILENAME" &
 
 cd "$DEPLOYED_DIR"
 yarn install
 cd proxy
-CHAIN_NAME_SCHAIN="Test" VERSION="$DEPLOYED_VERSION" npx hardhat run migrations/deploySkaleManagerComponents.ts --network localhost
+PRIVATE_KEY_FOR_ETHEREUM=$(cat "$ACCOUNTS_FILENAME" | jq -r  '.private_keys | to_entries | .[8].value')
+PRIVATE_KEY_FOR_SCHAIN=$(cat "$ACCOUNTS_FILENAME" | jq -r '.private_keys | to_entries | .[9].value')
+CHAIN_NAME_SCHAIN="Test" VERSION="$DEPLOYED_VERSION" PRIVATE_KEY_FOR_ETHEREUM="$PRIVATE_KEY_FOR_ETHEREUM" PRIVATE_KEY_FOR_SCHAIN="$PRIVATE_KEY_FOR_SCHAIN" npx hardhat run migrations/deploySkaleManagerComponents.ts --network localhost
 VERSION="$DEPLOYED_VERSION" npx hardhat run migrations/deployMainnet.ts --network localhost
 CHAIN_NAME_SCHAIN="Test" VERSION="$DEPLOYED_VERSION" npx hardhat run migrations/deploySchain.ts --network localhost
 cp "$GITHUB_WORKSPACE/proxy/migrations/generateManifest.ts" ./migrations/generateManifest.ts
diff --git a/test-tokens/yarn.lock b/test-tokens/yarn.lock
index 00881be31..c1d6ac2dd 100644
--- a/test-tokens/yarn.lock
+++ b/test-tokens/yarn.lock
@@ -912,6 +912,13 @@ block-stream@*:
   dependencies:
     inherits "~2.0.0"
 
+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=
+  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"
@@ -3330,6 +3337,40 @@ node-pre-gyp@^0.11.0:
     semver "^5.3.0"
     tar "^4"
 
+node-gyp@3.x:
+  version "3.8.0"
+  resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
+  integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==
+  dependencies:
+    fstream "^1.0.0"
+    glob "^7.0.3"
+    graceful-fs "^4.1.2"
+    mkdirp "^0.5.0"
+    nopt "2 || 3"
+    npmlog "0 || 1 || 2 || 3 || 4"
+    osenv "0"
+    request "^2.87.0"
+    rimraf "2"
+    semver "~5.3.0"
+    tar "^2.0.0"
+    which "1"
+
+node-pre-gyp@^0.11.0:
+  version "0.11.0"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054"
+  integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==
+  dependencies:
+    detect-libc "^1.0.2"
+    mkdirp "^0.5.1"
+    needle "^2.2.1"
+    nopt "^4.0.1"
+    npm-packlist "^1.1.6"
+    npmlog "^4.0.2"
+    rc "^1.2.7"
+    rimraf "^2.6.1"
+    semver "^5.3.0"
+    tar "^4"
+
 nofilter@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e"
@@ -3639,6 +3680,11 @@ printj@~1.1.0:
   resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
   integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
 
+printj@~1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.1.tgz#9af6b1d55647a1587ac44f4c1654a4b95b8e12cb"
+  integrity sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==
+
 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"
@@ -4815,8 +4861,8 @@ web3-utils@1.5.3:
   integrity sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==
   dependencies:
     bn.js "^4.11.9"
-    eth-lib "0.2.8"
     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"
@@ -4895,7 +4941,7 @@ which@1, which@1.3.1:
   dependencies:
     isexe "^2.0.0"
 
-wide-align@1.1.3:
+wide-align@1.1.3, 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==
diff --git a/test/agent-test.js b/test/agent-test.js
index da922465a..cb06ad64f 100644
--- a/test/agent-test.js
+++ b/test/agent-test.js
@@ -56,7 +56,6 @@ global.imaState = {
     "nLogMaxSizeBeforeRotation": -1,
     "nLogMaxFilesCount": -1,
     "isPrintGathered": true,
-    "isPrintSecurityValues": true,
 
     "bIsNeededCommonInit": true,
     "bSignMessages": false, // use BLS message signing, turned on with --sign-messages