MyCrypto is an open-source, client-side tool for generating ether wallets, handling ERC-20 tokens, and interacting with the blockchain more easily. https://mycrypto.com
Go to file
Danny Skubak b939e8ceda Request Payment SubTab - EIP 681 (#671)
* progress

* Normalize bity api response

* Filter api response

* Track swap information in component state

* Update dropdown onchange

* remove dead code

* Update Min Max Validation

* Update minmax err msg && fix onChangeOriginKind

* Add origin & destination to redux state

* Update types & Update tests

* Update types

* Update swap.spec.ts test

* Remove commented out code

* Remove hardcoded coin array

* Create types.ts for swap reducer

* Update swapinput type

* Update bityRates in localStorage & Replace all instances of ...Kind / ...Amount props

* Add shapeshift banner

* initial work for sagas

* Update Types

* Update swap reducer initial state

* Update Types & Store empty obj for bityRates / options

* Update more types

* added shapeshift file and rates comments

* action reducers and prop mapping to components

* add typings and swap icon

* more actions reducers and sagas

* debugging shapeshift service

* add Headers

* Fix content type

* add order reset saga and ui fixes

* remove console log and swap b/w Bity and Shapeshift

* working state for Shapeshift and Bity - tested with mainnet

* add icon component

* UI improvements and fix select bug

* fix timer bug

* add bity fallback options and toFixed floats

* tslint errors

* add arrow to dropdown and add support footer

* Add service provider

* fix minor $ bug and stop timer on order complete

* better load UX and dropdown UX

* fixed single test

* currRate prop bugs and reduce LS bloat

* takeEvery on timer saga and don't clear state.options to restartSwap reducer

* export tx sagas and fix minor type

* Add ShapeShift Rates functionality when selecting a ShapeShift pair.

* type fixes

* BugFix: Don't change displayed ShapeShift Rate Inputs on every dropdown change
Also contains some caching / performance improvements

* BugFix: Don't remote rate inputs when falsy amount

* fix type error

* Progress commit

* Implement saga logic

* Make address field factory component

* Shorten debounce time

* Make new actions / sagas  for handling single token lookup

* Implement working version of litesend

* make unit dropdown searchable, add props for all tokens, custom validation

* add string generators for EIP 681 token & ether transactions

* add new selectors

* add request payment tab

* Change saga into selector

* Add failing spec

* fix broken test

* add debounce to error message

* fix tests

* update snapshots

* test coverage

* move setState disabled property from debounce so we instantly can go to next step on valid amounts

* reset amount value (useful for switching between tabs)

* much deeper test coverage, fix debounce ux, and fix bity flashing at swap page load

* fix minor failing test

* seperate shapeshift erc20 token whitelist

* fix saveState store bug

* break orderTimeRemaining saga up and rewrite tests

* fix tslint error

* add isReadOnly prop to address field

* use AddressField component, add additional validation

* make prop optional

* correct validation

* allow for request tab to be used with view only wallet

* account for undefined activeTab

* add types
2018-01-02 21:18:10 -06:00
common Request Payment SubTab - EIP 681 (#671) 2018-01-02 21:18:10 -06:00
jest_config Address Derivation (CI) (#529) 2017-12-05 22:24:40 -08:00
spec Shapeshift Integration (#564) 2018-01-02 12:04:50 -06:00
static Manifest and Favicons (#69) 2017-07-22 15:55:59 -05:00
webpack_config Disable mangle (temporarily?) to fix prod build (#706) 2018-01-01 18:12:27 -06:00
.editorconfig update .editorconfig 2017-07-04 15:16:08 +04:00
.gitignore Update dependencies to enable Greenkeeper 🌴 (#344) 2017-11-07 15:59:27 -08:00
.npmrc Update dependencies to enable Greenkeeper 🌴 (#344) 2017-11-07 15:59:27 -08:00
.nvmrc Enforce node / npm versions, add package-lock.json (#57) 2017-07-18 19:41:17 -05:00
.prettierrc Ensure CI fails on non-prettier compliant PRs (#693) 2018-01-01 17:51:18 -06:00
.travis.yml Ensure CI fails on non-prettier compliant PRs (#693) 2018-01-01 17:51:18 -06:00
LICENSE Initial commit 2016-12-04 02:35:28 +01:00
README.md Fix router props (#634) 2017-12-19 11:23:57 -06:00
package.json chore(package): update @types/react to version 16.0.32 (#714) 2018-01-02 21:04:28 -06:00
tsconfig.json Webpack Upgrade (#665) 2017-12-30 14:29:04 -06:00
tslint.json Productionize Transaction Stack (#456) 2017-12-18 15:23:31 -06:00

README.md

MyEtherWallet V4+ (ALPHA - VISIT V3 for the production site)

Greenkeeper badge

Run:

npm run dev # run app in dev mode

Build:

npm run build # build app

It generates app in dist folder.

Unit Tests:

npm run test # run tests with Jest

Integration Tests:

npm run test:int # run tests with Jest

Dev (HTTPS):

  1. Create your own SSL Certificate (Heroku has a nice guide here)
  2. Move the .key and .crt files into webpack_config/server.*
  3. Run the following command:
npm run dev:https

Address Derivation Checker:

EthereumJS-Util previously contained a bug that would incorrectly derive addresses from private keys with a 1/128 probability of occurring. A summary of this issue can be found here.

As a reactionary measure, the address derivation checker was created.

To test for correct address derivation, the address derivation checker uses multiple sources of address derivation (EthereumJS and PyEthereum) to ensure that multiple official implementations derive the same address for any given private key.

The derivation checker utility assumes that you have:
  1. Docker installed/available
  2. dternyak/eth-priv-to-addr pulled from DockerHub
Docker setup instructions:
  1. Install docker (on macOS, Docker for Mac is suggested)
  2. docker pull dternyak/eth-priv-to-addr
Run Derivation Checker

The derivation checker utility runs as part of the integration test suite.

npm run test:int

Folder structure:

│
├── common
│   ├── actions - application actions
│   ├── api - Services and XHR utils
│   ├── 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.tsx - entry
│   ├── index.html
├── static
├── webpack_config - Webpack configuration
├── jest_config - Jest configuration

Style Guides and Philosophies

The following are guides for developers to follow for writing compliant code.

Redux and Actions

Each reducer has one file in reducers/[namespace].ts that contains the reducer and initial state, one file in actions/[namespace].ts that contains the action creators and their return types, and optionally one file in sagas/[namespace].ts that handles action side effects using redux-saga.

The files should be laid out as follows:

Reducer

  • State should be explicitly defined and exported
  • Initial state should match state typing, define every key
import { NamespaceAction } from "actions/[namespace]";
import { TypeKeys } from 'actions/[namespace]/constants';

export interface State { /* 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 TypeKeys.NAMESPACE_NAME_OF_ACTION:
			return {
				...state,
				// Alterations to state
			};
		default:
			return state;
	}
}

Actions

  • Define each action creator in actionCreator.ts
  • Define each action object type in actionTypes.ts
    • Export a union of all of the action types for use by the reducer
  • Define each action type as a string enum in constants.ts
  • Export actionCreators and actionTypes from module file index.ts
├── common
    ├── actions - application actions
        ├── [namespace] - action namespace
            ├── actionCreators.ts - action creators
            ├── actionTypes.ts - action interfaces / types
            ├── constants.ts - string enum
            ├── index.ts - exports all action creators and action object types
constants.ts
export enum TypeKeys {
  NAMESPACE_NAME_OF_ACTION = 'NAMESPACE_NAME_OF_ACTION'
}
actionTypes.ts
/*** Name of action ***/
export interface NameOfActionAction {
  type: TypeKeys.NAMESPACE_NAME_OF_ACTION;
  /* Rest of the action object shape */
}

/*** Action Union ***/
export type NamespaceAction = ActionOneAction | ActionTwoAction | ActionThreeAction;
actionCreators.ts
import * as interfaces from './actionTypes';
import { TypeKeys } from './constants';

export interface TNameOfAction = typeof nameOfAction;
export function nameOfAction(): interfaces.NameOfActionAction {
	return {
		type: TypeKeys.NAMESPACE_NAME_OF_ACTION,
		payload: {}
	};
};
index.ts
export * from './actionCreators';
export * from './actionTypes';

Typing Redux-Connected Components

Components that receive props directly from redux as a result of the connect function should use AppState for typing, rather than manually defining types. This makes refactoring reducers easier by catching mismatches or changes of types in components, and reduces the chance for inconsistency. It's also less code overall.

// Do this
import { AppState } from 'reducers';

interface Props {
	wallet: AppState['wallet']['inst'];
	rates: AppState['rates']['rates'];
	// ...
}

// Not this
import { IWallet } from 'libs/wallet';
import { Rates } from 'libs/rates';

interface Props {
	wallet: IWallet;
	rates: Rates;
	// ...
}

However, if you have a sub-component that takes in props from a connected component, it's OK to manually specify the type. Especially if you go from being type-or-null to guaranteeing the prop will be passed (because of a conditional render.)

Higher Order Components

Typing Injected Props

Props made available through higher order components can be tricky to type. You can inherit the injected props, and in the case of react router, specialize the generic in withRouter so it can omit all of its injected props from the component.

import { RouteComponentProps } from 'react-router-dom';

interface MyComponentProps extends RouteComponentProps<{}> {
  name: string;
  countryCode?: string;
}
class MyComponent extends React.Component<MyComponentProps, {}> {

  render() {
    const { name, countryCode, location } = this.props; // location being the one of the injected props from the withRouter HOC
    ...
  }
}

export default withRouter<Props>(MyComponent);

Event Handlers

Event handlers such as onChange and onClick, should be properly typed. For example, if you have an event listener on an input element inside a form:

public onValueChange = (e: React.FormEvent<HTMLInputElement>) => {
    if (this.props.onChange) {
      this.props.onChange(
        e.currentTarget.value,
        this.props.unit
      );
    }
  };

Where you type the event as a React.FormEvent of type HTML<TYPE>Element.

Class names

Dynamic class names should use the classnames module to simplify how they are created instead of using string template literals with expressions inside.

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:

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:

.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:

@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 &nbsp;s to margins
  • Ensure that there has been little to no deviation from screenshot

Adding Icon-fonts

  1. Download chosen icon-font
  2. Declare css font-family:
    @font-face {
    	font-family: 'social-media';
    	src: url('../assets/fonts/social-media.eot');
    	src: url('../assets/fonts/social-media.eot') format('embedded-opentype'),
    		url('../assets/fonts/social-media.woff2') format('woff2'),
    		url('../assets/fonts/social-media.woff') format('woff'),
    		url('../assets/fonts/social-media.ttf') format('truetype'),
    		url('../assets/fonts/social-media.svg') format('svg');
    	font-weight: normal;
    	font-style: normal;
    }
    
  3. Create classes for each icon using their unicode character
    .sm-logo-facebook:before {
        content: '\ea02';
      }
    
  4. Write some markup:
    <a href="/">
    	<i className={`sm-icon sm-logo-${text} sm-24px`} />
    	Hello World
    </a>
    

Thanks & Support

Cross browser testing and debugging provided by the very lovely team at BrowserStack.