merge development
This commit is contained in:
commit
e05b55d4a5
@ -1,5 +1,9 @@
|
||||
## 0x.js
|
||||
|
||||
A TypeScript/Javascript library for interacting with the 0x protocol.
|
||||
|
||||
### Read the [Documentation](0xproject.com/docs/0xjs).
|
||||
|
||||
## Installation
|
||||
|
||||
0x.js ships as both a [UMD](https://github.com/umdjs/umd) module and a [CommonJS](https://en.wikipedia.org/wiki/CommonJS) package.
|
||||
@ -38,10 +42,66 @@ Download the UMD module from our [releases page](https://github.com/0xProject/0x
|
||||
<script type="text/javascript" src="0x.js"></script>
|
||||
```
|
||||
|
||||
## Documentation
|
||||
## Contributing
|
||||
|
||||
Extensive documentation of 0x.js can be found on [our website][docs-url].
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
[website-url]: https://0xproject.com/
|
||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
||||
[docs-url]: https://0xproject.com/docs/0xjs
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
@ -57,3 +57,61 @@ See the [type definition](https://github.com/0xProject/0x-monorepo/tree/developm
|
||||
## Output files
|
||||
|
||||
Output files will be generated within an output folder with names converted to camel case and taken from abi file names. If you already have some files in that folder they will be overwritten.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
@ -26,11 +26,11 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -46,10 +46,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -23,11 +23,11 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -43,10 +43,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -34,11 +34,25 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
|
@ -41,11 +41,11 @@ var Compiler = require('@0xproject/deployer').Compiler;
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -61,16 +61,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -26,3 +26,67 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
"typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"],
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
@ -32,11 +32,11 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -52,16 +52,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -16,11 +16,11 @@ This will list out any dependencies that differ in versions between packages.
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -36,11 +36,25 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
@ -57,3 +71,9 @@ yarn clean
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
@ -20,7 +20,19 @@ Then install dependencies
|
||||
yarn install
|
||||
```
|
||||
|
||||
#### Start the dev server
|
||||
### Initial setup
|
||||
|
||||
The **first** time you work with this package, you must build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Note: If you move this package out of the monorepo, it will work without this step. Make sure you copy it out on the `master` branch since the `development` version might rely on not-yet published changes to other packages.
|
||||
|
||||
### Run dev server
|
||||
|
||||
The the `react-docs-example` root directory, run:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
@ -42,6 +54,12 @@ yarn deploy_example
|
||||
yarn build
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -51,11 +51,11 @@ Feel free to contribute to these improvements!
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage the community to help us make improvements. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -71,10 +71,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -18,11 +18,11 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -38,18 +38,38 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
@ -24,11 +24,11 @@ var CoverageSubprovider = require('@0xproject/sol-cov').CoverageSubprovider;
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage the community to help us make improvements. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -42,8 +42,46 @@ Then install dependencies
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
@ -87,11 +87,11 @@ In order to provide a custom environment to the tool, perform the following step
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -107,10 +107,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -6,6 +6,10 @@
|
||||
"note":
|
||||
"Refactor RedundantRPCSubprovider into RedundantSubprovider where it now accepts an array of subproviders rather then an array of RPC endpoints",
|
||||
"pr": 500
|
||||
},
|
||||
{
|
||||
"note": "Add private key subprovider and refactor shared functionality into a base wallet subprovider",
|
||||
"pr": 506
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -22,11 +22,11 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -34,17 +34,33 @@ If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
|
@ -12,6 +12,7 @@ export { LedgerSubprovider } from './subproviders/ledger';
|
||||
export { GanacheSubprovider } from './subproviders/ganache';
|
||||
export { Subprovider } from './subproviders/subprovider';
|
||||
export { NonceTrackerSubprovider } from './subproviders/nonce_tracker';
|
||||
export { PrivateKeyWalletSubprovider } from './subproviders/private_key_wallet_subprovider';
|
||||
export {
|
||||
Callback,
|
||||
ErrorCallback,
|
||||
|
@ -0,0 +1,137 @@
|
||||
import { assert } from '@0xproject/assert';
|
||||
import { JSONRPCRequestPayload, JSONRPCResponsePayload } from '@0xproject/types';
|
||||
import { addressUtils } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Callback, ErrorCallback, PartialTxParams, ResponseWithTxParams, WalletSubproviderErrors } from '../types';
|
||||
|
||||
import { Subprovider } from './subprovider';
|
||||
|
||||
export abstract class BaseWalletSubprovider extends Subprovider {
|
||||
protected static _validateTxParams(txParams: PartialTxParams) {
|
||||
assert.isETHAddressHex('to', txParams.to);
|
||||
assert.isHexString('nonce', txParams.nonce);
|
||||
assert.isHexString('gas', txParams.gas);
|
||||
}
|
||||
private static _validateSender(sender: string) {
|
||||
if (_.isUndefined(sender) || !addressUtils.isAddress(sender)) {
|
||||
throw new Error(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract async getAccountsAsync(): Promise<string[]>;
|
||||
public abstract async signTransactionAsync(txParams: PartialTxParams): Promise<string>;
|
||||
public abstract async signPersonalMessageAsync(data: string): Promise<string>;
|
||||
|
||||
/**
|
||||
* This method conforms to the web3-provider-engine interface.
|
||||
* It is called internally by the ProviderEngine when it is this subproviders
|
||||
* turn to handle a JSON RPC request.
|
||||
* @param payload JSON RPC payload
|
||||
* @param next Callback to call if this subprovider decides not to handle the request
|
||||
* @param end Callback to call if subprovider handled the request and wants to pass back the request.
|
||||
*/
|
||||
// tslint:disable-next-line:async-suffix
|
||||
public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback) {
|
||||
let accounts;
|
||||
let txParams;
|
||||
switch (payload.method) {
|
||||
case 'eth_coinbase':
|
||||
try {
|
||||
accounts = await this.getAccountsAsync();
|
||||
end(null, accounts[0]);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_accounts':
|
||||
try {
|
||||
accounts = await this.getAccountsAsync();
|
||||
end(null, accounts);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_sendTransaction':
|
||||
txParams = payload.params[0];
|
||||
try {
|
||||
BaseWalletSubprovider._validateSender(txParams.from);
|
||||
const filledParams = await this._populateMissingTxParamsAsync(txParams);
|
||||
const signedTx = await this.signTransactionAsync(filledParams);
|
||||
const response = await this._emitSendTransactionAsync(signedTx);
|
||||
end(null, response.result);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_signTransaction':
|
||||
txParams = payload.params[0];
|
||||
try {
|
||||
const filledParams = await this._populateMissingTxParamsAsync(txParams);
|
||||
const signedTx = await this.signTransactionAsync(filledParams);
|
||||
const result = {
|
||||
raw: signedTx,
|
||||
tx: txParams,
|
||||
};
|
||||
end(null, result);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_sign':
|
||||
case 'personal_sign':
|
||||
const data = payload.method === 'eth_sign' ? payload.params[1] : payload.params[0];
|
||||
try {
|
||||
const ecSignatureHex = await this.signPersonalMessageAsync(data);
|
||||
end(null, ecSignatureHex);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
private async _emitSendTransactionAsync(signedTx: string): Promise<JSONRPCResponsePayload> {
|
||||
const payload = {
|
||||
method: 'eth_sendRawTransaction',
|
||||
params: [signedTx],
|
||||
};
|
||||
const result = await this.emitPayloadAsync(payload);
|
||||
return result;
|
||||
}
|
||||
private async _populateMissingTxParamsAsync(partialTxParams: PartialTxParams): Promise<PartialTxParams> {
|
||||
let txParams = partialTxParams;
|
||||
if (_.isUndefined(partialTxParams.gasPrice)) {
|
||||
const gasPriceResult = await this.emitPayloadAsync({
|
||||
method: 'eth_gasPrice',
|
||||
params: [],
|
||||
});
|
||||
const gasPrice = gasPriceResult.result.toString();
|
||||
txParams = { ...txParams, gasPrice };
|
||||
}
|
||||
if (_.isUndefined(partialTxParams.nonce)) {
|
||||
const nonceResult = await this.emitPayloadAsync({
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [partialTxParams.from, 'pending'],
|
||||
});
|
||||
const nonce = nonceResult.result;
|
||||
txParams = { ...txParams, nonce };
|
||||
}
|
||||
if (_.isUndefined(partialTxParams.gas)) {
|
||||
const gasResult = await this.emitPayloadAsync({
|
||||
method: 'eth_estimateGas',
|
||||
params: [partialTxParams],
|
||||
});
|
||||
const gas = gasResult.result.toString();
|
||||
txParams = { ...txParams, gas };
|
||||
}
|
||||
return txParams;
|
||||
}
|
||||
}
|
@ -15,9 +15,10 @@ import {
|
||||
LedgerSubproviderErrors,
|
||||
PartialTxParams,
|
||||
ResponseWithTxParams,
|
||||
WalletSubproviderErrors,
|
||||
} from '../types';
|
||||
|
||||
import { Subprovider } from './subprovider';
|
||||
import { BaseWalletSubprovider } from './base_wallet_subprovider';
|
||||
|
||||
const DEFAULT_DERIVATION_PATH = `44'/60'/0'`;
|
||||
const DEFAULT_NUM_ADDRESSES_TO_FETCH = 10;
|
||||
@ -29,7 +30,7 @@ const SHOULD_GET_CHAIN_CODE = true;
|
||||
* This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and
|
||||
* re-routes them to a Ledger device plugged into the users computer.
|
||||
*/
|
||||
export class LedgerSubprovider extends Subprovider {
|
||||
export class LedgerSubprovider extends BaseWalletSubprovider {
|
||||
private _nonceLock = new Lock();
|
||||
private _connectionLock = new Lock();
|
||||
private _networkId: number;
|
||||
@ -38,11 +39,6 @@ export class LedgerSubprovider extends Subprovider {
|
||||
private _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync;
|
||||
private _ledgerClientIfExists?: LedgerEthereumClient;
|
||||
private _shouldAlwaysAskForConfirmation: boolean;
|
||||
private static _validateSender(sender: string) {
|
||||
if (_.isUndefined(sender) || !addressUtils.isAddress(sender)) {
|
||||
throw new Error(LedgerSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Instantiates a LedgerSubprovider. Defaults to derivationPath set to `44'/60'/0'`.
|
||||
* TestRPC/Ganache defaults to `m/44'/60'/0'/0`, so set this in the configs if desired.
|
||||
@ -133,6 +129,7 @@ export class LedgerSubprovider extends Subprovider {
|
||||
* @return Signed transaction hex string
|
||||
*/
|
||||
public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
|
||||
LedgerSubprovider._validateTxParams(txParams);
|
||||
this._ledgerClientIfExists = await this._createLedgerClientAsync();
|
||||
|
||||
const tx = new EthereumTx(txParams);
|
||||
@ -168,7 +165,7 @@ export class LedgerSubprovider extends Subprovider {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sign a personal Ethereum signed message. The signing address will be to one
|
||||
* Sign a personal Ethereum signed message. The signing address will be the one
|
||||
* retrieved given a derivationPath and pathIndex set on the subprovider.
|
||||
* The Ledger adds the Ethereum signed message prefix on-device. If you've added
|
||||
* the LedgerSubprovider to your app's provider, you can simply send an `eth_sign`
|
||||
@ -178,6 +175,10 @@ export class LedgerSubprovider extends Subprovider {
|
||||
* @return Signature hex string (order: rsv)
|
||||
*/
|
||||
public async signPersonalMessageAsync(data: string): Promise<string> {
|
||||
if (_.isUndefined(data)) {
|
||||
throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
|
||||
}
|
||||
assert.isHexString('data', data);
|
||||
this._ledgerClientIfExists = await this._createLedgerClientAsync();
|
||||
try {
|
||||
const derivationPath = this._getDerivationPath();
|
||||
@ -198,82 +199,6 @@ export class LedgerSubprovider extends Subprovider {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This method conforms to the web3-provider-engine interface.
|
||||
* It is called internally by the ProviderEngine when it is this subproviders
|
||||
* turn to handle a JSON RPC request.
|
||||
* @param payload JSON RPC payload
|
||||
* @param next Callback to call if this subprovider decides not to handle the request
|
||||
* @param end Callback to call if subprovider handled the request and wants to pass back the request.
|
||||
*/
|
||||
// tslint:disable-next-line:async-suffix
|
||||
public async handleRequest(
|
||||
payload: JSONRPCRequestPayload,
|
||||
next: Callback,
|
||||
end: (err: Error | null, result?: any) => void,
|
||||
) {
|
||||
let accounts;
|
||||
let txParams;
|
||||
switch (payload.method) {
|
||||
case 'eth_coinbase':
|
||||
try {
|
||||
accounts = await this.getAccountsAsync();
|
||||
end(null, accounts[0]);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_accounts':
|
||||
try {
|
||||
accounts = await this.getAccountsAsync();
|
||||
end(null, accounts);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_sendTransaction':
|
||||
txParams = payload.params[0];
|
||||
try {
|
||||
LedgerSubprovider._validateSender(txParams.from);
|
||||
const result = await this._sendTransactionAsync(txParams);
|
||||
end(null, result);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_signTransaction':
|
||||
txParams = payload.params[0];
|
||||
try {
|
||||
const result = await this._signTransactionWithoutSendingAsync(txParams);
|
||||
end(null, result);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'eth_sign':
|
||||
case 'personal_sign':
|
||||
const data = payload.method === 'eth_sign' ? payload.params[1] : payload.params[0];
|
||||
try {
|
||||
if (_.isUndefined(data)) {
|
||||
throw new Error(LedgerSubproviderErrors.DataMissingForSignPersonalMessage);
|
||||
}
|
||||
assert.isHexString('data', data);
|
||||
const ecSignatureHex = await this.signPersonalMessageAsync(data);
|
||||
end(null, ecSignatureHex);
|
||||
} catch (err) {
|
||||
end(err);
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
private _getDerivationPath() {
|
||||
const derivationPath = `${this.getPath()}/${this._derivationPathIndex}`;
|
||||
return derivationPath;
|
||||
@ -298,70 +223,4 @@ export class LedgerSubprovider extends Subprovider {
|
||||
this._ledgerClientIfExists = undefined;
|
||||
this._connectionLock.release();
|
||||
}
|
||||
private async _sendTransactionAsync(txParams: PartialTxParams): Promise<string> {
|
||||
await this._nonceLock.acquire();
|
||||
try {
|
||||
// fill in the extras
|
||||
const filledParams = await this._populateMissingTxParamsAsync(txParams);
|
||||
// sign it
|
||||
const signedTx = await this.signTransactionAsync(filledParams);
|
||||
// emit a submit
|
||||
const payload = {
|
||||
method: 'eth_sendRawTransaction',
|
||||
params: [signedTx],
|
||||
};
|
||||
const result = await this.emitPayloadAsync(payload);
|
||||
this._nonceLock.release();
|
||||
return result.result;
|
||||
} catch (err) {
|
||||
this._nonceLock.release();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
private async _signTransactionWithoutSendingAsync(txParams: PartialTxParams): Promise<ResponseWithTxParams> {
|
||||
await this._nonceLock.acquire();
|
||||
try {
|
||||
// fill in the extras
|
||||
const filledParams = await this._populateMissingTxParamsAsync(txParams);
|
||||
// sign it
|
||||
const signedTx = await this.signTransactionAsync(filledParams);
|
||||
|
||||
this._nonceLock.release();
|
||||
const result = {
|
||||
raw: signedTx,
|
||||
tx: txParams,
|
||||
};
|
||||
return result;
|
||||
} catch (err) {
|
||||
this._nonceLock.release();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
private async _populateMissingTxParamsAsync(txParams: PartialTxParams): Promise<PartialTxParams> {
|
||||
if (_.isUndefined(txParams.gasPrice)) {
|
||||
const gasPriceResult = await this.emitPayloadAsync({
|
||||
method: 'eth_gasPrice',
|
||||
params: [],
|
||||
});
|
||||
const gasPrice = gasPriceResult.result.toString();
|
||||
txParams.gasPrice = gasPrice;
|
||||
}
|
||||
if (_.isUndefined(txParams.nonce)) {
|
||||
const nonceResult = await this.emitPayloadAsync({
|
||||
method: 'eth_getTransactionCount',
|
||||
params: [txParams.from, 'pending'],
|
||||
});
|
||||
const nonce = nonceResult.result;
|
||||
txParams.nonce = nonce;
|
||||
}
|
||||
if (_.isUndefined(txParams.gas)) {
|
||||
const gasResult = await this.emitPayloadAsync({
|
||||
method: 'eth_estimateGas',
|
||||
params: [txParams],
|
||||
});
|
||||
const gas = gasResult.result.toString();
|
||||
txParams.gas = gas;
|
||||
}
|
||||
return txParams;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
import { assert } from '@0xproject/assert';
|
||||
import { JSONRPCRequestPayload } from '@0xproject/types';
|
||||
import EthereumTx = require('ethereumjs-tx');
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Callback, ErrorCallback, PartialTxParams, ResponseWithTxParams, WalletSubproviderErrors } from '../types';
|
||||
|
||||
import { BaseWalletSubprovider } from './base_wallet_subprovider';
|
||||
import { Subprovider } from './subprovider';
|
||||
|
||||
/**
|
||||
* This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
|
||||
* This subprovider intercepts all account related RPC requests (e.g message/transaction signing, etc...) and handles
|
||||
* all requests with the supplied Ethereum private key.
|
||||
*/
|
||||
export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider {
|
||||
private _address: string;
|
||||
private _privateKeyBuffer: Buffer;
|
||||
constructor(privateKey: string) {
|
||||
assert.isString('privateKey', privateKey);
|
||||
super();
|
||||
this._privateKeyBuffer = new Buffer(privateKey, 'hex');
|
||||
this._address = `0x${ethUtil.privateToAddress(this._privateKeyBuffer).toString('hex')}`;
|
||||
}
|
||||
/**
|
||||
* Retrieve the account associated with the supplied private key.
|
||||
* This method is implicitly called when issuing a `eth_accounts` JSON RPC request
|
||||
* via your providerEngine instance.
|
||||
* @return An array of accounts
|
||||
*/
|
||||
public async getAccountsAsync(): Promise<string[]> {
|
||||
return [this._address];
|
||||
}
|
||||
/**
|
||||
* Sign a transaction with the private key. If you've added this Subprovider to your
|
||||
* app's provider, you can simply send an `eth_sendTransaction` JSON RPC request, and
|
||||
* this method will be called auto-magically. If you are not using this via a ProviderEngine
|
||||
* instance, you can call it directly.
|
||||
* @param txParams Parameters of the transaction to sign
|
||||
* @return Signed transaction hex string
|
||||
*/
|
||||
public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
|
||||
PrivateKeyWalletSubprovider._validateTxParams(txParams);
|
||||
const tx = new EthereumTx(txParams);
|
||||
tx.sign(this._privateKeyBuffer);
|
||||
const rawTx = `0x${tx.serialize().toString('hex')}`;
|
||||
return rawTx;
|
||||
}
|
||||
/**
|
||||
* Sign a personal Ethereum signed message. The signing address will be
|
||||
* calculated from the private key.
|
||||
* If you've added the PKWalletSubprovider to your app's provider, you can simply send an `eth_sign`
|
||||
* or `personal_sign` JSON RPC request, and this method will be called auto-magically.
|
||||
* If you are not using this via a ProviderEngine instance, you can call it directly.
|
||||
* @param data Message to sign
|
||||
* @return Signature hex string (order: rsv)
|
||||
*/
|
||||
public async signPersonalMessageAsync(dataIfExists: string): Promise<string> {
|
||||
if (_.isUndefined(dataIfExists)) {
|
||||
throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
|
||||
}
|
||||
assert.isHexString('data', dataIfExists);
|
||||
const dataBuff = ethUtil.toBuffer(dataIfExists);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
|
||||
const sig = ethUtil.ecsign(msgHashBuff, this._privateKeyBuffer);
|
||||
const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
|
||||
return rpcSig;
|
||||
}
|
||||
}
|
@ -95,11 +95,13 @@ export interface ResponseWithTxParams {
|
||||
tx: PartialTxParams;
|
||||
}
|
||||
|
||||
export enum WalletSubproviderErrors {
|
||||
DataMissingForSignPersonalMessage = 'DATA_MISSING_FOR_SIGN_PERSONAL_MESSAGE',
|
||||
SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
|
||||
}
|
||||
export enum LedgerSubproviderErrors {
|
||||
TooOldLedgerFirmware = 'TOO_OLD_LEDGER_FIRMWARE',
|
||||
FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID',
|
||||
DataMissingForSignPersonalMessage = 'DATA_MISSING_FOR_SIGN_PERSONAL_MESSAGE',
|
||||
SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
|
||||
MultipleOpenConnectionsDisallowed = 'MULTIPLE_OPEN_CONNECTIONS_DISALLOWED',
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
import { LedgerSubprovider } from '../../src';
|
||||
import { DoneCallback, LedgerEthereumClient } from '../../src/types';
|
||||
import { chaiSetup } from '../chai_setup';
|
||||
import { fixtureData } from '../utils/fixture_data';
|
||||
import { reportCallbackErrors } from '../utils/report_callback_errors';
|
||||
|
||||
chaiSetup.configure();
|
||||
@ -25,17 +26,14 @@ async function ledgerEthereumNodeJsClientFactoryAsync(): Promise<LedgerEthereumC
|
||||
return ledgerEthClient;
|
||||
}
|
||||
|
||||
const TESTRPC_DERIVATION_PATH = `m/44'/60'/0'/0`;
|
||||
const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
|
||||
describe('LedgerSubprovider', () => {
|
||||
let ledgerSubprovider: LedgerSubprovider;
|
||||
const networkId: number = 42;
|
||||
const networkId: number = fixtureData.NETWORK_ID;
|
||||
before(async () => {
|
||||
ledgerSubprovider = new LedgerSubprovider({
|
||||
networkId,
|
||||
ledgerEthereumClientFactoryAsync: ledgerEthereumNodeJsClientFactoryAsync,
|
||||
derivationPath: TESTRPC_DERIVATION_PATH,
|
||||
derivationPath: fixtureData.TESTRPC_DERIVATION_PATH,
|
||||
});
|
||||
});
|
||||
describe('direct method calls', () => {
|
||||
@ -46,7 +44,7 @@ describe('LedgerSubprovider', () => {
|
||||
});
|
||||
it('returns the expected first account from a ledger set up with the test mnemonic', async () => {
|
||||
const accounts = await ledgerSubprovider.getAccountsAsync();
|
||||
expect(accounts[0]).to.be.equal(TEST_RPC_ACCOUNT_0);
|
||||
expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
|
||||
});
|
||||
it('returns requested number of accounts', async () => {
|
||||
const numberOfAccounts = 20;
|
||||
@ -55,24 +53,14 @@ describe('LedgerSubprovider', () => {
|
||||
expect(accounts.length).to.be.equal(numberOfAccounts);
|
||||
});
|
||||
it('signs a personal message', async () => {
|
||||
const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
|
||||
const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
|
||||
const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data);
|
||||
expect(ecSignatureHex.length).to.be.equal(132);
|
||||
expect(ecSignatureHex.substr(0, 2)).to.be.equal('0x');
|
||||
expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
|
||||
});
|
||||
it('signs a transaction', async () => {
|
||||
const tx = {
|
||||
nonce: '0x00',
|
||||
gas: '0x2710',
|
||||
to: '0x0000000000000000000000000000000000000000',
|
||||
value: '0x00',
|
||||
chainId: 3,
|
||||
from: TEST_RPC_ACCOUNT_0,
|
||||
};
|
||||
const txHex = await ledgerSubprovider.signTransactionAsync(tx);
|
||||
expect(txHex).to.be.equal(
|
||||
'0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178',
|
||||
);
|
||||
const txHex = await ledgerSubprovider.signTransactionAsync(fixtureData.TX_DATA);
|
||||
expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
|
||||
});
|
||||
});
|
||||
describe('calls through a provider', () => {
|
||||
@ -146,20 +134,15 @@ describe('LedgerSubprovider', () => {
|
||||
})().catch(done);
|
||||
});
|
||||
it('signs a transaction', (done: DoneCallback) => {
|
||||
const tx = {
|
||||
to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
|
||||
value: '0x00',
|
||||
};
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_signTransaction',
|
||||
params: [tx],
|
||||
params: [fixtureData.TX_DATA],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.be.a('null');
|
||||
expect(response.result.raw.length).to.be.equal(206);
|
||||
expect(response.result.raw.substr(0, 2)).to.be.equal('0x');
|
||||
expect(response.result.raw).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
|
||||
done();
|
||||
});
|
||||
ledgerProvider.sendAsync(payload, callback);
|
||||
@ -171,7 +154,7 @@ describe('LedgerSubprovider', () => {
|
||||
// Give first account on Ledger sufficient ETH to complete tx send
|
||||
let tx = {
|
||||
to: accounts[0],
|
||||
from: TEST_RPC_ACCOUNT_0,
|
||||
from: fixtureData.TEST_RPC_ACCOUNT_0,
|
||||
value: '0x8ac7230489e80000', // 10 ETH
|
||||
};
|
||||
let payload = {
|
||||
|
@ -6,8 +6,14 @@ import Web3 = require('web3');
|
||||
import Web3ProviderEngine = require('web3-provider-engine');
|
||||
|
||||
import { LedgerSubprovider } from '../../src';
|
||||
import { DoneCallback, LedgerCommunicationClient, LedgerSubproviderErrors } from '../../src/types';
|
||||
import {
|
||||
DoneCallback,
|
||||
LedgerCommunicationClient,
|
||||
LedgerSubproviderErrors,
|
||||
WalletSubproviderErrors,
|
||||
} from '../../src/types';
|
||||
import { chaiSetup } from '../chai_setup';
|
||||
import { fixtureData } from '../utils/fixture_data';
|
||||
import { ganacheSubprovider } from '../utils/ganache_subprovider';
|
||||
import { reportCallbackErrors } from '../utils/report_callback_errors';
|
||||
|
||||
@ -75,7 +81,7 @@ describe('LedgerSubprovider', () => {
|
||||
expect(accounts.length).to.be.equal(numberOfAccounts);
|
||||
});
|
||||
it('signs a personal message', async () => {
|
||||
const data = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
|
||||
const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
|
||||
const ecSignatureHex = await ledgerSubprovider.signPersonalMessageAsync(data);
|
||||
expect(ecSignatureHex).to.be.equal(
|
||||
'0xa6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae491480652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d001',
|
||||
@ -136,7 +142,7 @@ describe('LedgerSubprovider', () => {
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
it('signs a personal message with personal_sign', (done: DoneCallback) => {
|
||||
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
|
||||
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'personal_sign',
|
||||
@ -219,7 +225,7 @@ describe('LedgerSubprovider', () => {
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.not.be.a('null');
|
||||
expect(err.message).to.be.equal(LedgerSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
@ -238,7 +244,7 @@ describe('LedgerSubprovider', () => {
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.not.be.a('null');
|
||||
expect(err.message).to.be.equal(LedgerSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
|
@ -0,0 +1,170 @@
|
||||
import { JSONRPCResponsePayload } from '@0xproject/types';
|
||||
import * as chai from 'chai';
|
||||
import * as ethUtils from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
import Web3ProviderEngine = require('web3-provider-engine');
|
||||
|
||||
import { GanacheSubprovider, PrivateKeyWalletSubprovider } from '../../src/';
|
||||
import {
|
||||
DoneCallback,
|
||||
LedgerCommunicationClient,
|
||||
LedgerSubproviderErrors,
|
||||
WalletSubproviderErrors,
|
||||
} from '../../src/types';
|
||||
import { chaiSetup } from '../chai_setup';
|
||||
import { fixtureData } from '../utils/fixture_data';
|
||||
import { reportCallbackErrors } from '../utils/report_callback_errors';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('PrivateKeyWalletSubprovider', () => {
|
||||
let subprovider: PrivateKeyWalletSubprovider;
|
||||
before(async () => {
|
||||
subprovider = new PrivateKeyWalletSubprovider(fixtureData.TEST_RPC_ACCOUNT_0_ACCOUNT_PRIVATE_KEY);
|
||||
});
|
||||
describe('direct method calls', () => {
|
||||
describe('success cases', () => {
|
||||
it('returns the account', async () => {
|
||||
const accounts = await subprovider.getAccountsAsync();
|
||||
expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
|
||||
expect(accounts.length).to.be.equal(1);
|
||||
});
|
||||
it('signs a personal message', async () => {
|
||||
const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
|
||||
const ecSignatureHex = await subprovider.signPersonalMessageAsync(data);
|
||||
expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
|
||||
});
|
||||
it('signs a transaction', async () => {
|
||||
const txHex = await subprovider.signTransactionAsync(fixtureData.TX_DATA);
|
||||
expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('calls through a provider', () => {
|
||||
let provider: Web3ProviderEngine;
|
||||
before(() => {
|
||||
provider = new Web3ProviderEngine();
|
||||
provider.addProvider(subprovider);
|
||||
const ganacheSubprovider = new GanacheSubprovider({});
|
||||
provider.addProvider(ganacheSubprovider);
|
||||
provider.start();
|
||||
});
|
||||
describe('success cases', () => {
|
||||
it('returns a list of accounts', (done: DoneCallback) => {
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_accounts',
|
||||
params: [],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.be.a('null');
|
||||
expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
|
||||
expect(response.result.length).to.be.equal(1);
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
it('signs a personal message with eth_sign', (done: DoneCallback) => {
|
||||
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_sign',
|
||||
params: ['0x0000000000000000000000000000000000000000', messageHex],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.be.a('null');
|
||||
expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
it('signs a personal message with personal_sign', (done: DoneCallback) => {
|
||||
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'personal_sign',
|
||||
params: [messageHex, '0x0000000000000000000000000000000000000000'],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.be.a('null');
|
||||
expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
});
|
||||
describe('failure cases', () => {
|
||||
it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
|
||||
const nonHexMessage = 'hello world';
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_sign',
|
||||
params: ['0x0000000000000000000000000000000000000000', nonHexMessage],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.not.be.a('null');
|
||||
expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => {
|
||||
const nonHexMessage = 'hello world';
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'personal_sign',
|
||||
params: [nonHexMessage, '0x0000000000000000000000000000000000000000'],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.not.be.a('null');
|
||||
expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world');
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
it('should throw if `from` param missing when calling eth_sendTransaction', (done: DoneCallback) => {
|
||||
const tx = {
|
||||
to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
|
||||
value: '0xde0b6b3a7640000',
|
||||
};
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_sendTransaction',
|
||||
params: [tx],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.not.be.a('null');
|
||||
expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
it('should throw if `from` param invalid address when calling eth_sendTransaction', (done: DoneCallback) => {
|
||||
const tx = {
|
||||
to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
|
||||
from: '0xIncorrectEthereumAddress',
|
||||
value: '0xde0b6b3a7640000',
|
||||
};
|
||||
const payload = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_sendTransaction',
|
||||
params: [tx],
|
||||
id: 1,
|
||||
};
|
||||
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
|
||||
expect(err).to.not.be.a('null');
|
||||
expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied);
|
||||
done();
|
||||
});
|
||||
provider.sendAsync(payload, callback);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
23
packages/subproviders/test/utils/fixture_data.ts
Normal file
23
packages/subproviders/test/utils/fixture_data.ts
Normal file
@ -0,0 +1,23 @@
|
||||
const TEST_RPC_ACCOUNT_0 = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
const networkId = 42;
|
||||
export const fixtureData = {
|
||||
TEST_RPC_ACCOUNT_0,
|
||||
TEST_RPC_ACCOUNT_0_ACCOUNT_PRIVATE_KEY: 'F2F48EE19680706196E2E339E5DA3491186E0C4C5030670656B0E0164837257D',
|
||||
PERSONAL_MESSAGE_STRING: 'hello world',
|
||||
PERSONAL_MESSAGE_SIGNED_RESULT:
|
||||
'0x1b0ec5e2908e993d0c8ab6b46da46be2688fdf03c7ea6686075de37392e50a7d7fcc531446699132fbda915bd989882e0064d417018773a315fb8d43ed063c9b00',
|
||||
TESTRPC_DERIVATION_PATH: `m/44'/60'/0'/0`,
|
||||
NETWORK_ID: networkId,
|
||||
TX_DATA: {
|
||||
nonce: '0x00',
|
||||
gasPrice: '0x0',
|
||||
gas: '0x2710',
|
||||
to: '0x0000000000000000000000000000000000000000',
|
||||
value: '0x00',
|
||||
chainId: networkId,
|
||||
from: TEST_RPC_ACCOUNT_0,
|
||||
},
|
||||
// This is the signed result of the abouve Transaction Data
|
||||
TX_DATA_SIGNED_RESULT:
|
||||
'0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178',
|
||||
};
|
@ -4,15 +4,15 @@ This faucet dispenses 0.1 test ether to one recipient per second and 0.1 test ZR
|
||||
|
||||
## Installation
|
||||
|
||||
This is a private package and therefore is not published to npm. In order to build and run this package locally, see the [Install Dependencies](#Install-Dependencies) section and onwards below.
|
||||
This is a private package and therefore is not published to npm. In order to build and run this package locally, see the contributing instructions below.
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -26,6 +26,44 @@ Then install dependencies
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Start
|
||||
|
||||
Set the following environment variables:
|
||||
@ -125,9 +163,3 @@ docker run -d \
|
||||
-e INFURA_API_KEY=$INFURA_API_KEY \
|
||||
testnet-faucets
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
@ -9,15 +9,13 @@ import * as Web3 from 'web3';
|
||||
// we are not running in a browser env.
|
||||
// Filed issue: https://github.com/ethereum/web3.js/issues/844
|
||||
(global as any).XMLHttpRequest = undefined;
|
||||
import { NonceTrackerSubprovider } from '@0xproject/subproviders';
|
||||
import { NonceTrackerSubprovider, PrivateKeyWalletSubprovider } from '@0xproject/subproviders';
|
||||
import ProviderEngine = require('web3-provider-engine');
|
||||
import HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet');
|
||||
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
|
||||
import { configs } from './configs';
|
||||
import { DispatchQueue } from './dispatch_queue';
|
||||
import { dispenseAssetTasks } from './dispense_asset_tasks';
|
||||
import { idManagement } from './id_management';
|
||||
import { rpcUrls } from './rpc_urls';
|
||||
|
||||
interface NetworkConfig {
|
||||
@ -41,9 +39,12 @@ const FIVE_DAYS_IN_MS = 4.32e8; // TODO: make this configurable
|
||||
export class Handler {
|
||||
private _networkConfigByNetworkId: ItemByNetworkId<NetworkConfig> = {};
|
||||
private static _createProviderEngine(rpcUrl: string) {
|
||||
if (_.isUndefined(configs.DISPENSER_PRIVATE_KEY)) {
|
||||
throw new Error('Dispenser Private key not found');
|
||||
}
|
||||
const engine = new ProviderEngine();
|
||||
engine.addProvider(new NonceTrackerSubprovider());
|
||||
engine.addProvider(new HookedWalletSubprovider(idManagement));
|
||||
engine.addProvider(new PrivateKeyWalletSubprovider(configs.DISPENSER_PRIVATE_KEY));
|
||||
engine.addProvider(
|
||||
new RpcSubprovider({
|
||||
rpcUrl,
|
||||
|
@ -1,35 +0,0 @@
|
||||
import EthereumTx = require('ethereumjs-tx');
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { configs } from './configs';
|
||||
|
||||
type Callback = (err: Error | null, result: any) => void;
|
||||
|
||||
export const idManagement = {
|
||||
getAccounts(callback: Callback) {
|
||||
callback(null, [configs.DISPENSER_ADDRESS]);
|
||||
},
|
||||
approveTransaction(txData: object, callback: Callback) {
|
||||
callback(null, true);
|
||||
},
|
||||
signTransaction(txData: object, callback: Callback) {
|
||||
const tx = new EthereumTx(txData);
|
||||
const privateKeyBuffer = new Buffer(configs.DISPENSER_PRIVATE_KEY as string, 'hex');
|
||||
tx.sign(privateKeyBuffer);
|
||||
const rawTx = `0x${tx.serialize().toString('hex')}`;
|
||||
callback(null, rawTx);
|
||||
},
|
||||
signMessage(message: object, callback: Callback) {
|
||||
const dataIfExists = _.get(message, 'data');
|
||||
if (_.isUndefined(dataIfExists)) {
|
||||
callback(new Error('NO_DATA_TO_SIGN'), null);
|
||||
}
|
||||
const privateKeyBuffer = new Buffer(configs.DISPENSER_PRIVATE_KEY as string, 'hex');
|
||||
const dataBuff = ethUtil.toBuffer(dataIfExists);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
|
||||
const sig = ethUtil.ecsign(msgHashBuff, privateKeyBuffer);
|
||||
const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
|
||||
callback(null, rpcSig);
|
||||
},
|
||||
};
|
@ -20,11 +20,11 @@ Add the following to your `tslint.json` file
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -40,16 +40,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -24,13 +24,13 @@ import { TransactionReceipt, TxData, TxDataPayable } from '@0xproject/types';
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces e`nabled (Yarn < v1.0) - enable them:
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
@ -44,16 +44,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -20,11 +20,11 @@ This will allow the TS compiler to first look into that repo and then fallback t
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -38,6 +38,38 @@ Then install dependencies
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -24,11 +24,11 @@ import { addressUtils, bigNumberConfigs, classUtils, intervalUtils, promisify }
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -44,16 +44,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -20,11 +20,11 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
@ -40,16 +40,36 @@ yarn install
|
||||
|
||||
### Build
|
||||
|
||||
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
You can also build this specific package by running the following from within its directory:
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
|
@ -28,20 +28,24 @@ Add the following to your `/etc/hosts` file:
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Run dev server
|
||||
### Initial setup
|
||||
|
||||
The **first** time you work with this package, you must build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
yarn run dev
|
||||
yarn lerna:rebuild
|
||||
```
|
||||
|
||||
### Run dev server
|
||||
|
||||
The the `website` root directory, run:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Visit [0xproject.localhost:3572](http://0xproject.localhost:3572) in your browser.
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 3.8 KiB |
@ -15,6 +15,7 @@ import { EthWrappers } from 'ts/components/eth_wrappers';
|
||||
import { FillOrder } from 'ts/components/fill_order';
|
||||
import { Footer } from 'ts/components/footer';
|
||||
import { PortalMenu } from 'ts/components/portal_menu';
|
||||
import { RelayerIndex } from 'ts/components/relayer_index/relayer_index';
|
||||
import { TokenBalances } from 'ts/components/token_balances';
|
||||
import { TopBar } from 'ts/components/top_bar/top_bar';
|
||||
import { TradeHistory } from 'ts/components/trade_history/trade_history';
|
||||
@ -155,6 +156,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
|
||||
const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen.bind(
|
||||
this.props.dispatcher,
|
||||
);
|
||||
const isDevelopment = configs.ENVIRONMENT === Environments.DEVELOPMENT;
|
||||
const portalStyle: React.CSSProperties = {
|
||||
minHeight: '100vh',
|
||||
display: 'flex',
|
||||
@ -204,12 +206,18 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
|
||||
<div className="py2" style={{ backgroundColor: colors.grey50 }}>
|
||||
{this.props.blockchainIsLoaded ? (
|
||||
<Switch>
|
||||
{configs.ENVIRONMENT === Environments.DEVELOPMENT && (
|
||||
{isDevelopment && (
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/wallet`}
|
||||
render={this._renderWallet.bind(this)}
|
||||
/>
|
||||
)}
|
||||
{isDevelopment && (
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/relayers`}
|
||||
render={this._renderRelayers.bind(this)}
|
||||
/>
|
||||
)}
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/weth`}
|
||||
render={this._renderEthWrapper.bind(this)}
|
||||
@ -313,6 +321,15 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderRelayers() {
|
||||
return (
|
||||
<div className="flex flex-center">
|
||||
<div className="mx-auto" style={{ width: 800 }}>
|
||||
<RelayerIndex networkId={this.props.networkId} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderEthWrapper() {
|
||||
return (
|
||||
<EthWrappers
|
||||
|
@ -59,14 +59,24 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
|
||||
{this._renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')}
|
||||
</MenuItem>
|
||||
{configs.ENVIRONMENT === Environments.DEVELOPMENT && (
|
||||
<MenuItem
|
||||
style={this.props.menuItemStyle}
|
||||
className="py2"
|
||||
to={`${WebsitePaths.Portal}/wallet`}
|
||||
onClick={this.props.onClick.bind(this)}
|
||||
>
|
||||
{this._renderMenuItemWithIcon('Wallet', 'zmdi-balance-wallet')}
|
||||
</MenuItem>
|
||||
<div>
|
||||
<MenuItem
|
||||
style={this.props.menuItemStyle}
|
||||
className="py2"
|
||||
to={`${WebsitePaths.Portal}/wallet`}
|
||||
onClick={this.props.onClick.bind(this)}
|
||||
>
|
||||
{this._renderMenuItemWithIcon('Wallet', 'zmdi-balance-wallet')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
style={this.props.menuItemStyle}
|
||||
className="py2"
|
||||
to={`${WebsitePaths.Portal}/relayers`}
|
||||
onClick={this.props.onClick.bind(this)}
|
||||
>
|
||||
{this._renderMenuItemWithIcon('Relayers', 'zmdi-input-antenna')}
|
||||
</MenuItem>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -0,0 +1,84 @@
|
||||
import { colors, Styles } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import { GridTile } from 'material-ui/GridList';
|
||||
import * as React from 'react';
|
||||
|
||||
import { TopTokens } from 'ts/components/relayer_index/relayer_top_tokens';
|
||||
import { TokenIcon } from 'ts/components/ui/token_icon';
|
||||
import { RelayerInfo, Token } from 'ts/types';
|
||||
|
||||
export interface RelayerGridTileProps {
|
||||
relayerInfo: RelayerInfo;
|
||||
networkId: number;
|
||||
}
|
||||
|
||||
const styles: Styles = {
|
||||
root: {
|
||||
backgroundColor: colors.white,
|
||||
borderBottomRightRadius: 10,
|
||||
borderBottomLeftRadius: 10,
|
||||
borderTopRightRadius: 10,
|
||||
borderTopLeftRadius: 10,
|
||||
boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`,
|
||||
overflow: 'hidden',
|
||||
boxSizing: 'border-box',
|
||||
},
|
||||
innerDiv: {
|
||||
padding: 6,
|
||||
height: '100%',
|
||||
boxSizing: 'border-box',
|
||||
},
|
||||
header: {
|
||||
height: '50%',
|
||||
width: '100%',
|
||||
objectFit: 'cover',
|
||||
borderBottomRightRadius: 4,
|
||||
borderBottomLeftRadius: 4,
|
||||
borderTopRightRadius: 4,
|
||||
borderTopLeftRadius: 4,
|
||||
},
|
||||
body: {
|
||||
paddingLeft: 6,
|
||||
paddingRight: 6,
|
||||
height: '50%',
|
||||
width: '100%',
|
||||
boxSizing: 'border-box',
|
||||
},
|
||||
marketShareBar: {
|
||||
height: 14,
|
||||
width: '100%',
|
||||
backgroundColor: colors.mediumBlue,
|
||||
},
|
||||
subLabel: {
|
||||
fontSize: 12,
|
||||
color: colors.lightGrey,
|
||||
},
|
||||
relayerNameLabel: {
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
color: colors.black,
|
||||
},
|
||||
};
|
||||
|
||||
export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = (props: RelayerGridTileProps) => {
|
||||
return (
|
||||
<GridTile style={styles.root}>
|
||||
<div style={styles.innerDiv}>
|
||||
<img src={props.relayerInfo.headerUrl} style={styles.header} />
|
||||
<div style={styles.body}>
|
||||
<div className="py1" style={styles.relayerNameLabel}>
|
||||
{props.relayerInfo.name}
|
||||
</div>
|
||||
<div style={styles.marketShareBar} />
|
||||
<div className="py1" style={styles.subLabel}>
|
||||
Market share
|
||||
</div>
|
||||
<TopTokens tokens={props.relayerInfo.topTokens} networkId={props.networkId} />
|
||||
<div className="py1" style={styles.subLabel}>
|
||||
Top tokens
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</GridTile>
|
||||
);
|
||||
};
|
118
packages/website/ts/components/relayer_index/relayer_index.tsx
Normal file
118
packages/website/ts/components/relayer_index/relayer_index.tsx
Normal file
@ -0,0 +1,118 @@
|
||||
import { colors, Styles } from '@0xproject/react-shared';
|
||||
import { GridList } from 'material-ui/GridList';
|
||||
import * as React from 'react';
|
||||
|
||||
import { RelayerGridTile } from 'ts/components/relayer_index/relayer_grid_tile';
|
||||
import { RelayerInfo } from 'ts/types';
|
||||
|
||||
export interface RelayerIndexProps {
|
||||
networkId: number;
|
||||
}
|
||||
|
||||
const styles: Styles = {
|
||||
root: {
|
||||
width: '100%',
|
||||
},
|
||||
item: {
|
||||
backgroundColor: colors.white,
|
||||
borderBottomRightRadius: 10,
|
||||
borderBottomLeftRadius: 10,
|
||||
borderTopRightRadius: 10,
|
||||
borderTopLeftRadius: 10,
|
||||
boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`,
|
||||
overflow: 'hidden',
|
||||
padding: 4,
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: replace fake data with real, remote data
|
||||
const topTokens = [
|
||||
{
|
||||
address: '0x1dad4783cf3fe3085c1426157ab175a6119a04ba',
|
||||
decimals: 18,
|
||||
iconUrl: '/images/token_icons/makerdao.png',
|
||||
isRegistered: true,
|
||||
isTracked: true,
|
||||
name: 'Maker DAO',
|
||||
symbol: 'MKR',
|
||||
},
|
||||
{
|
||||
address: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
||||
decimals: 18,
|
||||
iconUrl: '/images/token_icons/melon.png',
|
||||
isRegistered: true,
|
||||
isTracked: true,
|
||||
name: 'Melon Token',
|
||||
symbol: 'MLN',
|
||||
},
|
||||
{
|
||||
address: '0xb18845c260f680d5b9d84649638813e342e4f8c9',
|
||||
decimals: 18,
|
||||
iconUrl: '/images/token_icons/augur.png',
|
||||
isRegistered: true,
|
||||
isTracked: true,
|
||||
name: 'Augur Reputation Token',
|
||||
symbol: 'REP',
|
||||
},
|
||||
];
|
||||
|
||||
const relayerInfos: RelayerInfo[] = [
|
||||
{
|
||||
id: '1',
|
||||
headerUrl: '/images/og_image.png',
|
||||
name: 'Radar Relay',
|
||||
marketShare: 0.5,
|
||||
topTokens,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
headerUrl: '/images/og_image.png',
|
||||
name: 'Paradex',
|
||||
marketShare: 0.5,
|
||||
topTokens,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
headerUrl: '/images/og_image.png',
|
||||
name: 'yo',
|
||||
marketShare: 0.5,
|
||||
topTokens,
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
headerUrl: '/images/og_image.png',
|
||||
name: 'test',
|
||||
marketShare: 0.5,
|
||||
topTokens,
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
headerUrl: '/images/og_image.png',
|
||||
name: 'blahg',
|
||||
marketShare: 0.5,
|
||||
topTokens,
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
headerUrl: '/images/og_image.png',
|
||||
name: 'hello',
|
||||
marketShare: 0.5,
|
||||
topTokens,
|
||||
},
|
||||
];
|
||||
|
||||
const CELL_HEIGHT = 260;
|
||||
const NUMBER_OF_COLUMNS = 4;
|
||||
const GRID_PADDING = 16;
|
||||
|
||||
export const RelayerIndex: React.StatelessComponent<RelayerIndexProps> = (props: RelayerIndexProps) => {
|
||||
return (
|
||||
<div style={styles.root}>
|
||||
<GridList cellHeight={CELL_HEIGHT} cols={NUMBER_OF_COLUMNS} padding={GRID_PADDING} style={styles.gridList}>
|
||||
{relayerInfos.map((relayerInfo: RelayerInfo) => (
|
||||
<RelayerGridTile key={relayerInfo.id} relayerInfo={relayerInfo} networkId={props.networkId} />
|
||||
))}
|
||||
</GridList>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,46 @@
|
||||
import { colors, EtherscanLinkSuffixes, Styles, utils as sharedUtils } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { TokenIcon } from 'ts/components/ui/token_icon';
|
||||
import { Token } from 'ts/types';
|
||||
|
||||
export interface TopTokensProps {
|
||||
tokens: Token[];
|
||||
networkId: number;
|
||||
}
|
||||
|
||||
const styles: Styles = {
|
||||
tokenLabel: {
|
||||
textDecoration: 'none',
|
||||
color: colors.mediumBlue,
|
||||
},
|
||||
followingTokenLabel: {
|
||||
paddingLeft: 16,
|
||||
},
|
||||
};
|
||||
|
||||
export const TopTokens: React.StatelessComponent<TopTokensProps> = (props: TopTokensProps) => {
|
||||
return (
|
||||
<div className="flex">
|
||||
{_.map(props.tokens, (token: Token, index: number) => {
|
||||
const firstItemStyle = { ...styles.tokenLabel, ...styles.followingTokenLabel };
|
||||
const style = index !== 0 ? firstItemStyle : styles.tokenLabel;
|
||||
return (
|
||||
<a
|
||||
key={token.address}
|
||||
href={tokenLinkFromToken(token, props.networkId)}
|
||||
target="_blank"
|
||||
style={style}
|
||||
>
|
||||
{token.symbol}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function tokenLinkFromToken(token: Token, networkId: number) {
|
||||
return sharedUtils.getEtherScanLinkIfExists(token.address, networkId, EtherscanLinkSuffixes.Address);
|
||||
}
|
@ -71,7 +71,7 @@ interface AccessoryItemConfig {
|
||||
}
|
||||
|
||||
const styles: Styles = {
|
||||
wallet: {
|
||||
root: {
|
||||
width: 346,
|
||||
backgroundColor: colors.white,
|
||||
borderBottomRightRadius: 10,
|
||||
@ -121,6 +121,10 @@ const ZRX_TOKEN_SYMBOL = 'ZRX';
|
||||
const ETHER_SYMBOL = 'ETH';
|
||||
const ICON_DIMENSION = 24;
|
||||
const TOKEN_AMOUNT_DISPLAY_PRECISION = 3;
|
||||
const HEADER_ITEM_KEY = 'HEADER';
|
||||
const FOOTER_ITEM_KEY = 'FOOTER';
|
||||
const DISCONNECTED_ITEM_KEY = 'DISCONNECTED';
|
||||
const ETHER_ITEM_KEY = 'ETHER';
|
||||
|
||||
export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
private _isUnmounted: boolean;
|
||||
@ -174,7 +178,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
}
|
||||
public render() {
|
||||
const isReadyToRender = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError;
|
||||
return <div style={styles.wallet}>{isReadyToRender && this._renderRows()}</div>;
|
||||
return <div style={styles.root}>{isReadyToRender && this._renderRows()}</div>;
|
||||
}
|
||||
private _renderRows() {
|
||||
const isAddressAvailable = !_.isEmpty(this.props.userAddress);
|
||||
@ -196,6 +200,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
const primaryText = 'wallet';
|
||||
return (
|
||||
<ListItem
|
||||
key={HEADER_ITEM_KEY}
|
||||
primaryText={primaryText.toUpperCase()}
|
||||
leftIcon={<ActionAccountBalanceWallet color={colors.mediumBlue} />}
|
||||
style={styles.paddedItem}
|
||||
@ -206,6 +211,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
private _renderDisconnectedRows() {
|
||||
return (
|
||||
<WalletDisconnectedItem
|
||||
key={DISCONNECTED_ITEM_KEY}
|
||||
providerType={this.props.providerType}
|
||||
injectedProviderName={this.props.injectedProviderName}
|
||||
onToggleLedgerDialog={this.props.onToggleLedgerDialog}
|
||||
@ -217,6 +223,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
const primaryText = utils.getAddressBeginAndEnd(userAddress);
|
||||
return (
|
||||
<ListItem
|
||||
key={HEADER_ITEM_KEY}
|
||||
primaryText={primaryText}
|
||||
leftIcon={<Identicon address={userAddress} diameter={ICON_DIMENSION} />}
|
||||
style={{ ...styles.paddedItem, ...styles.borderedItem }}
|
||||
@ -226,7 +233,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
}
|
||||
private _renderFooterRows() {
|
||||
const primaryText = '+ other tokens';
|
||||
return <ListItem primaryText={primaryText} innerDivStyle={styles.footerItemInnerDiv} />;
|
||||
return <ListItem key={FOOTER_ITEM_KEY} primaryText={primaryText} innerDivStyle={styles.footerItemInnerDiv} />;
|
||||
}
|
||||
private _renderEthRows() {
|
||||
const primaryText = this._renderAmount(
|
||||
@ -245,7 +252,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
: { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem };
|
||||
const etherToken = this._getEthToken();
|
||||
return (
|
||||
<div>
|
||||
<div key={ETHER_ITEM_KEY}>
|
||||
<ListItem
|
||||
primaryText={primaryText}
|
||||
leftIcon={<img style={{ width: ICON_DIMENSION, height: ICON_DIMENSION }} src={ETHER_ICON_PATH} />}
|
||||
@ -304,7 +311,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
: { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem };
|
||||
const etherToken = this._getEthToken();
|
||||
return (
|
||||
<div>
|
||||
<div key={token.address}>
|
||||
<ListItem
|
||||
primaryText={amount}
|
||||
leftIcon={this._renderTokenIcon(token, tokenLink)}
|
||||
|
@ -111,7 +111,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther
|
||||
disableTouchRipple={true}
|
||||
style={walletItemStyles.focusedItem}
|
||||
innerDivStyle={styles.innerDiv}
|
||||
leftIcon={this.state.isEthConversionHappening && this._renderIsEthConversionHappeningSpinner()}
|
||||
leftIcon={this._renderIsEthConversionHappeningSpinner()}
|
||||
rightAvatar={this._renderWrapEtherConfirmationButton()}
|
||||
/>
|
||||
);
|
||||
@ -123,11 +123,11 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther
|
||||
});
|
||||
}
|
||||
private _renderIsEthConversionHappeningSpinner() {
|
||||
return (
|
||||
return this.state.isEthConversionHappening ? (
|
||||
<div className="pl1" style={{ paddingTop: 10 }}>
|
||||
<i className="zmdi zmdi-spinner zmdi-hc-spin" />
|
||||
</div>
|
||||
);
|
||||
) : null;
|
||||
}
|
||||
private _renderWrapEtherConfirmationButton() {
|
||||
const isWrappingEth = this.props.direction === Side.Deposit;
|
||||
|
@ -39,7 +39,7 @@ const docsInfoConfig: DocsInfoConfig = {
|
||||
[docSections.installation]: InstallationMarkdown,
|
||||
},
|
||||
sectionNameToModulePath: {
|
||||
[docSections.web3Wrapper]: ['"web3-wrapper/src/index"'],
|
||||
[docSections.web3Wrapper]: ['"web3-wrapper/src/web3_wrapper"'],
|
||||
[docSections.types]: ['"types/src/index"'],
|
||||
},
|
||||
menuSubsectionToVersionWhenIntroduced: {},
|
||||
|
@ -490,4 +490,12 @@ export interface TokenState {
|
||||
allowance: BigNumber;
|
||||
isLoaded: boolean;
|
||||
}
|
||||
|
||||
export interface RelayerInfo {
|
||||
headerUrl: string;
|
||||
id: string;
|
||||
name: string;
|
||||
marketShare: number;
|
||||
topTokens: Token[];
|
||||
}
|
||||
// tslint:disable:max-file-line-count
|
||||
|
Loading…
x
Reference in New Issue
Block a user