Updates after deployment test (#75)

* Force ln to mitigate error when postinstall is repeated

* Update readme

* Using yarn in place of npm run

* Changed env order - home first

* Removed gh-pages UI deploy

* Readme cosmetics

* Removed duplicate bridge overview

* Update readme

* Update repository address

* Update readme

* Changed NPM to Yarn everywhere

* Update readme

* Using tokenbridge monorepo in deployment instead of token-bridge

* Update ui/README.md

Co-Authored-By: Andrew Gross <andogro@gmail.com>

* Revert and/or change as per @akolotov explanation

* Removed checkWorker3 that was used in legacy bridge-rust-v1-native-to-erc

* Update deployment/oracle/README.md

Co-Authored-By: Alexander Kolotov <alexandr.kolotov@gmail.com>

* Apply suggestions from code review

Co-Authored-By: Alexander Kolotov <alexandr.kolotov@gmail.com>

* Update root readme and Update sub-repo readmes to point to root monorepository initialization.

* Removed obsolete GET /stuckTransfers

* Remove stuckTransfers

* Use shell instead of unmaintained docker_service module. Update naming in templates.
This commit is contained in:
Przemyslaw Rzad 2019-05-31 14:54:32 +02:00 committed by GitHub
parent 1ab4a0eca8
commit 93347b47a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 201 additions and 295 deletions

7
.gitignore vendored

@ -17,8 +17,8 @@ build
.idea .idea
.nyc_output .nyc_output
logs/ logs/
responses/*
!responses/.gitkeep
*.err *.err
*.out *.out
data data
@ -44,3 +44,6 @@ Vagrantfile
vagrant-hosts.yml vagrant-hosts.yml
.vagrant .vagrant
#monitor
monitor/responses/*
!monitor/.gitkeep

@ -23,10 +23,10 @@ Sub-repositories maintained within this monorepo are listed below.
| [UI](ui/README.md) | DApp interface to transfer tokens and coins between chains. | | [UI](ui/README.md) | DApp interface to transfer tokens and coins between chains. |
| [Monitor](monitor/README.md) | Tool for checking balances and unprocessed events in bridged networks. | | [Monitor](monitor/README.md) | Tool for checking balances and unprocessed events in bridged networks. |
| [Deployment](deployment/README.md) | Ansible playbooks for deploying cross-chain bridges. | | [Deployment](deployment/README.md) | Ansible playbooks for deploying cross-chain bridges. |
| [Oracle-E2E]() | End to end tests for the Oracle | | [Oracle-E2E](oracle-e2e/README.md) | End to end tests for the Oracle |
| [UI-E2E]() | End to end tests for the UI | | [UI-E2E](ui-e2e/README.md) | End to end tests for the UI |
Additionally there are [Solidity contracts](https://github.com/poanetwork/poa-bridge-contracts) used to manage bridge validators, collect signatures, and confirm asset relay and disposal. Additionally there are [Smart Contracts](https://github.com/poanetwork/poa-bridge-contracts) used to manage bridge validators, collect signatures, and confirm asset relay and disposal.
## Network Definitions ## Network Definitions
@ -44,33 +44,55 @@ The POA TokenBridge provides three operational modes:
- [x] `ERC20-to-ERC20` ERC20-compatible tokens on the Foreign network are locked and minted as ERC20-compatible tokens (ERC677 tokens) on the Home network. When transferred from Home to Foreign, they are burnt on the Home side and unlocked in the Foreign network. This can be considered a form of atomic swap when a user swaps the token "X" in network "A" to the token "Y" in network "B". **More Information: [ERC20-to-ERC20](https://medium.com/poa-network/introducing-the-erc20-to-erc20-tokenbridge-ce266cc1a2d0)** - [x] `ERC20-to-ERC20` ERC20-compatible tokens on the Foreign network are locked and minted as ERC20-compatible tokens (ERC677 tokens) on the Home network. When transferred from Home to Foreign, they are burnt on the Home side and unlocked in the Foreign network. This can be considered a form of atomic swap when a user swaps the token "X" in network "A" to the token "Y" in network "B". **More Information: [ERC20-to-ERC20](https://medium.com/poa-network/introducing-the-erc20-to-erc20-tokenbridge-ce266cc1a2d0)**
- [x] `ERC20-to-Native`: Pre-existing **tokens** in the Foreign network are locked and **coins** are minted in the `Home` network. In this mode, the Home network consensus engine invokes [Parity's Block Reward contract](https://wiki.parity.io/Block-Reward-Contract.html) to mint coins per the bridge contract request. **More Information: [xDai Chain](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a)** - [x] `ERC20-to-Native`: Pre-existing **tokens** in the Foreign network are locked and **coins** are minted in the `Home` network. In this mode, the Home network consensus engine invokes [Parity's Block Reward contract](https://wiki.parity.io/Block-Reward-Contract.html) to mint coins per the bridge contract request. **More Information: [xDai Chain](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a)**
## Building, running, linting & tests ## Initializing the monorepository
To initialize submodules: Clone the repository with submodules:
```bash
git clone --recursive https://github.com/poanetwork/tokenbridge
`git submodule update --init` # or initialize submodules if already cloned without --recursive option:
git submodule update --init
```
To install dependencies: Install dependencies:
`yarn install` ```
yarn install && yarn install:deploy
```
To build all projects: _**Note**: The installation should be performed with an unprivileged Linux account or with the following flag: `yarn install --unsafe-perm`. [More information](https://docs.npmjs.com/misc/scripts#user)_
`yarn run build` Compile the Smart Contracts
```
yarn compile:contracts
```
## Linting
Running linter for all JS projects: Running linter for all JS projects:
`yarn lint` ```
yarn lint
```
Running linter for all Ansible playbooks: Running linter for all Ansible playbooks:
- [ansible-lint](https://github.com/ansible/ansible-lint) is required - [ansible-lint](https://github.com/ansible/ansible-lint) is required
`yarn ansible-lint` ```
yarn ansible-lint
```
## Tests
Running tests for all projects: Running tests for all projects:
`yarn test` ```
yarn test
```
Additionaly there are end-to-end tests for [Oracle](oracle-e2e/README.md) and [UI](ui-e2e/README.md).
For details on building, running and developing please refer to respective READMEs in sub-repositories. For details on building, running and developing please refer to respective READMEs in sub-repositories.

@ -13,7 +13,7 @@
1. Clone this repository and go to the `deployment/oracle` folder 1. Clone this repository and go to the `deployment/oracle` folder
``` ```
git clone https://github.com/poanetwork/tokenbridge git clone --recursive https://github.com/poanetwork/tokenbridge
cd tokenbridge/deployment/oracle cd tokenbridge/deployment/oracle
``` ```
2. Create the file `hosts.yml` from `hosts.yml.example` 2. Create the file `hosts.yml` from `hosts.yml.example`
@ -53,17 +53,17 @@ cp hosts.yml.example hosts.yml
1. The `group_vars/<bridge_name>.yml` file contains the public bridge parameters. This file is prepared by administrators for each bridge. The validator only needs to add the required bridge name in the hosts.yml file to tell Ansible which file to use. 1. The `group_vars/<bridge_name>.yml` file contains the public bridge parameters. This file is prepared by administrators for each bridge. The validator only needs to add the required bridge name in the hosts.yml file to tell Ansible which file to use.
`group_vars/example.yml` shows an example configuration for the POA/Sokol - POA/Sokol bridge. Parameter values should match values from the .env file for the token-bridge. See [Configuration parameters](../../oracle/README.md#configuration-parameters) for details. `group_vars/example.yml` shows an example configuration for the POA/Sokol - POA/Sokol bridge. Parameter values should match values from the .env file for the Oracle. See [Configuration parameters](../../oracle/README.md#configuration-parameters) for details.
2. You can also add the following parameters in the `group_vars` to change the default behavior of `deployment-bridge` playbooks: 2. You can also add the following parameters in the `group_vars` to change the default behavior of `deployment-bridge` playbooks:
2.1 `compose_service_user` - specifies users to be created by playbooks. This user will be used to run POA bridge. 2.1 `compose_service_user` - specifies users to be created by playbooks. This user will be used to run Token Bridge Oracle.
2.2 `bridge_repo` contains address of token-bridge repository. The default value is https://github.com/poanetwork/token-bridge. 2.2 `bridge_repo` contains address of Token Bridge Oracle repository. The default value is https://github.com/poanetwork/tokenbridge.
2.3 `bridge_repo_branch` points to the specific branch or commit to use with the `bridge_repo`. If `bridge_repo_branch` is not specified, the default (`master`) branch is used. 2.3 `bridge_repo_branch` points to the specific branch or commit to use with the `bridge_repo`. If `bridge_repo_branch` is not specified, the default (`master`) branch is used.
2.4 `bridge_path` set the path where token-bridge would be installed. By default it point to the home folder of `compose_service_user` 2.4 `bridge_path` set the path where Token Bridge Oracle would be installed. By default it point to the home folder of `compose_service_user`
2.5 `docker_compose_version` - specifies a version of docker-compose to be installed. 2.5 `docker_compose_version` - specifies a version of docker-compose to be installed.
@ -97,6 +97,8 @@ To be used with the ansible-playbook command, for example:
* `--private-key=<file_name>` - if private keyfile is required to connect to the ubuntu instance. * `--private-key=<file_name>` - if private keyfile is required to connect to the ubuntu instance.
* `--user=<username>` - connect as this username
## Bridge service commands ## Bridge service commands
The Bridge service is named `poabridge`. Use the default `SysVinit` commands to `start`, `stop`, `restart`, and `rebuild` the service and to check the `status` of the service. The Bridge service is named `poabridge`. Use the default `SysVinit` commands to `start`, `stop`, `restart`, and `rebuild` the service and to check the `status` of the service.

@ -1,5 +1,4 @@
- name: Launch container - name: Launch container
docker_service: shell: docker-compose up -d
project_src: "{{ bridge_path }}" args:
state: present chdir: "{{ bridge_path }}/oracle"
build: yes

@ -1,6 +1,6 @@
- name: Slurp docker compose file - name: Slurp docker compose file
slurp: slurp:
src: "{{ bridge_path }}/docker-compose.yml" src: "{{ bridge_path }}/oracle/docker-compose.yml"
register: docker_compose_slurp register: docker_compose_slurp
- name: Parse docker compose file - name: Parse docker compose file
@ -15,7 +15,7 @@
- name: Write new docker-compose file - name: Write new docker-compose file
copy: copy:
content: "{{ docker_compose_parsed | to_yaml }}" content: "{{ docker_compose_parsed | to_yaml }}"
dest: "{{ bridge_path }}/docker-compose.yml" dest: "{{ bridge_path }}/oracle/docker-compose.yml"
- name: Set the local container logs configuration file - name: Set the local container logs configuration file
template: template:

@ -5,7 +5,7 @@ template(name="DockerLogFileName" type="list") {
constant(value="/docker.log") constant(value="/docker.log")
} }
if $programname startswith 'bridge_' then \ if $programname startswith 'oracle_bridge_' then \
?DockerLogFileName ?DockerLogFileName
else else
/var/log/docker/no_tag/docker.log /var/log/docker/no_tag/docker.log

@ -11,7 +11,7 @@ template(name="RemoteForwardFormat" type="list") {
property(name="msg") property(name="msg")
} }
if $programname startswith 'bridge_' or $programname startswith 'docker' then { if $programname startswith 'oracle_bridge_' or $programname startswith 'docker' then {
action( action(
type="omfwd" type="omfwd"
protocol="{{ syslog_server_port.split(":")[0] }}" protocol="{{ syslog_server_port.split(":")[0] }}"

@ -2,12 +2,12 @@
become_user: "{{ compose_service_user }}" become_user: "{{ compose_service_user }}"
shell: docker-compose run --entrypoint "node scripts/getValidatorStartBlocks.js" bridge_affirmation shell: docker-compose run --entrypoint "node scripts/getValidatorStartBlocks.js" bridge_affirmation
args: args:
chdir: "{{ bridge_path }}" chdir: "{{ bridge_path }}/oracle"
register: BLOCKS register: BLOCKS
- name: Write blocks - name: Write blocks
blockinfile: blockinfile:
path: "{{ bridge_path }}/.env" path: "{{ bridge_path }}/oracle/.env"
marker: "## {mark} Calculated by scripts/getValidatorStartBlocks.js" marker: "## {mark} Calculated by scripts/getValidatorStartBlocks.js"
block: | block: |
HOME_START_BLOCK={{ (BLOCKS.stdout | from_json).homeStartBlock }} HOME_START_BLOCK={{ (BLOCKS.stdout | from_json).homeStartBlock }}
@ -17,7 +17,7 @@
become_user: "{{ compose_service_user }}" become_user: "{{ compose_service_user }}"
shell: docker-compose run -e VALIDATOR_ADDRESS_PRIVATE_KEY="{{ VALIDATOR_ADDRESS_PRIVATE_KEY }}" --entrypoint "node scripts/privateKeyToAddress.js" bridge_affirmation shell: docker-compose run -e VALIDATOR_ADDRESS_PRIVATE_KEY="{{ VALIDATOR_ADDRESS_PRIVATE_KEY }}" --entrypoint "node scripts/privateKeyToAddress.js" bridge_affirmation
args: args:
chdir: "{{ bridge_path }}" chdir: "{{ bridge_path }}/oracle"
register: VADDRESS register: VADDRESS
- name: Set VALIDATOR_ADDRESS variable - name: Set VALIDATOR_ADDRESS variable

@ -1,4 +1,4 @@
- name: Install .env config - name: Install .env config
template: template:
src: .env.j2 src: .env.j2
dest: "{{ bridge_path }}/.env" dest: "{{ bridge_path }}/oracle/.env"

@ -1,3 +1,3 @@
bridge_path: "/home/{{ compose_service_user }}/bridge" bridge_path: "/home/{{ compose_service_user }}/bridge"
bridge_repo: https://github.com/poanetwork/token-bridge.git bridge_repo: https://github.com/poanetwork/tokenbridge.git
bridge_repo_branch: master bridge_repo_branch: master

@ -10,7 +10,7 @@
# Description: Enable service provided by daemon. # Description: Enable service provided by daemon.
### END INIT INFO ### END INIT INFO
WORKDIR="{{ '/home/' + compose_service_user | default('poadocker') + '/' + bridge_path if bridge_path[:1] != "/" else bridge_path }}" WORKDIR="{{ '/home/' + compose_service_user | default('poadocker') + '/' + bridge_path + '/oracle' if bridge_path[:1] != "/" else bridge_path + '/oracle' }}"
#Getting path to private key file and variable name for parsing key file #Getting path to private key file and variable name for parsing key file
keyfile="{{ keyfile_path }}" keyfile="{{ keyfile_path }}"

@ -94,34 +94,23 @@ Example of an API
} }
``` ```
* `GET /stuckTransfers` - check stucked transfers that wasnot called by transferAndCall # How to run
```json
{
"stuckTransfers": [ ## Setup
{
"address": "0x6758B7d441a9739b98552B373703d8d3d14f9e62", 1. [Initialize](../README.md#initializing-the-monorepository) the monorepository.
"blockNumber": 5964312,
"transactionHash": "0x74413ba79509a292d5d0d6edd364b3617c83a57b13d603de9deb6c8e6b6c6daf", 2. Go to the monitor sub-repository:
... ```
"returnValues": { cd monitor
"0": "0x8D4bbc1B533aB9e3a743210870b6e3c4c0f7E935",
"1": "0xd819E948b14cA6AAD2b7Ffd333cCDf732b129EeD",
"2": "10000000000000000000000",
"from": "0x8D4bbc1B533aB9e3a743210870b6e3c4c0f7E935",
"to": "0xd819E948b14cA6AAD2b7Ffd333cCDf732b129EeD",
"value": "10000000000000000000000"
},
...
}
],
"total": 2,
"lastChecked": 1535058662
}
``` ```
# How to run 3. Create .env file:
Create .env file (see `.env.example` for parameters reference) ```
cp .env.example .env
```
#### Example:
```bash ```bash
HOME_RPC_URL=https://sokol.poa.network HOME_RPC_URL=https://sokol.poa.network
FOREIGN_RPC_URL=https://kovan.infura.io/mew FOREIGN_RPC_URL=https://kovan.infura.io/mew
@ -133,17 +122,19 @@ GAS_PRICE_FALLBACK=21
LEFT_TX_THRESHOLD=100 LEFT_TX_THRESHOLD=100
``` ```
```bash ## Check balances of contracts and validators
npm i ```
# check balances of contracts and validators
node checkWorker.js node checkWorker.js
# check unprocessed events ```
## Check unprocessed events
```
node checkWorker2.js node checkWorker2.js
# check stuck transfers called by transfer, not transferAndCall ```
# only applicable for bridge-rust-v1-native-to-erc
node checkWorker3.js ## Run web interface
# run web interface ```
node index.js yarn start
``` ```
To enabled debug logging, set `DEBUG=1` env variable. To enabled debug logging, set `DEBUG=1` env variable.

@ -1,23 +0,0 @@
const fs = require('fs')
const path = require('path')
const logger = require('./logger')('checkWorker3')
const stuckTransfers = require('./stuckTransfers')
async function checkWorker3() {
try {
logger.debug('calling stuckTransfers()')
const transfers = await stuckTransfers()
// console.log(transfers)
if (!transfers) throw new Error('transfers is empty: ' + JSON.stringify(transfers))
fs.writeFileSync(
path.join(__dirname, '/responses/stuckTransfers.json'),
JSON.stringify(transfers, null, 4)
)
logger.debug('Done')
return transfers
} catch (e) {
logger.error('checkWorker3.js', e)
throw e
}
}
checkWorker3()

@ -1,109 +0,0 @@
require('dotenv').config()
const Web3 = require('web3')
const logger = require('./logger')('stuckTransfers.js')
const { FOREIGN_RPC_URL, FOREIGN_BRIDGE_ADDRESS, ERC20_ADDRESS } = process.env
const FOREIGN_DEPLOYMENT_BLOCK = Number(process.env.FOREIGN_DEPLOYMENT_BLOCK) || 0
const foreignProvider = new Web3.providers.HttpProvider(FOREIGN_RPC_URL)
const web3Foreign = new Web3(foreignProvider)
const ABITransferWithoutData = [
{
anonymous: false,
inputs: [
{
indexed: true,
name: 'from',
type: 'address'
},
{
indexed: true,
name: 'to',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
}
],
name: 'Transfer',
type: 'event'
}
]
const ABIWithData = [
{
anonymous: false,
inputs: [
{
indexed: true,
name: 'from',
type: 'address'
},
{
indexed: true,
name: 'to',
type: 'address'
},
{
indexed: false,
name: 'value',
type: 'uint256'
},
{
indexed: false,
name: 'data',
type: 'bytes'
}
],
name: 'Transfer',
type: 'event'
}
]
function compareTransfers(transfersNormal) {
return withData => {
return (
transfersNormal.filter(normal => {
return normal.transactionHash === withData.transactionHash
}).length === 0
)
}
}
async function main() {
try {
// TODO: ERC20_ADDRESS is no longer an env constant. It has to be extracted from the ForeignBridge Contract.
const tokenContract = new web3Foreign.eth.Contract(ABITransferWithoutData, ERC20_ADDRESS)
const tokenContractWithData = new web3Foreign.eth.Contract(ABIWithData, ERC20_ADDRESS)
logger.debug('calling tokenContract.getPastEvents Transfer')
const transfersNormal = await tokenContract.getPastEvents('Transfer', {
filter: {
to: FOREIGN_BRIDGE_ADDRESS
},
fromBlock: FOREIGN_DEPLOYMENT_BLOCK,
toBlock: 'latest'
})
logger.debug('calling tokenContractWithData.getPastEvents Transfer')
const transfersWithData = await tokenContractWithData.getPastEvents('Transfer', {
filter: {
to: FOREIGN_BRIDGE_ADDRESS
},
fromBlock: FOREIGN_DEPLOYMENT_BLOCK,
toBlock: 'latest'
})
const stuckTransfers = transfersNormal.filter(compareTransfers(transfersWithData))
logger.debug('Done')
return {
stuckTransfers,
total: stuckTransfers.length,
lastChecked: Math.floor(Date.now() / 1000)
}
} catch (e) {
logger.error(e)
throw e
}
}
module.exports = main

@ -1,4 +1,4 @@
# oracle-e2e # POA Token Bridge / Oracle-E2E
End to end tests for the POA Token Bridge [Oracle](../oracle/README.md). End to end tests for the POA Token Bridge [Oracle](../oracle/README.md).
@ -16,7 +16,7 @@ so that you can use the CLI without sudo.
To run the bridge end-to-end tests, you just have to run: To run the bridge end-to-end tests, you just have to run:
``` ```
$ ./run-tests.sh ./run-tests.sh
``` ```
If this is the first time that you do this, it will take some time to build the If this is the first time that you do this, it will take some time to build the

@ -4,17 +4,17 @@ docker-compose down
docker-compose up -d --build --force-recreate docker-compose up -d --build --force-recreate
docker-compose run e2e yarn workspace oracle-e2e run deploy docker-compose run e2e yarn workspace oracle-e2e run deploy
docker-compose run -d bridge npm run watcher:signature-request docker-compose run -d bridge yarn watcher:signature-request
docker-compose run -d bridge npm run watcher:collected-signatures docker-compose run -d bridge yarn watcher:collected-signatures
docker-compose run -d bridge npm run watcher:affirmation-request docker-compose run -d bridge yarn watcher:affirmation-request
docker-compose run -d bridge-erc npm run watcher:signature-request docker-compose run -d bridge-erc yarn watcher:signature-request
docker-compose run -d bridge-erc npm run watcher:collected-signatures docker-compose run -d bridge-erc yarn watcher:collected-signatures
docker-compose run -d bridge-erc npm run watcher:affirmation-request docker-compose run -d bridge-erc yarn watcher:affirmation-request
docker-compose run -d bridge-erc-native npm run watcher:signature-request docker-compose run -d bridge-erc-native yarn watcher:signature-request
docker-compose run -d bridge-erc-native npm run watcher:collected-signatures docker-compose run -d bridge-erc-native yarn watcher:collected-signatures
docker-compose run -d bridge-erc-native npm run watcher:affirmation-request docker-compose run -d bridge-erc-native yarn watcher:affirmation-request
docker-compose run -d bridge npm run sender:home docker-compose run -d bridge yarn sender:home
docker-compose run -d bridge npm run sender:foreign docker-compose run -d bridge yarn sender:foreign
docker-compose run e2e yarn workspace oracle-e2e run start docker-compose run e2e yarn workspace oracle-e2e run start
rc=$? rc=$?

@ -49,16 +49,16 @@ For more information on the Redis/RabbitMQ requirements, see [#90](/../../issues
# How to Use # How to Use
## Installation and Deployment ## Deploy the Bridge Contracts
**Note:** The following steps detail the bridge deployment process for development and testing. For deployment in a production environment we recommend using the [Bridge Deployment Playbooks](../deployment/README.md). **Note:** The following steps detail the bridge deployment process for development and testing. For deployment in a production environment we recommend using the [Bridge Deployment Playbooks](../deployment/README.md).
#### Deploy the Bridge Contracts
1. [Deploy the bridge contracts](https://github.com/poanetwork/poa-bridge-contracts/blob/master/deploy/README.md) 1. [Deploy the bridge contracts](https://github.com/poanetwork/poa-bridge-contracts/blob/master/deploy/README.md)
2. Open `bridgeDeploymentResults.json` or copy the JSON output generated by the bridge contract deployment process. 2. Open `bridgeDeploymentResults.json` or copy the JSON output generated by the bridge contract deployment process.
#### Output examples
`Native-to-ERC20` mode example: `Native-to-ERC20` mode example:
```json ```json
{ {
@ -93,9 +93,19 @@ For more information on the Redis/RabbitMQ requirements, see [#90](/../../issues
} }
``` ```
## Configuration ## Install and configure the Oracle
1. Create a `.env` file: `cp .env.example .env` 1. [Initialize](../README.md#initializing-the-monorepository) the monorepository.
2. Go to the oracle sub-repository:
```
cd oracle
```
3. Create a `.env` file:
```
cp .env.example .env
```
2. Fill in the required information using the JSON output data. Check the tables with the [set of parameters](#configuration-parameters) below to see their explanation. 2. Fill in the required information using the JSON output data. Check the tables with the [set of parameters](#configuration-parameters) below to see their explanation.
@ -103,7 +113,7 @@ For more information on the Redis/RabbitMQ requirements, see [#90](/../../issues
There are two options to run the TokenBridge processes: There are two options to run the TokenBridge processes:
1. Docker containers. This requires [Docker](https://docs.docker.com/install/) and [Docker Compose](https://docs.docker.com/compose/install/). If you are on Linux, it's also recommended that you [create a docker group and add your user to it](https://docs.docker.com/install/linux/linux-postinstall/), so that you can use the CLI without sudo. 1. Docker containers. This requires [Docker](https://docs.docker.com/install/) and [Docker Compose](https://docs.docker.com/compose/install/). If you are on Linux, it's also recommended that you [create a docker group and add your user to it](https://docs.docker.com/install/linux/linux-postinstall/), so that you can use the CLI without sudo.
2. NodeJs Package Manager (NPM). 2. Yarn Package Manager.
### Docker ### Docker
@ -120,19 +130,19 @@ In case you need to reset your bridge or setup a new one (with different configu
* [View the logs](https://docs.docker.com/v17.09/compose/reference/logs/) : `docker-compose logs` * [View the logs](https://docs.docker.com/v17.09/compose/reference/logs/) : `docker-compose logs`
### NPM ### Yarn
- `redis-server` starts Redis. redis-cli ping will return a pong if Redis is running. - `redis-server` starts Redis. redis-cli ping will return a pong if Redis is running.
- `rabbitmq-server` starts RabbitMQ. Use rabbitmqctl status to check if RabbitMQ is running. - `rabbitmq-server` starts RabbitMQ. Use rabbitmqctl status to check if RabbitMQ is running.
- `npm run watcher:signature-request` - `yarn watcher:signature-request`
- `npm run watcher:collected-signatures` - `yarn watcher:collected-signatures`
- `npm run watcher:affirmation-request` - `yarn watcher:affirmation-request`
- `npm run sender:home` - `yarn sender:home`
- `npm run sender:foreign` - `yarn sender:foreign`
### Bridge UI ### Bridge UI
See the [Bridge UI installation instructions](https://github.com/poanetwork/bridge-ui/) to configure and use the optional Bridge UI. See the [UI instructions](../ui/README.md) to configure and use the optional Bridge UI.
## Rollback the Last Processed Block in Redis ## Rollback the Last Processed Block in Redis
@ -140,7 +150,7 @@ If the bridge does not handle an event properly (i.e. a transaction stalls due t
Execute this command in the bridge root directory: Execute this command in the bridge root directory:
for NPM installation: for local installation:
```shell ```shell
bash ./reset-lastBlock.sh <watcher> <block num> bash ./reset-lastBlock.sh <watcher> <block num>
``` ```
@ -210,7 +220,7 @@ Command | Description
## Testing ## Testing
```bash ```bash
npm test yarn test
``` ```
### E2E tests ### E2E tests

@ -40,7 +40,7 @@ services:
- NODE_ENV=production - NODE_ENV=production
- VALIDATOR_ADDRESS_PRIVATE_KEY=${VALIDATOR_ADDRESS_PRIVATE_KEY} - VALIDATOR_ADDRESS_PRIVATE_KEY=${VALIDATOR_ADDRESS_PRIVATE_KEY}
restart: unless-stopped restart: unless-stopped
entrypoint: npm run watcher:signature-request entrypoint: yarn watcher:signature-request
networks: networks:
- net_db_bridge_request - net_db_bridge_request
- net_rabbit_bridge_request - net_rabbit_bridge_request
@ -56,7 +56,7 @@ services:
- NODE_ENV=production - NODE_ENV=production
- VALIDATOR_ADDRESS=${VALIDATOR_ADDRESS} - VALIDATOR_ADDRESS=${VALIDATOR_ADDRESS}
restart: unless-stopped restart: unless-stopped
entrypoint: npm run watcher:collected-signatures entrypoint: yarn watcher:collected-signatures
networks: networks:
- net_db_bridge_collected - net_db_bridge_collected
- net_rabbit_bridge_collected - net_rabbit_bridge_collected
@ -72,7 +72,7 @@ services:
- NODE_ENV=production - NODE_ENV=production
- VALIDATOR_ADDRESS=${VALIDATOR_ADDRESS} - VALIDATOR_ADDRESS=${VALIDATOR_ADDRESS}
restart: unless-stopped restart: unless-stopped
entrypoint: npm run watcher:affirmation-request entrypoint: yarn watcher:affirmation-request
networks: networks:
- net_db_bridge_affirmation - net_db_bridge_affirmation
- net_rabbit_bridge_affirmation - net_rabbit_bridge_affirmation
@ -88,7 +88,7 @@ services:
- NODE_ENV=production - NODE_ENV=production
- VALIDATOR_ADDRESS_PRIVATE_KEY=${VALIDATOR_ADDRESS_PRIVATE_KEY} - VALIDATOR_ADDRESS_PRIVATE_KEY=${VALIDATOR_ADDRESS_PRIVATE_KEY}
restart: unless-stopped restart: unless-stopped
entrypoint: npm run sender:home entrypoint: yarn sender:home
networks: networks:
- net_db_bridge_senderhome - net_db_bridge_senderhome
- net_rabbit_bridge_senderhome - net_rabbit_bridge_senderhome
@ -104,7 +104,7 @@ services:
- NODE_ENV=production - NODE_ENV=production
- VALIDATOR_ADDRESS_PRIVATE_KEY=${VALIDATOR_ADDRESS_PRIVATE_KEY} - VALIDATOR_ADDRESS_PRIVATE_KEY=${VALIDATOR_ADDRESS_PRIVATE_KEY}
restart: unless-stopped restart: unless-stopped
entrypoint: npm run sender:foreign entrypoint: yarn sender:foreign
networks: networks:
- net_db_bridge_senderforeign - net_db_bridge_senderforeign
- net_rabbit_bridge_senderforeign - net_rabbit_bridge_senderforeign

@ -69,7 +69,7 @@ URL, `http://localhost:8546` as the foreign RPC URL and
`0xaaB52d66283F7A1D5978bcFcB55721ACB467384b` as the deployer and validator. `0xaaB52d66283F7A1D5978bcFcB55721ACB467384b` as the deployer and validator.
Deploy the contracts. Deploy the contracts.
To start the bridge, you can do `npm run dev`, or you can start all the scripts To start the bridge, you can do `yarn dev`, or you can start all the scripts
separately. separately.
## Generate a block with several transactions ## Generate a block with several transactions

@ -10,7 +10,7 @@
"watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-watcher", "watcher:affirmation-request": "./scripts/start-worker.sh watcher affirmation-request-watcher",
"sender:home": "./scripts/start-worker.sh sender home-sender", "sender:home": "./scripts/start-worker.sh sender home-sender",
"sender:foreign": "./scripts/start-worker.sh sender foreign-sender", "sender:foreign": "./scripts/start-worker.sh sender foreign-sender",
"dev": "concurrently -n 'watcher:signature-request,watcher:collected-signatures,watcher:affirmation-request,sender:home,sender:foreign' -c 'red,green,yellow,blue,magenta' 'npm run watcher:signature-request' 'npm run watcher:collected-signatures' 'npm run watcher:affirmation-request' 'npm run sender:home' 'npm run sender:foreign'", "dev": "concurrently -n 'watcher:signature-request,watcher:collected-signatures,watcher:affirmation-request,sender:home,sender:foreign' -c 'red,green,yellow,blue,magenta' 'yarn watcher:signature-request' 'yarn watcher:collected-signatures' 'yarn watcher:affirmation-request' 'yarn sender:home' 'yarn sender:foreign'",
"test": "NODE_ENV=test mocha", "test": "NODE_ENV=test mocha",
"test:watch": "NODE_ENV=test mocha --watch --reporter=min", "test:watch": "NODE_ENV=test mocha --watch --reporter=min",
"coverage": "NODE_ENV=test nyc --reporter=text --reporter=html mocha", "coverage": "NODE_ENV=test nyc --reporter=text --reporter=html mocha",

@ -40,6 +40,6 @@
"clean": "rm -rf ./node_modules ./**/node_modules ./**/**/node_modules ./**/build", "clean": "rm -rf ./node_modules ./**/node_modules ./**/**/node_modules ./**/build",
"compile:contracts": "yarn workspace poa-parity-bridge-contracts run compile", "compile:contracts": "yarn workspace poa-parity-bridge-contracts run compile",
"install:deploy": "cd contracts/deploy && npm install --silent", "install:deploy": "cd contracts/deploy && npm install --silent",
"postinstall": "ln -s $(pwd)/node_modules/openzeppelin-solidity/ contracts/node_modules/openzeppelin-solidity" "postinstall": "ln -sf $(pwd)/node_modules/openzeppelin-solidity/ contracts/node_modules/openzeppelin-solidity"
} }
} }

