Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4117f29a74 | ||
|
|
1921087ad1 | ||
|
|
b4abbc4910 | ||
|
|
bcbe34a839 | ||
|
|
738442e4cf | ||
|
|
64c5a5670f | ||
|
|
c8c589536b | ||
|
|
7b0edff624 | ||
|
|
b02b879b02 | ||
|
|
5b4b01a79b | ||
|
|
881fafe9a8 | ||
|
|
c1ed6f21e6 | ||
|
|
8ae0fa82d5 | ||
|
|
dbf3d3d90d | ||
|
|
8977ed6d3b | ||
|
|
df0dc1c313 | ||
|
|
7b2bebbcf0 | ||
|
|
85104d67c0 | ||
|
|
2a3d7c8e08 | ||
|
|
e6052f162a | ||
|
|
52ed4e85e2 | ||
|
|
bc6dd13193 | ||
|
|
bce1e6509e | ||
|
|
52358d477b | ||
|
|
232f807e9d | ||
|
|
fe4a569e34 | ||
|
|
c408d57716 | ||
|
|
7fcb118c8c | ||
|
|
1eaf774e33 | ||
|
|
8650ba4d21 | ||
|
|
edc51c78e2 | ||
|
|
612f130544 | ||
|
|
73d5002105 | ||
|
|
65dd131107 | ||
|
|
4de24efc01 | ||
|
|
727371f251 | ||
|
|
9cb1a2041d | ||
|
|
b6d96d7f62 | ||
|
|
dc06ee8ceb | ||
|
|
8c2f58b06f | ||
|
|
3ad62d6a7f | ||
|
|
9f9638970a | ||
|
|
7054ff26a0 | ||
|
|
afb601b7f5 | ||
|
|
1736fd615d | ||
|
|
ef0a734650 | ||
|
|
6e2238fc9b | ||
|
|
0f3bea5a41 | ||
|
|
0829c95561 | ||
|
|
5bb99a7e95 | ||
|
|
3cd53f7bda | ||
|
|
0eeae74ffa | ||
|
|
8fa715089b | ||
|
|
ab2c0ea120 | ||
|
|
5583ea8b6b | ||
|
|
a4eb446f7b | ||
|
|
2d526a1454 | ||
|
|
9811c13a04 | ||
|
|
406ede9352 | ||
|
|
1360c79e69 | ||
|
|
12229e5e0b | ||
|
|
588b289bb9 | ||
|
|
b3419ccca6 | ||
|
|
ecd20890c8 | ||
|
|
b6588ff3c5 | ||
|
|
ed2de112a2 | ||
|
|
c19f48ef3f | ||
|
|
eb8de323ee | ||
|
|
c42b2f03b7 | ||
|
|
303b02f3ca | ||
|
|
98e0f8e998 | ||
|
|
ecf613954a |
@@ -14,7 +14,7 @@ orbs:
|
||||
- run:
|
||||
name: Install Chrome
|
||||
command: |
|
||||
wget -O chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
wget -O chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_77.0.3865.120-1_amd64.deb
|
||||
sudo dpkg -i chrome.deb
|
||||
install-node:
|
||||
steps:
|
||||
@@ -210,7 +210,15 @@ jobs:
|
||||
name: Run the scenario
|
||||
command: deployment-e2e/molecule.sh repo
|
||||
no_output_timeout: 40m
|
||||
|
||||
deployment-multiple:
|
||||
executor: tokenbridge-orb/machine-with-docker-caching
|
||||
steps:
|
||||
- checkout
|
||||
- run: git submodule update --init
|
||||
- run:
|
||||
name: Run the scenario
|
||||
command: deployment-e2e/molecule.sh multiple
|
||||
no_output_timeout: 40m
|
||||
ultimate:
|
||||
executor: tokenbridge-orb/machine-with-docker-caching
|
||||
parameters:
|
||||
@@ -222,6 +230,11 @@ jobs:
|
||||
type: string
|
||||
ui-e2e-grep:
|
||||
description: "Mocha grep string used to run ui-e2e tests specific to given type of bridge"
|
||||
default: ''
|
||||
type: string
|
||||
oracle-e2e-script:
|
||||
description: "Yarn script string used to run oracle-e2e tests specific to given type of bridge"
|
||||
default: ''
|
||||
type: string
|
||||
steps:
|
||||
- checkout
|
||||
@@ -232,16 +245,24 @@ jobs:
|
||||
- tokenbridge-orb/yarn-install-cached-on-machine
|
||||
- run:
|
||||
name: Prepare the infrastructure
|
||||
command: e2e-commons/up.sh deploy << parameters.scenario-name >>
|
||||
command: e2e-commons/up.sh deploy << parameters.scenario-name >> blocks
|
||||
no_output_timeout: 50m
|
||||
- tokenbridge-orb/wait-for-oracle:
|
||||
redis-key: << parameters.redis-key >>
|
||||
- when:
|
||||
condition: << parameters.ui-e2e-grep >>
|
||||
steps:
|
||||
- run:
|
||||
name: Run the ui-e2e tests
|
||||
command: |
|
||||
nvm use default;
|
||||
node ./e2e-commons/scripts/blocks.js &
|
||||
cd ui-e2e; yarn mocha -g "<< parameters.ui-e2e-grep >>" -b ./test.js
|
||||
- when:
|
||||
condition: << parameters.oracle-e2e-script >>
|
||||
steps:
|
||||
- run:
|
||||
name: Run the oracle-e2e tests
|
||||
command: cd e2e-commons && docker-compose run e2e yarn workspace oracle-e2e run << parameters.oracle-e2e-script >>
|
||||
workflows:
|
||||
tokenbridge:
|
||||
jobs:
|
||||
@@ -272,6 +293,7 @@ workflows:
|
||||
- deployment-ui
|
||||
- deployment-monitor
|
||||
- deployment-repo
|
||||
- deployment-multiple
|
||||
- ultimate:
|
||||
name: "ultimate: native to erc"
|
||||
scenario-name: native-to-erc
|
||||
@@ -287,3 +309,8 @@ workflows:
|
||||
scenario-name: erc-to-erc
|
||||
redis-key: erc-erc-collected-signatures:lastProcessedBlock
|
||||
ui-e2e-grep: "ERC TO ERC"
|
||||
- ultimate:
|
||||
name: "ultimate: amb"
|
||||
scenario-name: amb
|
||||
redis-key: amb-collected-signatures:lastProcessedBlock
|
||||
oracle-e2e-script: "amb"
|
||||
|
||||
@@ -2,3 +2,4 @@ node_modules
|
||||
submodules
|
||||
coverage
|
||||
lib
|
||||
dist
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@ coverage
|
||||
|
||||
# production
|
||||
build
|
||||
dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
@@ -69,3 +69,5 @@ MONITOR_VALIDATOR_HOME_TX_LIMIT | Average gas usage of a transaction sent by a v
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT | Average gas usage of a transaction sent by a validator, it is used to estimate the number of transaction that can be paid by the validator. | integer
|
||||
MONITOR_TX_NUMBER_THRESHOLD | If estimated number of transaction is equal to or below this value, the monitor will report that the validator has less funds than it is required. | integer
|
||||
MONITOR_PORT | The port for the Monitor. | integer
|
||||
MONITOR_BRIDGE_NAME | The name to be used in the url path for the bridge | string
|
||||
MONITOR_CACHE_EVENTS | If set to true, monitor will cache obtained events for other workers runs
|
||||
|
||||
@@ -66,11 +66,13 @@ Clone the repository:
|
||||
git clone https://github.com/poanetwork/tokenbridge
|
||||
```
|
||||
|
||||
Initialize submodules, install dependencies, compile the Smart Contracts:
|
||||
If there is no need to build docker images for the TokenBridge components (oracle, monitor, UI), initialize submodules, install dependencies, compile the Smart Contracts:
|
||||
```
|
||||
yarn initialize
|
||||
```
|
||||
|
||||
Then refer to the corresponding README files to get information about particular TokenBridge component.
|
||||
|
||||
## Linting
|
||||
|
||||
Running linter for all JS projects:
|
||||
@@ -106,5 +108,4 @@ This project is licensed under the GNU Lesser General Public License v3.0. See t
|
||||
|
||||
## References
|
||||
|
||||
* [Additional Documentation](https://forum.poa.network/c/tokenbridge)
|
||||
* [POA20 Bridge FAQ](https://forum.poa.network/c/tokenbridge/poa20-bridge)
|
||||
* [TokenBridge Documentation](http://www.tokenbridge.net/)
|
||||
|
||||
Binary file not shown.
31
burner-wallet-plugin/.eslintrc.js
Normal file
31
burner-wallet-plugin/.eslintrc.js
Normal file
@@ -0,0 +1,31 @@
|
||||
module.exports = {
|
||||
parser: "@typescript-eslint/parser", // Specifies the ESLint parser
|
||||
extends: [
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/recommended", // Uses the recommended rules from @typescript-eslint/eslint-plugin
|
||||
"../.eslintrc"
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
|
||||
sourceType: "module", // Allows for the use of imports
|
||||
ecmaFeatures: {
|
||||
jsx: true // Allows for the parsing of JSX
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off", // Reduce the use of 'any'
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"react/prop-types": "off",
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/member-delimiter-style": "off",
|
||||
"@typescript-eslint/indent": "off",
|
||||
"@typescript-eslint/explicit-member-accessibility": "off"
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
}
|
||||
}
|
||||
};
|
||||
30
burner-wallet-plugin/Dockerfile
Normal file
30
burner-wallet-plugin/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
||||
FROM node:12 as plugin-base
|
||||
|
||||
WORKDIR /mono
|
||||
COPY package.json .
|
||||
RUN mkdir -p contracts/node_modules
|
||||
|
||||
COPY burner-wallet-plugin/package.json ./burner-wallet-plugin/
|
||||
COPY burner-wallet-plugin/lerna.json ./burner-wallet-plugin/
|
||||
COPY burner-wallet-plugin/yarn.lock ./burner-wallet-plugin/
|
||||
COPY burner-wallet-plugin/tsconfig.json ./burner-wallet-plugin/
|
||||
COPY burner-wallet-plugin/tokenbridge-bw-exchange/package.json ./burner-wallet-plugin/tokenbridge-bw-exchange/
|
||||
COPY burner-wallet-plugin/staging/package.json ./burner-wallet-plugin/staging/
|
||||
COPY burner-wallet-plugin/testing/package.json ./burner-wallet-plugin/testing/
|
||||
COPY yarn.lock .
|
||||
RUN yarn install --production --frozen-lockfile
|
||||
|
||||
COPY ./burner-wallet-plugin/tokenbridge-bw-exchange ./burner-wallet-plugin/tokenbridge-bw-exchange
|
||||
RUN yarn build:plugin
|
||||
|
||||
|
||||
FROM plugin-base as testing
|
||||
COPY ./burner-wallet-plugin/testing ./burner-wallet-plugin/testing
|
||||
WORKDIR /mono/burner-wallet-plugin
|
||||
CMD ["yarn", "start-testing"]
|
||||
|
||||
|
||||
FROM plugin-base as staging
|
||||
COPY ./burner-wallet-plugin/staging ./burner-wallet-plugin/staging
|
||||
WORKDIR /mono/burner-wallet-plugin
|
||||
CMD ["yarn", "start-staging"]
|
||||
41
burner-wallet-plugin/README.md
Normal file
41
burner-wallet-plugin/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# TokenBridge Burner Wallet 2 Plugin
|
||||
|
||||
Please refer to the [Plugin README](./tokenrbdige-bw-exchange/README.md) for resources provided, instructions to install and use the plugin.
|
||||
|
||||
### Setup
|
||||
1. [Initialize](../README.md#initializing-the-monorepository) the monorepository.
|
||||
2. Run `yarn build` or from the monorepository root `yarn build:plugin`
|
||||
|
||||
### Run Burner Wallet with the plugin in Mainnet & Classic
|
||||
1. Create `.env` file in `staging` folder and set `REACT_APP_INFURA_KEY=<your key from infura.com>`
|
||||
2. Run `yarn start-staging` to start the wallet connected to Mainnet & Classic and interact with the ETH - WETC Bridge.
|
||||
|
||||
### Run Burner Wallet with the plugin in Sokol & Kovan
|
||||
1. Create `.env` file in `testing` folder and set `REACT_APP_INFURA_KEY=<your key from infura.com>`.
|
||||
Also, a private key can be set to start the wallet with the specified account `REACT_APP_PK=0x...`
|
||||
2. Run `yarn start-testing` to start the wallet connected to Sokol & Kovan and interact with a test bridge
|
||||
that works on top of the AMB bridge.
|
||||
|
||||
### Docker Setup
|
||||
Docker can be used to build the services and run the testing and staging wallets.
|
||||
|
||||
First you may want to create the `.env` files for testing and staging as mentioned before. This is optional before building the containers, variables can be passes later using `--env-file` or `--env` parameters in `docker run`.
|
||||
|
||||
Build the services with docker-compose:
|
||||
```bash
|
||||
docker-compose build
|
||||
```
|
||||
|
||||
### Run Burner Wallet with the plugin in Mainnet & Classic using Docker
|
||||
```bash
|
||||
docker run -ti -p 8080:8080 -e PORT=8080 --rm burner-wallet-plugin_staging
|
||||
```
|
||||
|
||||
### Run Burner Wallet with the plugin in Sokol & Kovan using Docker
|
||||
```bash
|
||||
docker run -ti -p 8080:8080 -e PORT=8080 --rm burner-wallet-plugin_testing
|
||||
```
|
||||
### Publish to npm
|
||||
In order to make this plugin accessible, it should be available as a npm package. Follow the [instructions](publish.md) to publish
|
||||
the package to npm registry.
|
||||
|
||||
17
burner-wallet-plugin/docker-compose.yml
Normal file
17
burner-wallet-plugin/docker-compose.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
version: '2.4'
|
||||
services:
|
||||
staging:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: burner-wallet-plugin/Dockerfile
|
||||
target: staging
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
testing:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: burner-wallet-plugin/Dockerfile
|
||||
target: testing
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
10
burner-wallet-plugin/lerna.json
Normal file
10
burner-wallet-plugin/lerna.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"packages": [
|
||||
"basic-wallet",
|
||||
"local-wallet",
|
||||
"tokenbridge-bw-exchange"
|
||||
],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "independent"
|
||||
}
|
||||
28
burner-wallet-plugin/package.json
Normal file
28
burner-wallet-plugin/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "burner-wallet-plugin",
|
||||
"description": "Burner Wallet 2 plugin",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-only",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"install": "lerna bootstrap",
|
||||
"build": "lerna run --ignore testing --ignore staging build --stream",
|
||||
"lint": "eslint '*/**/*.{js,ts,tsx}' --ignore-path ../.eslintignore",
|
||||
"start-staging": "lerna run --scope staging start --stream",
|
||||
"start-testing": "lerna run --scope testing start --stream",
|
||||
"test": "lerna run --ignore testing --ignore staging test --stream"
|
||||
},
|
||||
"workspaces": [
|
||||
"staging",
|
||||
"testing",
|
||||
"tokenbridge-bw-exchange"
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/color": "3.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "1.13.0",
|
||||
"@typescript-eslint/parser": "1.13.0",
|
||||
"eslint-plugin-react": "7.19.0",
|
||||
"lerna": "3.16.4",
|
||||
"typescript": "3.5.3"
|
||||
}
|
||||
}
|
||||
36
burner-wallet-plugin/publish.md
Normal file
36
burner-wallet-plugin/publish.md
Normal file
@@ -0,0 +1,36 @@
|
||||
## Plugin Package Information
|
||||
|
||||
The package to be published gets its configuration from `tokenbridge/burner-wallet-plugin/tokenbridge-bw-exchange/package.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "tokenbridge-bw-exchange",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"/dist"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `name` is the name of how package will be available in npm.
|
||||
- `main` is entry point for the package
|
||||
- `types` is the entry point for typescript types
|
||||
- `files` is the list of files included when publishing the package. So we have to run `yarn build` first to
|
||||
generate the `dist` folder.
|
||||
|
||||
## Steps to publish to npm
|
||||
|
||||
1. Create account in https://www.npmjs.com/
|
||||
|
||||
2. Go to `tokenbridge/burner-wallet-plugin/tokenbridge-bw-exchange/`
|
||||
|
||||
3. Run `yarn build`. Make sure it generates the `dist` folder
|
||||
|
||||
4. Update `version` in `tokenbridge/burner-wallet-plugin/tokenbridge-bw-exchange/package.json`
|
||||
5. Run `yarn login` and fill login information if required.
|
||||
6. Run `yarn publish --access public`.
|
||||
The prompt will ask for the new version, complete it with the version from `package.json`
|
||||
|
||||
More information in https://classic.yarnpkg.com/en/docs/publishing-a-package/
|
||||
1
burner-wallet-plugin/staging/.env.example
Normal file
1
burner-wallet-plugin/staging/.env.example
Normal file
@@ -0,0 +1 @@
|
||||
REACT_APP_INFURA_KEY=
|
||||
40
burner-wallet-plugin/staging/package.json
Normal file
40
burner-wallet-plugin/staging/package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "staging",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@burner-wallet/assets": "^1.1.10",
|
||||
"@burner-wallet/core": "^1.1.0",
|
||||
"@burner-wallet/exchange": "^1.1.4",
|
||||
"@burner-wallet/metamask-plugin": "^1.0.0",
|
||||
"@burner-wallet/modern-ui": "^1.0.7",
|
||||
"@poanet/tokenbridge-bw-exchange": "^1.0.0",
|
||||
"@types/node": "12.0.4",
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "16.8.4",
|
||||
"@types/react-router-dom": "^4.3.3",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-scripts": "3.0.1",
|
||||
"typescript": "3.5.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
BIN
burner-wallet-plugin/staging/public/favicon.ico
Normal file
BIN
burner-wallet-plugin/staging/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
38
burner-wallet-plugin/staging/public/index.html
Normal file
38
burner-wallet-plugin/staging/public/index.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
15
burner-wallet-plugin/staging/public/manifest.json
Normal file
15
burner-wallet-plugin/staging/public/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
21
burner-wallet-plugin/staging/src/index.tsx
Normal file
21
burner-wallet-plugin/staging/src/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import BurnerCore from '@burner-wallet/core'
|
||||
import { InjectedSigner, LocalSigner } from '@burner-wallet/core/signers'
|
||||
import { InfuraGateway, InjectedGateway } from '@burner-wallet/core/gateways'
|
||||
import Exchange from '@burner-wallet/exchange'
|
||||
import ModernUI from '@burner-wallet/modern-ui'
|
||||
import { Etc, Wetc, TokenBridgeGateway, WETCBridge } from '@poanet/tokenbridge-bw-exchange'
|
||||
import MetamaskPlugin from '@burner-wallet/metamask-plugin'
|
||||
|
||||
const core = new BurnerCore({
|
||||
signers: [new InjectedSigner(), new LocalSigner()],
|
||||
gateways: [new InjectedGateway(), new InfuraGateway(process.env.REACT_APP_INFURA_KEY), new TokenBridgeGateway()],
|
||||
assets: [Wetc, Etc]
|
||||
})
|
||||
|
||||
const exchange = new Exchange([new WETCBridge()])
|
||||
|
||||
const BurnerWallet = () => <ModernUI title="Staging Wallet" core={core} plugins={[exchange, new MetamaskPlugin()]} />
|
||||
|
||||
ReactDOM.render(<BurnerWallet />, document.getElementById('root'))
|
||||
1
burner-wallet-plugin/staging/src/react-app-env.d.ts
vendored
Normal file
1
burner-wallet-plugin/staging/src/react-app-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="react-scripts" />
|
||||
25
burner-wallet-plugin/staging/tsconfig.json
Normal file
25
burner-wallet-plugin/staging/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
14
burner-wallet-plugin/testing/.env.example
Normal file
14
burner-wallet-plugin/testing/.env.example
Normal file
@@ -0,0 +1,14 @@
|
||||
REACT_APP_INFURA_KEY=
|
||||
#REACT_APP_PK=0x
|
||||
|
||||
REACT_APP_MODE=AMB_NATIVE_TO_ERC677
|
||||
|
||||
REACT_APP_HOME_TOKEN_NAME=sPOA
|
||||
REACT_APP_HOME_NETWORK=77
|
||||
REACT_APP_HOME_MEDIATOR_ADDRESS=0x867949C3F2f66D827Ed40847FaA7B3a369370e13
|
||||
REACT_APP_HOME_TOKEN_ADDRESS=
|
||||
|
||||
REACT_APP_FOREIGN_TOKEN_NAME=ksPOA
|
||||
REACT_APP_FOREIGN_NETWORK=42
|
||||
REACT_APP_FOREIGN_MEDIATOR_ADDRESS=0x99FB1a25caeB9c3a5Bf132686E2fe5e27BC0e2dd
|
||||
REACT_APP_FOREIGN_TOKEN_ADDRESS=0xff94183659f549D6273349696d73686Ee1d2AC83
|
||||
43
burner-wallet-plugin/testing/package.json
Normal file
43
burner-wallet-plugin/testing/package.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "testing",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@burner-wallet/assets": "^1.1.10",
|
||||
"@burner-wallet/core": "^1.1.0",
|
||||
"@burner-wallet/exchange": "^1.1.4",
|
||||
"@burner-wallet/metamask-plugin": "^1.0.0",
|
||||
"@burner-wallet/modern-ui": "^1.0.7",
|
||||
"@poanet/tokenbridge-bw-exchange": "^1.0.0",
|
||||
"@types/node": "12.0.4",
|
||||
"@types/react": "16.8.19",
|
||||
"@types/react-dom": "16.8.4",
|
||||
"@types/react-router-dom": "^4.3.3",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-scripts": "3.0.1",
|
||||
"typescript": "3.5.1",
|
||||
"web3": "1.0.0-beta.55"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.19.0"
|
||||
}
|
||||
}
|
||||
BIN
burner-wallet-plugin/testing/public/favicon.ico
Normal file
BIN
burner-wallet-plugin/testing/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
38
burner-wallet-plugin/testing/public/index.html
Normal file
38
burner-wallet-plugin/testing/public/index.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
15
burner-wallet-plugin/testing/public/manifest.json
Normal file
15
burner-wallet-plugin/testing/public/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "Burner Wallet",
|
||||
"name": "Burner Wallet",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
73
burner-wallet-plugin/testing/src/index.tsx
Normal file
73
burner-wallet-plugin/testing/src/index.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Asset } from '@burner-wallet/assets'
|
||||
import BurnerCore from '@burner-wallet/core'
|
||||
import { InjectedSigner, LocalSigner } from '@burner-wallet/core/signers'
|
||||
import { InfuraGateway, InjectedGateway } from '@burner-wallet/core/gateways'
|
||||
import ModernUI from '@burner-wallet/modern-ui'
|
||||
import Exchange from '@burner-wallet/exchange'
|
||||
import { Mediator, sPOA, ERC677Asset, TokenBridgeGateway } from '@poanet/tokenbridge-bw-exchange'
|
||||
import MetamaskPlugin from '@burner-wallet/metamask-plugin'
|
||||
|
||||
let assetIdAtHome = 'assetAtHome'
|
||||
const assetIdAtForeign = 'assetAtForeign'
|
||||
let assetAtHome: Asset
|
||||
let assetAtForeign: Asset
|
||||
|
||||
if (process.env.REACT_APP_MODE === 'AMB_NATIVE_TO_ERC677') {
|
||||
sPOA.setMediatorAddress(process.env.REACT_APP_HOME_MEDIATOR_ADDRESS)
|
||||
assetAtHome = sPOA
|
||||
assetIdAtHome = sPOA.id
|
||||
|
||||
assetAtForeign = new ERC677Asset({
|
||||
id: 'assetAtForeign',
|
||||
// @ts-ignore
|
||||
name: process.env.REACT_APP_FOREIGN_TOKEN_NAME,
|
||||
// @ts-ignore
|
||||
network: process.env.REACT_APP_FOREIGN_NETWORK,
|
||||
// @ts-ignore
|
||||
address: process.env.REACT_APP_FOREIGN_TOKEN_ADDRESS
|
||||
})
|
||||
} else {
|
||||
// process.env.REACT_APP_MODE === 'AMB_ERC677_TO_ERC677'
|
||||
assetAtHome = new ERC677Asset({
|
||||
id: 'assetAtHome',
|
||||
// @ts-ignore
|
||||
name: process.env.REACT_APP_HOME_TOKEN_NAME,
|
||||
// @ts-ignore
|
||||
network: process.env.REACT_APP_HOME_NETWORK,
|
||||
// @ts-ignore
|
||||
address: process.env.REACT_APP_HOME_TOKEN_ADDRESS
|
||||
})
|
||||
|
||||
assetAtForeign = new ERC677Asset({
|
||||
id: 'assetAtForeign',
|
||||
// @ts-ignore
|
||||
name: process.env.REACT_APP_FOREIGN_TOKEN_NAME,
|
||||
// @ts-ignore
|
||||
network: process.env.REACT_APP_FOREIGN_NETWORK,
|
||||
// @ts-ignore
|
||||
address: process.env.REACT_APP_FOREIGN_TOKEN_ADDRESS
|
||||
})
|
||||
}
|
||||
|
||||
const testBridge = new Mediator({
|
||||
assetA: assetIdAtHome,
|
||||
// @ts-ignore
|
||||
assetABridge: process.env.REACT_APP_HOME_MEDIATOR_ADDRESS,
|
||||
assetB: assetIdAtForeign,
|
||||
// @ts-ignore
|
||||
assetBBridge: process.env.REACT_APP_FOREIGN_MEDIATOR_ADDRESS
|
||||
})
|
||||
|
||||
const core = new BurnerCore({
|
||||
signers: [new InjectedSigner(), new LocalSigner({ privateKey: process.env.REACT_APP_PK, saveKey: false })],
|
||||
gateways: [new InjectedGateway(), new TokenBridgeGateway(), new InfuraGateway(process.env.REACT_APP_INFURA_KEY)],
|
||||
assets: [assetAtHome, assetAtForeign]
|
||||
})
|
||||
|
||||
const exchange = new Exchange([testBridge])
|
||||
|
||||
const BurnerWallet = () => <ModernUI title="Testing Wallet" core={core} plugins={[exchange, new MetamaskPlugin()]} />
|
||||
|
||||
ReactDOM.render(<BurnerWallet />, document.getElementById('root'))
|
||||
1
burner-wallet-plugin/testing/src/react-app-env.d.ts
vendored
Normal file
1
burner-wallet-plugin/testing/src/react-app-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="react-scripts" />
|
||||
25
burner-wallet-plugin/testing/tsconfig.json
Normal file
25
burner-wallet-plugin/testing/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
37
burner-wallet-plugin/tokenbridge-bw-exchange/README.md
Normal file
37
burner-wallet-plugin/tokenbridge-bw-exchange/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# TokenBridge Burner Wallet 2 Plugin
|
||||
|
||||
This plugin defines a Bridge trading pair to be used in the Exchange Plugin.
|
||||
|
||||
Bridge trading pairs and assets supported:
|
||||
* ETC - WETC Bridge
|
||||
|
||||
It also provides some generic resources that can be used and extended:
|
||||
* **ERC677Asset** - A representation of an Erc677 token
|
||||
* **NativeMediatorAsset** - Represents a native token that interacts with a Mediator extension.
|
||||
* **Mediator Pair** - Represents an Exchange Pair that interacts with mediators extensions.
|
||||
* **TokenBridgeGateway** - A gateway to operate with ETC, POA Sokol and POA Core networks.
|
||||
|
||||
### Install package
|
||||
```
|
||||
yarn add @poanet/tokenbridge-bw-exchange
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```javascript
|
||||
import { Etc, Wetc, EtcGateway, WETCBridge } from '@poanet/tokenbridge-bw-exchange'
|
||||
|
||||
const core = new BurnerCore({
|
||||
...
|
||||
gateways: [new EtcGateway(), new InfuraGateway(process.env.REACT_APP_INFURA_KEY)],
|
||||
assets: [Etc, Wetc]
|
||||
})
|
||||
|
||||
const exchange = new Exchange({
|
||||
pairs: [new WETCBridge()]
|
||||
})
|
||||
```
|
||||
|
||||
This is how the exchange plugin will look like:
|
||||
|
||||

|
||||
40
burner-wallet-plugin/tokenbridge-bw-exchange/package.json
Normal file
40
burner-wallet-plugin/tokenbridge-bw-exchange/package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@poanet/tokenbridge-bw-exchange",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"/dist",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start-basic": "tsc -w",
|
||||
"start-local": "tsc -w",
|
||||
"test": "TS_NODE_PROJECT=\"tsconfig.testing.json\" mocha -r ts-node/register test/**/*.spec.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@burner-wallet/assets": "^1.1.10",
|
||||
"@burner-wallet/core": "^1.1.9",
|
||||
"@burner-wallet/exchange": "^1.1.4",
|
||||
"@burner-wallet/types": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^7.0.2",
|
||||
"chai": "^4.2.0",
|
||||
"mocha": "^5.2.0",
|
||||
"ts-node": "^8.8.2",
|
||||
"typescript": "^3.5.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/poanetwork/tokenbridge.git",
|
||||
"directory": "burner-wallet-plugin/tokenbridge-bw-exchange"
|
||||
},
|
||||
"homepage": "https://tokenbridge.net/",
|
||||
"keywords": [
|
||||
"tokenbridge",
|
||||
"burner-wallet"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import { ERC20Asset } from '@burner-wallet/assets'
|
||||
import { ERC677_ABI } from '../../utils'
|
||||
|
||||
const TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
|
||||
const BLOCK_LOOKBACK = 250
|
||||
|
||||
interface ERC677Constructor {
|
||||
abi?: object
|
||||
address: string
|
||||
id: string
|
||||
name: string
|
||||
network: string
|
||||
}
|
||||
|
||||
export default class ERC677Asset extends ERC20Asset {
|
||||
constructor({ abi = ERC677_ABI, ...params }: ERC677Constructor) {
|
||||
super({ abi, type: 'erc677', ...params })
|
||||
}
|
||||
|
||||
async _send({ from, to, value }) {
|
||||
const receipt = await this.getContract()
|
||||
.methods.transferAndCall(to, value, '0x')
|
||||
.send({ from })
|
||||
return {
|
||||
...receipt,
|
||||
txHash: receipt.transactionHash,
|
||||
id: `${receipt.transactionHash}-${receipt.events.Transfer.logIndex}`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides ERC20Asset `startWatchingAddress` to get the `Transfer` events by topic instead of
|
||||
* the event name because ERC677 abi has two events definitions named `Transfer` and
|
||||
* `getPastEvents` method does not provide a way to choose the correct one to use.
|
||||
* @param address
|
||||
*/
|
||||
startWatchingAddress(address) {
|
||||
let block = 0
|
||||
return this.poll(async () => {
|
||||
const currentBlock = await this.getWeb3().eth.getBlockNumber()
|
||||
if (block === 0) {
|
||||
block = Math.max(currentBlock - BLOCK_LOOKBACK, 0)
|
||||
}
|
||||
|
||||
const allTransferEvents = await this.getContract().getPastEvents('allEvents', {
|
||||
fromBlock: block,
|
||||
toBlock: currentBlock,
|
||||
topics: [TRANSFER_TOPIC]
|
||||
})
|
||||
// Manually filter `to` parameter because `filter` option does not work with allEvents
|
||||
const events = allTransferEvents.filter(e => e.returnValues.to.toLowerCase() === address.toLowerCase())
|
||||
|
||||
await events.map(async event =>
|
||||
this.core.addHistoryEvent({
|
||||
id: `${event.transactionHash}-${event.logIndex}`,
|
||||
asset: this.id,
|
||||
type: 'send',
|
||||
value: event.returnValues.value.toString(),
|
||||
from: event.returnValues.from,
|
||||
to: event.returnValues.to,
|
||||
tx: event.transactionHash,
|
||||
timestamp: await this._getBlockTimestamp(event.blockNumber)
|
||||
})
|
||||
)
|
||||
|
||||
block = currentBlock
|
||||
}, this._pollInterval)
|
||||
}
|
||||
|
||||
async getTx(txHash) {
|
||||
const historyEvents = this.core.getHistoryEvents({ asset: this.id })
|
||||
const eventMatch = historyEvents.filter(e => e.tx === txHash)
|
||||
if (eventMatch.length > 0) {
|
||||
return eventMatch[0]
|
||||
} else {
|
||||
return super.getTx(txHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import NativeMediatorAsset from './NativeMediatorAsset'
|
||||
import { isBridgeContract, HOME_NATIVE_TO_ERC_ABI } from '../../utils'
|
||||
|
||||
class EtcNativeAsset extends NativeMediatorAsset {
|
||||
constructor(props) {
|
||||
super({ mediatorAddress: '0x073081832B4Ecdce79d4D6753565c85Ba4b3BeA9', ...props })
|
||||
}
|
||||
|
||||
async scanMediatorEvents(address, fromBlock, toBlock) {
|
||||
const web3 = this.getWeb3()
|
||||
const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.mediatorAddress)
|
||||
const listenToBridgeEvent = await isBridgeContract(contract)
|
||||
if (listenToBridgeEvent && this.mediatorAddress != '') {
|
||||
const events = await contract.getPastEvents('AffirmationCompleted', {
|
||||
fromBlock,
|
||||
toBlock
|
||||
})
|
||||
const filteredEvents = events.filter(
|
||||
event => event.returnValues.recipient.toLowerCase() === address.toLowerCase()
|
||||
)
|
||||
|
||||
for (const event of filteredEvents) {
|
||||
this.core.addHistoryEvent({
|
||||
id: `${event.transactionHash}-${event.logIndex}`,
|
||||
asset: this.id,
|
||||
type: 'send',
|
||||
value: event.returnValues.value.toString(),
|
||||
from: this.mediatorAddress,
|
||||
to: event.returnValues.recipient,
|
||||
tx: event.transactionHash,
|
||||
timestamp: await this._getBlockTimestamp(event.blockNumber)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
await super.scanMediatorEvents(address, fromBlock, toBlock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new EtcNativeAsset({
|
||||
id: 'etc',
|
||||
name: 'ETC',
|
||||
network: '61',
|
||||
icon: 'https://user-images.githubusercontent.com/4614574/77648741-666cf800-6f47-11ea-8cb4-01b9db00c264.png'
|
||||
})
|
||||
@@ -0,0 +1,65 @@
|
||||
import { NativeAsset } from '@burner-wallet/assets'
|
||||
import { Contract, EventData } from 'web3-eth-contract'
|
||||
import { MEDIATOR_ABI } from '../../utils'
|
||||
|
||||
interface NativeMediatorConstructor {
|
||||
mediatorAddress?: string
|
||||
id: string
|
||||
name: string
|
||||
network: string
|
||||
}
|
||||
|
||||
export default class NativeMediatorAsset extends NativeAsset {
|
||||
protected mediatorAddress: string
|
||||
|
||||
constructor({ mediatorAddress = '', ...params }: NativeMediatorConstructor) {
|
||||
super({ ...params })
|
||||
this.mediatorAddress = mediatorAddress
|
||||
}
|
||||
|
||||
async scanBlocks(address, fromBlock, toBlock) {
|
||||
await super.scanBlocks(address, fromBlock, toBlock)
|
||||
await this.scanMediatorEvents(address, fromBlock, toBlock)
|
||||
}
|
||||
|
||||
async getTx(txHash) {
|
||||
const historyEvents = this.core.getHistoryEvents({ asset: this.id, account: this.mediatorAddress })
|
||||
const eventMatch = historyEvents.filter(e => e.tx === txHash)
|
||||
if (eventMatch.length > 0) {
|
||||
return eventMatch[0]
|
||||
} else {
|
||||
return super.getTx(txHash)
|
||||
}
|
||||
}
|
||||
|
||||
async scanMediatorEvents(address, fromBlock, toBlock) {
|
||||
if (this.mediatorAddress != '') {
|
||||
const web3 = this.getWeb3()
|
||||
const contract: Contract = new web3.eth.Contract(MEDIATOR_ABI, this.mediatorAddress)
|
||||
const events: EventData[] = await contract.getPastEvents('TokensBridged', {
|
||||
fromBlock,
|
||||
toBlock,
|
||||
filter: {
|
||||
recipient: address
|
||||
}
|
||||
})
|
||||
|
||||
for (const event of events) {
|
||||
this.core.addHistoryEvent({
|
||||
id: `${event.transactionHash}-${event.logIndex}`,
|
||||
asset: this.id,
|
||||
type: 'send',
|
||||
value: event.returnValues.value.toString(),
|
||||
from: this.mediatorAddress,
|
||||
to: event.returnValues.recipient,
|
||||
tx: event.transactionHash,
|
||||
timestamp: await this._getBlockTimestamp(event.blockNumber)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setMediatorAddress(mediatorAddress) {
|
||||
this.mediatorAddress = mediatorAddress
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { default as ERC677Asset } from './ERC677Asset'
|
||||
|
||||
export default new ERC677Asset({
|
||||
id: 'wetc',
|
||||
name: 'WETC',
|
||||
network: '1',
|
||||
address: '0x86aabcc646f290b9fc9bd05ce17c3858d1511da1'
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
import NativeMediatorAsset from './NativeMediatorAsset'
|
||||
|
||||
export default new NativeMediatorAsset({
|
||||
id: 'spoa',
|
||||
name: 'sPOA',
|
||||
network: '77'
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Gateway } from '@burner-wallet/core/gateways'
|
||||
import Web3 from 'web3'
|
||||
|
||||
export default class TokenBridgeGateway extends Gateway {
|
||||
private readonly providers: object
|
||||
private readonly providerStrings: { [id: string]: string }
|
||||
constructor() {
|
||||
super()
|
||||
this.providerStrings = {
|
||||
'61': `https://www.ethercluster.com/etc`,
|
||||
'77': 'https://sokol.poa.network',
|
||||
'99': 'https://core.poa.network'
|
||||
}
|
||||
this.providers = {}
|
||||
}
|
||||
|
||||
isAvailable() {
|
||||
return true
|
||||
}
|
||||
|
||||
getNetworks() {
|
||||
return ['61', '77', '99']
|
||||
}
|
||||
|
||||
_provider(network) {
|
||||
if (!this.providers[network]) {
|
||||
this._makeProvider(network)
|
||||
}
|
||||
return this.providers[network]
|
||||
}
|
||||
|
||||
_makeProvider(network) {
|
||||
if (!this.providerStrings[network]) {
|
||||
throw new Error(`Network ${network} not supported by TokenBridgeGateway`)
|
||||
}
|
||||
|
||||
this.providers[network] = new Web3.providers.HttpProvider(this.providerStrings[network])
|
||||
}
|
||||
|
||||
send(network, payload) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.getNetworks().indexOf(network) === -1) {
|
||||
return reject(new Error('TokenBridgeGateway does not support this network'))
|
||||
}
|
||||
|
||||
this._provider(network).send(payload, (err, response) => {
|
||||
if (err) {
|
||||
return reject(err)
|
||||
}
|
||||
return resolve(response.result)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export { default as sPOA } from './assets/sPOA'
|
||||
export { default as Etc } from './assets/Etc'
|
||||
export { default as Wetc } from './assets/Wetc'
|
||||
export { default as ERC677Asset } from './assets/ERC677Asset'
|
||||
export { default as NativeMediatorAsset } from './assets/NativeMediatorAsset'
|
||||
export { default as TokenBridgeGateway } from './gateways/TokenBridgeGateway'
|
||||
export { default as Mediator } from './pairs/Mediator'
|
||||
@@ -0,0 +1,107 @@
|
||||
import BN from 'bn.js'
|
||||
import { Bridge, EstimateReturn, ValueTypes } from '@burner-wallet/exchange'
|
||||
import { waitForEvent, constants } from '../../utils'
|
||||
import { MEDIATOR_ABI, MEDIATOR_FEE_MANAGER_ABI } from '../../utils'
|
||||
import { fromWei, toBN } from 'web3-utils'
|
||||
|
||||
interface MediatorConstructor {
|
||||
assetA: string
|
||||
assetABridge: string
|
||||
assetB: string
|
||||
assetBBridge: string
|
||||
}
|
||||
|
||||
export default class Mediator extends Bridge {
|
||||
constructor({ assetA, assetABridge, assetB, assetBBridge }: MediatorConstructor) {
|
||||
super({ assetA, assetABridge, assetB, assetBBridge })
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async detectExchangeBToAFinished(account, value, sendResult) {
|
||||
const asset = this.getExchange().getAsset(this.assetA)
|
||||
const web3 = asset.getWeb3()
|
||||
const contract = new web3.eth.Contract(MEDIATOR_ABI, this.assetABridge)
|
||||
await waitForEvent(web3, contract, 'TokensBridged', this.processMediatorEvents(account))
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async detectExchangeAToBFinished(account, value, sendResult) {
|
||||
const web3 = this.getExchange()
|
||||
.getAsset(this.assetB)
|
||||
.getWeb3()
|
||||
const contract = new web3.eth.Contract(MEDIATOR_ABI, this.assetBBridge)
|
||||
await waitForEvent(web3, contract, 'TokensBridged', this.processMediatorEvents(account))
|
||||
}
|
||||
|
||||
processMediatorEvents(account) {
|
||||
return events => {
|
||||
const confirmationEvent = events.filter(
|
||||
event => event.returnValues.recipient.toLowerCase() === account.toLowerCase()
|
||||
)
|
||||
return confirmationEvent.length > 0
|
||||
}
|
||||
}
|
||||
|
||||
async estimateAtoB(value: ValueTypes): Promise<EstimateReturn> {
|
||||
const web3 = this.getExchange()
|
||||
.getAsset(this.assetB)
|
||||
.getWeb3()
|
||||
|
||||
const userAmount = this._getValue(value)
|
||||
|
||||
const contract = new web3.eth.Contract(MEDIATOR_ABI, this.assetBBridge)
|
||||
const { feeAmount, feePercentage } = await this.getFee(web3, contract, userAmount)
|
||||
const finalAmount = toBN(userAmount).sub(feeAmount)
|
||||
const estimateInfo = feeAmount.isZero() ? null : `${constants.ESTIMATE_FEE_MESSAGE} Fee: ${feePercentage}%`
|
||||
|
||||
return {
|
||||
estimate: finalAmount.toString(),
|
||||
estimateInfo
|
||||
}
|
||||
}
|
||||
|
||||
async estimateBtoA(value: ValueTypes): Promise<EstimateReturn> {
|
||||
const web3 = this.getExchange()
|
||||
.getAsset(this.assetA)
|
||||
.getWeb3()
|
||||
|
||||
const userAmount = this._getValue(value)
|
||||
|
||||
const contract = new web3.eth.Contract(MEDIATOR_ABI, this.assetABridge)
|
||||
const { feeAmount, feePercentage } = await this.getFee(web3, contract, userAmount)
|
||||
const finalAmount = toBN(userAmount).sub(feeAmount)
|
||||
const estimateInfo = feeAmount.isZero() ? null : `${constants.ESTIMATE_FEE_MESSAGE} Fee: ${feePercentage}%`
|
||||
|
||||
return {
|
||||
estimate: finalAmount.toString(),
|
||||
estimateInfo
|
||||
}
|
||||
}
|
||||
|
||||
async getFee(web3, contract, value): Promise<{ feeAmount: BN; feePercentage: number }> {
|
||||
const feeManagerAddress = await this.getFeeManagerContract(contract)
|
||||
if (feeManagerAddress != constants.ZERO_ADDRESS) {
|
||||
const feeManagerContract = new web3.eth.Contract(MEDIATOR_FEE_MANAGER_ABI, feeManagerAddress)
|
||||
const fee = toBN(await feeManagerContract.methods.fee().call())
|
||||
const feePercentage = Number(fromWei(fee, 'ether')) * 100
|
||||
const feeAmount = toBN(await feeManagerContract.methods.calculateFee(value).call())
|
||||
return {
|
||||
feeAmount,
|
||||
feePercentage
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
feeAmount: toBN(0),
|
||||
feePercentage: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getFeeManagerContract(contract) {
|
||||
try {
|
||||
return await contract.methods.feeManagerContract().call()
|
||||
} catch (e) {
|
||||
return constants.ZERO_ADDRESS
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { ERC677Asset, NativeMediatorAsset, sPOA, Etc, Wetc, TokenBridgeGateway, Mediator } from './burner-wallet'
|
||||
export { WETCBridge } from './wetc-bridge'
|
||||
@@ -0,0 +1,5 @@
|
||||
export { default as ERC677_ABI } from './abis/ERC677'
|
||||
export { default as FOREIGN_NATIVE_TO_ERC_ABI } from './abis/ForeignBridgeNativeToErc'
|
||||
export { default as HOME_NATIVE_TO_ERC_ABI } from './abis/HomeBridgeNativeToErc'
|
||||
export { default as MEDIATOR_ABI } from './abis/Mediator'
|
||||
export { default as MEDIATOR_FEE_MANAGER_ABI } from './abis/MediatorFeeManager'
|
||||
@@ -0,0 +1,275 @@
|
||||
export default [
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: '_spender',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: '_value',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'approve',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'totalSupply',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: '_from',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: '_to',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: '_value',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'transferFrom',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: '_who',
|
||||
type: 'address'
|
||||
}
|
||||
],
|
||||
name: 'balanceOf',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: '_to',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: '_value',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'transfer',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: '_owner',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: '_spender',
|
||||
type: 'address'
|
||||
}
|
||||
],
|
||||
name: 'allowance',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
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'
|
||||
},
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
indexed: true,
|
||||
name: 'owner',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
indexed: true,
|
||||
name: 'spender',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
indexed: false,
|
||||
name: 'value',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'Approval',
|
||||
type: 'event'
|
||||
},
|
||||
{
|
||||
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'
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
},
|
||||
{
|
||||
name: '',
|
||||
type: 'bytes'
|
||||
}
|
||||
],
|
||||
name: 'transferAndCall',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'spender',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: 'addedValue',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'increaseAllowance',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'spender',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
name: 'subtractedValue',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'decreaseAllowance',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function'
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,49 @@
|
||||
export default [
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: '_txHash',
|
||||
type: 'bytes32'
|
||||
}
|
||||
],
|
||||
name: 'relayedMessages',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bool'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'deployedAtBlock',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'getHomeFee',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,52 @@
|
||||
export default [
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
indexed: false,
|
||||
name: 'recipient',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
indexed: false,
|
||||
name: 'value',
|
||||
type: 'uint256'
|
||||
},
|
||||
{
|
||||
indexed: false,
|
||||
name: 'transactionHash',
|
||||
type: 'bytes32'
|
||||
}
|
||||
],
|
||||
name: 'AffirmationCompleted',
|
||||
type: 'event'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'deployedAtBlock',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'getForeignFee',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,38 @@
|
||||
export default [
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
indexed: true,
|
||||
name: 'recipient',
|
||||
type: 'address'
|
||||
},
|
||||
{
|
||||
indexed: false,
|
||||
name: 'value',
|
||||
type: 'uint256'
|
||||
},
|
||||
{
|
||||
indexed: true,
|
||||
name: 'messageId',
|
||||
type: 'bytes32'
|
||||
}
|
||||
],
|
||||
name: 'TokensBridged',
|
||||
type: 'event'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'feeManagerContract',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'address'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,35 @@
|
||||
export default [
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
name: 'calculateFee',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'fee',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256'
|
||||
}
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function'
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
export { constants, wait, waitForEvent, isBridgeContract } from './utils'
|
||||
export {
|
||||
ERC677_ABI,
|
||||
FOREIGN_NATIVE_TO_ERC_ABI,
|
||||
HOME_NATIVE_TO_ERC_ABI,
|
||||
MEDIATOR_ABI,
|
||||
MEDIATOR_FEE_MANAGER_ABI
|
||||
} from './abis'
|
||||
@@ -0,0 +1,40 @@
|
||||
import { EventData, Contract } from 'web3-eth-contract'
|
||||
import { toWei } from 'web3-utils'
|
||||
|
||||
export const wait = (time: number) => new Promise(resolve => setTimeout(resolve, time))
|
||||
|
||||
export const constants = {
|
||||
EXCHANGE_TIMEOUT: 300000,
|
||||
MAX_FEE: toWei('1', 'ether'),
|
||||
ESTIMATE_FEE_MESSAGE: 'Estimation takes fee charges into consideration.',
|
||||
ZERO_ADDRESS: '0x0000000000000000000000000000000000000000'
|
||||
}
|
||||
|
||||
export const waitForEvent = async (web3, contract: Contract, event: string, callback: Function) => {
|
||||
let fromBlock = await web3.eth.getBlockNumber()
|
||||
|
||||
const stopTime = Date.now() + constants.EXCHANGE_TIMEOUT
|
||||
while (Date.now() <= stopTime) {
|
||||
const currentBlock = await web3.eth.getBlockNumber()
|
||||
const events: EventData[] = await contract.getPastEvents(event, {
|
||||
fromBlock,
|
||||
toBlock: currentBlock
|
||||
})
|
||||
const eventFound = await callback(events)
|
||||
|
||||
if (eventFound) {
|
||||
return
|
||||
}
|
||||
fromBlock = currentBlock
|
||||
await wait(10000)
|
||||
}
|
||||
}
|
||||
|
||||
export const isBridgeContract = async (contract: Contract): Promise<boolean> => {
|
||||
try {
|
||||
await contract.methods.deployedAtBlock().call()
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { Mediator } from '../burner-wallet'
|
||||
import { HOME_NATIVE_TO_ERC_ABI, FOREIGN_NATIVE_TO_ERC_ABI } from '../utils'
|
||||
import { waitForEvent, isBridgeContract, constants } from '../utils'
|
||||
import { ValueTypes } from '@burner-wallet/exchange'
|
||||
import { toBN, fromWei } from 'web3-utils'
|
||||
|
||||
export default class WETCBridge extends Mediator {
|
||||
constructor() {
|
||||
super({
|
||||
assetA: 'etc',
|
||||
assetABridge: '0x073081832B4Ecdce79d4D6753565c85Ba4b3BeA9',
|
||||
assetB: 'wetc',
|
||||
assetBBridge: '0x0cB781EE62F815bdD9CD4c2210aE8600d43e7040'
|
||||
})
|
||||
}
|
||||
|
||||
async detectExchangeBToAFinished(account, value, sendResult) {
|
||||
const web3 = this.getExchange()
|
||||
.getAsset(this.assetA)
|
||||
.getWeb3()
|
||||
const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.assetABridge)
|
||||
const listenToBridgeEvent = await isBridgeContract(contract)
|
||||
if (listenToBridgeEvent) {
|
||||
await waitForEvent(web3, contract, 'AffirmationCompleted', this.processBridgeEvents(sendResult.txHash))
|
||||
} else {
|
||||
await super.detectExchangeBToAFinished(account, value, sendResult)
|
||||
}
|
||||
}
|
||||
|
||||
async detectExchangeAToBFinished(account, value, sendResult) {
|
||||
const web3 = this.getExchange()
|
||||
.getAsset(this.assetB)
|
||||
.getWeb3()
|
||||
const contract = new web3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, this.assetBBridge)
|
||||
const listenToBridgeEvent = await isBridgeContract(contract)
|
||||
if (listenToBridgeEvent) {
|
||||
await waitForEvent(web3, contract, 'RelayedMessage', this.processBridgeEvents(sendResult.txHash))
|
||||
} else {
|
||||
await super.detectExchangeAToBFinished(account, value, sendResult)
|
||||
}
|
||||
}
|
||||
|
||||
processBridgeEvents(txHash) {
|
||||
return events => {
|
||||
const confirmationEvent = events.filter(event => event.returnValues.transactionHash === txHash)
|
||||
return confirmationEvent.length > 0
|
||||
}
|
||||
}
|
||||
|
||||
async estimateAtoB(value: ValueTypes) {
|
||||
const web3 = this.getExchange()
|
||||
.getAsset(this.assetB)
|
||||
.getWeb3()
|
||||
const contract = new web3.eth.Contract(FOREIGN_NATIVE_TO_ERC_ABI, this.assetBBridge)
|
||||
|
||||
const useBridgeContract = await isBridgeContract(contract)
|
||||
|
||||
if (useBridgeContract) {
|
||||
const fee = toBN(await contract.methods.getHomeFee().call())
|
||||
const feeAmount = toBN(this._getValue(value))
|
||||
.mul(fee)
|
||||
.div(toBN(constants.MAX_FEE))
|
||||
const finalAmount = toBN(this._getValue(value)).sub(feeAmount)
|
||||
const feePercentage = Number(fromWei(fee, 'ether')) * 100
|
||||
const estimateInfo = feeAmount.isZero() ? null : `${constants.ESTIMATE_FEE_MESSAGE} Fee: ${feePercentage}%`
|
||||
|
||||
return {
|
||||
estimate: finalAmount.toString(),
|
||||
estimateInfo
|
||||
}
|
||||
} else {
|
||||
return await super.estimateAtoB(value)
|
||||
}
|
||||
}
|
||||
|
||||
async estimateBtoA(value: ValueTypes) {
|
||||
const web3 = this.getExchange()
|
||||
.getAsset(this.assetA)
|
||||
.getWeb3()
|
||||
const contract = new web3.eth.Contract(HOME_NATIVE_TO_ERC_ABI, this.assetABridge)
|
||||
|
||||
const useBridgeContract = await isBridgeContract(contract)
|
||||
|
||||
if (useBridgeContract) {
|
||||
const fee = toBN(await contract.methods.getForeignFee().call())
|
||||
const feeAmount = toBN(this._getValue(value))
|
||||
.mul(fee)
|
||||
.div(toBN(constants.MAX_FEE))
|
||||
const finalAmount = toBN(this._getValue(value)).sub(feeAmount)
|
||||
const feePercentage = Number(fromWei(fee, 'ether')) * 100
|
||||
const estimateInfo = feeAmount.isZero() ? null : `${constants.ESTIMATE_FEE_MESSAGE} Fee: ${feePercentage}%`
|
||||
return {
|
||||
estimate: finalAmount.toString(),
|
||||
estimateInfo
|
||||
}
|
||||
} else {
|
||||
return await super.estimateBtoA(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default as WETCBridge } from './WETCBridge'
|
||||
@@ -0,0 +1,112 @@
|
||||
import { expect } from 'chai'
|
||||
import 'mocha'
|
||||
import ERC677Asset from '../src/burner-wallet/assets/ERC677Asset'
|
||||
|
||||
const ACCOUNT1 = '0x1010101010101010101010101010101010101010'
|
||||
const ACCOUNT2 = '0x0000000000000000000000000000000000000001'
|
||||
const TX_HASH = '0x376565f5614bd4483fd716c441aff43446b50f7772bef75496edef7faa070a85'
|
||||
const ONE_ETH = '1000000000000000000'
|
||||
const TRANSFER_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
|
||||
|
||||
describe('ERC677Asset', () => {
|
||||
it('should add an event when sent', done => {
|
||||
const asset = new ERC677Asset({
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
network: '5777',
|
||||
address: '0xcbfaa26289d24a6b4c5fe562bdd9a1b623260359'
|
||||
})
|
||||
|
||||
const testConditions = event => {
|
||||
expect(event.asset).to.equal('test')
|
||||
expect(event.type).to.equal('send')
|
||||
expect(event.value).to.equal(ONE_ETH)
|
||||
expect(event.from).to.equal(ACCOUNT2)
|
||||
expect(event.to).to.equal(ACCOUNT1)
|
||||
expect(event.id).to.equal(`${TX_HASH}-0`)
|
||||
expect(event.tx).to.equal(TX_HASH)
|
||||
done()
|
||||
}
|
||||
|
||||
const burnerCore = {
|
||||
addHistoryEvent: testConditions,
|
||||
getWeb3: () => ({
|
||||
eth: {
|
||||
methods: {},
|
||||
Contract: function Contract() {
|
||||
this.methods = {
|
||||
transferAndCall() {
|
||||
return {
|
||||
send() {
|
||||
return {
|
||||
transactionHash: TX_HASH,
|
||||
events: {
|
||||
Transfer: {
|
||||
logIndex: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
asset.setCore(burnerCore)
|
||||
asset.send({ to: ACCOUNT1, from: ACCOUNT2, value: ONE_ETH })
|
||||
})
|
||||
it('should watch an address and add events for new transactions', done => {
|
||||
const asset = new ERC677Asset({
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
network: '5777',
|
||||
address: '0xcbfaa26289d24a6b4c5fe562bdd9a1b623260359'
|
||||
})
|
||||
|
||||
const testConditions = event => {
|
||||
expect(event.asset).to.equal('test')
|
||||
expect(event.type).to.equal('send')
|
||||
expect(event.value).to.equal(ONE_ETH)
|
||||
expect(event.from).to.equal(ACCOUNT2)
|
||||
expect(event.to).to.equal(ACCOUNT1)
|
||||
expect(event.tx).to.equal(TX_HASH)
|
||||
expect(event.timestamp).to.equal(1571234034)
|
||||
done()
|
||||
}
|
||||
|
||||
const burnerCore = {
|
||||
addHistoryEvent: testConditions,
|
||||
getWeb3: () => ({
|
||||
eth: {
|
||||
getBlockNumber: () => 100,
|
||||
getBlock: () => ({ timestamp: 1571234034 }),
|
||||
Contract: function Contract() {
|
||||
// @ts-ignore
|
||||
this.getPastEvents = (eventName, { topics }) => {
|
||||
expect(eventName).to.equal('allEvents')
|
||||
expect(topics[0]).to.equal(TRANSFER_TOPIC)
|
||||
return [
|
||||
{
|
||||
event: 'Transfer',
|
||||
returnValues: {
|
||||
to: ACCOUNT1,
|
||||
from: ACCOUNT2,
|
||||
value: ONE_ETH
|
||||
},
|
||||
transactionHash: TX_HASH
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
asset.setCore(burnerCore)
|
||||
const unsubscribe = asset.startWatchingAddress(ACCOUNT1)
|
||||
unsubscribe()
|
||||
})
|
||||
})
|
||||
10
burner-wallet-plugin/tokenbridge-bw-exchange/tsconfig.json
Normal file
10
burner-wallet-plugin/tokenbridge-bw-exchange/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"./src"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs"
|
||||
}
|
||||
}
|
||||
27
burner-wallet-plugin/tsconfig.json
Normal file
27
burner-wallet-plugin/tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react",
|
||||
"target": "esnext",
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"noImplicitAny": false,
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
15931
burner-wallet-plugin/yarn.lock
Normal file
15931
burner-wallet-plugin/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/Rewardab
|
||||
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
|
||||
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
|
||||
const BOX_ABI = require('../contracts/build/contracts/Box').abi
|
||||
const SAI_TOP = require('../contracts/build/contracts/SaiTopMock').abi
|
||||
|
||||
const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis')
|
||||
const { BRIDGE_MODES } = require('./constants')
|
||||
@@ -92,5 +93,6 @@ module.exports = {
|
||||
ERC20_BYTES32_ABI,
|
||||
HOME_AMB_ABI,
|
||||
FOREIGN_AMB_ABI,
|
||||
BOX_ABI
|
||||
BOX_ABI,
|
||||
SAI_TOP
|
||||
}
|
||||
|
||||
Submodule contracts updated: 20d262702d...a7ce4441ab
3
deployment-e2e/molecule/monitor/converge.yml
Normal file
3
deployment-e2e/molecule/monitor/converge.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
- import_playbook: ../../../deployment/site.yml
|
||||
- import_playbook: ./run-checks.yml
|
||||
@@ -29,10 +29,11 @@ provisioner:
|
||||
r: ["bug"]
|
||||
playbooks:
|
||||
prepare: ../prepare.yml
|
||||
converge: ../../../deployment/site.yml
|
||||
converge: ./converge.yml
|
||||
inventory:
|
||||
host_vars:
|
||||
monitor-host:
|
||||
MONITOR_PORT: 3003
|
||||
syslog_server_port: "udp://127.0.0.1:514"
|
||||
verifier:
|
||||
name: testinfra
|
||||
|
||||
7
deployment-e2e/molecule/monitor/run-checks.yml
Normal file
7
deployment-e2e/molecule/monitor/run-checks.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Generate initial data for monitor
|
||||
hosts: monitor
|
||||
become: true
|
||||
tasks:
|
||||
- name: Run monitor checks
|
||||
shell: /bin/bash -c 'cd /home/poadocker/bridge/monitor/scripts; ./getBridgeStats.sh >cronWorker.out 2>cronWorker.err'
|
||||
@@ -34,14 +34,14 @@ def test_logging(host, filename):
|
||||
|
||||
def test_home_exists(host):
|
||||
assert host.run_test(
|
||||
'curl -s http://localhost:3003 | '
|
||||
'curl -s http://localhost:3003/bridge | '
|
||||
'grep -q -i "home"'
|
||||
)
|
||||
|
||||
|
||||
def test_foreign_exists(host):
|
||||
assert host.run_test(
|
||||
'curl -s http://localhost:3003 | '
|
||||
'curl -s http://localhost:3003/bridge | '
|
||||
'grep -q -i "foreign"'
|
||||
)
|
||||
|
||||
@@ -49,6 +49,6 @@ def test_foreign_exists(host):
|
||||
def test_no_error(host):
|
||||
assert host.run_expect(
|
||||
[1],
|
||||
'curl -s http://localhost:3003 | '
|
||||
'curl -s http://localhost:3003/bridge | '
|
||||
'grep -i -q "error"'
|
||||
)
|
||||
|
||||
14
deployment-e2e/molecule/multiple/Dockerfile.j2
Normal file
14
deployment-e2e/molecule/multiple/Dockerfile.j2
Normal file
@@ -0,0 +1,14 @@
|
||||
# Molecule managed
|
||||
|
||||
{% if item.registry is defined %}
|
||||
FROM {{ item.registry.url }}/{{ item.image }}
|
||||
{% else %}
|
||||
FROM {{ item.image }}
|
||||
{% endif %}
|
||||
|
||||
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
|
||||
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
|
||||
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
|
||||
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
|
||||
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
|
||||
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi
|
||||
59
deployment-e2e/molecule/multiple/molecule.yml
Normal file
59
deployment-e2e/molecule/multiple/molecule.yml
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
dependency:
|
||||
name: galaxy
|
||||
driver:
|
||||
name: docker
|
||||
lint:
|
||||
name: yamllint
|
||||
enabled: True
|
||||
options:
|
||||
config-data:
|
||||
ignore: ../../hosts.yml
|
||||
platforms:
|
||||
- name: multiple-host
|
||||
groups:
|
||||
- example
|
||||
children:
|
||||
- oracle
|
||||
- monitor
|
||||
- ui
|
||||
image: ubuntu:16.04
|
||||
privileged: true
|
||||
network_mode: host
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
provisioner:
|
||||
name: ansible
|
||||
lint:
|
||||
name: ansible-lint
|
||||
enabled: True
|
||||
options:
|
||||
r: ["bug"]
|
||||
playbooks:
|
||||
prepare: ../prepare.yml
|
||||
converge: ../monitor/converge.yml
|
||||
inventory:
|
||||
host_vars:
|
||||
multiple-host:
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
MONITOR_PORT: 3003
|
||||
syslog_server_port: "udp://127.0.0.1:514"
|
||||
verifier:
|
||||
name: testinfra
|
||||
lint:
|
||||
name: flake8
|
||||
additional_files_or_dirs:
|
||||
- ../../tests/*
|
||||
scenario:
|
||||
name: multiple
|
||||
test_sequence:
|
||||
- lint
|
||||
- cleanup
|
||||
- destroy
|
||||
- dependency
|
||||
- syntax
|
||||
- create
|
||||
- prepare
|
||||
- converge
|
||||
- verify
|
||||
- destroy
|
||||
32
deployment-e2e/molecule/multiple/tests/test_multiple.py
Normal file
32
deployment-e2e/molecule/multiple/tests/test_multiple.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import os
|
||||
import pytest
|
||||
import testinfra.utils.ansible_runner
|
||||
|
||||
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
|
||||
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("service", [
|
||||
("poabridge"),
|
||||
("tokenbridge-ui"),
|
||||
("tokenbridge-monitor")
|
||||
])
|
||||
def test_services(host, service):
|
||||
assert host.service(service).is_enabled
|
||||
assert host.service(service).is_running
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", [
|
||||
("oracle_rabbit_1"),
|
||||
("oracle_redis_1"),
|
||||
("oracle_bridge_request_1"),
|
||||
("oracle_bridge_collected_1"),
|
||||
("oracle_bridge_affirmation_1"),
|
||||
("oracle_bridge_senderhome_1"),
|
||||
("oracle_bridge_senderforeign_1"),
|
||||
("ui_ui_1"),
|
||||
("monitor_monitor_1")
|
||||
])
|
||||
def test_docker_containers(host, name):
|
||||
container = host.docker(name)
|
||||
assert container.is_running
|
||||
@@ -9,7 +9,6 @@ testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
|
||||
def test_repo(host):
|
||||
assert host.file('/home/poadocker/bridge').exists
|
||||
assert host.file('/home/poadocker/bridge').is_directory
|
||||
assert host.file('/home/poadocker/bridge/package.json').exists
|
||||
|
||||
|
||||
def test_docker_group(host):
|
||||
|
||||
14
deployment-e2e/molecule/ultimate-amb/Dockerfile.j2
Normal file
14
deployment-e2e/molecule/ultimate-amb/Dockerfile.j2
Normal file
@@ -0,0 +1,14 @@
|
||||
# Molecule managed
|
||||
|
||||
{% if item.registry is defined %}
|
||||
FROM {{ item.registry.url }}/{{ item.image }}
|
||||
{% else %}
|
||||
FROM {{ item.image }}
|
||||
{% endif %}
|
||||
|
||||
RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get install -y python sudo bash ca-certificates && apt-get clean; \
|
||||
elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python*-dnf bash && dnf clean all; \
|
||||
elif [ $(command -v yum) ]; then yum makecache fast && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \
|
||||
elif [ $(command -v zypper) ]; then zypper refresh && zypper install -y python sudo bash python-xml && zypper clean -a; \
|
||||
elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \
|
||||
elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi
|
||||
40
deployment-e2e/molecule/ultimate-amb/molecule.yml
Normal file
40
deployment-e2e/molecule/ultimate-amb/molecule.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
driver:
|
||||
name: docker
|
||||
platforms:
|
||||
- name: oracle-amb-host
|
||||
groups:
|
||||
- ultimate
|
||||
- amb
|
||||
children:
|
||||
- oracle
|
||||
image: ubuntu:16.04
|
||||
privileged: true
|
||||
network_mode: host
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
provisioner:
|
||||
name: ansible
|
||||
playbooks:
|
||||
prepare: ../prepare.yml
|
||||
converge: ../ultimate-commons/converge.yml
|
||||
inventory:
|
||||
host_vars:
|
||||
oracle-amb-host:
|
||||
COMMON_HOME_RPC_URL: "http://parity1:8545"
|
||||
COMMON_FOREIGN_RPC_URL: "http://parity2:8545"
|
||||
ORACLE_VALIDATOR_ADDRESS: "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b"
|
||||
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY: "8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
verifier:
|
||||
name: testinfra
|
||||
lint:
|
||||
name: flake8
|
||||
scenario:
|
||||
name: ultimate-amb
|
||||
test_sequence:
|
||||
- cleanup
|
||||
- destroy
|
||||
- syntax
|
||||
- create
|
||||
- prepare
|
||||
- converge
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
- name: Slurp docker compose file
|
||||
slurp:
|
||||
src: "/home/poadocker/bridge/oracle/{{ file }}.yml"
|
||||
register: docker_compose_slurp
|
||||
- name: Parse docker compose file
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}"
|
||||
|
||||
- name: Add the external network used to connect to Parity nodes
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}"
|
||||
|
||||
- name: Add all Oracle containers to the network
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {item: {'networks': docker_compose_parsed.services[item].networks | union(['ultimate'])}}}, recursive=True) }}"
|
||||
with_items: "{{ docker_compose_parsed.services }}"
|
||||
|
||||
- name: Expose Redis port to allow connecting from redis-cli
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {'redis': {'ports': ['6379:6379']}}}, recursive=True) }}"
|
||||
|
||||
- name: Write updated docker file
|
||||
copy:
|
||||
content: "{{ docker_compose_parsed | to_yaml }}"
|
||||
dest: "/home/poadocker/bridge/oracle/{{ file }}.yml"
|
||||
@@ -6,57 +6,30 @@
|
||||
- name: stop the service
|
||||
shell: service poabridge stop
|
||||
|
||||
- name: Slurp docker compose file
|
||||
slurp:
|
||||
src: "/home/poadocker/bridge/oracle/docker-compose.yml"
|
||||
register: docker_compose_slurp
|
||||
- name: Parse docker compose file
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}"
|
||||
- name: Build current oracle image
|
||||
shell: docker build -t oracle:ultimate-testing --file oracle/Dockerfile .
|
||||
delegate_to: 127.0.0.1
|
||||
become: false
|
||||
args:
|
||||
chdir: "{{ lookup('env', 'PWD') }}/.."
|
||||
|
||||
- name: Add the external network used to connect to Parity nodes
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}"
|
||||
- name: Replace oracle image
|
||||
replace:
|
||||
path: "/home/poadocker/bridge/oracle/{{ item }}.yml"
|
||||
regexp: 'poanetwork/tokenbridge-oracle:latest'
|
||||
replace: "oracle:ultimate-testing"
|
||||
with_items:
|
||||
- docker-compose
|
||||
- docker-compose-transfer
|
||||
- docker-compose-erc-native
|
||||
|
||||
- name: Add all Oracle containers to the network
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {item: {'networks': docker_compose_parsed.services[item].networks | union(['ultimate'])}}}, recursive=True) }}"
|
||||
with_items: "{{ docker_compose_parsed.services }}"
|
||||
|
||||
- name: Expose Redis port to allow connecting from redis-cli
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed | combine({'services': {'redis': {'ports': ['6379:6379']}}}, recursive=True) }}"
|
||||
|
||||
- name: Write new docker-compose file
|
||||
copy:
|
||||
content: "{{ docker_compose_parsed | to_yaml }}"
|
||||
dest: "/home/poadocker/bridge/oracle/docker-compose.yml"
|
||||
|
||||
- name: Slurp docker compose extended file
|
||||
slurp:
|
||||
src: "/home/poadocker/bridge/oracle/docker-compose-transfer.yml"
|
||||
register: docker_compose_extended_slurp
|
||||
- name: Parse docker compose file
|
||||
set_fact:
|
||||
docker_compose_extended_parsed: "{{ docker_compose_extended_slurp['content'] | b64decode | from_yaml }}"
|
||||
|
||||
- name: Add the external network used to connect to Parity nodes in compose extended file
|
||||
set_fact:
|
||||
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}"
|
||||
|
||||
- name: Add all Oracle containers to the network in compose extended file
|
||||
set_fact:
|
||||
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed | combine({'services': {item: {'networks': docker_compose_extended_parsed.services[item].networks | union(['ultimate'])}}}, recursive=True) }}"
|
||||
with_items: "{{ docker_compose_extended_parsed.services }}"
|
||||
|
||||
- name: Expose Redis port to allow connecting from redis-cli in compose extended file
|
||||
set_fact:
|
||||
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed | combine({'services': {'redis': {'ports': ['6379:6379']}}}, recursive=True) }}"
|
||||
|
||||
- name: Write new docker-compose extended file
|
||||
copy:
|
||||
content: "{{ docker_compose_extended_parsed | to_yaml }}"
|
||||
dest: "/home/poadocker/bridge/oracle/docker-compose-transfer.yml"
|
||||
- include_tasks: oracle-add-docker-external-network.yml
|
||||
with_items:
|
||||
- docker-compose
|
||||
- docker-compose-transfer
|
||||
- docker-compose-erc-native
|
||||
loop_control:
|
||||
loop_var: file
|
||||
|
||||
- name: start the service
|
||||
shell: service poabridge start
|
||||
|
||||
@@ -79,6 +79,10 @@ Example config for installing only UI:
|
||||
`cd group_vars`
|
||||
2. Note the <bridge_name> and add it to the hosts.yml configuration. For example, if a bridge file is named sokol-kovan.yml, you would change the <bridge_name> value in hosts.yml to sokol-kovan.
|
||||
|
||||
## Examples
|
||||
|
||||
[Deploy a monitor for multiple bridges](./MONITOR.md)
|
||||
|
||||
## Administrator Configurations
|
||||
|
||||
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.
|
||||
|
||||
106
deployment/MONITOR.md
Normal file
106
deployment/MONITOR.md
Normal file
@@ -0,0 +1,106 @@
|
||||
## Deploy multiple bridge monitor on the same host
|
||||
|
||||
If you want to deploy a monitor for different bridges, the [monitor variables](../monitor/.env.example) should be configured in `group_vars/<bridge_name>.yml` for each bridge.
|
||||
|
||||
For example, let's say we are going to deploy a monitor for xDai bridge and for WETC bridge.
|
||||
|
||||
#### Setup ansible configuration for xDai Bridge
|
||||
|
||||
First we create `hosts.yml` file to deploy the monitor for xdai bridge
|
||||
```yaml
|
||||
---
|
||||
xdai:
|
||||
children:
|
||||
monitor:
|
||||
hosts:
|
||||
<host_ip_A>:
|
||||
ansible_user: ubuntu
|
||||
```
|
||||
In `group_vars/xdai.yml`
|
||||
```
|
||||
---
|
||||
MONITOR_BRIDGE_NAME: "xdai"
|
||||
MONITOR_PORT: 3003
|
||||
MONITOR_CACHE_EVENTS: "true"
|
||||
|
||||
COMMON_HOME_RPC_URL: "https://dai.poa.network"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6"
|
||||
COMMON_FOREIGN_RPC_URL: "https://mainnet.infura.io/v3/INFURA_KEY"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x4aa42145Aa6Ebf72e164C9bBC74fbD3788045016"
|
||||
|
||||
COMMON_HOME_GAS_PRICE_FALLBACK: 0
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
|
||||
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
|
||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK: 10000000000
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR: 1
|
||||
|
||||
MONITOR_HOME_START_BLOCK: 759
|
||||
MONITOR_FOREIGN_START_BLOCK: 6478417
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT: 0
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
|
||||
MONITOR_TX_NUMBER_THRESHOLD: 100
|
||||
```
|
||||
|
||||
Run the playbook to deploy the monitor for xdai bridge
|
||||
```
|
||||
ansible-playbook -i hosts.yml site.yml
|
||||
```
|
||||
|
||||
This command will deploy the monitor component and enable statistics for xdai bridge.
|
||||
|
||||
#### Setup ansible configuration for WETC Bridge
|
||||
|
||||
Update `hosts.yml` file to deploy the monitor for WETC Bridge
|
||||
```yaml
|
||||
---
|
||||
wetc:
|
||||
children:
|
||||
monitor:
|
||||
hosts:
|
||||
<host_ip_A>:
|
||||
ansible_user: ubuntu
|
||||
```
|
||||
|
||||
In `group_vars/wetc.yml`
|
||||
```
|
||||
---
|
||||
MONITOR_BRIDGE_NAME: "wetc"
|
||||
MONITOR_CACHE_EVENTS: "true"
|
||||
|
||||
COMMON_HOME_RPC_URL: "https://ethereumclassic.network"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x073081832B4Ecdce79d4D6753565c85Ba4b3BeA9"
|
||||
COMMON_FOREIGN_RPC_URL: "https://mainnet.infura.io/v3/32e8e252699a4ac1b5dd5c1ef53cc301"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x0cB781EE62F815bdD9CD4c2210aE8600d43e7040"
|
||||
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL: "https://gasprice-etc.poa.network/"
|
||||
COMMON_HOME_GAS_PRICE_SPEED_TYPE: "standard"
|
||||
COMMON_HOME_GAS_PRICE_FALLBACK: 15000000000
|
||||
COMMON_HOME_GAS_PRICE_FACTOR: 1
|
||||
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL: "https://gasprice.poa.network/"
|
||||
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE: "standard"
|
||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK: 10000000000
|
||||
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR: 1
|
||||
|
||||
MONITOR_HOME_START_BLOCK: 7703292
|
||||
MONITOR_FOREIGN_START_BLOCK: 7412459
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
|
||||
MONITOR_TX_NUMBER_THRESHOLD: 100
|
||||
```
|
||||
Given that there is a monitor component deployed in the system, the `MONITOR_PORT` variable is not needed.
|
||||
|
||||
Run the playbook to deploy the monitor for WETC Bridge
|
||||
```
|
||||
ansible-playbook -i hosts.yml site.yml
|
||||
```
|
||||
|
||||
They playbook will detect that the monitor component is already deployed in the system, so it will only generate the configuration needed to enable the WETC Bridge statistics.
|
||||
|
||||
##### Get Monitor results
|
||||
The monitor output will be available at `http://host_ip_A:MONITOR_PORT/MONITOR_BRIDGE_NAME`.
|
||||
|
||||
Given that in `xdai.env` the variable `MONITOR_BRIDGE_NAME` is set to `xdai`, the results are in the url `http://host_ip_A:3003/xdai/`.
|
||||
|
||||
Similar to the xdai case, in `wetc.env` the variable `MONITOR_BRIDGE_NAME` is set to `wetc`, so the results are in the url `http://host_ip_A:3003/wetc/`.
|
||||
5
deployment/group_vars/amb.yml
Normal file
5
deployment/group_vars/amb.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
ORACLE_BRIDGE_MODE: "ARBITRARY_MESSAGE"
|
||||
COMMON_HOME_BRIDGE_ADDRESS: "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0"
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS: "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0"
|
||||
MONITOR_PORT: 3013
|
||||
@@ -42,7 +42,9 @@ UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
|
||||
## Monitor
|
||||
MONITOR_BRIDGE_NAME: "xdai"
|
||||
MONITOR_PORT: 3003
|
||||
MONITOR_CACHE_EVENTS: "true"
|
||||
MONITOR_HOME_START_BLOCK: 759
|
||||
MONITOR_FOREIGN_START_BLOCK: 6478417
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
|
||||
|
||||
@@ -44,9 +44,11 @@ UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
|
||||
## Monitor
|
||||
MONITOR_BRIDGE_NAME: "bridge"
|
||||
MONITOR_PORT: 3003
|
||||
MONITOR_CACHE_EVENTS: "false"
|
||||
MONITOR_HOME_START_BLOCK: 0
|
||||
MONITOR_FOREIGN_START_BLOCK: 0
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
|
||||
MONITOR_LEFT_TX_THRESHOLD: 100
|
||||
MONITOR_TX_NUMBER_THRESHOLD: 100
|
||||
|
||||
@@ -41,9 +41,11 @@ UI_FOREIGN_EXPLORER_ADDRESS_TEMPLATE: https://blockscout.com/eth/kovan/address/%
|
||||
UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
|
||||
#montior
|
||||
#monitor
|
||||
MONITOR_BRIDGE_NAME: "bridge"
|
||||
MONITOR_CACHE_EVENTS: "true"
|
||||
MONITOR_HOME_START_BLOCK: 0
|
||||
MONITOR_FOREIGN_START_BLOCK: 0
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT: 300000
|
||||
MONITOR_LEFT_TX_THRESHOLD: 100
|
||||
MONITOR_TX_NUMBER_THRESHOLD: 100
|
||||
|
||||
@@ -43,7 +43,9 @@ UI_HOME_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
UI_FOREIGN_GAS_PRICE_UPDATE_INTERVAL: 600000
|
||||
|
||||
## Monitor
|
||||
MONITOR_BRIDGE_NAME: "wetc"
|
||||
MONITOR_PORT: 3003
|
||||
MONITOR_CACHE_EVENTS: "true"
|
||||
MONITOR_HOME_START_BLOCK: 7703292
|
||||
MONITOR_FOREIGN_START_BLOCK: 7412459
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT: 300000
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
group: "root"
|
||||
mode: "0755"
|
||||
|
||||
- name: Upgrade pip version
|
||||
shell: pip3 install --upgrade pip
|
||||
|
||||
- name: Install python docker library
|
||||
shell: pip3 install docker docker-compose setuptools
|
||||
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
---
|
||||
- include_tasks: dependencies.yml
|
||||
- include_tasks: repo.yml
|
||||
- include_tasks: logging.yml
|
||||
- name: Check if component is already deployed
|
||||
shell: "test -f {{ bridge_path }}/{{ component }}/.env && echo 'true'"
|
||||
ignore_errors: True
|
||||
register: already_deployed
|
||||
when: check_deployed is defined
|
||||
|
||||
- name: Set if tasks should be skipped
|
||||
set_fact: skip_task="{{ already_deployed.stdout | default('false') }}"
|
||||
|
||||
- name: Include dependencies tasks
|
||||
include_tasks: dependencies.yml
|
||||
when: skip_task != true
|
||||
|
||||
- name: Include repo tasks
|
||||
include_tasks: repo.yml
|
||||
when: skip_task != true and skip_repo is undefined
|
||||
|
||||
- name: Include logging tasks
|
||||
include_tasks: logging.yml
|
||||
when: skip_task != true
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- role: common
|
||||
- { role: common, skip_repo: true, check_deployed: true, component: 'monitor' }
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
day: "{{ monitor_cron_schedule.split(' ')[2] }}"
|
||||
month: "{{ monitor_cron_schedule.split(' ')[3] }}"
|
||||
weekday: "{{ monitor_cron_schedule.split(' ')[4] }}"
|
||||
job: "/bin/bash -c 'cd {{ bridge_path }}/monitor/scripts; ./checkDocker.sh >cronWorker.out 2>cronWorker.err'"
|
||||
job: "/bin/bash -c 'cd {{ bridge_path }}/monitor/scripts; ./getBridgeStats.sh >cronWorker.out 2>cronWorker.err'"
|
||||
- name: Add cron entry
|
||||
cron:
|
||||
name: "RUN_MONITOR_CHECKS"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Build the containers
|
||||
shell: docker-compose build
|
||||
- name: Pull the containers images
|
||||
shell: docker-compose pull
|
||||
args:
|
||||
chdir: "{{ bridge_path }}/monitor"
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
---
|
||||
- include_tasks: pre_config.yml
|
||||
- include_tasks: logging.yml
|
||||
- include_tasks: jumpbox.yml
|
||||
- include_tasks: servinstall.yml
|
||||
- include_tasks: cron.yml
|
||||
|
||||
- name: Include logging tasks
|
||||
include_tasks: logging.yml
|
||||
when: skip_task != true
|
||||
|
||||
- name: Include jumpbox tasks
|
||||
include_tasks: jumpbox.yml
|
||||
when: skip_task != true
|
||||
|
||||
- name: Include servinstall tasks
|
||||
include_tasks: servinstall.yml
|
||||
when: skip_task != true
|
||||
|
||||
- name: Include cron tasks
|
||||
include_tasks: cron.yml
|
||||
when: skip_task != true
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
---
|
||||
- name: Create configs directory
|
||||
file:
|
||||
path: "{{ bridge_path }}/monitor/configs"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when: skip_task != true
|
||||
|
||||
- name: Create responses directory
|
||||
file:
|
||||
path: "{{ bridge_path }}/monitor/responses"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when: skip_task != true
|
||||
|
||||
- name: Create scripts directory
|
||||
file:
|
||||
path: "{{ bridge_path }}/monitor/scripts"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when: skip_task != true
|
||||
|
||||
- name: Install .env config
|
||||
template:
|
||||
src: .env.j2
|
||||
dest: "{{ bridge_path }}/monitor/.env"
|
||||
when: skip_task != true
|
||||
|
||||
- name: Copy docker-compose file
|
||||
copy:
|
||||
src: ../../../../monitor/docker-compose.yml
|
||||
dest: "{{ bridge_path }}/monitor/docker-compose.yml"
|
||||
mode: '0755'
|
||||
when: skip_task != true
|
||||
|
||||
- name: Copy script file
|
||||
copy:
|
||||
src: ../../../../monitor/scripts/getBridgeStats.sh
|
||||
dest: "{{ bridge_path }}/monitor/scripts/getBridgeStats.sh"
|
||||
owner: "{{ compose_service_user }}"
|
||||
mode: '0755'
|
||||
when: skip_task != true
|
||||
|
||||
- name: Install bridge config env
|
||||
template:
|
||||
src: config.env.j2
|
||||
dest: "{{ bridge_path }}/monitor/configs/{{ MONITOR_BRIDGE_NAME }}.env"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# This role creates a tokenbridge-monitor service which is designed to manage docker-compose monitor deployment.
|
||||
# /etc/init.d/tokenbridge-monitor start, status, stop, restart - does what the services usually do in such cases.
|
||||
# /etc/init.d/tokenbridge-monitor rebuild - builds a new monitor deployment from scratch.
|
||||
---
|
||||
- name: "Set the service"
|
||||
template:
|
||||
|
||||
@@ -1,24 +1 @@
|
||||
COMMON_HOME_RPC_URL={{ COMMON_HOME_RPC_URL }}
|
||||
COMMON_FOREIGN_RPC_URL={{ COMMON_FOREIGN_RPC_URL }}
|
||||
COMMON_HOME_BRIDGE_ADDRESS={{ COMMON_HOME_BRIDGE_ADDRESS }}
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS={{ COMMON_FOREIGN_BRIDGE_ADDRESS }}
|
||||
MONITOR_HOME_START_BLOCK={{ MONITOR_HOME_START_BLOCK }}
|
||||
MONITOR_FOREIGN_START_BLOCK={{ MONITOR_FOREIGN_START_BLOCK }}
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT={{ MONITOR_VALIDATOR_HOME_TX_LIMIT }}
|
||||
{% if COMMON_HOME_GAS_PRICE_SUPPLIER_URL | default('') != '' %}
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL={{ COMMON_HOME_GAS_PRICE_SUPPLIER_URL }}
|
||||
{% endif %}
|
||||
{% if COMMON_HOME_GAS_PRICE_SPEED_TYPE | default('') != '' %}
|
||||
COMMON_HOME_GAS_PRICE_SPEED_TYPE={{ COMMON_HOME_GAS_PRICE_SPEED_TYPE }}
|
||||
{% endif %}
|
||||
COMMON_HOME_GAS_PRICE_FALLBACK={{ COMMON_HOME_GAS_PRICE_FALLBACK }}
|
||||
{% if COMMON_HOME_GAS_PRICE_FACTOR | default('') != '' %}
|
||||
COMMON_HOME_GAS_PRICE_FACTOR={{ COMMON_HOME_GAS_PRICE_FACTOR }}
|
||||
{% endif %}
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT={{ MONITOR_VALIDATOR_FOREIGN_TX_LIMIT }}
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL={{ COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL }}
|
||||
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE={{ COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE }}
|
||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK={{ COMMON_FOREIGN_GAS_PRICE_FALLBACK }}
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR={{ COMMON_FOREIGN_GAS_PRICE_FACTOR }}
|
||||
MONITOR_LEFT_TX_THRESHOLD={{ MONITOR_LEFT_TX_THRESHOLD }}
|
||||
MONITOR_PORT={{ MONITOR_PORT }}
|
||||
|
||||
36
deployment/roles/monitor/templates/config.env.j2
Normal file
36
deployment/roles/monitor/templates/config.env.j2
Normal file
@@ -0,0 +1,36 @@
|
||||
MONITOR_BRIDGE_NAME={{ MONITOR_BRIDGE_NAME }}
|
||||
|
||||
COMMON_HOME_RPC_URL={{ COMMON_HOME_RPC_URL }}
|
||||
COMMON_HOME_BRIDGE_ADDRESS={{ COMMON_HOME_BRIDGE_ADDRESS }}
|
||||
COMMON_FOREIGN_RPC_URL={{ COMMON_FOREIGN_RPC_URL }}
|
||||
COMMON_FOREIGN_BRIDGE_ADDRESS={{ COMMON_FOREIGN_BRIDGE_ADDRESS }}
|
||||
|
||||
{% if COMMON_HOME_GAS_PRICE_SUPPLIER_URL | default('') != '' %}
|
||||
COMMON_HOME_GAS_PRICE_SUPPLIER_URL={{ COMMON_HOME_GAS_PRICE_SUPPLIER_URL }}
|
||||
{% endif %}
|
||||
{% if COMMON_HOME_GAS_PRICE_SPEED_TYPE | default('') != '' %}
|
||||
COMMON_HOME_GAS_PRICE_SPEED_TYPE={{ COMMON_HOME_GAS_PRICE_SPEED_TYPE }}
|
||||
{% endif %}
|
||||
COMMON_HOME_GAS_PRICE_FALLBACK={{ COMMON_HOME_GAS_PRICE_FALLBACK }}
|
||||
{% if COMMON_HOME_GAS_PRICE_FACTOR | default('') != '' %}
|
||||
COMMON_HOME_GAS_PRICE_FACTOR={{ COMMON_HOME_GAS_PRICE_FACTOR }}
|
||||
{% endif %}
|
||||
|
||||
{% if COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL | default('') != '' %}
|
||||
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL={{ COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL }}
|
||||
{% endif %}
|
||||
{% if COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE | default('') != '' %}
|
||||
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE={{ COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE }}
|
||||
{% endif %}
|
||||
COMMON_FOREIGN_GAS_PRICE_FALLBACK={{ COMMON_FOREIGN_GAS_PRICE_FALLBACK }}
|
||||
{% if COMMON_FOREIGN_GAS_PRICE_FACTOR | default('') != '' %}
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR={{ COMMON_FOREIGN_GAS_PRICE_FACTOR }}
|
||||
{% endif %}
|
||||
|
||||
MONITOR_HOME_START_BLOCK={{ MONITOR_HOME_START_BLOCK }}
|
||||
MONITOR_FOREIGN_START_BLOCK={{ MONITOR_FOREIGN_START_BLOCK }}
|
||||
MONITOR_VALIDATOR_HOME_TX_LIMIT={{ MONITOR_VALIDATOR_HOME_TX_LIMIT }}
|
||||
MONITOR_VALIDATOR_FOREIGN_TX_LIMIT={{ MONITOR_VALIDATOR_FOREIGN_TX_LIMIT }}
|
||||
MONITOR_TX_NUMBER_THRESHOLD={{ MONITOR_TX_NUMBER_THRESHOLD }}
|
||||
|
||||
MONITOR_CACHE_EVENTS={{ MONITOR_CACHE_EVENTS }}
|
||||
@@ -18,6 +18,7 @@ start(){
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose down -v
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose rm -fv
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose up --detach
|
||||
sudo -u "{{ compose_service_user }}" /bin/bash -c 'cd scripts; ./getBridgeStats.sh >cronWorker.out 2>cronWorker.err'
|
||||
}
|
||||
|
||||
stop(){
|
||||
@@ -33,14 +34,6 @@ status(){
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose ps
|
||||
}
|
||||
|
||||
rebuild(){
|
||||
echo "Rebuild TokenBridge Monitor.."
|
||||
cd $WORKDIR
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose down -v
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose rm -fv
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose up --detach --force-recreate --no-deps --build
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
|
||||
@@ -62,12 +55,8 @@ case "$1" in
|
||||
start
|
||||
;;
|
||||
|
||||
rebuild)
|
||||
rebuild
|
||||
;;
|
||||
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|restart|rebuild|status}"
|
||||
echo $"Usage: $0 {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- role: common
|
||||
- { role: common, skip_repo: true }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Build the containers
|
||||
shell: docker-compose build
|
||||
- name: Pull the containers images
|
||||
shell: docker-compose pull
|
||||
args:
|
||||
chdir: "{{ bridge_path }}/oracle"
|
||||
|
||||
@@ -1,41 +1,11 @@
|
||||
---
|
||||
- name: Slurp docker compose file
|
||||
slurp:
|
||||
src: "{{ bridge_path }}/oracle/docker-compose.yml"
|
||||
register: docker_compose_slurp
|
||||
|
||||
- name: Parse docker compose file
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}"
|
||||
|
||||
- name: Set logger to remote server
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed |combine({'services': {item: {'logging': {'driver': 'syslog','options': {'tag': '{{.Name}}/{{.ID}}'}}}}}, recursive=True) }}"
|
||||
with_items: "{{ docker_compose_parsed.services }}"
|
||||
|
||||
- name: Write new docker-compose file
|
||||
copy:
|
||||
content: "{{ docker_compose_parsed | to_yaml }}"
|
||||
dest: "{{ bridge_path }}/oracle/docker-compose.yml"
|
||||
|
||||
- name: Slurp docker compose extended file
|
||||
slurp:
|
||||
src: "{{ bridge_path }}/oracle/docker-compose-transfer.yml"
|
||||
register: docker_compose_extended_slurp
|
||||
|
||||
- name: Parse docker compose extended file
|
||||
set_fact:
|
||||
docker_compose_extended_parsed: "{{ docker_compose_extended_slurp['content'] | b64decode | from_yaml }}"
|
||||
|
||||
- name: Set logger to remote server for extended file
|
||||
set_fact:
|
||||
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed |combine({'services': {item: {'logging': {'driver': 'syslog','options': {'tag': '{{.Name}}/{{.ID}}'}}}}}, recursive=True) }}"
|
||||
with_items: "{{ docker_compose_extended_parsed.services }}"
|
||||
|
||||
- name: Write new docker-compose-extended file
|
||||
copy:
|
||||
content: "{{ docker_compose_extended_parsed | to_yaml }}"
|
||||
dest: "{{ bridge_path }}/oracle/docker-compose-transfer.yml"
|
||||
- include_tasks: logging_by_syslog.yml
|
||||
with_items:
|
||||
- docker-compose
|
||||
- docker-compose-transfer
|
||||
- docker-compose-erc-native
|
||||
loop_control:
|
||||
loop_var: file
|
||||
|
||||
- name: Set the local container logs configuration file
|
||||
template:
|
||||
|
||||
19
deployment/roles/oracle/tasks/logging_by_syslog.yml
Normal file
19
deployment/roles/oracle/tasks/logging_by_syslog.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: Slurp docker compose file
|
||||
slurp:
|
||||
src: "{{ bridge_path }}/oracle/{{ file }}.yml"
|
||||
register: docker_compose_slurp
|
||||
|
||||
- name: Parse docker compose file
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_slurp['content'] | b64decode | from_yaml }}"
|
||||
|
||||
- name: Set logger to remote server
|
||||
set_fact:
|
||||
docker_compose_parsed: "{{ docker_compose_parsed |combine({'services': {item: {'logging': {'driver': 'syslog','options': {'tag': '{{.Name}}/{{.ID}}'}}}}}, recursive=True) }}"
|
||||
with_items: "{{ docker_compose_parsed.services }}"
|
||||
|
||||
- name: Write updated docker file
|
||||
copy:
|
||||
content: "{{ docker_compose_parsed | to_yaml }}"
|
||||
dest: "{{ bridge_path }}/oracle/{{ file }}.yml"
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: Get blocks
|
||||
become_user: "{{ compose_service_user }}"
|
||||
shell: docker-compose run --entrypoint "node scripts/getValidatorStartBlocks.js" bridge_affirmation
|
||||
shell: docker-compose run --rm --entrypoint "node scripts/getValidatorStartBlocks.js" bridge_affirmation
|
||||
args:
|
||||
chdir: "{{ bridge_path }}/oracle"
|
||||
register: BLOCKS
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
- name: Get validator address
|
||||
become_user: "{{ compose_service_user }}"
|
||||
shell: docker-compose run -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY="{{ ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY }}" --entrypoint "node scripts/privateKeyToAddress.js" bridge_affirmation
|
||||
shell: docker-compose run --rm -e ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY="{{ ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY }}" --entrypoint "node scripts/privateKeyToAddress.js" bridge_affirmation
|
||||
args:
|
||||
chdir: "{{ bridge_path }}/oracle"
|
||||
register: VADDRESS
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
- name: Get foreign erc type
|
||||
become_user: "{{ compose_service_user }}"
|
||||
shell: docker-compose run --entrypoint "node scripts/initialChecks.js" bridge_affirmation
|
||||
shell: docker-compose run --rm --entrypoint "node scripts/initialChecks.js" bridge_affirmation
|
||||
args:
|
||||
chdir: "{{ bridge_path }}/oracle"
|
||||
register: ERCTYPE
|
||||
@@ -40,7 +40,11 @@
|
||||
|
||||
- name: Extend docker compose file
|
||||
set_fact: composefileoverride="-f docker-compose-transfer.yml"
|
||||
when: ORACLE_BRIDGE_MODE == "ERC_TO_NATIVE" or ( ORACLE_BRIDGE_MODE == "ERC_TO_ERC" and FOREIGN_ERC_TYPE != "ERC677")
|
||||
when: ORACLE_BRIDGE_MODE == "ERC_TO_ERC" and FOREIGN_ERC_TYPE != "ERC677"
|
||||
|
||||
- name: Extend docker compose file for erc to native
|
||||
set_fact: composefileoverride="-f docker-compose-erc-native.yml"
|
||||
when: ORACLE_BRIDGE_MODE == "ERC_TO_NATIVE"
|
||||
|
||||
- name: Install .key config
|
||||
template:
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
---
|
||||
- name: Create oracle directory
|
||||
file:
|
||||
path: "{{ bridge_path }}/oracle"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Install .env config
|
||||
template:
|
||||
src: .env.j2
|
||||
dest: "{{ bridge_path }}/oracle/.env"
|
||||
|
||||
- name: Copy docker-compose files
|
||||
copy:
|
||||
src: ../../../../oracle/{{ item }}
|
||||
dest: "{{ bridge_path }}/oracle/"
|
||||
mode: '0755'
|
||||
with_items:
|
||||
- docker-compose.yml
|
||||
- docker-compose-transfer.yml
|
||||
- docker-compose-erc-native.yml
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# This role creates a poabridge service which is designed to manage docker-compose bridge deployment.
|
||||
# /etc/init.d/poabridge start, status, stop, restart - does what the services usually do in such cases.
|
||||
# /etc/init.d/poabridge rebuild - builds a new bridge deployment from scratch.
|
||||
---
|
||||
- name: "Set poabridge service"
|
||||
template:
|
||||
|
||||
@@ -52,14 +52,6 @@ status(){
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride ps
|
||||
}
|
||||
|
||||
rebuild(){
|
||||
echo "Rebuild bridge.."
|
||||
cd $WORKDIR
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride down -v
|
||||
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride rm -fv
|
||||
sudo -u "{{ compose_service_user }}" ORACLE_VALIDATOR_ADDRESS=$vaddr ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=$vkey /usr/local/bin/docker-compose $composefileoverride up --detach --force-recreate --no-deps --build
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
|
||||
@@ -81,12 +73,8 @@ case "$1" in
|
||||
start
|
||||
;;
|
||||
|
||||
rebuild)
|
||||
rebuild
|
||||
;;
|
||||
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|restart|rebuild|status}"
|
||||
echo $"Usage: $0 {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
|
||||
@@ -16,3 +16,5 @@ COMMON_FOREIGN_GAS_PRICE_FALLBACK=1000000000
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR=1
|
||||
MONITOR_TX_NUMBER_THRESHOLD=100
|
||||
MONITOR_PORT=3013
|
||||
MONITOR_BRIDGE_NAME=bridge
|
||||
MONITOR_CACHE_EVENTS=false
|
||||
|
||||
@@ -16,3 +16,5 @@ COMMON_FOREIGN_GAS_PRICE_FALLBACK=1000000000
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR=1
|
||||
MONITOR_TX_NUMBER_THRESHOLD=100
|
||||
MONITOR_PORT=3012
|
||||
MONITOR_BRIDGE_NAME=bridge
|
||||
MONITOR_CACHE_EVENTS=false
|
||||
|
||||
@@ -16,3 +16,5 @@ COMMON_FOREIGN_GAS_PRICE_FALLBACK=1000000000
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR=1
|
||||
MONITOR_TX_NUMBER_THRESHOLD=100
|
||||
MONITOR_PORT=3011
|
||||
MONITOR_BRIDGE_NAME=bridge
|
||||
MONITOR_CACHE_EVENTS=false
|
||||
|
||||
@@ -16,3 +16,5 @@ COMMON_FOREIGN_GAS_PRICE_FALLBACK=1000000000
|
||||
COMMON_FOREIGN_GAS_PRICE_FACTOR=1
|
||||
MONITOR_TX_NUMBER_THRESHOLD=100
|
||||
MONITOR_PORT=3010
|
||||
MONITOR_BRIDGE_NAME=bridge
|
||||
MONITOR_CACHE_EVENTS=false
|
||||
|
||||
@@ -7,10 +7,26 @@
|
||||
"address": "0xcca2fb44C8C36E51f743269d6F484Fd027B9F9Aa",
|
||||
"privateKey": "0xcf954e07e6a439faf392eb474e95ddb444c2ca444847f2ad6ecc79e1a585e2b8"
|
||||
},
|
||||
"thirdUser": {
|
||||
"address": "0x441cc8537aB6cE63d060b63F3A44eE021d62e6cF",
|
||||
"privateKey": "0xd3915199f27691d7784cb01ab0c7220308053b229f95d592e97493326314a8d0"
|
||||
},
|
||||
"fourthUser": {
|
||||
"address": "0x3CC5baAB679eC0732C175760079Bf48F564ad26B",
|
||||
"privateKey": "0xedb53ee050631b7914d5f1a66c2f0d2df3ec85a9ed2a9616b16a7b1b7a10b8d1"
|
||||
},
|
||||
"validator": {
|
||||
"address": "0xaaB52d66283F7A1D5978bcFcB55721ACB467384b",
|
||||
"privateKey": "0x8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9"
|
||||
},
|
||||
"secondValidator": {
|
||||
"address": "0xdCC784657C78054aa61FbcFFd2605F32374816A4",
|
||||
"privateKey": "0x5a5c3645d0f04e9eb4f27f94ed4c244a225587405b8838e7456f7781ce3a9513"
|
||||
},
|
||||
"thirdValidator": {
|
||||
"address": "0xDcef88209a20D52165230104B245803C3269454d",
|
||||
"privateKey": "0xf877f62a1c19f852cff1d29f0fb1ecac18821c0080d4cc0520c60c098293dca1"
|
||||
},
|
||||
"blockGenerator": {
|
||||
"address": "0xB4579fd5AfEaB60B03Db3F408AAdD315035943f7",
|
||||
"privateKey": "0xd6143d390d8b28c33601bb0fe29392fb1c35c24ccfe8722c09c2bdd6ada2699f"
|
||||
@@ -20,7 +36,7 @@
|
||||
"foreign": "0x2B6871b9B02F73fa24F4864322CdC78604207769",
|
||||
"foreignToken": "0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B",
|
||||
"ui": "http://localhost:3000",
|
||||
"monitor": "http://monitor:3010"
|
||||
"monitor": "http://monitor:3010/bridge"
|
||||
},
|
||||
"ercToErcBridge": {
|
||||
"home": "0x1feB40aD9420b186F019A717c37f5546165d411E",
|
||||
@@ -28,21 +44,24 @@
|
||||
"homeToken": "0x792455a6bCb62Ed4C4362D323E0590654CA4765c",
|
||||
"foreignToken": "0x3C665A31199694Bf723fD08844AD290207B5797f",
|
||||
"ui": "http://localhost:3001",
|
||||
"monitor": "http://monitor-erc20:3011"
|
||||
"monitor": "http://monitor-erc20:3011/bridge"
|
||||
},
|
||||
"ercToNativeBridge": {
|
||||
"home": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||
"foreign": "0x488Af810997eD1730cB3a3918cD83b3216E6eAda",
|
||||
"foreignToken": "0x3C665A31199694Bf723fD08844AD290207B5797f",
|
||||
"foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9",
|
||||
"halfDuplexToken": "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359",
|
||||
"saiTop": "0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3",
|
||||
"chaiToken": "0x06af07097c9eeb7fd685c692751d5c66db49c215",
|
||||
"ui": "http://localhost:3002",
|
||||
"monitor": "http://monitor-erc20-native:3012"
|
||||
"monitor": "http://monitor-erc20-native:3012/bridge"
|
||||
},
|
||||
"amb": {
|
||||
"home": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
||||
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
|
||||
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
|
||||
"monitor": "http://monitor-amb:3013"
|
||||
"monitor": "http://monitor-amb:3013/bridge"
|
||||
},
|
||||
"homeRPC": {
|
||||
"URL": "http://parity1:8545",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user