2017-08-15 13:56:29 +00:00
|
|
|
# MyEtherWallet V4+ (ALPHA - VISIT [V3](https://github.com/kvhnuke/etherwallet) for the production site)
|
2017-04-12 05:06:09 +00:00
|
|
|
|
|
|
|
#### Run:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run dev # run app in dev mode
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Build:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run build # build app
|
|
|
|
```
|
|
|
|
|
|
|
|
It generates app in `dist` folder.
|
|
|
|
|
|
|
|
#### Test:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run test # run tests with Jest
|
|
|
|
```
|
|
|
|
|
2017-09-20 00:47:46 +00:00
|
|
|
#### Dev (HTTPS):
|
|
|
|
|
|
|
|
1. Create your own SSL Certificate (Heroku has a [nice guide here](https://devcenter.heroku.com/articles/ssl-certificate-self))
|
|
|
|
2. Move the `.key` and `.crt` files into `webpack_config/server.*`
|
|
|
|
3. Run the following command:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm run dev:https
|
|
|
|
```
|
|
|
|
|
2017-08-24 16:41:47 +00:00
|
|
|
#### Derivation Check:
|
|
|
|
##### The derivation checker utility assumes that you have:
|
|
|
|
1. Docker installed/available
|
|
|
|
2. [dternyak/eth-priv-to-addr](https://hub.docker.com/r/dternyak/eth-priv-to-addr/) pulled from DockerHub
|
|
|
|
|
|
|
|
##### Docker setup instructions:
|
|
|
|
1. Install docker (on macOS, I suggest [Docker for Mac](https://docs.docker.com/docker-for-mac/))
|
|
|
|
2. `docker pull dternyak/eth-priv-to-addr`
|
2017-09-20 00:47:46 +00:00
|
|
|
|
2017-08-24 16:41:47 +00:00
|
|
|
##### Run Derivation Checker
|
|
|
|
```bash
|
|
|
|
npm run derivation-checker
|
|
|
|
```
|
|
|
|
|
2017-04-12 05:06:09 +00:00
|
|
|
## Folder structure:
|
|
|
|
|
|
|
|
```
|
2017-04-12 05:09:28 +00:00
|
|
|
│
|
2017-04-12 05:06:09 +00:00
|
|
|
├── common - Your App
|
2017-04-27 03:59:16 +00:00
|
|
|
│ ├── actions - application actions
|
2017-04-12 05:06:09 +00:00
|
|
|
│ ├── api - Services and XHR utils(also custom form validation, see InputComponent from components/common)
|
|
|
|
│ ├── components - components according to "Redux philosophy"
|
|
|
|
│ ├── config - frontend config depending on REACT_WEBPACK_ENV
|
|
|
|
│ ├── containers - containers according to "Redux philosophy"
|
|
|
|
│ ├── reducers - application reducers
|
|
|
|
│ ├── routing - application routing
|
|
|
|
│ ├── index.jsx - entry
|
|
|
|
│ ├── index.html
|
2017-04-12 22:38:25 +00:00
|
|
|
├── static
|
2017-04-12 05:06:09 +00:00
|
|
|
├── webpack_config - Webpack configuration
|
|
|
|
├── jest_config - Jest configuration
|
2017-04-27 03:59:16 +00:00
|
|
|
```
|
2017-07-11 03:03:08 +00:00
|
|
|
|
|
|
|
## Docker setup
|
|
|
|
You should already have docker and docker-compose setup for your platform as a pre-req.
|
|
|
|
|
|
|
|
```bash
|
|
|
|
docker-compose up
|
|
|
|
```
|
2017-07-15 04:16:36 +00:00
|
|
|
|
|
|
|
## Style Guides and Philosophies
|
|
|
|
|
|
|
|
The following are guides for developers to follow for writing compliant code.
|
|
|
|
|
2017-07-27 17:05:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
### Redux and Actions
|
|
|
|
|
|
|
|
Each reducer has one file in `reducers/[namespace].js` that contains the reducer
|
|
|
|
and initial state, one file in `actions/[namespace].js` that contains the action
|
|
|
|
creators and their return types, and optionally one file in
|
|
|
|
`sagas/[namespace].js` that handles action side effects using
|
|
|
|
[`redux-saga`](https://github.com/redux-saga/redux-saga).
|
|
|
|
|
|
|
|
The files should be laid out as follows:
|
|
|
|
|
|
|
|
#### Reducer
|
|
|
|
|
|
|
|
* State should be explicitly defined and exported
|
|
|
|
* Initial state should match state flow typing, define every key
|
|
|
|
* Reducer function should handle all cases for actions. If state does not change
|
|
|
|
as a result of an action (Because it merely kicks off side-effects in saga) then
|
|
|
|
define the case above default, and have it fall through.
|
|
|
|
|
|
|
|
```js
|
|
|
|
// @flow
|
|
|
|
import type { NamespaceAction } from "actions/namespace";
|
|
|
|
|
|
|
|
export type State = { /* Flowtype definition for state object */ };
|
|
|
|
export const INITIAL_STATE: State = { /* Initial state shape */ };
|
|
|
|
|
|
|
|
export function namespace(
|
|
|
|
state: State = INITIAL_STATE,
|
|
|
|
action: NamespaceAction
|
|
|
|
): State {
|
|
|
|
switch (action.type) {
|
|
|
|
case 'NAMESPACE_NAME_OF_ACTION':
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
// Alterations to state
|
|
|
|
};
|
|
|
|
|
|
|
|
case 'NAMESPACE_NAME_OF_SAGA_ACTION':
|
|
|
|
default:
|
|
|
|
// Ensures every action was handled in reducer
|
|
|
|
// Unhandled actions should just fall into default
|
|
|
|
(action: empty);
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Actions
|
|
|
|
|
|
|
|
* Define each action object type beside the action creator
|
|
|
|
* Export a union of all of the action types for use by the reducer
|
|
|
|
|
|
|
|
```js
|
|
|
|
/*** Name of action ***/
|
|
|
|
export type NameOfActionAction = {
|
|
|
|
type: 'NAMESPACE_NAME_OF_ACTION',
|
|
|
|
/* Rest of the action object shape */
|
|
|
|
};
|
|
|
|
|
|
|
|
export function nameOfAction(): NameOfActionAction {
|
|
|
|
return {
|
|
|
|
type: 'NAMESPACE_NAME_OF_ACTION',
|
|
|
|
/* Rest of the action object */
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/*** Action Union ***/
|
|
|
|
export type NamespaceAction =
|
|
|
|
| ActionOneAction
|
|
|
|
| ActionTwoAction
|
|
|
|
| ActionThreeAction;
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Action Constants
|
|
|
|
|
|
|
|
Action constants are not used thanks to flow type checking. To avoid typos, we
|
|
|
|
use `(action: empty)` in the default case which assures every case is accounted
|
|
|
|
for. If you need to use another reducer's action, import that action type into
|
|
|
|
your reducer, and create a new action union of your actions, and the other
|
|
|
|
action types used.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-07-15 04:16:36 +00:00
|
|
|
### Styling
|
|
|
|
|
|
|
|
Legacy styles are housed under `common/assets/styles` and written with LESS.
|
|
|
|
However, going forward, each styled component should create a a `.scss` file of
|
|
|
|
the same name in the same folder, and import it like so:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import React from "react";
|
|
|
|
|
|
|
|
import "./MyComponent.scss";
|
|
|
|
|
|
|
|
export default class MyComponent extends React.component {
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<div className="MyComponent">
|
|
|
|
<div className="MyComponent-child">Hello!</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
These style modules adhere to [SuitCSS naming convention](https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md):
|
|
|
|
|
|
|
|
```scss
|
|
|
|
.MyComponent {
|
|
|
|
/* Styles */
|
|
|
|
|
|
|
|
&-child {
|
|
|
|
/* Styles */
|
|
|
|
|
|
|
|
&.is-hidden {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
All elements inside of a component should extend its parent class namespace, or
|
|
|
|
create a new namespace (Potentially breaking that out into its own component.)
|
|
|
|
|
|
|
|
Variables and mixins can be imported from the files in `common/styles`:
|
|
|
|
|
|
|
|
```scss
|
|
|
|
@import "sass/colors";
|
|
|
|
|
|
|
|
code {
|
|
|
|
color: $code-color;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Converting Styles
|
|
|
|
|
|
|
|
When working on a module that has styling in Less, try to do the following:
|
|
|
|
|
|
|
|
* Screenshot the component in question
|
|
|
|
* Create a new SCSS file in the same directory
|
|
|
|
* Remove styling from LESS file, convert it to the SCSS file (Mostly s/@/$)
|
|
|
|
* Convert class names to SuitCSS naming convention
|
|
|
|
* Convert any utility classes from `etherewallet-utilities.less` into mixins
|
|
|
|
* Convert as many element selectors to class name selectors as possible
|
|
|
|
* Convert as many `<br/>` tags or ` `s to margins
|
|
|
|
* Ensure that there has been little to no deviation from screenshot
|
2017-09-25 02:55:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Thanks & Support
|
|
|
|
|
|
|
|
<a href="https://browserstack.com/">
|
|
|
|
<img src="https://i.imgur.com/Rib9y9E.png" align="left" />
|
|
|
|
</a>
|
|
|
|
|
|
|
|
Cross browser testing and debugging provided by the very lovely team at BrowserStack.
|