@ -1,8 +1,17 @@
### ui-e2e # POA Token Bridge / UI-E2E
End to end tests for the UI
End to end tests for the POA Token Bridge [UI](../UI/README.md).
- Configure startURL, homeAccount, foreignAccount in ```config.json``` - Configure startURL, homeAccount, foreignAccount in ```config.json```
## Running
To run the bridge end-to-end tests, you just have to run:
```
./run-tests.sh
```
#### Tests #### Tests
``` ```

@ -6,17 +6,17 @@ docker-compose up -d --build --force-recreate
node ./scripts/blocks.js & node ./scripts/blocks.js &
docker-compose run e2e yarn workspace ui-e2e run deploy docker-compose run e2e yarn workspace ui-e2e run deploy
docker-compose run -d bridge npm run watcher:signature-request docker-compose run -d bridge yarn watcher:signature-request
docker-compose run -d bridge npm run watcher:collected-signatures docker-compose run -d bridge yarn watcher:collected-signatures
docker-compose run -d bridge npm run watcher:affirmation-request docker-compose run -d bridge yarn watcher:affirmation-request
docker-compose run -d bridge-erc20 npm run watcher:signature-request docker-compose run -d bridge-erc20 yarn watcher:signature-request
docker-compose run -d bridge-erc20 npm run watcher:collected-signatures docker-compose run -d bridge-erc20 yarn watcher:collected-signatures
docker-compose run -d bridge-erc20 npm run watcher:affirmation-request docker-compose run -d bridge-erc20 yarn watcher:affirmation-request
docker-compose run -d bridge-erc20-native npm run watcher:signature-request docker-compose run -d bridge-erc20-native yarn watcher:signature-request
docker-compose run -d bridge-erc20-native npm run watcher:collected-signatures docker-compose run -d bridge-erc20-native yarn watcher:collected-signatures
docker-compose run -d bridge-erc20-native npm run watcher:affirmation-request docker-compose run -d bridge-erc20-native yarn watcher:affirmation-request
docker-compose run -d bridge npm run sender:home docker-compose run -d bridge yarn sender:home
docker-compose run -d bridge npm run sender:foreign docker-compose run -d bridge yarn sender:foreign
docker-compose run -d -p 3000:3000 ui yarn workspace ui run start docker-compose run -d -p 3000:3000 ui yarn workspace ui run start
docker-compose run -d -p 3001:3000 ui-erc20 yarn workspace ui run start docker-compose run -d -p 3001:3000 ui-erc20 yarn workspace ui run start
docker-compose run -d -p 3002:3000 ui-erc20-native yarn workspace ui run start docker-compose run -d -p 3002:3000 ui-erc20-native yarn workspace ui run start

@ -1,7 +1,8 @@
REACT_APP_HOME_BRIDGE_ADDRESS=0xABb4C1399DcC28FBa3Beb76CAE2b50Be3e087353 REACT_APP_HOME_BRIDGE_ADDRESS=0xABb4C1399DcC28FBa3Beb76CAE2b50Be3e087353
REACT_APP_FOREIGN_BRIDGE_ADDRESS=0xE405F6872cE38a7a4Ff63DcF946236D458c2ca3a REACT_APP_FOREIGN_BRIDGE_ADDRESS=0xE405F6872cE38a7a4Ff63DcF946236D458c2ca3a
REACT_APP_FOREIGN_HTTP_PARITY_URL=https://kovan.infura.io/mew
REACT_APP_HOME_HTTP_PARITY_URL=https://sokol.poa.network REACT_APP_HOME_HTTP_PARITY_URL=https://sokol.poa.network
REACT_APP_FOREIGN_HTTP_PARITY_URL=https://kovan.infura.io/mew
REACT_APP_HOME_NATIVE_NAME=POA REACT_APP_HOME_NATIVE_NAME=POA

@ -8,12 +8,6 @@ Please refer to the [POA Token Bridge](../README.md) overview first of all.
The UI provides an intuitive interface for assets transfer between networks running the Bridge smart contracts. Users can connect to a web3 wallet such as [Nifty Wallet](https://github.com/poanetwork/nifty-wallet) or [MetaMask](https://metamask.io/) and complete the transfer through a web browser. The UI provides an intuitive interface for assets transfer between networks running the Bridge smart contracts. Users can connect to a web3 wallet such as [Nifty Wallet](https://github.com/poanetwork/nifty-wallet) or [MetaMask](https://metamask.io/) and complete the transfer through a web browser.
The current implementation allows for several bridge modes.
1. `Native-to-ERC20` Coins on a Home network can be converted to ERC20-compatible tokens on a Foreign network. Coins are locked on the Home side and the corresponding amount of ERC20 tokens are minted on the Foreign side. When the operation is reversed, tokens are burnt on the Foreign side and unlocked in the Home network.
2. `ERC20-to-ERC20` ERC20-compatible tokens on the Foreign network are locked and minted as ERC20-compatible tokens (ERC677 tokens) on the Home network. When transferred from Home to Foreign, they are burnt on the Home side and unlocked in the Foreign network. This can be considered a form of atomic swap when a user swaps the token "X" in network "A" to the token "Y" in network "B".
3. `ERC20-to-Native` Pre-existing tokens in the Foreign network are locked and coins are minted in the Home network. In this mode, the Home network consensus engine invokes Parity's Block Reward contract to mint coins per the bridge contract request.
![Bridge UI](bridge-ui.png) ![Bridge UI](bridge-ui.png)
### UI Features ### UI Features
@ -58,9 +52,9 @@ The following is an example setup using the POA Sokol testnet as the Home networ
### Dependencies ### Dependencies
- [poa-bridge-contracts](https://github.com/poanetwork/poa-bridge-contracts) - [Smart Contracts](https://github.com/poanetwork/poa-bridge-contracts)
- [oracle](../oracle/README.md) - [Oracle](../oracle/README.md)
- [node.js](https://nodejs.org/en/download/) - [Node.js](https://nodejs.org/en/download/)
- [AlphaWallet](https://alphawallet.com/) or [Nifty Wallet](https://github.com/poanetwork/nifty-wallet) or [MetaMask](https://metamask.io/) - [AlphaWallet](https://alphawallet.com/) or [Nifty Wallet](https://github.com/poanetwork/nifty-wallet) or [MetaMask](https://metamask.io/)
### Example Setup ### Example Setup
@ -94,14 +88,16 @@ The following is an example setup using the POA Sokol testnet as the Home networ
* `FOREIGN_RPC_URL`=https://kovan.infura.io/mew * `FOREIGN_RPC_URL`=https://kovan.infura.io/mew
* When deployment is finished, check that the `bridgeDeploymentResults.json` file exists in the `poa-bridge-contracts/deploy` directory and includes the bridge contract addresses. * When deployment is finished, check that the `bridgeDeploymentResults.json` file exists in the `poa-bridge-contracts/deploy` directory and includes the bridge contract addresses.
5. Install and run the POA Token Bridge Oracle. 5. Install and run the Token Bridge Oracle.
* Go to the `sokol-kovan-bridge` folder and `git clone https://github.com/poanetwork/tokenbridge` * Go to the `sokol-kovan-bridge` folder
* `cd tokenbridge/oracle` * [Initialize](../README.md#initializing-the-monorepository) the monorepository
* Follow instructions in the [Oracle](../oracle/README.md). * Go to `oracle` sub-repository
* Follow the [Oracle instructions](../oracle/README.md).
If successful, you will see bridge processes run when you issue a command. For example, run `npm run watcher:signature-request` If successful, you will see bridge processes run when you issue a command.
For example, run `yarn watcher:signature-request`.
**Example NPM Output:** **Example Yarn Output:**
```bash ```bash
[1539195000507] INFO (watcher-signature-request): Connected to redis [1539195000507] INFO (watcher-signature-request): Connected to redis
[1539195000545] INFO (watcher-signature-request): Connected to amqp Broker [1539195000545] INFO (watcher-signature-request): Connected to amqp Broker
@ -119,22 +115,19 @@ If successful, you will see bridge processes run when you issue a command. For e
{"level":30,"time":1539366885587,"msg":"Found 0 UserRequestForSignature events","validator":"0x..........","name":"watcher-signature-request","v":1} {"level":30,"time":1539366885587,"msg":"Found 0 UserRequestForSignature events","validator":"0x..........","name":"watcher-signature-request","v":1}
``` ```
6. Keep the bridge processes running. Open a separate terminal window and go to the `sokol-kovan-bridge` folder to install and unpack this repository. 6. Keep the bridge processes running. Open a separate terminal window and go to the `sokol-kovan-bridge` folder to install and run the UI.
* `git clone https://github.com/poanetwork/tokenbridge` * Go to the `sokol-kovan-bridge/tokenbridge` monorepository that was initialized in step **5.**
* `cd tokenbridge` * Go to `ui` sub-repository
* Update submodules
`git submodule update --init --recursive`
* Install dependencies
`yarn install`
* Go to UI sub-repository
`cd ui`
_**Note**: The bridge UI configuration should be performed with an unprivileged Linux account or with the following flag `npm install --unsafe-perm`. [More information](https://docs.npmjs.com/misc/scripts#user)_
* Create a .env file from the example file [.env.example](.env.example) * Create a .env file from the example file [.env.example](.env.example)
`cp .env.example .env` ```
cp .env.example .env
````
* Insert the addresses from the bridgeDeploymentResults.json file (from step 4) into the .env file. No other changes are needed, see [Env Parameter Details](#env-parameter-details) for information about each parameter. * Insert the addresses from the bridgeDeploymentResults.json file (from step 4) into the .env file. No other changes are needed, see [Env Parameter Details](#env-parameter-details) for information about each parameter.
`cat ../poa-bridge-contracts/deploy/bridgeDeploymentResults.json` ```
cat ../poa-bridge-contracts/deploy/bridgeDeploymentResults.json
```
```bash ```bash
# HomeBridge address in bridgeDeploymentResults.json # HomeBridge address in bridgeDeploymentResults.json
REACT_APP_HOME_BRIDGE_ADDRESS=0x.. REACT_APP_HOME_BRIDGE_ADDRESS=0x..
@ -146,7 +139,11 @@ _**Note**: The bridge UI configuration should be performed with an unprivileged
REACT_APP_HOME_HTTP_PARITY_URL=https://sokol.poa.network REACT_APP_HOME_HTTP_PARITY_URL=https://sokol.poa.network
``` ```
* Run `npm run start` * Run the dApp
```
yarn start
```
* Make sure your web3 wallet (Nifty Wallet, AlphaWallet or MetaMask) is funded and connected to the POA Sokol Network (see step 2) * Make sure your web3 wallet (Nifty Wallet, AlphaWallet or MetaMask) is funded and connected to the POA Sokol Network (see step 2)
* Specify an amount and click `Transfer` to complete a cross-chain transaction from Sokol to Kovan * Specify an amount and click `Transfer` to complete a cross-chain transaction from Sokol to Kovan
@ -184,19 +181,27 @@ APP_STYLES | The set of styles to render the bridge UI page. Currently only `cla
To run tests To run tests
`npm run test` ```
yarn test
```
To run linting To run linting
`npm run lint` ```
yarn lint
```
To run tests with coverage To run tests with coverage
`npm run coverage` ```
yarn coverage
```
To build the project To build the project
`npm run build` ```
yarn build
```
## Contributing ## Contributing

@ -2,7 +2,6 @@
"name": "ui", "name": "ui",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"homepage": "https://poanetwork.github.io/",
"dependencies": { "dependencies": {
"@babel/plugin-proposal-decorators": "^7.4.0", "@babel/plugin-proposal-decorators": "^7.4.0",
"bignumber.js": "^6.0.0", "bignumber.js": "^6.0.0",
@ -11,7 +10,6 @@
"customize-cra": "^0.2.12", "customize-cra": "^0.2.12",
"dotenv": "^7.0.0", "dotenv": "^7.0.0",
"fs-extra": "^5.0.0", "fs-extra": "^5.0.0",
"gh-pages": "^1.1.0",
"mobx": "^4.0.2", "mobx": "^4.0.2",
"mobx-react": "^5.0.0", "mobx-react": "^5.0.0",
"node-sass-chokidar": "^1.0.1", "node-sass-chokidar": "^1.0.1",
@ -34,16 +32,14 @@
"lint": "eslint . --ignore-path ../.eslintignore", "lint": "eslint . --ignore-path ../.eslintignore",
"select-css-theme": "node scripts/selectTheme.js", "select-css-theme": "node scripts/selectTheme.js",
"build-css": "node-sass-chokidar src/assets/stylesheets -o src/assets/stylesheets --output-style=compressed -m application*.css", "build-css": "node-sass-chokidar src/assets/stylesheets -o src/assets/stylesheets --output-style=compressed -m application*.css",
"watch-css": "nodemon -e scss -x \"npm run build-css\"", "watch-css": "nodemon -e scss -x \"yarn build-css\"",
"start": "npm run build-css && npm run select-css-theme && react-app-rewired start", "start": "yarn build-css && yarn select-css-theme && react-app-rewired start",
"build": "npm run build-css && npm run select-css-theme && react-app-rewired build", "build": "yarn build-css && yarn select-css-theme && react-app-rewired build",
"test": "react-app-rewired test --env=jsdom --no-watch", "test": "react-app-rewired test --env=jsdom --no-watch",
"test:watch": "react-app-rewired test --env=jsdom", "test:watch": "react-app-rewired test --env=jsdom",
"coverage": "react-app-rewired test --env=jsdom --coverage", "coverage": "react-app-rewired test --env=jsdom --coverage",
"coveralls": "cat ./coverage/lcov.info | node node_modules/.bin/coveralls", "coveralls": "cat ./coverage/lcov.info | node node_modules/.bin/coveralls",
"eject": "react-app-rewired eject", "eject": "react-app-rewired eject",
"predeploy": "npm run build",
"deploy": "gh-pages -d build -o origin",
"postinstall": "(cp lib/web3-eth/index.js ../node_modules/web3-eth/src && cp lib/web3-eth/index.js ./node_modules/web3-eth/src)" "postinstall": "(cp lib/web3-eth/index.js ../node_modules/web3-eth/src && cp lib/web3-eth/index.js ./node_modules/web3-eth/src)"
}, },
"devDependencies": { "devDependencies": {

@ -17,7 +17,7 @@ export const SocialIcons = () => {
}, },
{ {
icon: <IconGithub />, icon: <IconGithub />,
link: 'https://github.com/poanetwork/token-bridge' link: 'https://github.com/poanetwork/tokenbridge'
} }
] ]