Migrate to Typescript (#224)
* Refactor babel/types * Refactor entry point * Refactor actions * Refactor api * Full project refactor -- Broad type fixing sweep * - completely fix merge conflicts - handle various type errors * Add tslint to package.json * Dependency cleanup * Fix module resolution * Work on type definitions for untyped libs * progress commit * Add more definition typing * various type additions * Add unit types * Fix sagaiterator + unit types * various types added * additional type additions * Fix typing on Sagas * remove flowfixmes; swap translate for translateRaw * Get rid of contracts - awaiting Henry's contract PR * Remove contracts from routing * Fix most of actions/reducers * refactor actions directory structure * fix reducer action type imports * Fix most of type errors pre-actions refactor * fix action creator imports in containers * Refactor more * Refactor index of actions * fix action imports; use module level index export * package-lock.json updated * Use action types in props * Type up action creators * Fix most of connect errors * Typefixing progress * More types * Fix run-time errors * Caching improvements for webpack * Remove path resolve from webpack * Update non-breaking packages to latest version * Fix token typing * Remove unused color code * Fix wallet decrypt dispatch * Set redux-form related props/functions to ANY, since we're stripping it out later on * Revert BigNumber.js package changes * Extend window to custom object for Perf * Format Navigation * Typecase keystore errors as any (since we shouldnt touch this) * Push wallet context fix * - find/replace value->payload in swap - properly type swap state properties - extract inline reducer into reducer function * - type local storage retrieved items as generic * - bind all RPCClient methods with fat arrow * - reformat * Change to enums for constants * Change state into any * Fix swap errors * ensure that seconds are passed into state as integers * Fix rest of errors * use parseInt explicitly instead of type coercion * Fix derivation-checker, remove flow command, add tslint command, add tslint-react, tell travis to use tslint instead of flow. * Whoops, remove those tests. * Remove unsupported (yet) config option. * Fix precommit to target ts and tsx files. * Fix some errors, ignore some silly rules. * Revert jest to v19, use ts-jest and make all tests typescript. Fixes all but one. * Get rid of saga tests * Fix tslint errors
This commit is contained in:
parent
5e66cccac5
commit
5d4b36d453
25
.babelrc
25
.babelrc
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"plugins": [
|
|
||||||
[
|
|
||||||
"transform-runtime", {
|
|
||||||
"helpers": false,
|
|
||||||
"polyfill": false,
|
|
||||||
"regenerator": true,
|
|
||||||
"moduleName": "babel-runtime"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
["module-resolver", {
|
|
||||||
"root": ["./common"],
|
|
||||||
"alias": {
|
|
||||||
"underscore": "lodash"
|
|
||||||
},
|
|
||||||
"cwd": "babelrc"
|
|
||||||
}],
|
|
||||||
"react-hot-loader/babel"],
|
|
||||||
"presets": ["es2015", "react", "stage-0", "flow"],
|
|
||||||
"env": {
|
|
||||||
"production": {
|
|
||||||
"presets": ["react-optimize"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"extends": ["eslint:recommended", "plugin:react/recommended"],
|
|
||||||
"parser": "babel-eslint",
|
|
||||||
"plugins": ["react"],
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true,
|
|
||||||
"modules": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"amd": true,
|
|
||||||
"es6": true,
|
|
||||||
"node": true,
|
|
||||||
"jest": true
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"comma-dangle": 1,
|
|
||||||
"quotes": [1, "single"],
|
|
||||||
"no-undef": 1,
|
|
||||||
"global-strict": 0,
|
|
||||||
"no-extra-semi": 1,
|
|
||||||
"no-underscore-dangle": 0,
|
|
||||||
"no-console": 0,
|
|
||||||
"no-unused-vars": 0,
|
|
||||||
"no-constant-condition": 0,
|
|
||||||
"no-trailing-spaces": [1, { "skipBlankLines": true }],
|
|
||||||
"no-unreachable": 1,
|
|
||||||
"no-alert": 0,
|
|
||||||
"react/jsx-uses-react": 1,
|
|
||||||
"no-unused-vars": [1, { "argsIgnorePattern": "^_" }],
|
|
||||||
"no-restricted-globals": ["error", "event"]
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"SyntheticInputEvent": false,
|
|
||||||
"SyntheticKeyboardEvent": false,
|
|
||||||
"Generator": false,
|
|
||||||
"$Keys": false,
|
|
||||||
"SyntheticMouseEvent": false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -46,6 +46,7 @@ jspm_packages
|
||||||
.vscode/
|
.vscode/
|
||||||
static/dll.vendor.js
|
static/dll.vendor.js
|
||||||
dll
|
dll
|
||||||
|
.cache-loader
|
||||||
|
|
||||||
# SSL cert stuff
|
# SSL cert stuff
|
||||||
webpack_config/server.key
|
webpack_config/server.key
|
||||||
|
|
|
@ -15,4 +15,4 @@ notifications:
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- npm run test
|
- npm run test
|
||||||
- npm run flow
|
- npm run tslint
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
/*** Change Language ***/
|
|
||||||
export type ChangeLanguageAction = {
|
|
||||||
type: 'CONFIG_LANGUAGE_CHANGE',
|
|
||||||
value: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export function changeLanguage(sign: string): ChangeLanguageAction {
|
|
||||||
return {
|
|
||||||
type: 'CONFIG_LANGUAGE_CHANGE',
|
|
||||||
value: sign
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Change Node ***/
|
|
||||||
export type ChangeNodeAction = {
|
|
||||||
type: 'CONFIG_NODE_CHANGE',
|
|
||||||
// FIXME $keyof?
|
|
||||||
value: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export function changeNode(value: string): ChangeNodeAction {
|
|
||||||
return {
|
|
||||||
type: 'CONFIG_NODE_CHANGE',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Change gas price ***/
|
|
||||||
export type ChangeGasPriceAction = {
|
|
||||||
type: 'CONFIG_GAS_PRICE',
|
|
||||||
value: number
|
|
||||||
};
|
|
||||||
|
|
||||||
export function changeGasPrice(value: number): ChangeGasPriceAction {
|
|
||||||
return {
|
|
||||||
type: 'CONFIG_GAS_PRICE',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Union Type ***/
|
|
||||||
export type ConfigAction =
|
|
||||||
| ChangeNodeAction
|
|
||||||
| ChangeLanguageAction
|
|
||||||
| ChangeGasPriceAction;
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
export type TChangeLanguage = typeof changeLanguage;
|
||||||
|
export function changeLanguage(sign: string): interfaces.ChangeLanguageAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.CONFIG_LANGUAGE_CHANGE,
|
||||||
|
value: sign
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TChangeNode = typeof changeNode;
|
||||||
|
export function changeNode(value: string): interfaces.ChangeNodeAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.CONFIG_NODE_CHANGE,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TChangeGasPrice = typeof changeGasPrice;
|
||||||
|
export function changeGasPrice(value: number): interfaces.ChangeGasPriceAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.CONFIG_GAS_PRICE,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
/*** Change Language ***/
|
||||||
|
export interface ChangeLanguageAction {
|
||||||
|
type: TypeKeys.CONFIG_LANGUAGE_CHANGE;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Change Node ***/
|
||||||
|
export interface ChangeNodeAction {
|
||||||
|
type: TypeKeys.CONFIG_NODE_CHANGE;
|
||||||
|
// FIXME $keyof?
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Change gas price ***/
|
||||||
|
export interface ChangeGasPriceAction {
|
||||||
|
type: TypeKeys.CONFIG_GAS_PRICE;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Union Type ***/
|
||||||
|
export type ConfigAction =
|
||||||
|
| ChangeNodeAction
|
||||||
|
| ChangeLanguageAction
|
||||||
|
| ChangeGasPriceAction;
|
|
@ -0,0 +1,5 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
CONFIG_LANGUAGE_CHANGE = 'CONFIG_LANGUAGE_CHANGE',
|
||||||
|
CONFIG_NODE_CHANGE = 'CONFIG_NODE_CHANGE',
|
||||||
|
CONFIG_GAS_PRICE = 'CONFIG_GAS_PRICE'
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './actionCreators';
|
||||||
|
export * from './actionTypes';
|
|
@ -1,47 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
/***** Access Contract *****/
|
|
||||||
export type AccessContractAction = {
|
|
||||||
type: 'ACCESS_CONTRACT',
|
|
||||||
address: string,
|
|
||||||
abiJson: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export function accessContract(
|
|
||||||
address: string,
|
|
||||||
abiJson: string
|
|
||||||
): AccessContractAction {
|
|
||||||
return {
|
|
||||||
type: 'ACCESS_CONTRACT',
|
|
||||||
address,
|
|
||||||
abiJson
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Set Interactive Contract *****/
|
|
||||||
export type ABIFunctionField = {
|
|
||||||
name: string,
|
|
||||||
type: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ABIFunction = {
|
|
||||||
name: string,
|
|
||||||
type: string,
|
|
||||||
constant: boolean,
|
|
||||||
inputs: Array<ABIFunctionField>,
|
|
||||||
outputs: Array<ABIFunctionField>
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SetInteractiveContractAction = {
|
|
||||||
type: 'SET_INTERACTIVE_CONTRACT',
|
|
||||||
functions: Array<ABIFunction>
|
|
||||||
};
|
|
||||||
|
|
||||||
export function setInteractiveContract(
|
|
||||||
functions: Array<ABIFunction>
|
|
||||||
): SetInteractiveContractAction {
|
|
||||||
return {
|
|
||||||
type: 'SET_INTERACTIVE_CONTRACT',
|
|
||||||
functions
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
export function accessContract(
|
||||||
|
address: string,
|
||||||
|
abiJson: string
|
||||||
|
): interfaces.AccessContractAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.ACCESS_CONTRACT,
|
||||||
|
address,
|
||||||
|
abiJson
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setInteractiveContract(
|
||||||
|
functions: interfaces.ABIFunction[]
|
||||||
|
): interfaces.SetInteractiveContractAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SET_INTERACTIVE_CONTRACT,
|
||||||
|
functions
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
/***** Set Interactive Contract *****/
|
||||||
|
export interface ABIFunctionField {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ABIFunction {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
constant: boolean;
|
||||||
|
inputs: ABIFunctionField[];
|
||||||
|
outputs: ABIFunctionField[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SetInteractiveContractAction {
|
||||||
|
type: TypeKeys.SET_INTERACTIVE_CONTRACT;
|
||||||
|
functions: ABIFunction[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Access Contract *****/
|
||||||
|
export interface AccessContractAction {
|
||||||
|
type: TypeKeys.ACCESS_CONTRACT;
|
||||||
|
address: string;
|
||||||
|
abiJson: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Union Type ***/
|
||||||
|
export type ContractsAction =
|
||||||
|
| SetInteractiveContractAction
|
||||||
|
| AccessContractAction;
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
ACCESS_CONTRACT = 'ACCESS_CONTRACT',
|
||||||
|
SET_INTERACTIVE_CONTRACT = 'SET_INTERACTIVE_CONTRACT'
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './constants';
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './actionCreators';
|
|
@ -1,31 +0,0 @@
|
||||||
// @flow
|
|
||||||
import type { Token } from 'config/data';
|
|
||||||
|
|
||||||
/*** Add custom token ***/
|
|
||||||
export type AddCustomTokenAction = {
|
|
||||||
type: 'CUSTOM_TOKEN_ADD',
|
|
||||||
payload: Token
|
|
||||||
};
|
|
||||||
|
|
||||||
export function addCustomToken(payload: Token): AddCustomTokenAction {
|
|
||||||
return {
|
|
||||||
type: 'CUSTOM_TOKEN_ADD',
|
|
||||||
payload
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Remove Custom Token ***/
|
|
||||||
export type RemoveCustomTokenAction = {
|
|
||||||
type: 'CUSTOM_TOKEN_REMOVE',
|
|
||||||
payload: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export function removeCustomToken(payload: string): RemoveCustomTokenAction {
|
|
||||||
return {
|
|
||||||
type: 'CUSTOM_TOKEN_REMOVE',
|
|
||||||
payload
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Union Type ***/
|
|
||||||
export type CustomTokenAction = AddCustomTokenAction | RemoveCustomTokenAction;
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { Token } from 'config/data';
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
export type TAddCustomToken = typeof addCustomToken;
|
||||||
|
export function addCustomToken(
|
||||||
|
payload: Token
|
||||||
|
): interfaces.AddCustomTokenAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.CUSTOM_TOKEN_ADD,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TRemoveCustomToken = typeof removeCustomToken;
|
||||||
|
|
||||||
|
export function removeCustomToken(
|
||||||
|
payload: string
|
||||||
|
): interfaces.RemoveCustomTokenAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.CUSTOM_TOKEN_REMOVE,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Token } from 'config/data';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
/*** Add custom token ***/
|
||||||
|
export interface AddCustomTokenAction {
|
||||||
|
type: TypeKeys.CUSTOM_TOKEN_ADD;
|
||||||
|
payload: Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Remove Custom Token ***/
|
||||||
|
export interface RemoveCustomTokenAction {
|
||||||
|
type: TypeKeys.CUSTOM_TOKEN_REMOVE;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CustomTokenAction = AddCustomTokenAction | RemoveCustomTokenAction;
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
CUSTOM_TOKEN_ADD = 'CUSTOM_TOKEN_ADD',
|
||||||
|
CUSTOM_TOKEN_REMOVE = 'CUSTOM_TOKEN_REMOVE'
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './actionCreators';
|
||||||
|
export * from './actionTypes';
|
|
@ -1,105 +0,0 @@
|
||||||
// @flow
|
|
||||||
import type Big from 'bignumber.js';
|
|
||||||
|
|
||||||
export type TokenValues = { [string]: ?Big };
|
|
||||||
|
|
||||||
export type DeterministicWalletData = {
|
|
||||||
index: number,
|
|
||||||
address: string,
|
|
||||||
value?: Big,
|
|
||||||
tokenValues: TokenValues
|
|
||||||
};
|
|
||||||
|
|
||||||
/*** Get determinstic wallets ***/
|
|
||||||
export type GetDeterministicWalletsAction = {
|
|
||||||
type: 'DW_GET_WALLETS',
|
|
||||||
payload: {
|
|
||||||
seed: ?string,
|
|
||||||
dPath: string,
|
|
||||||
publicKey: ?string,
|
|
||||||
chainCode: ?string,
|
|
||||||
limit: number,
|
|
||||||
offset: number
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export type GetDeterministicWalletsArgs = {
|
|
||||||
seed: ?string,
|
|
||||||
dPath: string,
|
|
||||||
publicKey: ?string,
|
|
||||||
chainCode: ?string,
|
|
||||||
limit?: number,
|
|
||||||
offset?: number
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getDeterministicWallets(
|
|
||||||
args: GetDeterministicWalletsArgs
|
|
||||||
): GetDeterministicWalletsAction {
|
|
||||||
const { seed, dPath, publicKey, chainCode, limit, offset } = args;
|
|
||||||
return {
|
|
||||||
type: 'DW_GET_WALLETS',
|
|
||||||
payload: {
|
|
||||||
seed,
|
|
||||||
dPath,
|
|
||||||
publicKey,
|
|
||||||
chainCode,
|
|
||||||
limit: limit || 5,
|
|
||||||
offset: offset || 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Set deterministic wallets ***/
|
|
||||||
export type SetDeterministicWalletsAction = {
|
|
||||||
type: 'DW_SET_WALLETS',
|
|
||||||
payload: DeterministicWalletData[]
|
|
||||||
};
|
|
||||||
|
|
||||||
export function setDeterministicWallets(
|
|
||||||
wallets: DeterministicWalletData[]
|
|
||||||
): SetDeterministicWalletsAction {
|
|
||||||
return {
|
|
||||||
type: 'DW_SET_WALLETS',
|
|
||||||
payload: wallets
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Set desired token ***/
|
|
||||||
export type SetDesiredTokenAction = {
|
|
||||||
type: 'DW_SET_DESIRED_TOKEN',
|
|
||||||
payload: ?string
|
|
||||||
};
|
|
||||||
|
|
||||||
export function setDesiredToken(token: ?string): SetDesiredTokenAction {
|
|
||||||
return {
|
|
||||||
type: 'DW_SET_DESIRED_TOKEN',
|
|
||||||
payload: token
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Set wallet values ***/
|
|
||||||
export type UpdateDeterministicWalletArgs = {
|
|
||||||
address: string,
|
|
||||||
value: ?Big,
|
|
||||||
tokenValues: ?TokenValues
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UpdateDeterministicWalletAction = {
|
|
||||||
type: 'DW_UPDATE_WALLET',
|
|
||||||
payload: UpdateDeterministicWalletArgs
|
|
||||||
};
|
|
||||||
|
|
||||||
export function updateDeterministicWallet(
|
|
||||||
args: UpdateDeterministicWalletArgs
|
|
||||||
): UpdateDeterministicWalletAction {
|
|
||||||
return {
|
|
||||||
type: 'DW_UPDATE_WALLET',
|
|
||||||
payload: args
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Union Type ***/
|
|
||||||
export type DeterministicWalletAction =
|
|
||||||
| GetDeterministicWalletsAction
|
|
||||||
| UpdateDeterministicWalletAction
|
|
||||||
| SetDesiredTokenAction;
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
export function getDeterministicWallets(
|
||||||
|
args: interfaces.GetDeterministicWalletsArgs
|
||||||
|
): interfaces.GetDeterministicWalletsAction {
|
||||||
|
const { seed, dPath, publicKey, chainCode, limit, offset } = args;
|
||||||
|
return {
|
||||||
|
type: TypeKeys.DW_GET_WALLETS,
|
||||||
|
payload: {
|
||||||
|
seed,
|
||||||
|
dPath,
|
||||||
|
publicKey,
|
||||||
|
chainCode,
|
||||||
|
limit: limit || 5,
|
||||||
|
offset: offset || 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setDeterministicWallets(
|
||||||
|
wallets: interfaces.DeterministicWalletData[]
|
||||||
|
): interfaces.SetDeterministicWalletsAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.DW_SET_WALLETS,
|
||||||
|
payload: wallets
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setDesiredToken(
|
||||||
|
token: string | undefined
|
||||||
|
): interfaces.SetDesiredTokenAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.DW_SET_DESIRED_TOKEN,
|
||||||
|
payload: token
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateDeterministicWallet(
|
||||||
|
args: interfaces.UpdateDeterministicWalletArgs
|
||||||
|
): interfaces.UpdateDeterministicWalletAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.DW_UPDATE_WALLET,
|
||||||
|
payload: args
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { BigNumber } from 'bignumber.js';
|
||||||
|
|
||||||
|
export interface TokenValues {
|
||||||
|
[key: string]: BigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeterministicWalletData {
|
||||||
|
index: number;
|
||||||
|
address: string;
|
||||||
|
value?: BigNumber;
|
||||||
|
tokenValues: TokenValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Get determinstic wallets ***/
|
||||||
|
export interface GetDeterministicWalletsAction {
|
||||||
|
type: 'DW_GET_WALLETS';
|
||||||
|
payload: {
|
||||||
|
seed?: string;
|
||||||
|
dPath: string;
|
||||||
|
publicKey?: string;
|
||||||
|
chainCode?: string;
|
||||||
|
limit: number;
|
||||||
|
offset: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Set deterministic wallets ***/
|
||||||
|
export interface SetDeterministicWalletsAction {
|
||||||
|
type: 'DW_SET_WALLETS';
|
||||||
|
payload: DeterministicWalletData[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Set desired token ***/
|
||||||
|
export interface SetDesiredTokenAction {
|
||||||
|
type: 'DW_SET_DESIRED_TOKEN';
|
||||||
|
payload: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Set wallet values ***/
|
||||||
|
export interface UpdateDeterministicWalletArgs {
|
||||||
|
address: string;
|
||||||
|
value?: BigNumber;
|
||||||
|
tokenValues?: TokenValues;
|
||||||
|
index?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateDeterministicWalletAction {
|
||||||
|
type: 'DW_UPDATE_WALLET';
|
||||||
|
payload: UpdateDeterministicWalletArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetDeterministicWalletsArgs {
|
||||||
|
seed?: string;
|
||||||
|
dPath: string;
|
||||||
|
publicKey?: string;
|
||||||
|
chainCode?: string;
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Union Type ***/
|
||||||
|
export type DeterministicWalletAction =
|
||||||
|
| SetDeterministicWalletsAction
|
||||||
|
| GetDeterministicWalletsAction
|
||||||
|
| UpdateDeterministicWalletAction
|
||||||
|
| SetDesiredTokenAction;
|
|
@ -0,0 +1,6 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
DW_GET_WALLETS = 'DW_GET_WALLETS',
|
||||||
|
DW_SET_WALLETS = 'DW_SET_WALLETS',
|
||||||
|
DW_SET_DESIRED_TOKEN = 'DW_SET_DESIRED_TOKEN',
|
||||||
|
DW_UPDATE_WALLET = 'DW_UPDATE_WALLET'
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './actionCreators';
|
|
@ -1,39 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
/*** Resolve ENS name ***/
|
|
||||||
export type ResolveEnsNameAction = {
|
|
||||||
type: 'ENS_RESOLVE',
|
|
||||||
payload: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export function resolveEnsName(name: string): ResolveEnsNameAction {
|
|
||||||
return {
|
|
||||||
type: 'ENS_RESOLVE',
|
|
||||||
payload: name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Cache ENS address ***/
|
|
||||||
export type CacheEnsAddressAction = {
|
|
||||||
type: 'ENS_CACHE',
|
|
||||||
payload: {
|
|
||||||
ensName: string,
|
|
||||||
address: string
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export function cacheEnsAddress(
|
|
||||||
ensName: string,
|
|
||||||
address: string
|
|
||||||
): CacheEnsAddressAction {
|
|
||||||
return {
|
|
||||||
type: 'ENS_CACHE',
|
|
||||||
payload: {
|
|
||||||
ensName,
|
|
||||||
address
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Union Type ***/
|
|
||||||
export type EnsAction = ResolveEnsNameAction | CacheEnsAddressAction;
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import * as constants from './constants';
|
||||||
|
|
||||||
|
export function resolveEnsName(name: string): interfaces.ResolveEnsNameAction {
|
||||||
|
return {
|
||||||
|
type: constants.ENS_RESOLVE,
|
||||||
|
payload: name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cacheEnsAddress(
|
||||||
|
ensName: string,
|
||||||
|
address: string
|
||||||
|
): interfaces.CacheEnsAddressAction {
|
||||||
|
return {
|
||||||
|
type: constants.ENS_CACHE,
|
||||||
|
payload: {
|
||||||
|
ensName,
|
||||||
|
address
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import * as constants from './constants';
|
||||||
|
|
||||||
|
/*** Resolve ENS name ***/
|
||||||
|
export interface ResolveEnsNameAction {
|
||||||
|
type: 'ENS_RESOLVE';
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Cache ENS address ***/
|
||||||
|
export interface CacheEnsAddressAction {
|
||||||
|
type: 'ENS_CACHE';
|
||||||
|
payload: {
|
||||||
|
ensName: string;
|
||||||
|
address: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Union Type ***/
|
||||||
|
export type EnsAction = ResolveEnsNameAction | CacheEnsAddressAction;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export const ENS_RESOLVE = 'ENS_RESOLVE';
|
||||||
|
export const ENS_CACHE = 'ENS_CACHE';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './constants';
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './actionCreators';
|
|
@ -1,38 +0,0 @@
|
||||||
// @flow
|
|
||||||
import { PrivKeyWallet } from 'libs/wallet';
|
|
||||||
|
|
||||||
/*** Generate Wallet File ***/
|
|
||||||
export type GenerateNewWalletAction = {
|
|
||||||
type: 'GENERATE_WALLET_GENERATE_WALLET',
|
|
||||||
wallet: PrivKeyWallet,
|
|
||||||
password: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export function generateNewWallet(password: string): GenerateNewWalletAction {
|
|
||||||
return {
|
|
||||||
type: 'GENERATE_WALLET_GENERATE_WALLET',
|
|
||||||
wallet: PrivKeyWallet.generate(),
|
|
||||||
password
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Confirm Continue To Paper ***/
|
|
||||||
export type ContinueToPaperAction = {
|
|
||||||
type: 'GENERATE_WALLET_CONTINUE_TO_PAPER'
|
|
||||||
};
|
|
||||||
|
|
||||||
export function continueToPaper(): ContinueToPaperAction {
|
|
||||||
return { type: 'GENERATE_WALLET_CONTINUE_TO_PAPER' };
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Reset Generate Wallet ***/
|
|
||||||
export type ResetGenerateWalletAction = {
|
|
||||||
type: 'GENERATE_WALLET_RESET'
|
|
||||||
};
|
|
||||||
|
|
||||||
export function resetGenerateWallet(): ResetGenerateWalletAction {
|
|
||||||
return { type: 'GENERATE_WALLET_RESET' };
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Action Union ***/
|
|
||||||
export type GenerateWalletAction = GenerateWalletAction;
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { PrivKeyWallet } from 'libs/wallet';
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
export type TGenerateNewWallet = typeof generateNewWallet;
|
||||||
|
export function generateNewWallet(
|
||||||
|
password: string
|
||||||
|
): interfaces.GenerateNewWalletAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.GENERATE_WALLET_GENERATE_WALLET,
|
||||||
|
wallet: PrivKeyWallet.generate(),
|
||||||
|
password
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TContinueToPaper = typeof continueToPaper;
|
||||||
|
export function continueToPaper(): interfaces.ContinueToPaperAction {
|
||||||
|
return { type: TypeKeys.GENERATE_WALLET_CONTINUE_TO_PAPER };
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TResetGenerateWallet = typeof resetGenerateWallet;
|
||||||
|
export function resetGenerateWallet(): interfaces.ResetGenerateWalletAction {
|
||||||
|
return { type: TypeKeys.GENERATE_WALLET_RESET };
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { PrivKeyWallet } from 'libs/wallet';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
/*** Generate Wallet File ***/
|
||||||
|
export interface GenerateNewWalletAction {
|
||||||
|
type: TypeKeys.GENERATE_WALLET_GENERATE_WALLET;
|
||||||
|
wallet: PrivKeyWallet;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Reset Generate Wallet ***/
|
||||||
|
export interface ResetGenerateWalletAction {
|
||||||
|
type: TypeKeys.GENERATE_WALLET_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Confirm Continue To Paper ***/
|
||||||
|
export interface ContinueToPaperAction {
|
||||||
|
type: TypeKeys.GENERATE_WALLET_CONTINUE_TO_PAPER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Action Union ***/
|
||||||
|
export type GenerateWalletAction =
|
||||||
|
| GenerateNewWalletAction
|
||||||
|
| ContinueToPaperAction
|
||||||
|
| ResetGenerateWalletAction;
|
|
@ -0,0 +1,5 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
GENERATE_WALLET_GENERATE_WALLET = 'GENERATE_WALLET_GENERATE_WALLET',
|
||||||
|
GENERATE_WALLET_CONTINUE_TO_PAPER = 'GENERATE_WALLET_CONTINUE_TO_PAPER',
|
||||||
|
GENERATE_WALLET_RESET = 'GENERATE_WALLET_RESET'
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './constants';
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './actionCreators';
|
|
@ -1,53 +0,0 @@
|
||||||
// @flow
|
|
||||||
import type { Element } from 'react';
|
|
||||||
|
|
||||||
/*** Shared types ***/
|
|
||||||
export type NOTIFICATION_LEVEL = 'danger' | 'warning' | 'success' | 'info';
|
|
||||||
export type INFINITY = 'infinity';
|
|
||||||
|
|
||||||
export type Notification = {
|
|
||||||
level: NOTIFICATION_LEVEL,
|
|
||||||
msg: Element<*> | string,
|
|
||||||
duration?: number | INFINITY
|
|
||||||
};
|
|
||||||
|
|
||||||
/*** Show Notification ***/
|
|
||||||
export type ShowNotificationAction = {
|
|
||||||
type: 'SHOW_NOTIFICATION',
|
|
||||||
payload: Notification
|
|
||||||
};
|
|
||||||
|
|
||||||
export function showNotification(
|
|
||||||
level: NOTIFICATION_LEVEL = 'info',
|
|
||||||
msg: Element<*> | string,
|
|
||||||
duration?: number | INFINITY
|
|
||||||
): ShowNotificationAction {
|
|
||||||
return {
|
|
||||||
type: 'SHOW_NOTIFICATION',
|
|
||||||
payload: {
|
|
||||||
level,
|
|
||||||
msg,
|
|
||||||
duration
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Close notification ***/
|
|
||||||
export type CloseNotificationAction = {
|
|
||||||
type: 'CLOSE_NOTIFICATION',
|
|
||||||
payload: Notification
|
|
||||||
};
|
|
||||||
|
|
||||||
export function closeNotification(
|
|
||||||
notification: Notification
|
|
||||||
): CloseNotificationAction {
|
|
||||||
return {
|
|
||||||
type: 'CLOSE_NOTIFICATION',
|
|
||||||
payload: notification
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Union Type ***/
|
|
||||||
export type NotificationsAction =
|
|
||||||
| ShowNotificationAction
|
|
||||||
| CloseNotificationAction;
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
import * as types from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
export type TShowNotification = typeof showNotification;
|
||||||
|
export function showNotification(
|
||||||
|
level: types.NOTIFICATION_LEVEL = 'info',
|
||||||
|
msg: ReactElement<any> | string,
|
||||||
|
duration?: number | types.INFINITY
|
||||||
|
): types.ShowNotificationAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SHOW_NOTIFICATION,
|
||||||
|
payload: {
|
||||||
|
level,
|
||||||
|
msg,
|
||||||
|
duration
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TCloseNotification = typeof closeNotification;
|
||||||
|
export function closeNotification(
|
||||||
|
notification: types.Notification
|
||||||
|
): types.CloseNotificationAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.CLOSE_NOTIFICATION,
|
||||||
|
payload: notification
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
/*** Shared types ***/
|
||||||
|
export type NOTIFICATION_LEVEL = 'danger' | 'warning' | 'success' | 'info';
|
||||||
|
export type INFINITY = 'infinity';
|
||||||
|
|
||||||
|
export interface Notification {
|
||||||
|
level: NOTIFICATION_LEVEL;
|
||||||
|
msg: ReactElement<any> | string;
|
||||||
|
duration?: number | INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Close notification ***/
|
||||||
|
export interface CloseNotificationAction {
|
||||||
|
type: TypeKeys.CLOSE_NOTIFICATION;
|
||||||
|
payload: Notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Show Notification ***/
|
||||||
|
export interface ShowNotificationAction {
|
||||||
|
type: TypeKeys.SHOW_NOTIFICATION;
|
||||||
|
payload: Notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Union Type ***/
|
||||||
|
export type NotificationsAction =
|
||||||
|
| ShowNotificationAction
|
||||||
|
| CloseNotificationAction;
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
SHOW_NOTIFICATION = 'SHOW_NOTIFICATION',
|
||||||
|
CLOSE_NOTIFICATION = 'CLOSE_NOTIFICATION'
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './actionCreators';
|
|
@ -1,29 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
export type FiatRequestedRatesAction = {
|
|
||||||
type: 'RATES_FIAT_REQUESTED'
|
|
||||||
};
|
|
||||||
|
|
||||||
export function fiatRequestedRates() {
|
|
||||||
return {
|
|
||||||
type: 'RATES_FIAT_REQUESTED'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Set rates ***/
|
|
||||||
export type FiatSucceededRatesAction = {
|
|
||||||
type: 'RATES_FIAT_SUCCEEDED',
|
|
||||||
payload: { [string]: number }
|
|
||||||
};
|
|
||||||
|
|
||||||
export function fiatSucceededRates(payload: {
|
|
||||||
[string]: number
|
|
||||||
}): FiatSucceededRatesAction {
|
|
||||||
return {
|
|
||||||
type: 'RATES_FIAT_SUCCEEDED',
|
|
||||||
payload
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Union Type ***/
|
|
||||||
export type RatesAction = FiatSucceededRatesAction | FiatRequestedRatesAction;
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
export type TFiatRequestedRates = typeof fiatRequestedRates;
|
||||||
|
export function fiatRequestedRates(): interfaces.FiatRequestedRatesAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.RATES_FIAT_REQUESTED
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TFiatSucceededRates = typeof fiatSucceededRates;
|
||||||
|
export function fiatSucceededRates(payload: {
|
||||||
|
[key: string]: number;
|
||||||
|
}): interfaces.FiatSucceededRatesAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.RATES_FIAT_SUCCEEDED,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
export interface FiatRequestedRatesAction {
|
||||||
|
type: TypeKeys.RATES_FIAT_REQUESTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Set rates ***/
|
||||||
|
export interface FiatSucceededRatesAction {
|
||||||
|
type: TypeKeys.RATES_FIAT_SUCCEEDED;
|
||||||
|
payload: { [key: string]: number };
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Union Type ***/
|
||||||
|
export type RatesAction = FiatSucceededRatesAction | FiatRequestedRatesAction;
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
RATES_FIAT_REQUESTED = 'RATES_FIAT_REQUESTED',
|
||||||
|
RATES_FIAT_SUCCEEDED = 'RATES_FIAT_SUCCEEDED'
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './actionCreators';
|
||||||
|
export * from './actionTypes';
|
|
@ -1,169 +0,0 @@
|
||||||
// @flow
|
|
||||||
import type {
|
|
||||||
OriginKindSwapAction,
|
|
||||||
DestinationKindSwapAction,
|
|
||||||
OriginAmountSwapAction,
|
|
||||||
DestinationAmountSwapAction,
|
|
||||||
LoadBityRatesSucceededSwapAction,
|
|
||||||
DestinationAddressSwapAction,
|
|
||||||
BityOrderCreateSucceededSwapAction,
|
|
||||||
BityOrderCreateRequestedSwapAction,
|
|
||||||
OrderStatusSucceededSwapAction,
|
|
||||||
ChangeStepSwapAction,
|
|
||||||
Pairs,
|
|
||||||
RestartSwapAction,
|
|
||||||
LoadBityRatesRequestedSwapAction,
|
|
||||||
StopLoadBityRatesSwapAction,
|
|
||||||
BityOrderResponse,
|
|
||||||
BityOrderPostResponse,
|
|
||||||
OrderStatusRequestedSwapAction,
|
|
||||||
StopOrderTimerSwapAction,
|
|
||||||
StartOrderTimerSwapAction,
|
|
||||||
StartPollBityOrderStatusAction,
|
|
||||||
StopPollBityOrderStatusAction
|
|
||||||
} from './swapTypes';
|
|
||||||
|
|
||||||
export function changeStepSwap(value: number): ChangeStepSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_STEP',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function originKindSwap(value: string): OriginKindSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_ORIGIN_KIND',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function destinationKindSwap(value: string): DestinationKindSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_DESTINATION_KIND',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function originAmountSwap(value: ?number): OriginAmountSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_ORIGIN_AMOUNT',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function destinationAmountSwap(
|
|
||||||
value: ?number
|
|
||||||
): DestinationAmountSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_DESTINATION_AMOUNT',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadBityRatesSucceededSwap(
|
|
||||||
value: Pairs
|
|
||||||
): LoadBityRatesSucceededSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_LOAD_BITY_RATES_SUCCEEDED',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function destinationAddressSwap(
|
|
||||||
value: ?string
|
|
||||||
): DestinationAddressSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_DESTINATION_ADDRESS',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function restartSwap(): RestartSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_RESTART'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadBityRatesRequestedSwap(): LoadBityRatesRequestedSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_LOAD_BITY_RATES_REQUESTED'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopLoadBityRatesSwap(): StopLoadBityRatesSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_STOP_LOAD_BITY_RATES'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function orderTimeSwap(value: number) {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_ORDER_TIME',
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bityOrderCreateSucceededSwap(
|
|
||||||
payload: BityOrderPostResponse
|
|
||||||
): BityOrderCreateSucceededSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_BITY_ORDER_CREATE_SUCCEEDED',
|
|
||||||
payload
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bityOrderCreateRequestedSwap(
|
|
||||||
amount: number,
|
|
||||||
destinationAddress: string,
|
|
||||||
pair: string,
|
|
||||||
mode: number = 0
|
|
||||||
): BityOrderCreateRequestedSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_ORDER_CREATE_REQUESTED',
|
|
||||||
payload: {
|
|
||||||
amount,
|
|
||||||
destinationAddress,
|
|
||||||
pair,
|
|
||||||
mode
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function orderStatusSucceededSwap(
|
|
||||||
payload: BityOrderResponse
|
|
||||||
): OrderStatusSucceededSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_BITY_ORDER_STATUS_SUCCEEDED',
|
|
||||||
payload
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function orderStatusRequestedSwap(): OrderStatusRequestedSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_BITY_ORDER_STATUS_REQUESTED'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function startOrderTimerSwap(): StartOrderTimerSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_ORDER_START_TIMER'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopOrderTimerSwap(): StopOrderTimerSwapAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_ORDER_STOP_TIMER'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function startPollBityOrderStatus(): StartPollBityOrderStatusAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_START_POLL_BITY_ORDER_STATUS'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopPollBityOrderStatus(): StopPollBityOrderStatusAction {
|
|
||||||
return {
|
|
||||||
type: 'SWAP_STOP_POLL_BITY_ORDER_STATUS'
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
import * as interfaces from './actionTypes';
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
|
||||||
|
export type TChangeStepSwap = typeof changeStepSwap;
|
||||||
|
export function changeStepSwap(
|
||||||
|
payload: number
|
||||||
|
): interfaces.ChangeStepSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_STEP,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TOriginKindSwap = typeof originKindSwap;
|
||||||
|
export function originKindSwap(
|
||||||
|
payload: string
|
||||||
|
): interfaces.OriginKindSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_ORIGIN_KIND,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TDestinationKindSwap = typeof destinationKindSwap;
|
||||||
|
export function destinationKindSwap(
|
||||||
|
payload: string
|
||||||
|
): interfaces.DestinationKindSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_DESTINATION_KIND,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TOriginAmountSwap = typeof originAmountSwap;
|
||||||
|
export function originAmountSwap(
|
||||||
|
payload?: number | null
|
||||||
|
): interfaces.OriginAmountSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_ORIGIN_AMOUNT,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TDestinationAmountSwap = typeof destinationAmountSwap;
|
||||||
|
export function destinationAmountSwap(
|
||||||
|
payload?: number | null
|
||||||
|
): interfaces.DestinationAmountSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_DESTINATION_AMOUNT,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TLoadBityRatesSucceededSwap = typeof loadBityRatesSucceededSwap;
|
||||||
|
export function loadBityRatesSucceededSwap(
|
||||||
|
payload: interfaces.Pairs
|
||||||
|
): interfaces.LoadBityRatesSucceededSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_LOAD_BITY_RATES_SUCCEEDED,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TDestinationAddressSwap = typeof destinationAddressSwap;
|
||||||
|
export function destinationAddressSwap(
|
||||||
|
payload?: string
|
||||||
|
): interfaces.DestinationAddressSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_DESTINATION_ADDRESS,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TRestartSwap = typeof restartSwap;
|
||||||
|
export function restartSwap(): interfaces.RestartSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_RESTART
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TLoadBityRatesRequestedSwap = typeof loadBityRatesRequestedSwap;
|
||||||
|
export function loadBityRatesRequestedSwap(): interfaces.LoadBityRatesRequestedSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_LOAD_BITY_RATES_REQUESTED
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TStopLoadBityRatesSwap = typeof stopLoadBityRatesSwap;
|
||||||
|
export function stopLoadBityRatesSwap(): interfaces.StopLoadBityRatesSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_STOP_LOAD_BITY_RATES
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TOrderTimeSwap = typeof orderTimeSwap;
|
||||||
|
export function orderTimeSwap(
|
||||||
|
payload: number
|
||||||
|
): interfaces.OrderSwapTimeSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_ORDER_TIME,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TBityOrderCreateSucceededSwap = typeof bityOrderCreateSucceededSwap;
|
||||||
|
export function bityOrderCreateSucceededSwap(
|
||||||
|
payload: interfaces.BityOrderPostResponse
|
||||||
|
): interfaces.BityOrderCreateSucceededSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_BITY_ORDER_CREATE_SUCCEEDED,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TBityOrderCreateRequestedSwap = typeof bityOrderCreateRequestedSwap;
|
||||||
|
export function bityOrderCreateRequestedSwap(
|
||||||
|
amount: number,
|
||||||
|
destinationAddress: string,
|
||||||
|
pair: string,
|
||||||
|
mode: number = 0
|
||||||
|
): interfaces.BityOrderCreateRequestedSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_ORDER_CREATE_REQUESTED,
|
||||||
|
payload: {
|
||||||
|
amount,
|
||||||
|
destinationAddress,
|
||||||
|
pair,
|
||||||
|
mode
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bityOrderCreateFailedSwap(): interfaces.BityOrderCreateFailedSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_ORDER_CREATE_FAILED
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TOrderStatusSucceededSwap = typeof orderStatusSucceededSwap;
|
||||||
|
export function orderStatusSucceededSwap(
|
||||||
|
payload: interfaces.BityOrderResponse
|
||||||
|
): interfaces.OrderStatusSucceededSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_BITY_ORDER_STATUS_SUCCEEDED,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TOrderStatusRequestedSwap = typeof orderStatusRequestedSwap;
|
||||||
|
export function orderStatusRequestedSwap(): interfaces.OrderStatusRequestedSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_BITY_ORDER_STATUS_REQUESTED
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TStartOrderTimerSwap = typeof startOrderTimerSwap;
|
||||||
|
export function startOrderTimerSwap(): interfaces.StartOrderTimerSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_ORDER_START_TIMER
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TStopOrderTimerSwap = typeof stopOrderTimerSwap;
|
||||||
|
export function stopOrderTimerSwap(): interfaces.StopOrderTimerSwapAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_ORDER_STOP_TIMER
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TStartPollBityOrderStatus = typeof startPollBityOrderStatus;
|
||||||
|
export function startPollBityOrderStatus(): interfaces.StartPollBityOrderStatusAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_START_POLL_BITY_ORDER_STATUS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TStopPollBityOrderStatus = typeof stopPollBityOrderStatus;
|
||||||
|
export function stopPollBityOrderStatus(): interfaces.StopPollBityOrderStatusAction {
|
||||||
|
return {
|
||||||
|
type: TypeKeys.SWAP_STOP_POLL_BITY_ORDER_STATUS
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
import { TypeKeys } from './constants';
|
||||||
|
export interface Pairs {
|
||||||
|
ETHBTC: number;
|
||||||
|
ETHREP: number;
|
||||||
|
BTCETH: number;
|
||||||
|
BTCREP: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OriginKindSwapAction {
|
||||||
|
type: TypeKeys.SWAP_ORIGIN_KIND;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DestinationKindSwapAction {
|
||||||
|
type: TypeKeys.SWAP_DESTINATION_KIND;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OriginAmountSwapAction {
|
||||||
|
type: TypeKeys.SWAP_ORIGIN_AMOUNT;
|
||||||
|
payload?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DestinationAmountSwapAction {
|
||||||
|
type: TypeKeys.SWAP_DESTINATION_AMOUNT;
|
||||||
|
payload?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoadBityRatesSucceededSwapAction {
|
||||||
|
type: TypeKeys.SWAP_LOAD_BITY_RATES_SUCCEEDED;
|
||||||
|
payload: Pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DestinationAddressSwapAction {
|
||||||
|
type: TypeKeys.SWAP_DESTINATION_ADDRESS;
|
||||||
|
payload?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RestartSwapAction {
|
||||||
|
type: TypeKeys.SWAP_RESTART;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoadBityRatesRequestedSwapAction {
|
||||||
|
type: TypeKeys.SWAP_LOAD_BITY_RATES_REQUESTED;
|
||||||
|
payload?: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChangeStepSwapAction {
|
||||||
|
type: TypeKeys.SWAP_STEP;
|
||||||
|
payload: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StopLoadBityRatesSwapAction {
|
||||||
|
type: TypeKeys.SWAP_STOP_LOAD_BITY_RATES;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderSwapTimeSwapAction {
|
||||||
|
type: TypeKeys.SWAP_ORDER_TIME;
|
||||||
|
payload: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BityOrderCreateRequestedSwapAction {
|
||||||
|
type: TypeKeys.SWAP_ORDER_CREATE_REQUESTED;
|
||||||
|
payload: {
|
||||||
|
amount: number;
|
||||||
|
destinationAddress: string;
|
||||||
|
pair: string;
|
||||||
|
mode: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BityOrderInput {
|
||||||
|
amount: string;
|
||||||
|
currency: string;
|
||||||
|
reference: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BityOrderOutput {
|
||||||
|
amount: string;
|
||||||
|
currency: string;
|
||||||
|
reference: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BityOrderResponse {
|
||||||
|
input: BityOrderInput;
|
||||||
|
output: BityOrderOutput;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BityOrderPostResponse = BityOrderResponse & {
|
||||||
|
payment_address: string;
|
||||||
|
status: string;
|
||||||
|
input: BityOrderInput;
|
||||||
|
output: BityOrderOutput;
|
||||||
|
timestamp_created: string;
|
||||||
|
validFor: number;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface BityOrderCreateSucceededSwapAction {
|
||||||
|
type: TypeKeys.SWAP_BITY_ORDER_CREATE_SUCCEEDED;
|
||||||
|
payload: BityOrderPostResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BityOrderCreateFailedSwapAction {
|
||||||
|
type: TypeKeys.SWAP_ORDER_CREATE_FAILED;
|
||||||
|
}
|
||||||
|
export interface OrderStatusRequestedSwapAction {
|
||||||
|
type: TypeKeys.SWAP_BITY_ORDER_STATUS_REQUESTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderStatusSucceededSwapAction {
|
||||||
|
type: TypeKeys.SWAP_BITY_ORDER_STATUS_SUCCEEDED;
|
||||||
|
payload: BityOrderResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StartOrderTimerSwapAction {
|
||||||
|
type: TypeKeys.SWAP_ORDER_START_TIMER;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StopOrderTimerSwapAction {
|
||||||
|
type: TypeKeys.SWAP_ORDER_STOP_TIMER;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StartPollBityOrderStatusAction {
|
||||||
|
type: TypeKeys.SWAP_START_POLL_BITY_ORDER_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StopPollBityOrderStatusAction {
|
||||||
|
type: TypeKeys.SWAP_STOP_POLL_BITY_ORDER_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Action Type Union ***/
|
||||||
|
export type SwapAction =
|
||||||
|
| ChangeStepSwapAction
|
||||||
|
| OriginKindSwapAction
|
||||||
|
| DestinationKindSwapAction
|
||||||
|
| OriginAmountSwapAction
|
||||||
|
| DestinationAmountSwapAction
|
||||||
|
| LoadBityRatesSucceededSwapAction
|
||||||
|
| DestinationAddressSwapAction
|
||||||
|
| RestartSwapAction
|
||||||
|
| LoadBityRatesRequestedSwapAction
|
||||||
|
| StopLoadBityRatesSwapAction
|
||||||
|
| BityOrderCreateRequestedSwapAction
|
||||||
|
| BityOrderCreateSucceededSwapAction
|
||||||
|
| OrderStatusSucceededSwapAction
|
||||||
|
| StartPollBityOrderStatusAction
|
||||||
|
| BityOrderCreateFailedSwapAction
|
||||||
|
| OrderSwapTimeSwapAction;
|
|
@ -0,0 +1,22 @@
|
||||||
|
export enum TypeKeys {
|
||||||
|
SWAP_STEP = 'SWAP_STEP',
|
||||||
|
SWAP_ORIGIN_KIND = 'SWAP_ORIGIN_KIND',
|
||||||
|
SWAP_DESTINATION_KIND = 'SWAP_DESTINATION_KIND',
|
||||||
|
SWAP_ORIGIN_AMOUNT = 'SWAP_ORIGIN_AMOUNT',
|
||||||
|
SWAP_DESTINATION_AMOUNT = 'SWAP_DESTINATION_AMOUNT',
|
||||||
|
SWAP_LOAD_BITY_RATES_SUCCEEDED = 'SWAP_LOAD_BITY_RATES_SUCCEEDED',
|
||||||
|
SWAP_DESTINATION_ADDRESS = 'SWAP_DESTINATION_ADDRESS',
|
||||||
|
SWAP_RESTART = 'SWAP_RESTART',
|
||||||
|
SWAP_LOAD_BITY_RATES_REQUESTED = 'SWAP_LOAD_BITY_RATES_REQUESTED',
|
||||||
|
SWAP_STOP_LOAD_BITY_RATES = 'SWAP_STOP_LOAD_BITY_RATES',
|
||||||
|
SWAP_ORDER_TIME = 'SWAP_ORDER_TIME',
|
||||||
|
SWAP_BITY_ORDER_CREATE_SUCCEEDED = 'SWAP_BITY_ORDER_CREATE_SUCCEEDED',
|
||||||
|
SWAP_BITY_ORDER_STATUS_SUCCEEDED = 'SWAP_BITY_ORDER_STATUS_SUCCEEDED',
|
||||||
|
SWAP_BITY_ORDER_STATUS_REQUESTED = 'SWAP_BITY_ORDER_STATUS_REQUESTED',
|
||||||
|
SWAP_ORDER_START_TIMER = 'SWAP_ORDER_START_TIMER',
|
||||||
|
SWAP_ORDER_STOP_TIMER = 'SWAP_ORDER_STOP_TIMER',
|
||||||
|
SWAP_START_POLL_BITY_ORDER_STATUS = 'SWAP_START_POLL_BITY_ORDER_STATUS',
|
||||||
|
SWAP_STOP_POLL_BITY_ORDER_STATUS = 'SWAP_STOP_POLL_BITY_ORDER_STATUS',
|
||||||
|
SWAP_ORDER_CREATE_REQUESTED = 'SWAP_ORDER_CREATE_REQUESTED',
|
||||||
|
SWAP_ORDER_CREATE_FAILED = 'SWAP_ORDER_CREATE_FAILED'
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './actionCreators';
|
|
@ -1,128 +0,0 @@
|
||||||
export type Pairs = {
|
|
||||||
ETHBTC: number,
|
|
||||||
ETHREP: number,
|
|
||||||
BTCETH: number,
|
|
||||||
BTCREP: number
|
|
||||||
};
|
|
||||||
|
|
||||||
export type OriginKindSwapAction = {
|
|
||||||
type: 'SWAP_ORIGIN_KIND',
|
|
||||||
value: string
|
|
||||||
};
|
|
||||||
export type DestinationKindSwapAction = {
|
|
||||||
type: 'SWAP_DESTINATION_KIND',
|
|
||||||
value: string
|
|
||||||
};
|
|
||||||
export type OriginAmountSwapAction = {
|
|
||||||
type: 'SWAP_ORIGIN_AMOUNT',
|
|
||||||
value: ?number
|
|
||||||
};
|
|
||||||
export type DestinationAmountSwapAction = {
|
|
||||||
type: 'SWAP_DESTINATION_AMOUNT',
|
|
||||||
value: ?number
|
|
||||||
};
|
|
||||||
export type LoadBityRatesSucceededSwapAction = {
|
|
||||||
type: 'SWAP_LOAD_BITY_RATES_SUCCEEDED',
|
|
||||||
value: Pairs
|
|
||||||
};
|
|
||||||
export type DestinationAddressSwapAction = {
|
|
||||||
type: 'SWAP_DESTINATION_ADDRESS',
|
|
||||||
value: ?number
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RestartSwapAction = {
|
|
||||||
type: 'SWAP_RESTART'
|
|
||||||
};
|
|
||||||
|
|
||||||
export type LoadBityRatesRequestedSwapAction = {
|
|
||||||
type: 'SWAP_LOAD_BITY_RATES_REQUESTED'
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ChangeStepSwapAction = {
|
|
||||||
type: 'SWAP_STEP',
|
|
||||||
value: number
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StopLoadBityRatesSwapAction = {
|
|
||||||
type: 'SWAP_STOP_LOAD_BITY_RATES'
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BityOrderCreateRequestedSwapAction = {
|
|
||||||
type: 'SWAP_ORDER_CREATE_REQUESTED',
|
|
||||||
payload: {
|
|
||||||
amount: number,
|
|
||||||
destinationAddress: string,
|
|
||||||
pair: string,
|
|
||||||
mode: number
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
type BityOrderInput = {
|
|
||||||
amount: string
|
|
||||||
};
|
|
||||||
|
|
||||||
type BityOrderOutput = {
|
|
||||||
amount: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BityOrderResponse = {
|
|
||||||
status: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BityOrderPostResponse = BityOrderResponse & {
|
|
||||||
payment_address: string,
|
|
||||||
status: string,
|
|
||||||
input: BityOrderInput,
|
|
||||||
output: BityOrderOutput,
|
|
||||||
timestamp_created: string,
|
|
||||||
validFor: number
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BityOrderCreateSucceededSwapAction = {
|
|
||||||
type: 'SWAP_BITY_ORDER_CREATE_SUCCEEDED',
|
|
||||||
payload: BityOrderPostResponse
|
|
||||||
};
|
|
||||||
|
|
||||||
export type OrderStatusRequestedSwapAction = {
|
|
||||||
type: 'SWAP_BITY_ORDER_STATUS_REQUESTED',
|
|
||||||
payload: BityOrderResponse
|
|
||||||
};
|
|
||||||
|
|
||||||
export type OrderStatusSucceededSwapAction = {
|
|
||||||
type: 'SWAP_BITY_ORDER_STATUS_SUCCEEDED',
|
|
||||||
payload: BityOrderResponse
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StartOrderTimerSwapAction = {
|
|
||||||
type: 'SWAP_ORDER_START_TIMER'
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StopOrderTimerSwapAction = {
|
|
||||||
type: 'SWAP_ORDER_STOP_TIMER'
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StartPollBityOrderStatusAction = {
|
|
||||||
type: 'SWAP_START_POLL_BITY_ORDER_STATUS'
|
|
||||||
};
|
|
||||||
|
|
||||||
export type StopPollBityOrderStatusAction = {
|
|
||||||
type: 'SWAP_STOP_POLL_BITY_ORDER_STATUS'
|
|
||||||
};
|
|
||||||
|
|
||||||
/*** Action Type Union ***/
|
|
||||||
export type SwapAction =
|
|
||||||
| ChangeStepSwapAction
|
|
||||||
| OriginKindSwapAction
|
|
||||||
| DestinationKindSwapAction
|
|
||||||
| OriginAmountSwapAction
|
|
||||||
| DestinationAmountSwapAction
|
|
||||||
| LoadBityRatesSucceededSwapAction
|
|
||||||
| DestinationAddressSwapAction
|
|
||||||
| RestartSwapAction
|
|
||||||
| LoadBityRatesRequestedSwapAction
|
|
||||||
| StopLoadBityRatesSwapAction
|
|
||||||
| BityOrderCreateRequestedSwapAction
|
|
||||||
| BityOrderCreateSucceededSwapAction
|
|
||||||
| BityOrderResponse
|
|
||||||
| OrderStatusSucceededSwapAction
|
|
||||||
| StartPollBityOrderStatusAction;
|
|
|
@ -1,134 +0,0 @@
|
||||||
// @flow
|
|
||||||
import type { IWallet } from 'libs/wallet/IWallet';
|
|
||||||
import Big from 'bignumber.js';
|
|
||||||
import { Wei } from 'libs/units';
|
|
||||||
|
|
||||||
/*** Unlock Private Key ***/
|
|
||||||
export type PrivateKeyUnlockParams = {
|
|
||||||
key: string,
|
|
||||||
password: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UnlockPrivateKeyAction = {
|
|
||||||
type: 'WALLET_UNLOCK_PRIVATE_KEY',
|
|
||||||
payload: PrivateKeyUnlockParams
|
|
||||||
};
|
|
||||||
|
|
||||||
export function unlockPrivateKey(
|
|
||||||
value: PrivateKeyUnlockParams
|
|
||||||
): UnlockPrivateKeyAction {
|
|
||||||
return {
|
|
||||||
type: 'WALLET_UNLOCK_PRIVATE_KEY',
|
|
||||||
payload: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Unlock Keystore File ***/
|
|
||||||
export type KeystoreUnlockParams = {
|
|
||||||
file: string,
|
|
||||||
password: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UnlockKeystoreAction = {
|
|
||||||
type: 'WALLET_UNLOCK_KEYSTORE',
|
|
||||||
payload: KeystoreUnlockParams
|
|
||||||
};
|
|
||||||
|
|
||||||
export function unlockKeystore(
|
|
||||||
value: KeystoreUnlockParams
|
|
||||||
): UnlockKeystoreAction {
|
|
||||||
return {
|
|
||||||
type: 'WALLET_UNLOCK_KEYSTORE',
|
|
||||||
payload: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Unlock Mnemonic ***/
|
|
||||||
export type MnemonicUnlockParams = {
|
|
||||||
phrase: string,
|
|
||||||
pass: string,
|
|
||||||
path: string,
|
|
||||||
address: string
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UnlockMnemonicAction = {
|
|
||||||
type: 'WALLET_UNLOCK_MNEMONIC',
|
|
||||||
payload: MnemonicUnlockParams
|
|
||||||
};
|
|
||||||
|
|
||||||
export function unlockMnemonic(
|
|
||||||
value: MnemonicUnlockParams
|
|
||||||
): UnlockMnemonicAction {
|
|
||||||
return {
|
|
||||||
type: 'WALLET_UNLOCK_MNEMONIC',
|
|
||||||
payload: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Set Wallet ***/
|
|
||||||
export type SetWalletAction = {
|
|
||||||
type: 'WALLET_SET',
|
|
||||||
payload: IWallet
|
|
||||||
};
|
|
||||||
|
|
||||||
export function setWallet(value: IWallet): SetWalletAction {
|
|
||||||
return {
|
|
||||||
type: 'WALLET_SET',
|
|
||||||
payload: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Set Balance ***/
|
|
||||||
export type SetBalanceAction = {
|
|
||||||
type: 'WALLET_SET_BALANCE',
|
|
||||||
payload: Wei
|
|
||||||
};
|
|
||||||
|
|
||||||
export function setBalance(value: Wei): SetBalanceAction {
|
|
||||||
return {
|
|
||||||
type: 'WALLET_SET_BALANCE',
|
|
||||||
payload: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Set Token Balance ***/
|
|
||||||
export type SetTokenBalancesAction = {
|
|
||||||
type: 'WALLET_SET_TOKEN_BALANCES',
|
|
||||||
payload: {
|
|
||||||
[string]: Big
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export function setTokenBalances(payload: {
|
|
||||||
[string]: Big
|
|
||||||
}): SetTokenBalancesAction {
|
|
||||||
return {
|
|
||||||
type: 'WALLET_SET_TOKEN_BALANCES',
|
|
||||||
payload
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Broadcast Tx ***/
|
|
||||||
export type BroadcastTxRequestedAction = {
|
|
||||||
type: 'WALLET_BROADCAST_TX_REQUESTED',
|
|
||||||
payload: {
|
|
||||||
signedTx: string
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export function broadcastTx(signedTx: string): BroadcastTxRequestedAction {
|
|
||||||
return {
|
|
||||||
type: 'WALLET_BROADCAST_TX_REQUESTED',
|
|
||||||
payload: {
|
|
||||||
signedTx
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Union Type ***/
|
|
||||||
export type WalletAction =
|
|
||||||
| UnlockPrivateKeyAction
|
|
||||||
| SetWalletAction
|
|
||||||
| SetBalanceAction
|
|
||||||
| SetTokenBalancesAction
|
|
||||||
| BroadcastTxRequestedAction;
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
import { BigNumber } from 'bignumber.js';
|
||||||
|
import { Wei } from 'libs/units';
|
||||||
|
import { IWallet } from 'libs/wallet/IWallet';
|
||||||
|
import * as types from './actionTypes';
|
||||||
|
import * as constants from './constants';
|
||||||
|
|
||||||
|
export type TUnlockPrivateKey = typeof unlockPrivateKey;
|
||||||
|
export function unlockPrivateKey(
|
||||||
|
value: types.PrivateKeyUnlockParams
|
||||||
|
): types.UnlockPrivateKeyAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_UNLOCK_PRIVATE_KEY,
|
||||||
|
payload: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TUnlockKeystore = typeof unlockKeystore;
|
||||||
|
export function unlockKeystore(
|
||||||
|
value: types.KeystoreUnlockParams
|
||||||
|
): types.UnlockKeystoreAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_UNLOCK_KEYSTORE,
|
||||||
|
payload: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TUnlockMnemonic = typeof unlockMnemonic;
|
||||||
|
export function unlockMnemonic(
|
||||||
|
value: types.MnemonicUnlockParams
|
||||||
|
): types.UnlockMnemonicAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_UNLOCK_MNEMONIC,
|
||||||
|
payload: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TSetWallet = typeof setWallet;
|
||||||
|
export function setWallet(value: IWallet): types.SetWalletAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_SET,
|
||||||
|
payload: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TSetBalance = typeof setBalance;
|
||||||
|
export function setBalance(value: Wei): types.SetBalanceAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_SET_BALANCE,
|
||||||
|
payload: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TSetTokenBalances = typeof setTokenBalances;
|
||||||
|
export function setTokenBalances(payload: {
|
||||||
|
[key: string]: BigNumber;
|
||||||
|
}): types.SetTokenBalancesAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_SET_TOKEN_BALANCES,
|
||||||
|
payload
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TBroadcastTx = typeof broadcastTx;
|
||||||
|
export function broadcastTx(
|
||||||
|
signedTx: string
|
||||||
|
): types.BroadcastTxRequestedAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_BROADCAST_TX_REQUESTED,
|
||||||
|
payload: {
|
||||||
|
signedTx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TBroadcastTxSucceded = typeof broadcastTxSucceded;
|
||||||
|
export function broadcastTxSucceded(
|
||||||
|
txHash: string,
|
||||||
|
signedTx: string
|
||||||
|
): types.BroadcastTxSuccededAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_BROADCAST_TX_SUCCEEDED,
|
||||||
|
payload: {
|
||||||
|
txHash,
|
||||||
|
signedTx
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TBroadCastTxFailed = typeof broadCastTxFailed;
|
||||||
|
export function broadCastTxFailed(
|
||||||
|
signedTx: string,
|
||||||
|
errorMsg: string
|
||||||
|
): types.BroadcastTxFailedAction {
|
||||||
|
return {
|
||||||
|
type: constants.WALLET_BROADCAST_TX_FAILED,
|
||||||
|
payload: {
|
||||||
|
signedTx,
|
||||||
|
error: errorMsg
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { BigNumber } from 'bignumber.js';
|
||||||
|
import { Wei } from 'libs/units';
|
||||||
|
import { IWallet } from 'libs/wallet/IWallet';
|
||||||
|
|
||||||
|
/*** Unlock Private Key ***/
|
||||||
|
export interface PrivateKeyUnlockParams {
|
||||||
|
key: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UnlockPrivateKeyAction {
|
||||||
|
type: 'WALLET_UNLOCK_PRIVATE_KEY';
|
||||||
|
payload: PrivateKeyUnlockParams;
|
||||||
|
}
|
||||||
|
export interface UnlockMnemonicAction {
|
||||||
|
type: 'WALLET_UNLOCK_MNEMONIC';
|
||||||
|
payload: MnemonicUnlockParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Set Wallet ***/
|
||||||
|
export interface SetWalletAction {
|
||||||
|
type: 'WALLET_SET';
|
||||||
|
payload: IWallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Set Balance ***/
|
||||||
|
export interface SetBalanceAction {
|
||||||
|
type: 'WALLET_SET_BALANCE';
|
||||||
|
payload: Wei;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Set Token Balance ***/
|
||||||
|
export interface SetTokenBalancesAction {
|
||||||
|
type: 'WALLET_SET_TOKEN_BALANCES';
|
||||||
|
payload: {
|
||||||
|
[key: string]: BigNumber;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Broadcast Tx ***/
|
||||||
|
export interface BroadcastTxRequestedAction {
|
||||||
|
type: 'WALLET_BROADCAST_TX_REQUESTED';
|
||||||
|
payload: {
|
||||||
|
signedTx: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Unlock Mnemonic ***/
|
||||||
|
export interface MnemonicUnlockParams {
|
||||||
|
phrase: string;
|
||||||
|
pass: string;
|
||||||
|
path: string;
|
||||||
|
address: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Unlock Keystore File ***/
|
||||||
|
export interface KeystoreUnlockParams {
|
||||||
|
file: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UnlockKeystoreAction {
|
||||||
|
type: 'WALLET_UNLOCK_KEYSTORE';
|
||||||
|
payload: KeystoreUnlockParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BroadcastTxSuccededAction {
|
||||||
|
type: 'WALLET_BROADCAST_TX_SUCCEEDED';
|
||||||
|
payload: {
|
||||||
|
txHash: string;
|
||||||
|
signedTx: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BroadcastTxFailedAction {
|
||||||
|
type: 'WALLET_BROADCAST_TX_FAILED';
|
||||||
|
payload: {
|
||||||
|
signedTx: string;
|
||||||
|
error: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Union Type ***/
|
||||||
|
export type WalletAction =
|
||||||
|
| UnlockPrivateKeyAction
|
||||||
|
| SetWalletAction
|
||||||
|
| SetBalanceAction
|
||||||
|
| SetTokenBalancesAction
|
||||||
|
| BroadcastTxRequestedAction
|
||||||
|
| BroadcastTxFailedAction
|
||||||
|
| BroadcastTxSuccededAction;
|
|
@ -0,0 +1,9 @@
|
||||||
|
export const WALLET_UNLOCK_PRIVATE_KEY = 'WALLET_UNLOCK_PRIVATE_KEY';
|
||||||
|
export const WALLET_UNLOCK_KEYSTORE = 'WALLET_UNLOCK_KEYSTORE';
|
||||||
|
export const WALLET_UNLOCK_MNEMONIC = 'WALLET_UNLOCK_MNEMONIC';
|
||||||
|
export const WALLET_SET = 'WALLET_SET';
|
||||||
|
export const WALLET_SET_BALANCE = 'WALLET_SET_BALANCE';
|
||||||
|
export const WALLET_SET_TOKEN_BALANCES = 'WALLET_SET_TOKEN_BALANCES';
|
||||||
|
export const WALLET_BROADCAST_TX_REQUESTED = 'WALLET_BROADCAST_TX_REQUESTED';
|
||||||
|
export const WALLET_BROADCAST_TX_FAILED = 'WALLET_BROADCAST_TX_FAILED';
|
||||||
|
export const WALLET_BROADCAST_TX_SUCCEEDED = 'WALLET_BROADCAST_TX_SUCCEEDED';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './constants';
|
||||||
|
export * from './actionTypes';
|
||||||
|
export * from './actionCreators';
|
|
@ -1,22 +1,10 @@
|
||||||
// @flow
|
|
||||||
import bityConfig from 'config/bity';
|
import bityConfig from 'config/bity';
|
||||||
import { checkHttpStatus, parseJSON } from './utils';
|
import { checkHttpStatus, parseJSON } from './utils';
|
||||||
// import { combineAndUpper } from 'utils/formatters';
|
|
||||||
|
|
||||||
// function findRateFromBityRateList(rateObjects, pairName: string) {
|
|
||||||
// return rateObjects.find(x => x.pair === pairName);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function _getRate(bityRates, originKind: string, destinationKind: string) {
|
|
||||||
// const pairName = combineAndUpper(originKind, destinationKind);
|
|
||||||
// const rateObjects = bityRates.objects;
|
|
||||||
// return findRateFromBityRateList(rateObjects, pairName);
|
|
||||||
// }
|
|
||||||
|
|
||||||
export function getAllRates() {
|
export function getAllRates() {
|
||||||
const mappedRates = {};
|
const mappedRates = {};
|
||||||
return _getAllRates().then(bityRates => {
|
return _getAllRates().then((bityRates) => {
|
||||||
bityRates.objects.forEach(each => {
|
bityRates.objects.forEach((each) => {
|
||||||
const pairName = each.pair;
|
const pairName = each.pair;
|
||||||
mappedRates[pairName] = parseFloat(each.rate_we_sell);
|
mappedRates[pairName] = parseFloat(each.rate_we_sell);
|
||||||
});
|
});
|
||||||
|
@ -44,11 +32,11 @@ export function postOrder(
|
||||||
.then(parseJSON);
|
.then(parseJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOrderStatus(orderid: string) {
|
export function getOrderStatus(orderId: string) {
|
||||||
return fetch(`${bityConfig.serverURL}/status`, {
|
return fetch(`${bityConfig.serverURL}/status`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
orderid
|
orderid: orderId
|
||||||
}),
|
}),
|
||||||
headers: bityConfig.postConfig.headers
|
headers: bityConfig.postConfig.headers
|
||||||
})
|
})
|
||||||
|
@ -61,5 +49,3 @@ function _getAllRates() {
|
||||||
.then(checkHttpStatus)
|
.then(checkHttpStatus)
|
||||||
.then(parseJSON);
|
.then(parseJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function requestOrderStatus() {}
|
|
|
@ -2,8 +2,9 @@ export function checkHttpStatus(response) {
|
||||||
if (response.status >= 200 && response.status < 300) {
|
if (response.status >= 200 && response.status < 300) {
|
||||||
return response;
|
return response;
|
||||||
} else {
|
} else {
|
||||||
let error = new Error(response.statusText);
|
const error = new Error(response.statusText);
|
||||||
error.response = response;
|
// TODO: why assign response?
|
||||||
|
// error.response = response;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,35 +3,17 @@ import './index.scss';
|
||||||
|
|
||||||
const LS_KEY = 'acknowledged-alpha';
|
const LS_KEY = 'acknowledged-alpha';
|
||||||
|
|
||||||
export default class AlphaAgreement extends React.Component {
|
interface State {
|
||||||
state = {
|
isFading: boolean;
|
||||||
isFading: false,
|
hasAcknowledged: boolean;
|
||||||
hasAcknowledged: false
|
}
|
||||||
|
export default class AlphaAgreement extends React.Component<{}, State> {
|
||||||
|
public state = {
|
||||||
|
hasAcknowledged: !!localStorage.getItem(LS_KEY),
|
||||||
|
isFading: false
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
public render() {
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
hasAcknowledged: localStorage.getItem(LS_KEY),
|
|
||||||
isFading: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_continue = () => {
|
|
||||||
localStorage.setItem(LS_KEY, true);
|
|
||||||
this.setState({ isFading: true });
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({ hasAcknowledged: true });
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
_reject = () => {
|
|
||||||
window.location = 'https://myetherwallet.com';
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.state.hasAcknowledged) {
|
if (this.state.hasAcknowledged) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -58,13 +40,13 @@ export default class AlphaAgreement extends React.Component {
|
||||||
<div className="AlphaAgreement-content-buttons">
|
<div className="AlphaAgreement-content-buttons">
|
||||||
<button
|
<button
|
||||||
className="AlphaAgreement-content-buttons-btn is-reject"
|
className="AlphaAgreement-content-buttons-btn is-reject"
|
||||||
onClick={this._reject}
|
onClick={this.reject}
|
||||||
>
|
>
|
||||||
No, Take Me to v3
|
No, Take Me to v3
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="AlphaAgreement-content-buttons-btn is-continue"
|
className="AlphaAgreement-content-buttons-btn is-continue"
|
||||||
onClick={this._continue}
|
onClick={this.doContinue}
|
||||||
>
|
>
|
||||||
Yes, Continue to v4
|
Yes, Continue to v4
|
||||||
</button>
|
</button>
|
||||||
|
@ -73,4 +55,17 @@ export default class AlphaAgreement extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private doContinue = () => {
|
||||||
|
localStorage.setItem(LS_KEY, 'true');
|
||||||
|
this.setState({ isFading: true });
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({ hasAcknowledged: true });
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
private reject = () => {
|
||||||
|
window.location.assign('https://myetherwallet.com');
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -1,37 +1,39 @@
|
||||||
// @flow
|
import { FiatRequestedRatesAction } from 'actions/rates';
|
||||||
import './AccountInfo.scss';
|
import { Identicon } from 'components/ui';
|
||||||
|
import { NetworkConfig } from 'config/data';
|
||||||
|
import { Ether } from 'libs/units';
|
||||||
|
import { IWallet } from 'libs/wallet';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
import { Identicon } from 'components/ui';
|
|
||||||
import { formatNumber } from 'utils/formatters';
|
import { formatNumber } from 'utils/formatters';
|
||||||
import type { IWallet } from 'libs/wallet';
|
import './AccountInfo.scss';
|
||||||
import type { NetworkConfig } from 'config/data';
|
|
||||||
import { Ether } from 'libs/units';
|
|
||||||
import type { FiatRequestedRatesAction } from 'actions/rates';
|
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
balance: Ether,
|
balance: Ether;
|
||||||
wallet: IWallet,
|
wallet: IWallet;
|
||||||
network: NetworkConfig,
|
network: NetworkConfig;
|
||||||
fiatRequestedRates: () => FiatRequestedRatesAction
|
fiatRequestedRates(): FiatRequestedRatesAction;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class AccountInfo extends React.Component {
|
interface State {
|
||||||
props: Props;
|
showLongBalance: boolean;
|
||||||
|
address: string;
|
||||||
state = {
|
}
|
||||||
|
export default class AccountInfo extends React.Component<Props, State> {
|
||||||
|
public state = {
|
||||||
showLongBalance: false,
|
showLongBalance: false,
|
||||||
address: ''
|
address: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
public componentDidMount() {
|
||||||
this.props.fiatRequestedRates();
|
this.props.fiatRequestedRates();
|
||||||
this.props.wallet.getAddress().then(addr => {
|
this.props.wallet.getAddress().then(addr => {
|
||||||
this.setState({ address: addr });
|
this.setState({ address: addr });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleShowLongBalance = (e: SyntheticMouseEvent) => {
|
// TODO: don't use any;
|
||||||
|
public toggleShowLongBalance = (e: any) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return {
|
return {
|
||||||
|
@ -40,7 +42,7 @@ export default class AccountInfo extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { network, balance } = this.props;
|
const { network, balance } = this.props;
|
||||||
const { blockExplorer, tokenExplorer } = network;
|
const { blockExplorer, tokenExplorer } = network;
|
||||||
const { address } = this.state;
|
const { address } = this.state;
|
|
@ -1,21 +1,18 @@
|
||||||
// @flow
|
import { Ether } from 'libs/units';
|
||||||
import './EquivalentValues.scss';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
import { formatNumber } from 'utils/formatters';
|
import { formatNumber } from 'utils/formatters';
|
||||||
import { Ether } from 'libs/units';
|
import './EquivalentValues.scss';
|
||||||
|
|
||||||
const ratesKeys = ['BTC', 'REP', 'EUR', 'USD', 'GBP', 'CHF'];
|
const ratesKeys = ['BTC', 'REP', 'EUR', 'USD', 'GBP', 'CHF'];
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
balance: ?Ether,
|
balance?: Ether;
|
||||||
rates: ?{ [string]: number }
|
rates?: { [key: string]: number };
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class EquivalentValues extends React.Component {
|
export default class EquivalentValues extends React.Component<Props, {}> {
|
||||||
props: Props;
|
public render() {
|
||||||
|
|
||||||
render() {
|
|
||||||
const { balance, rates } = this.props;
|
const { balance, rates } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -27,7 +24,9 @@ export default class EquivalentValues extends React.Component {
|
||||||
<ul className="EquivalentValues-values">
|
<ul className="EquivalentValues-values">
|
||||||
{rates
|
{rates
|
||||||
? ratesKeys.map(key => {
|
? ratesKeys.map(key => {
|
||||||
if (!rates[key]) return null;
|
if (!rates[key]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<li className="EquivalentValues-values-currency" key={key}>
|
<li className="EquivalentValues-values-currency" key={key}>
|
||||||
<span className="EquivalentValues-values-currency-label">
|
<span className="EquivalentValues-values-currency-label">
|
|
@ -1,14 +1,14 @@
|
||||||
// @flow
|
|
||||||
import './Promos.scss';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
|
import './Promos.scss';
|
||||||
|
|
||||||
const promos = [
|
const promos = [
|
||||||
{
|
{
|
||||||
|
isExternal: true,
|
||||||
color: '#6e9a3e',
|
color: '#6e9a3e',
|
||||||
href:
|
href:
|
||||||
'https://myetherwallet.groovehq.com/knowledge_base/topics/protecting-yourself-and-your-funds',
|
'https://myetherwallet.groovehq.com/knowledge_base/topics/protecting-yourself-and-your-funds',
|
||||||
isExternal: true,
|
|
||||||
texts: [<h6 key="1">Learn more about protecting your funds.</h6>],
|
texts: [<h6 key="1">Learn more about protecting your funds.</h6>],
|
||||||
images: [
|
images: [
|
||||||
require('assets/images/logo-ledger.svg'),
|
require('assets/images/logo-ledger.svg'),
|
||||||
|
@ -16,10 +16,10 @@ const promos = [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
isExternal: true,
|
||||||
color: '#2b71b1',
|
color: '#2b71b1',
|
||||||
href:
|
href:
|
||||||
'https://buy.coinbase.com?code=a6e1bd98-6464-5552-84dd-b27f0388ac7d&address=0xA7DeFf12461661212734dB35AdE9aE7d987D648c&crypto_currency=ETH¤cy=USD',
|
'https://buy.coinbase.com?code=a6e1bd98-6464-5552-84dd-b27f0388ac7d&address=0xA7DeFf12461661212734dB35AdE9aE7d987D648c&crypto_currency=ETH¤cy=USD',
|
||||||
isExternal: true,
|
|
||||||
texts: [
|
texts: [
|
||||||
<p key="1">It’s now easier to get more ETH</p>,
|
<p key="1">It’s now easier to get more ETH</p>,
|
||||||
<h5 key="2">Buy ETH with USD</h5>
|
<h5 key="2">Buy ETH with USD</h5>
|
||||||
|
@ -27,6 +27,7 @@ const promos = [
|
||||||
images: [require('assets/images/logo-coinbase.svg')]
|
images: [require('assets/images/logo-coinbase.svg')]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
isExternal: false,
|
||||||
color: '#006e79',
|
color: '#006e79',
|
||||||
href: '/swap',
|
href: '/swap',
|
||||||
texts: [
|
texts: [
|
||||||
|
@ -37,64 +38,60 @@ const promos = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class Promos extends React.Component {
|
interface State {
|
||||||
state: { activePromo: number };
|
activePromo: number;
|
||||||
|
}
|
||||||
|
|
||||||
state = {
|
export default class Promos extends React.Component<{}, State> {
|
||||||
activePromo: parseInt(Math.random() * promos.length)
|
public state = {
|
||||||
|
activePromo: parseInt(String(Math.random() * promos.length), 10)
|
||||||
};
|
};
|
||||||
|
|
||||||
_navigateToPromo = (idx: number) => {
|
public render() {
|
||||||
this.setState({ activePromo: Math.max(0, Math.min(promos.length, idx)) });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { activePromo } = this.state;
|
const { activePromo } = this.state;
|
||||||
const promo = promos[activePromo];
|
const promo = promos[activePromo];
|
||||||
|
|
||||||
const promoContent = (
|
const promoContent = (
|
||||||
<div className="Promos-promo-inner">
|
<div className="Promos-promo-inner">
|
||||||
<div className="Promos-promo-text">
|
<div className="Promos-promo-text">{promo.texts}</div>
|
||||||
{promo.texts}
|
|
||||||
</div>
|
|
||||||
<div className="Promos-promo-images">
|
<div className="Promos-promo-images">
|
||||||
{promo.images.map((img, idx) => <img src={img} key={idx} />)}
|
{promo.images.map((img, idx) => <img src={img} key={idx} />)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const promoEl = promo.isExternal
|
const promoEl = promo.isExternal ? (
|
||||||
? <a
|
<a
|
||||||
className="Promos-promo"
|
className="Promos-promo"
|
||||||
key={promo.href}
|
key={promo.href}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href={promo.href}
|
href={promo.href}
|
||||||
style={{ backgroundColor: promo.color }}
|
style={{ backgroundColor: promo.color }}
|
||||||
>
|
>
|
||||||
{promoContent}
|
{promoContent}
|
||||||
</a>
|
</a>
|
||||||
: <Link
|
) : (
|
||||||
className="Promos-promo"
|
<Link
|
||||||
key={promo.href}
|
className="Promos-promo"
|
||||||
to={promo.href}
|
key={promo.href}
|
||||||
style={{ backgroundColor: promo.color }}
|
to={promo.href}
|
||||||
>
|
style={{ backgroundColor: promo.color }}
|
||||||
<div className="Promos-promo-inner">
|
>
|
||||||
{promoContent}
|
<div className="Promos-promo-inner">{promoContent}</div>
|
||||||
</div>
|
</Link>
|
||||||
</Link>;
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="Promos">
|
<div className="Promos">
|
||||||
{promoEl}
|
{promoEl}
|
||||||
<div className="Promos-nav">
|
<div className="Promos-nav">
|
||||||
{promos.map((promo, idx) => {
|
{promos.map((_, index) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`Promos-nav-btn ${idx === activePromo
|
className={`Promos-nav-btn ${index === activePromo
|
||||||
? 'is-active'
|
? 'is-active'
|
||||||
: ''}`}
|
: ''}`}
|
||||||
key={idx}
|
key={index}
|
||||||
onClick={() => this._navigateToPromo(idx)}
|
onClick={this.navigateToPromo(index)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -102,4 +99,8 @@ export default class Promos extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private navigateToPromo = (idx: number) => () => {
|
||||||
|
this.setState({ activePromo: Math.max(0, Math.min(promos.length, idx)) });
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -1,20 +1,27 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { isValidETHAddress, isPositiveIntegerOrZero } from 'libs/validators';
|
import { Token } from 'config/data';
|
||||||
|
import { isPositiveIntegerOrZero, isValidETHAddress } from 'libs/validators';
|
||||||
|
import React from 'react';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
|
|
||||||
export default class AddCustomTokenForm extends React.Component {
|
interface Props {
|
||||||
props: {
|
onSave(params: Token): void;
|
||||||
onSave: ({ address: string, symbol: string, decimal: number }) => void
|
}
|
||||||
};
|
|
||||||
state = {
|
interface State {
|
||||||
|
address: string;
|
||||||
|
symbol: string;
|
||||||
|
decimal: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class AddCustomTokenForm extends React.Component<Props, State> {
|
||||||
|
public state = {
|
||||||
address: '',
|
address: '',
|
||||||
symbol: '',
|
symbol: '',
|
||||||
decimal: ''
|
decimal: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { address, symbol, decimal } = this.state;
|
const { address, symbol, decimal } = this.state;
|
||||||
const inputClasses = 'AddCustom-field-input form-control input-sm';
|
const inputClasses = 'AddCustom-field-input form-control input-sm';
|
||||||
const errors = this.getErrors();
|
const errors = this.getErrors();
|
||||||
|
@ -42,9 +49,7 @@ export default class AddCustomTokenForm extends React.Component {
|
||||||
{fields.map(field => {
|
{fields.map(field => {
|
||||||
return (
|
return (
|
||||||
<label className="AddCustom-field form-group" key={field.name}>
|
<label className="AddCustom-field form-group" key={field.name}>
|
||||||
<span className="AddCustom-field-label">
|
<span className="AddCustom-field-label">{field.label}</span>
|
||||||
{field.label}
|
|
||||||
</span>
|
|
||||||
<input
|
<input
|
||||||
className={classnames(
|
className={classnames(
|
||||||
inputClasses,
|
inputClasses,
|
||||||
|
@ -69,9 +74,13 @@ export default class AddCustomTokenForm extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getErrors() {
|
public getErrors() {
|
||||||
const { address, symbol, decimal } = this.state;
|
const { address, symbol, decimal } = this.state;
|
||||||
const errors = {};
|
const errors = {
|
||||||
|
decimal: false,
|
||||||
|
address: false,
|
||||||
|
symbol: false
|
||||||
|
};
|
||||||
|
|
||||||
if (!isPositiveIntegerOrZero(parseInt(decimal, 10))) {
|
if (!isPositiveIntegerOrZero(parseInt(decimal, 10))) {
|
||||||
errors.decimal = true;
|
errors.decimal = true;
|
||||||
|
@ -86,17 +95,18 @@ export default class AddCustomTokenForm extends React.Component {
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid() {
|
public isValid() {
|
||||||
return !Object.keys(this.getErrors()).length;
|
return !Object.keys(this.getErrors()).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
onFieldChange = (e: SyntheticInputEvent) => {
|
public onFieldChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||||
var name = e.target.name;
|
// TODO: typescript bug: https://github.com/Microsoft/TypeScript/issues/13948
|
||||||
var value = e.target.value;
|
const name: any = (e.target as HTMLInputElement).name;
|
||||||
|
const value = (e.target as HTMLInputElement).value;
|
||||||
this.setState({ [name]: value });
|
this.setState({ [name]: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
onSave = (ev: SyntheticInputEvent) => {
|
public onSave = (ev: React.SyntheticEvent<HTMLFormElement>) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (!this.isValid()) {
|
if (!this.isValid()) {
|
||||||
return;
|
return;
|
|
@ -1,22 +1,24 @@
|
||||||
// @flow
|
|
||||||
import './TokenRow.scss';
|
|
||||||
import React from 'react';
|
|
||||||
import Big from 'bignumber.js';
|
|
||||||
import { formatNumber } from 'utils/formatters';
|
|
||||||
import removeIcon from 'assets/images/icon-remove.svg';
|
import removeIcon from 'assets/images/icon-remove.svg';
|
||||||
|
import { BigNumber } from 'bignumber.js';
|
||||||
|
import React from 'react';
|
||||||
|
import { formatNumber } from 'utils/formatters';
|
||||||
|
import './TokenRow.scss';
|
||||||
|
|
||||||
export default class TokenRow extends React.Component {
|
interface Props {
|
||||||
props: {
|
balance: BigNumber;
|
||||||
balance: Big,
|
symbol: string;
|
||||||
symbol: string,
|
custom?: boolean;
|
||||||
custom?: boolean,
|
onRemove(symbol: string): void;
|
||||||
onRemove: (symbol: string) => void
|
}
|
||||||
};
|
interface State {
|
||||||
|
showLongBalance: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
state = {
|
export default class TokenRow extends React.Component<Props, State> {
|
||||||
|
public state = {
|
||||||
showLongBalance: false
|
showLongBalance: false
|
||||||
};
|
};
|
||||||
render() {
|
public render() {
|
||||||
const { balance, symbol, custom } = this.props;
|
const { balance, symbol, custom } = this.props;
|
||||||
const { showLongBalance } = this.state;
|
const { showLongBalance } = this.state;
|
||||||
return (
|
return (
|
||||||
|
@ -32,7 +34,7 @@ export default class TokenRow extends React.Component {
|
||||||
className="TokenRow-balance-remove"
|
className="TokenRow-balance-remove"
|
||||||
title="Remove Token"
|
title="Remove Token"
|
||||||
onClick={this.onRemove}
|
onClick={this.onRemove}
|
||||||
tabIndex="0"
|
tabIndex={0}
|
||||||
/>}
|
/>}
|
||||||
<span>
|
<span>
|
||||||
{showLongBalance ? balance.toString() : formatNumber(balance)}
|
{showLongBalance ? balance.toString() : formatNumber(balance)}
|
||||||
|
@ -45,7 +47,10 @@ export default class TokenRow extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleShowLongBalance = (e: SyntheticInputEvent) => {
|
public toggleShowLongBalance = (
|
||||||
|
// TODO: don't use any
|
||||||
|
e: any
|
||||||
|
) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return {
|
return {
|
||||||
|
@ -54,7 +59,7 @@ export default class TokenRow extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onRemove = () => {
|
public onRemove = () => {
|
||||||
this.props.onRemove(this.props.symbol);
|
this.props.onRemove(this.props.symbol);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,26 +1,28 @@
|
||||||
// @flow
|
import { Token } from 'config/data';
|
||||||
import './index.scss';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { TokenBalance } from 'selectors/wallet';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
import TokenRow from './TokenRow';
|
|
||||||
import AddCustomTokenForm from './AddCustomTokenForm';
|
import AddCustomTokenForm from './AddCustomTokenForm';
|
||||||
import type { TokenBalance } from 'selectors/wallet';
|
import './index.scss';
|
||||||
import type { Token } from 'config/data';
|
import TokenRow from './TokenRow';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
tokens: TokenBalance[],
|
tokens: TokenBalance[];
|
||||||
onAddCustomToken: (token: Token) => any,
|
onAddCustomToken(token: Token): any;
|
||||||
onRemoveCustomToken: (symbol: string) => any
|
onRemoveCustomToken(symbol: string): any;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class TokenBalances extends React.Component {
|
interface State {
|
||||||
props: Props;
|
showAllTokens: boolean;
|
||||||
state = {
|
showCustomTokenForm: boolean;
|
||||||
|
}
|
||||||
|
export default class TokenBalances extends React.Component<Props, State> {
|
||||||
|
public state = {
|
||||||
showAllTokens: false,
|
showAllTokens: false,
|
||||||
showCustomTokenForm: false
|
showCustomTokenForm: false
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { tokens } = this.props;
|
const { tokens } = this.props;
|
||||||
const shownTokens = tokens.filter(
|
const shownTokens = tokens.filter(
|
||||||
token => !token.balance.eq(0) || token.custom || this.state.showAllTokens
|
token => !token.balance.eq(0) || token.custom || this.state.showAllTokens
|
||||||
|
@ -70,7 +72,7 @@ export default class TokenBalances extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleShowAllTokens = () => {
|
public toggleShowAllTokens = () => {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return {
|
return {
|
||||||
showAllTokens: !state.showAllTokens
|
showAllTokens: !state.showAllTokens
|
||||||
|
@ -78,7 +80,7 @@ export default class TokenBalances extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleShowCustomTokenForm = () => {
|
public toggleShowCustomTokenForm = () => {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return {
|
return {
|
||||||
showCustomTokenForm: !state.showCustomTokenForm
|
showCustomTokenForm: !state.showCustomTokenForm
|
||||||
|
@ -86,7 +88,7 @@ export default class TokenBalances extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
addCustomToken = (token: Token) => {
|
public addCustomToken = (token: Token) => {
|
||||||
this.props.onAddCustomToken(token);
|
this.props.onAddCustomToken(token);
|
||||||
this.setState({ showCustomTokenForm: false });
|
this.setState({ showCustomTokenForm: false });
|
||||||
};
|
};
|
|
@ -1,39 +1,51 @@
|
||||||
// @flow
|
import {
|
||||||
|
addCustomToken,
|
||||||
|
removeCustomToken,
|
||||||
|
TAddCustomToken,
|
||||||
|
TRemoveCustomToken
|
||||||
|
} from 'actions/customTokens';
|
||||||
|
import { showNotification, TShowNotification } from 'actions/notifications';
|
||||||
|
import {
|
||||||
|
fiatRequestedRates as dFiatRequestedRates,
|
||||||
|
TFiatRequestedRates
|
||||||
|
} from 'actions/rates';
|
||||||
|
import { NetworkConfig } from 'config/data';
|
||||||
|
import { Ether } from 'libs/units';
|
||||||
|
import { IWallet } from 'libs/wallet/IWallet';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IWallet } from 'libs/wallet';
|
|
||||||
import type { NetworkConfig } from 'config/data';
|
|
||||||
import type { State } from 'reducers';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { getWalletInst, getTokenBalances } from 'selectors/wallet';
|
import { AppState } from 'reducers';
|
||||||
import type { TokenBalance } from 'selectors/wallet';
|
|
||||||
import { getNetworkConfig } from 'selectors/config';
|
import { getNetworkConfig } from 'selectors/config';
|
||||||
import * as customTokenActions from 'actions/customTokens';
|
import {
|
||||||
import { showNotification } from 'actions/notifications';
|
getTokenBalances,
|
||||||
import { fiatRequestedRates } from 'actions/rates';
|
getWalletInst,
|
||||||
import type { FiatRequestedRatesAction } from 'actions/rates';
|
TokenBalance
|
||||||
|
} from 'selectors/wallet';
|
||||||
import AccountInfo from './AccountInfo';
|
import AccountInfo from './AccountInfo';
|
||||||
|
import EquivalentValues from './EquivalentValues';
|
||||||
import Promos from './Promos';
|
import Promos from './Promos';
|
||||||
import TokenBalances from './TokenBalances';
|
import TokenBalances from './TokenBalances';
|
||||||
import EquivalentValues from './EquivalentValues';
|
|
||||||
import { Ether } from 'libs/units';
|
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
wallet: IWallet,
|
wallet: IWallet;
|
||||||
balance: Ether,
|
balance: Ether;
|
||||||
network: NetworkConfig,
|
network: NetworkConfig;
|
||||||
tokenBalances: TokenBalance[],
|
tokenBalances: TokenBalance[];
|
||||||
rates: { [string]: number },
|
rates: { [key: string]: number };
|
||||||
showNotification: Function,
|
showNotification: TShowNotification;
|
||||||
addCustomToken: typeof customTokenActions.addCustomToken,
|
addCustomToken: TAddCustomToken;
|
||||||
removeCustomToken: typeof customTokenActions.removeCustomToken,
|
removeCustomToken: TRemoveCustomToken;
|
||||||
fiatRequestedRates: () => FiatRequestedRatesAction
|
fiatRequestedRates: TFiatRequestedRates;
|
||||||
};
|
}
|
||||||
|
|
||||||
export class BalanceSidebar extends React.Component {
|
interface Block {
|
||||||
props: Props;
|
name: string;
|
||||||
|
content: React.ReactElement<any>;
|
||||||
|
isFullWidth?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
export class BalanceSidebar extends React.Component<Props, {}> {
|
||||||
|
public render() {
|
||||||
const {
|
const {
|
||||||
wallet,
|
wallet,
|
||||||
balance,
|
balance,
|
||||||
|
@ -46,7 +58,7 @@ export class BalanceSidebar extends React.Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blocks = [
|
const blocks: Block[] = [
|
||||||
{
|
{
|
||||||
name: 'Account Info',
|
name: 'Account Info',
|
||||||
content: (
|
content: (
|
||||||
|
@ -94,7 +106,7 @@ export class BalanceSidebar extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state: State) {
|
function mapStateToProps(state: AppState) {
|
||||||
return {
|
return {
|
||||||
wallet: getWalletInst(state),
|
wallet: getWalletInst(state),
|
||||||
balance: state.wallet.balance,
|
balance: state.wallet.balance,
|
||||||
|
@ -105,7 +117,8 @@ function mapStateToProps(state: State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, {
|
export default connect(mapStateToProps, {
|
||||||
...customTokenActions,
|
addCustomToken,
|
||||||
|
removeCustomToken,
|
||||||
showNotification,
|
showNotification,
|
||||||
fiatRequestedRates
|
fiatRequestedRates: dFiatRequestedRates
|
||||||
})(BalanceSidebar);
|
})(BalanceSidebar);
|
|
@ -1,11 +1,11 @@
|
||||||
|
import { BlockExplorerConfig } from 'config/data';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { BlockExplorerConfig } from 'config.data';
|
import {translateRaw} from 'translations';
|
||||||
import translate from 'translations';
|
|
||||||
|
|
||||||
export type TransactionSucceededProps = {
|
export interface TransactionSucceededProps {
|
||||||
txHash: string,
|
txHash: string;
|
||||||
blockExplorer: BlockExplorerConfig
|
blockExplorer: BlockExplorerConfig;
|
||||||
};
|
}
|
||||||
|
|
||||||
const TransactionSucceeded = ({
|
const TransactionSucceeded = ({
|
||||||
txHash,
|
txHash,
|
||||||
|
@ -17,7 +17,7 @@ const TransactionSucceeded = ({
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
{translate('SUCCESS_3', true) + txHash}
|
{translateRaw('SUCCESS_3') + txHash}
|
||||||
</p>
|
</p>
|
||||||
<a
|
<a
|
||||||
className="btn btn-xs btn-info string"
|
className="btn btn-xs btn-info string"
|
|
@ -1,10 +1,9 @@
|
||||||
|
import logo from 'assets/images/logo-myetherwallet.svg';
|
||||||
|
import { bityReferralURL, donationAddressMap } from 'config/data';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
import { donationAddressMap } from 'config/data';
|
|
||||||
import logo from 'assets/images/logo-myetherwallet.svg';
|
|
||||||
import { bityReferralURL } from 'config/data';
|
|
||||||
import PreFooter from './PreFooter';
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
import PreFooter from './PreFooter';
|
||||||
|
|
||||||
const LINKS_LEFT = [
|
const LINKS_LEFT = [
|
||||||
{
|
{
|
||||||
|
@ -93,7 +92,7 @@ const LINKS_SOCIAL = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class Footer extends Component {
|
export default class Footer extends Component {
|
||||||
render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<PreFooter />
|
<PreFooter />
|
|
@ -1,30 +1,24 @@
|
||||||
// @flow
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import throttle from 'lodash/throttle';
|
|
||||||
|
|
||||||
import './GasPriceDropdown.scss';
|
|
||||||
import { gasPriceDefaults } from 'config/data';
|
import { gasPriceDefaults } from 'config/data';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import './GasPriceDropdown.scss';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
value: number,
|
value: number;
|
||||||
onChange: (gasPrice: number) => void
|
onChange(gasPrice: number): void;
|
||||||
};
|
}
|
||||||
|
interface State {
|
||||||
export default class GasPriceDropdown extends Component {
|
expanded: boolean;
|
||||||
state = { expanded: false };
|
}
|
||||||
|
export default class GasPriceDropdown extends Component<Props, State> {
|
||||||
static propTypes = {
|
public state = { expanded: false };
|
||||||
value: PropTypes.number,
|
|
||||||
onChange: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.updateGasPrice = throttle(this.updateGasPrice, 50);
|
this.updateGasPrice = throttle(this.updateGasPrice, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { expanded } = this.state;
|
const { expanded } = this.state;
|
||||||
return (
|
return (
|
||||||
<span className={`dropdown ${expanded ? 'open' : ''}`}>
|
<span className={`dropdown ${expanded ? 'open' : ''}`}>
|
||||||
|
@ -78,7 +72,7 @@ export default class GasPriceDropdown extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleExpanded = () => {
|
public toggleExpanded = () => {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return {
|
return {
|
||||||
expanded: !state.expanded
|
expanded: !state.expanded
|
||||||
|
@ -86,11 +80,11 @@ export default class GasPriceDropdown extends Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
updateGasPrice = (value: string) => {
|
public updateGasPrice = (value: string) => {
|
||||||
this.props.onChange(parseInt(value, 10));
|
this.props.onChange(parseInt(value, 10));
|
||||||
};
|
};
|
||||||
|
|
||||||
handleGasPriceChange = (e: SyntheticInputEvent) => {
|
public handleGasPriceChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||||
this.updateGasPrice(e.target.value);
|
this.updateGasPrice((e.target as HTMLInputElement).value);
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
import NavigationLink from './NavigationLink';
|
import NavigationLink from './NavigationLink';
|
||||||
|
|
||||||
import './Navigation.scss';
|
import './Navigation.scss';
|
||||||
|
@ -20,10 +20,6 @@ const tabs = [
|
||||||
{
|
{
|
||||||
name: 'NAV_Offline'
|
name: 'NAV_Offline'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'NAV_Contracts',
|
|
||||||
to: 'contracts'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'NAV_ViewWallet'
|
name: 'NAV_ViewWallet'
|
||||||
// to: 'view-wallet'
|
// to: 'view-wallet'
|
||||||
|
@ -39,27 +35,35 @@ const tabs = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class Navigation extends Component {
|
interface Props {
|
||||||
constructor(props) {
|
location: object;
|
||||||
super(props);
|
color?: string;
|
||||||
this.state = {
|
}
|
||||||
showLeftArrow: false,
|
|
||||||
showRightArrow: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
interface State {
|
||||||
location: PropTypes.object,
|
showLeftArrow: boolean;
|
||||||
color: PropTypes.string
|
showRightArrow: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BorderStyle {
|
||||||
|
borderTopColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Navigation extends Component<Props, State> {
|
||||||
|
public state = {
|
||||||
|
showLeftArrow: false,
|
||||||
|
showRightArrow: false
|
||||||
};
|
};
|
||||||
|
|
||||||
scrollLeft() {}
|
/*
|
||||||
|
* public scrollLeft() {}
|
||||||
|
public scrollRight() {}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
scrollRight() {}
|
public render() {
|
||||||
|
|
||||||
render() {
|
|
||||||
const { location, color } = this.props;
|
const { location, color } = this.props;
|
||||||
const borderStyle = {};
|
const borderStyle: BorderStyle = {};
|
||||||
|
|
||||||
if (color) {
|
if (color) {
|
||||||
borderStyle.borderTopColor = color;
|
borderStyle.borderTopColor = color;
|
||||||
|
@ -72,14 +76,15 @@ export default class Navigation extends Component {
|
||||||
className="Navigation"
|
className="Navigation"
|
||||||
style={borderStyle}
|
style={borderStyle}
|
||||||
>
|
>
|
||||||
{this.state.showLeftArrow &&
|
{this.state.showLeftArrow && (
|
||||||
<a
|
<a
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="Navigation-arrow Navigation-arrow--left"
|
className="Navigation-arrow Navigation-arrow--left"
|
||||||
onClick={() => this.scrollLeft(100)}
|
// onClick={() => this.scrollLeft()}
|
||||||
>
|
>
|
||||||
«
|
«
|
||||||
</a>}
|
</a>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="Navigation-scroll container">
|
<div className="Navigation-scroll container">
|
||||||
<ul className="Navigation-links">
|
<ul className="Navigation-links">
|
||||||
|
@ -95,14 +100,15 @@ export default class Navigation extends Component {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.state.showRightArrow &&
|
{this.state.showRightArrow && (
|
||||||
<a
|
<a
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="Navigation-arrow Navigation-arrow-right"
|
className="Navigation-arrow Navigation-arrow-right"
|
||||||
onClick={() => this.scrollRight(100)}
|
// onClick={() => this.scrollRight()}
|
||||||
>
|
>
|
||||||
»
|
»
|
||||||
</a>}
|
</a>
|
||||||
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -1,51 +0,0 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import translate from 'translations';
|
|
||||||
import { Link } from 'react-router';
|
|
||||||
import './NavigationLink.scss';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
link: {
|
|
||||||
name: string,
|
|
||||||
to?: string,
|
|
||||||
external?: boolean
|
|
||||||
},
|
|
||||||
location: Object
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class NavigationLink extends React.Component {
|
|
||||||
props: Props;
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { link, location } = this.props;
|
|
||||||
const linkClasses = classnames({
|
|
||||||
'NavigationLink-link': true,
|
|
||||||
'is-disabled': !link.to,
|
|
||||||
'is-active':
|
|
||||||
location.pathname === link.to ||
|
|
||||||
location.pathname.substring(1) === link.to
|
|
||||||
});
|
|
||||||
// $FlowFixMe flow is wrong, this isn't an element
|
|
||||||
const linkLabel = `nav item: ${translate(link.name, true)}`;
|
|
||||||
|
|
||||||
const linkEl = link.external
|
|
||||||
? <a
|
|
||||||
className={linkClasses}
|
|
||||||
href={link.to}
|
|
||||||
aria-label={linkLabel}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{translate(link.name)}
|
|
||||||
</a>
|
|
||||||
: <Link className={linkClasses} to={link.to} aria-label={linkLabel}>
|
|
||||||
{translate(link.name)}
|
|
||||||
</Link>;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li className="NavigationLink">
|
|
||||||
{linkEl}
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router';
|
||||||
|
import translate, { translateRaw } from 'translations';
|
||||||
|
import './NavigationLink.scss';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
link: {
|
||||||
|
name: string;
|
||||||
|
to?: string;
|
||||||
|
external?: boolean;
|
||||||
|
};
|
||||||
|
location: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class NavigationLink extends React.Component<Props, {}> {
|
||||||
|
public render() {
|
||||||
|
const { link, location } = this.props;
|
||||||
|
const linkClasses = classnames({
|
||||||
|
'NavigationLink-link': true,
|
||||||
|
'is-disabled': !link.to,
|
||||||
|
'is-active':
|
||||||
|
location.pathname === link.to ||
|
||||||
|
location.pathname.substring(1) === link.to
|
||||||
|
});
|
||||||
|
const linkLabel = `nav item: ${translateRaw(link.name)}`;
|
||||||
|
|
||||||
|
const linkEl = link.external ? (
|
||||||
|
<a
|
||||||
|
className={linkClasses}
|
||||||
|
href={link.to}
|
||||||
|
aria-label={linkLabel}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{translate(link.name)}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<Link
|
||||||
|
className={linkClasses}
|
||||||
|
to={(link as any).to}
|
||||||
|
aria-label={linkLabel}
|
||||||
|
>
|
||||||
|
{translate(link.name)}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
|
||||||
|
return <li className="NavigationLink">{linkEl}</li>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,49 +1,53 @@
|
||||||
// @flow
|
import { TChangeGasPrice, TChangeLanguage, TChangeNode } from 'actions/config';
|
||||||
import React, { Component } from 'react';
|
|
||||||
import Navigation from './components/Navigation';
|
|
||||||
import GasPriceDropdown from './components/GasPriceDropdown';
|
|
||||||
import { Link } from 'react-router';
|
|
||||||
import { Dropdown } from 'components/ui';
|
|
||||||
import {
|
|
||||||
languages,
|
|
||||||
NODES,
|
|
||||||
NETWORKS,
|
|
||||||
VERSION,
|
|
||||||
ANNOUNCEMENT_TYPE,
|
|
||||||
ANNOUNCEMENT_MESSAGE
|
|
||||||
} from '../../config/data';
|
|
||||||
import logo from 'assets/images/logo-myetherwallet.svg';
|
import logo from 'assets/images/logo-myetherwallet.svg';
|
||||||
|
import { Dropdown } from 'components/ui';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Link } from 'react-router';
|
||||||
|
import {
|
||||||
|
ANNOUNCEMENT_MESSAGE,
|
||||||
|
ANNOUNCEMENT_TYPE,
|
||||||
|
languages,
|
||||||
|
NETWORKS,
|
||||||
|
NODES,
|
||||||
|
VERSION
|
||||||
|
} from '../../config/data';
|
||||||
|
import GasPriceDropdown from './components/GasPriceDropdown';
|
||||||
|
import Navigation from './components/Navigation';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
export default class Header extends Component {
|
interface Props {
|
||||||
props: {
|
location: {};
|
||||||
location: {},
|
languageSelection: string;
|
||||||
languageSelection: string,
|
nodeSelection: string;
|
||||||
nodeSelection: string,
|
gasPriceGwei: number;
|
||||||
gasPriceGwei: number,
|
|
||||||
|
|
||||||
changeLanguage: (sign: string) => any,
|
changeLanguage: TChangeLanguage;
|
||||||
changeNode: (key: string) => any,
|
changeNode: TChangeNode;
|
||||||
changeGasPrice: (price: number) => any
|
changeGasPrice: TChangeGasPrice;
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
export default class Header extends Component<Props, {}> {
|
||||||
|
public render() {
|
||||||
const { languageSelection, changeNode, nodeSelection } = this.props;
|
const { languageSelection, changeNode, nodeSelection } = this.props;
|
||||||
const selectedLanguage =
|
const selectedLanguage =
|
||||||
languages.find(l => l.sign === languageSelection) || languages[0];
|
languages.find(l => l.sign === languageSelection) || languages[0];
|
||||||
const selectedNode = NODES[nodeSelection];
|
const selectedNode = NODES[nodeSelection];
|
||||||
const selectedNetwork = NETWORKS[selectedNode.network];
|
const selectedNetwork = NETWORKS[selectedNode.network];
|
||||||
|
const LanguageDropDown = Dropdown as new () => Dropdown<
|
||||||
|
typeof selectedLanguage
|
||||||
|
>;
|
||||||
|
const NodeDropDown = Dropdown as new () => Dropdown<keyof typeof NODES>;
|
||||||
return (
|
return (
|
||||||
<div className="Header">
|
<div className="Header">
|
||||||
{ANNOUNCEMENT_MESSAGE &&
|
{ANNOUNCEMENT_MESSAGE && (
|
||||||
<div
|
<div
|
||||||
className={`Header-announcement is-${ANNOUNCEMENT_TYPE}`}
|
className={`Header-announcement is-${ANNOUNCEMENT_TYPE}`}
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: ANNOUNCEMENT_MESSAGE
|
__html: ANNOUNCEMENT_MESSAGE
|
||||||
}}
|
}}
|
||||||
/>}
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<section className="Header-branding">
|
<section className="Header-branding">
|
||||||
<section className="Header-branding-inner container">
|
<section className="Header-branding-inner container">
|
||||||
|
@ -71,10 +75,10 @@ export default class Header extends Component {
|
||||||
onChange={this.props.changeGasPrice}
|
onChange={this.props.changeGasPrice}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Dropdown
|
<LanguageDropDown
|
||||||
ariaLabel={`change language. current language ${selectedLanguage.name}`}
|
ariaLabel={`change language. current language ${selectedLanguage.name}`}
|
||||||
options={languages}
|
options={languages}
|
||||||
formatTitle={o => o.name}
|
formatTitle={this.extractName}
|
||||||
value={selectedLanguage}
|
value={selectedLanguage}
|
||||||
extra={[
|
extra={[
|
||||||
<li key={'separator'} role="separator" className="divider" />,
|
<li key={'separator'} role="separator" className="divider" />,
|
||||||
|
@ -87,20 +91,14 @@ export default class Header extends Component {
|
||||||
onChange={this.changeLanguage}
|
onChange={this.changeLanguage}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Dropdown
|
<NodeDropDown
|
||||||
ariaLabel={`change node. current node ${selectedNode.network} node by ${selectedNode.service}`}
|
ariaLabel={`change node. current node ${selectedNode.network} node by ${selectedNode.service}`}
|
||||||
options={Object.keys(NODES)}
|
options={Object.keys(NODES)}
|
||||||
formatTitle={o => [
|
formatTitle={this.nodeNetworkAndService}
|
||||||
NODES[o].network,
|
|
||||||
' ',
|
|
||||||
<small key="service">
|
|
||||||
({NODES[o].service})
|
|
||||||
</small>
|
|
||||||
]}
|
|
||||||
value={nodeSelection}
|
value={nodeSelection}
|
||||||
extra={
|
extra={
|
||||||
<li>
|
<li>
|
||||||
<a onClick={() => {}}>Add Custom Node</a>
|
<a>Add Custom Node</a>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
onChange={changeNode}
|
onChange={changeNode}
|
||||||
|
@ -111,13 +109,23 @@ export default class Header extends Component {
|
||||||
|
|
||||||
<Navigation
|
<Navigation
|
||||||
location={this.props.location}
|
location={this.props.location}
|
||||||
color={selectedNetwork.color}
|
// color={selectedNetwork.color}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeLanguage = (value: { sign: string }) => {
|
public changeLanguage = (value: { sign: string }) => {
|
||||||
this.props.changeLanguage(value.sign);
|
this.props.changeLanguage(value.sign);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private extractName(): (option: { sign: string; name: string }) => string {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private nodeNetworkAndService = (option: string) => [
|
||||||
|
NODES[option].network,
|
||||||
|
' ',
|
||||||
|
<small key="service">({NODES[option].service}) </small>
|
||||||
|
];
|
||||||
}
|
}
|
|
@ -1,16 +1,15 @@
|
||||||
// @flow
|
import { Identicon, QRCode } from 'components/ui';
|
||||||
|
import PrivKeyWallet from 'libs/wallet/privkey';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { QRCode, Identicon } from 'components/ui';
|
|
||||||
import type PrivKeyWallet from 'libs/wallet/privkey';
|
|
||||||
|
|
||||||
import ethLogo from 'assets/images/logo-ethereum-1.png';
|
import ethLogo from 'assets/images/logo-ethereum-1.png';
|
||||||
import sidebarImg from 'assets/images/print-sidebar.png';
|
|
||||||
import notesBg from 'assets/images/notes-bg.png';
|
import notesBg from 'assets/images/notes-bg.png';
|
||||||
|
import sidebarImg from 'assets/images/print-sidebar.png';
|
||||||
|
|
||||||
const walletWidth = 680;
|
const walletWidth = 680;
|
||||||
const walletHeight = 280;
|
const walletHeight = 280;
|
||||||
|
|
||||||
const styles = {
|
const styles: any = {
|
||||||
container: {
|
container: {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
|
@ -91,22 +90,26 @@ const styles = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
wallet: PrivKeyWallet
|
wallet: PrivKeyWallet;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class PaperWallet extends React.Component {
|
interface State {
|
||||||
props: Props;
|
address: string;
|
||||||
state = { address: '' };
|
}
|
||||||
|
export default class PaperWallet extends React.Component<Props, State> {
|
||||||
|
public state = { address: '' };
|
||||||
|
|
||||||
componentDidMount() {
|
public componentDidMount() {
|
||||||
if (!this.props.wallet) return;
|
if (!this.props.wallet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.props.wallet.getAddress().then(addr => {
|
this.props.wallet.getAddress().then(addr => {
|
||||||
this.setState({ address: addr });
|
this.setState({ address: addr });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const privateKey = this.props.wallet.getPrivateKey();
|
const privateKey = this.props.wallet.getPrivateKey();
|
||||||
|
|
||||||
return (
|
return (
|
|
@ -1,22 +1,15 @@
|
||||||
// @flow
|
import { PaperWallet } from 'components';
|
||||||
|
import PrivKeyWallet from 'libs/wallet/privkey';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
import printElement from 'utils/printElement';
|
import printElement from 'utils/printElement';
|
||||||
import { PaperWallet } from 'components';
|
|
||||||
import type PrivKeyWallet from 'libs/wallet/privkey';
|
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
wallet: PrivKeyWallet
|
wallet: PrivKeyWallet;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class PrintableWallet extends Component {
|
export default class PrintableWallet extends Component<Props, {}> {
|
||||||
props: Props;
|
public print = () => {
|
||||||
static propTypes = {
|
|
||||||
wallet: PropTypes.object.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
print = () => {
|
|
||||||
printElement(<PaperWallet wallet={this.props.wallet} />, {
|
printElement(<PaperWallet wallet={this.props.wallet} />, {
|
||||||
popupFeatures: {
|
popupFeatures: {
|
||||||
scrollbars: 'no'
|
scrollbars: 'no'
|
||||||
|
@ -36,7 +29,7 @@ export default class PrintableWallet extends Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<PaperWallet wallet={this.props.wallet} />
|
<PaperWallet wallet={this.props.wallet} />
|
|
@ -1,16 +1,16 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { Router } from 'react-router';
|
import { Router } from 'react-router';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
export default class Root extends Component {
|
// TODO: fix this
|
||||||
static propTypes = {
|
interface Props {
|
||||||
store: PropTypes.object,
|
store: any;
|
||||||
history: PropTypes.object,
|
history: any;
|
||||||
routes: PropTypes.func
|
routes(): null;
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
export default class Root extends Component<Props, {}> {
|
||||||
|
public render() {
|
||||||
const { store, history, routes } = this.props;
|
const { store, history, routes } = this.props;
|
||||||
// key={Math.random()} = hack for HMR from https://github.com/webpack/webpack-dev-server/issues/395
|
// key={Math.random()} = hack for HMR from https://github.com/webpack/webpack-dev-server/issues/395
|
||||||
return (
|
return (
|
|
@ -1,11 +1,10 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Markdown from 'react-markdown';
|
import Markdown from 'react-markdown';
|
||||||
import { translateRaw } from 'translations';
|
import { translateRaw } from 'translations';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
translationKey: string
|
translationKey: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
const Translate = ({ translationKey }: Props) => {
|
const Translate = ({ translationKey }: Props) => {
|
||||||
const source = translateRaw(translationKey);
|
const source = translateRaw(translationKey);
|
|
@ -1,60 +1,59 @@
|
||||||
// @flow
|
|
||||||
import './DeterministicWalletsModal.scss';
|
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import Modal from 'components/ui/Modal';
|
|
||||||
import {
|
import {
|
||||||
getDeterministicWallets,
|
|
||||||
setDesiredToken
|
|
||||||
} from 'actions/deterministicWallets';
|
|
||||||
import { getNetworkConfig } from 'selectors/config';
|
|
||||||
import { getTokens } from 'selectors/wallet';
|
|
||||||
import { isValidPath } from 'libs/validators';
|
|
||||||
import type {
|
|
||||||
DeterministicWalletData,
|
DeterministicWalletData,
|
||||||
GetDeterministicWalletsArgs,
|
getDeterministicWallets,
|
||||||
GetDeterministicWalletsAction,
|
GetDeterministicWalletsAction,
|
||||||
|
GetDeterministicWalletsArgs,
|
||||||
|
setDesiredToken,
|
||||||
SetDesiredTokenAction
|
SetDesiredTokenAction
|
||||||
} from 'actions/deterministicWallets';
|
} from 'actions/deterministicWallets';
|
||||||
import type { NetworkConfig, Token } from 'config/data';
|
import Modal, { IButton } from 'components/ui/Modal';
|
||||||
|
import { NetworkConfig, Token } from 'config/data';
|
||||||
|
import { isValidPath } from 'libs/validators';
|
||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { getNetworkConfig } from 'selectors/config';
|
||||||
|
import { getTokens, MergedToken } from 'selectors/wallet';
|
||||||
|
import './DeterministicWalletsModal.scss';
|
||||||
|
|
||||||
const WALLETS_PER_PAGE = 5;
|
const WALLETS_PER_PAGE = 5;
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
|
// Passed props
|
||||||
|
isOpen?: boolean;
|
||||||
|
walletType?: string;
|
||||||
|
dPath: string;
|
||||||
|
dPaths: { label: string; value: string }[];
|
||||||
|
publicKey?: string;
|
||||||
|
chainCode?: string;
|
||||||
|
seed?: string;
|
||||||
|
|
||||||
// Redux state
|
// Redux state
|
||||||
wallets: DeterministicWalletData[],
|
wallets: DeterministicWalletData[];
|
||||||
desiredToken: string,
|
desiredToken: string;
|
||||||
network: NetworkConfig,
|
network: NetworkConfig;
|
||||||
tokens: Token[],
|
tokens: MergedToken[];
|
||||||
|
|
||||||
// Redux actions
|
// Redux actions
|
||||||
getDeterministicWallets: GetDeterministicWalletsArgs => GetDeterministicWalletsAction,
|
getDeterministicWallets(
|
||||||
setDesiredToken: (tkn: ?string) => SetDesiredTokenAction,
|
args: GetDeterministicWalletsArgs
|
||||||
|
): GetDeterministicWalletsAction;
|
||||||
|
setDesiredToken(tkn: string | undefined): SetDesiredTokenAction;
|
||||||
|
|
||||||
// Passed props
|
onCancel(): void;
|
||||||
isOpen?: boolean,
|
onConfirmAddress(address: string, addressIndex: number): void;
|
||||||
walletType: ?string,
|
onPathChange(path: string): void;
|
||||||
dPath: string,
|
}
|
||||||
dPaths: { label: string, value: string }[],
|
|
||||||
publicKey: ?string,
|
|
||||||
chainCode: ?string,
|
|
||||||
seed: ?string,
|
|
||||||
onCancel: () => void,
|
|
||||||
onConfirmAddress: (string, number) => void,
|
|
||||||
onPathChange: string => void
|
|
||||||
};
|
|
||||||
|
|
||||||
type State = {
|
interface State {
|
||||||
selectedAddress: string,
|
selectedAddress: string;
|
||||||
selectedAddrIndex: number,
|
selectedAddrIndex: number;
|
||||||
isCustomPath: boolean,
|
isCustomPath: boolean;
|
||||||
customPath: string,
|
customPath: string;
|
||||||
page: number
|
page: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
class DeterministicWalletsModal extends React.Component {
|
class DeterministicWalletsModal extends React.Component<Props, State> {
|
||||||
props: Props;
|
public state = {
|
||||||
state: State = {
|
|
||||||
selectedAddress: '',
|
selectedAddress: '',
|
||||||
selectedAddrIndex: 0,
|
selectedAddrIndex: 0,
|
||||||
isCustomPath: false,
|
isCustomPath: false,
|
||||||
|
@ -62,11 +61,11 @@ class DeterministicWalletsModal extends React.Component {
|
||||||
page: 0
|
page: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
public componentDidMount() {
|
||||||
this._getAddresses();
|
this.getAddresses();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
public componentWillReceiveProps(nextProps) {
|
||||||
const { publicKey, chainCode, seed, dPath } = this.props;
|
const { publicKey, chainCode, seed, dPath } = this.props;
|
||||||
if (
|
if (
|
||||||
nextProps.publicKey !== publicKey ||
|
nextProps.publicKey !== publicKey ||
|
||||||
|
@ -74,11 +73,125 @@ class DeterministicWalletsModal extends React.Component {
|
||||||
nextProps.dPath !== dPath ||
|
nextProps.dPath !== dPath ||
|
||||||
nextProps.seed !== seed
|
nextProps.seed !== seed
|
||||||
) {
|
) {
|
||||||
this._getAddresses(nextProps);
|
this.getAddresses(nextProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getAddresses(props: Props = this.props) {
|
public render() {
|
||||||
|
const {
|
||||||
|
wallets,
|
||||||
|
desiredToken,
|
||||||
|
network,
|
||||||
|
tokens,
|
||||||
|
dPath,
|
||||||
|
dPaths,
|
||||||
|
onCancel,
|
||||||
|
walletType
|
||||||
|
} = this.props;
|
||||||
|
const { selectedAddress, isCustomPath, customPath, page } = this.state;
|
||||||
|
const validPathClass = isValidPath(customPath) ? 'is-valid' : 'is-invalid';
|
||||||
|
|
||||||
|
const buttons: IButton[] = [
|
||||||
|
{
|
||||||
|
text: 'Unlock this Address',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: this.handleConfirmAddress,
|
||||||
|
disabled: !selectedAddress
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Cancel',
|
||||||
|
type: 'default',
|
||||||
|
onClick: onCancel
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={`Unlock your ${walletType || ''} Wallet`}
|
||||||
|
isOpen={this.props.isOpen}
|
||||||
|
buttons={buttons}
|
||||||
|
handleClose={onCancel}
|
||||||
|
>
|
||||||
|
<div className="DWModal">
|
||||||
|
<form
|
||||||
|
className="DWModal-path form-group-sm"
|
||||||
|
onSubmit={this.handleSubmitCustomPath}
|
||||||
|
>
|
||||||
|
<span className="DWModal-path-label">Addresses for</span>
|
||||||
|
<select
|
||||||
|
className="form-control"
|
||||||
|
onChange={this.handleChangePath}
|
||||||
|
value={isCustomPath ? 'custom' : dPath}
|
||||||
|
>
|
||||||
|
{dPaths.map(dp =>
|
||||||
|
<option key={dp.value} value={dp.value}>
|
||||||
|
{dp.label}
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
<option value="custom">Custom path...</option>
|
||||||
|
</select>
|
||||||
|
{isCustomPath &&
|
||||||
|
<input
|
||||||
|
className={`form-control ${validPathClass}`}
|
||||||
|
value={customPath}
|
||||||
|
placeholder="m/44'/60'/0'/0"
|
||||||
|
onChange={this.handleChangeCustomPath}
|
||||||
|
/>}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div className="DWModal-addresses">
|
||||||
|
<table className="DWModal-addresses-table table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>#</td>
|
||||||
|
<td>Address</td>
|
||||||
|
<td>
|
||||||
|
{network.unit}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select
|
||||||
|
className="DWModal-addresses-table-token"
|
||||||
|
value={desiredToken}
|
||||||
|
onChange={this.handleChangeToken}
|
||||||
|
>
|
||||||
|
<option value="">-Token-</option>
|
||||||
|
{tokens.map(t =>
|
||||||
|
<option key={t.symbol} value={t.symbol}>
|
||||||
|
{t.symbol}
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>More</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{wallets.map(wallet => this.renderWalletRow(wallet))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div className="DWModal-addresses-nav">
|
||||||
|
<button
|
||||||
|
className="DWModal-addresses-nav-btn btn btn-sm btn-default"
|
||||||
|
disabled={page === 0}
|
||||||
|
onClick={this.prevPage}
|
||||||
|
>
|
||||||
|
← Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="DWModal-addresses-nav-btn btn btn-sm btn-default"
|
||||||
|
onClick={this.nextPage}
|
||||||
|
>
|
||||||
|
More →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAddresses(props: Props = this.props) {
|
||||||
const { dPath, publicKey, chainCode, seed } = props;
|
const { dPath, publicKey, chainCode, seed } = props;
|
||||||
|
|
||||||
if (dPath && ((publicKey && chainCode) || seed) && isValidPath(dPath)) {
|
if (dPath && ((publicKey && chainCode) || seed) && isValidPath(dPath)) {
|
||||||
|
@ -93,8 +206,8 @@ class DeterministicWalletsModal extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleChangePath = (ev: SyntheticInputEvent) => {
|
private handleChangePath = (ev: React.SyntheticEvent<HTMLSelectElement>) => {
|
||||||
const { value } = ev.target;
|
const { value } = ev.target as HTMLSelectElement;
|
||||||
|
|
||||||
if (value === 'custom') {
|
if (value === 'custom') {
|
||||||
this.setState({ isCustomPath: true });
|
this.setState({ isCustomPath: true });
|
||||||
|
@ -106,21 +219,29 @@ class DeterministicWalletsModal extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleChangeCustomPath = (ev: SyntheticInputEvent) => {
|
private handleChangeCustomPath = (
|
||||||
this.setState({ customPath: ev.target.value });
|
ev: React.SyntheticEvent<HTMLInputElement>
|
||||||
|
) => {
|
||||||
|
this.setState({ customPath: (ev.target as HTMLInputElement).value });
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleSubmitCustomPath = (ev: SyntheticInputEvent) => {
|
private handleSubmitCustomPath = (
|
||||||
|
ev: React.SyntheticEvent<HTMLFormElement>
|
||||||
|
) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (!isValidPath(this.state.customPath)) return;
|
if (!isValidPath(this.state.customPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.props.onPathChange(this.state.customPath);
|
this.props.onPathChange(this.state.customPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleChangeToken = (ev: SyntheticInputEvent) => {
|
private handleChangeToken = (ev: React.SyntheticEvent<HTMLSelectElement>) => {
|
||||||
this.props.setDesiredToken(ev.target.value || null);
|
this.props.setDesiredToken(
|
||||||
|
(ev.target as HTMLSelectElement).value || undefined
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleConfirmAddress = () => {
|
private handleConfirmAddress = () => {
|
||||||
if (this.state.selectedAddress) {
|
if (this.state.selectedAddress) {
|
||||||
this.props.onConfirmAddress(
|
this.props.onConfirmAddress(
|
||||||
this.state.selectedAddress,
|
this.state.selectedAddress,
|
||||||
|
@ -129,22 +250,22 @@ class DeterministicWalletsModal extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_selectAddress(selectedAddress, selectedAddrIndex) {
|
private selectAddress(selectedAddress, selectedAddrIndex) {
|
||||||
this.setState({ selectedAddress, selectedAddrIndex });
|
this.setState({ selectedAddress, selectedAddrIndex });
|
||||||
}
|
}
|
||||||
|
|
||||||
_nextPage = () => {
|
private nextPage = () => {
|
||||||
this.setState({ page: this.state.page + 1 }, this._getAddresses);
|
this.setState({ page: this.state.page + 1 }, this.getAddresses);
|
||||||
};
|
};
|
||||||
|
|
||||||
_prevPage = () => {
|
private prevPage = () => {
|
||||||
this.setState(
|
this.setState(
|
||||||
{ page: Math.max(this.state.page - 1, 0) },
|
{ page: Math.max(this.state.page - 1, 0) },
|
||||||
this._getAddresses
|
this.getAddresses
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
_renderWalletRow(wallet) {
|
private renderWalletRow(wallet) {
|
||||||
const { desiredToken, network } = this.props;
|
const { desiredToken, network } = this.props;
|
||||||
const { selectedAddress } = this.state;
|
const { selectedAddress } = this.state;
|
||||||
|
|
||||||
|
@ -157,7 +278,7 @@ class DeterministicWalletsModal extends React.Component {
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
key={wallet.address}
|
key={wallet.address}
|
||||||
onClick={this._selectAddress.bind(this, wallet.address, wallet.index)}
|
onClick={this.selectAddress.bind(this, wallet.address, wallet.index)}
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
{wallet.index + 1}
|
{wallet.index + 1}
|
||||||
|
@ -188,120 +309,6 @@ class DeterministicWalletsModal extends React.Component {
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
wallets,
|
|
||||||
desiredToken,
|
|
||||||
network,
|
|
||||||
tokens,
|
|
||||||
dPath,
|
|
||||||
dPaths,
|
|
||||||
onCancel,
|
|
||||||
walletType
|
|
||||||
} = this.props;
|
|
||||||
const { selectedAddress, isCustomPath, customPath, page } = this.state;
|
|
||||||
const validPathClass = isValidPath(customPath) ? 'is-valid' : 'is-invalid';
|
|
||||||
|
|
||||||
const buttons = [
|
|
||||||
{
|
|
||||||
text: 'Unlock this Address',
|
|
||||||
type: 'primary',
|
|
||||||
onClick: this._handleConfirmAddress,
|
|
||||||
disabled: !selectedAddress
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Cancel',
|
|
||||||
type: 'default',
|
|
||||||
onClick: onCancel
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
title={`Unlock your ${walletType || ''} Wallet`}
|
|
||||||
isOpen={this.props.isOpen}
|
|
||||||
buttons={buttons}
|
|
||||||
handleClose={onCancel}
|
|
||||||
>
|
|
||||||
<div className="DWModal">
|
|
||||||
<form
|
|
||||||
className="DWModal-path form-group-sm"
|
|
||||||
onSubmit={this._handleSubmitCustomPath}
|
|
||||||
>
|
|
||||||
<span className="DWModal-path-label">Addresses for</span>
|
|
||||||
<select
|
|
||||||
className="form-control"
|
|
||||||
onChange={this._handleChangePath}
|
|
||||||
value={isCustomPath ? 'custom' : dPath}
|
|
||||||
>
|
|
||||||
{dPaths.map(dp =>
|
|
||||||
<option key={dp.value} value={dp.value}>
|
|
||||||
{dp.label}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
<option value="custom">Custom path...</option>
|
|
||||||
</select>
|
|
||||||
{isCustomPath &&
|
|
||||||
<input
|
|
||||||
className={`form-control ${validPathClass}`}
|
|
||||||
value={customPath}
|
|
||||||
placeholder="m/44'/60'/0'/0"
|
|
||||||
onChange={this._handleChangeCustomPath}
|
|
||||||
/>}
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div className="DWModal-addresses">
|
|
||||||
<table className="DWModal-addresses-table table table-striped table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td>#</td>
|
|
||||||
<td>Address</td>
|
|
||||||
<td>
|
|
||||||
{network.unit}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select
|
|
||||||
className="DWModal-addresses-table-token"
|
|
||||||
value={desiredToken}
|
|
||||||
onChange={this._handleChangeToken}
|
|
||||||
>
|
|
||||||
<option value="">-Token-</option>
|
|
||||||
{tokens.map(t =>
|
|
||||||
<option key={t.symbol} value={t.symbol}>
|
|
||||||
{t.symbol}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
<td>More</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{wallets.map(wallet => this._renderWalletRow(wallet))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div className="DWModal-addresses-nav">
|
|
||||||
<button
|
|
||||||
className="DWModal-addresses-nav-btn btn btn-sm btn-default"
|
|
||||||
disabled={page === 0}
|
|
||||||
onClick={this._prevPage}
|
|
||||||
>
|
|
||||||
← Back
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="DWModal-addresses-nav-btn btn btn-sm btn-default"
|
|
||||||
onClick={this._nextPage}
|
|
||||||
>
|
|
||||||
More →
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
|
@ -1,33 +1,33 @@
|
||||||
|
import { isKeystorePassRequired } from 'libs/keystore';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { isKeystorePassRequired } from 'libs/keystore';
|
|
||||||
|
|
||||||
export type KeystoreValue = {
|
export interface KeystoreValue {
|
||||||
file: string,
|
file: string;
|
||||||
password: string,
|
password: string;
|
||||||
valid: boolean
|
valid: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
function isPassRequired(file: string): boolean {
|
function isPassRequired(file: string): boolean {
|
||||||
let passReq = false;
|
let passReq = false;
|
||||||
try {
|
try {
|
||||||
passReq = isKeystorePassRequired(file);
|
passReq = isKeystorePassRequired(file);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//TODO: communicate invalid file to user
|
// TODO: communicate invalid file to user
|
||||||
}
|
}
|
||||||
return passReq;
|
return passReq;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class KeystoreDecrypt extends Component {
|
export default class KeystoreDecrypt extends Component {
|
||||||
props: {
|
public props: {
|
||||||
value: KeystoreValue,
|
value: KeystoreValue;
|
||||||
onChange: (value: KeystoreValue) => void,
|
onChange(value: KeystoreValue): void;
|
||||||
onUnlock: () => void
|
onUnlock(): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { file, password } = this.props.value;
|
const { file, password } = this.props.value;
|
||||||
let passReq = isPassRequired(file);
|
const passReq = isPassRequired(file);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="col-md-4 col-sm-6">
|
<section className="col-md-4 col-sm-6">
|
||||||
|
@ -47,7 +47,7 @@ export default class KeystoreDecrypt extends Component {
|
||||||
<a
|
<a
|
||||||
className="btn btn-default btn-block"
|
className="btn btn-default btn-block"
|
||||||
id="aria1"
|
id="aria1"
|
||||||
tabIndex="0"
|
tabIndex={0}
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
{translate('ADD_Radio_2_short')}
|
{translate('ADD_Radio_2_short')}
|
||||||
|
@ -74,7 +74,7 @@ export default class KeystoreDecrypt extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (e: SyntheticKeyboardEvent) => {
|
public onKeyDown = (e: any) => {
|
||||||
if (e.keyCode === 13) {
|
if (e.keyCode === 13) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -82,7 +82,7 @@ export default class KeystoreDecrypt extends Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onPasswordChange = (e: SyntheticInputEvent) => {
|
public onPasswordChange = (e: any) => {
|
||||||
const valid = this.props.value.file.length && e.target.value.length;
|
const valid = this.props.value.file.length && e.target.value.length;
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
...this.props.value,
|
...this.props.value,
|
||||||
|
@ -91,13 +91,14 @@ export default class KeystoreDecrypt extends Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleFileSelection = (e: SyntheticInputEvent) => {
|
public handleFileSelection = (e: any) => {
|
||||||
const fileReader = new FileReader();
|
const fileReader = new FileReader();
|
||||||
const inputFile = e.target.files[0];
|
const target = e.target;
|
||||||
|
const inputFile = target.files[0];
|
||||||
|
|
||||||
fileReader.onload = () => {
|
fileReader.onload = () => {
|
||||||
const keystore = fileReader.result;
|
const keystore = fileReader.result;
|
||||||
let passReq = isPassRequired(keystore);
|
const passReq = isPassRequired(keystore);
|
||||||
|
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
...this.props.value,
|
...this.props.value,
|
|
@ -2,11 +2,13 @@ import React, { Component } from 'react';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
|
|
||||||
export default class LedgerNanoSDecrypt extends Component {
|
export default class LedgerNanoSDecrypt extends Component {
|
||||||
render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<section className="col-md-4 col-sm-6">
|
<section className="col-md-4 col-sm-6">
|
||||||
<div id="selectedUploadKey">
|
<div id="selectedUploadKey">
|
||||||
<h4>{translate('ADD_Radio_2_alt')}</h4>
|
<h4>
|
||||||
|
{translate('ADD_Radio_2_alt')}
|
||||||
|
</h4>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<input type="file" id="fselector" />
|
<input type="file" id="fselector" />
|
||||||
|
@ -14,7 +16,7 @@ export default class LedgerNanoSDecrypt extends Component {
|
||||||
<a
|
<a
|
||||||
className="btn-file marg-v-sm"
|
className="btn-file marg-v-sm"
|
||||||
id="aria1"
|
id="aria1"
|
||||||
tabIndex="0"
|
tabIndex={0}
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
{translate('ADD_Radio_2_short')}
|
{translate('ADD_Radio_2_short')}
|
|
@ -1,29 +1,30 @@
|
||||||
|
import { mnemonicToSeed, validateMnemonic } from 'bip39';
|
||||||
|
import DPATHS from 'config/dpaths';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { validateMnemonic, mnemonicToSeed } from 'bip39';
|
|
||||||
|
|
||||||
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
||||||
|
|
||||||
import DPATHS from 'config/dpaths.js';
|
|
||||||
const DEFAULT_PATH = DPATHS.MNEMONIC[0].value;
|
const DEFAULT_PATH = DPATHS.MNEMONIC[0].value;
|
||||||
|
|
||||||
type State = {
|
interface Props {
|
||||||
phrase: string,
|
onUnlock(param: any): void;
|
||||||
pass: string,
|
}
|
||||||
seed: string,
|
interface State {
|
||||||
dPath: string
|
phrase: string;
|
||||||
};
|
pass: string;
|
||||||
|
seed: string;
|
||||||
|
dPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default class MnemonicDecrypt extends Component {
|
export default class MnemonicDecrypt extends Component<Props, State> {
|
||||||
props: { onUnlock: any => void };
|
public state: State = {
|
||||||
state: State = {
|
|
||||||
phrase: '',
|
phrase: '',
|
||||||
pass: '',
|
pass: '',
|
||||||
seed: '',
|
seed: '',
|
||||||
dPath: DEFAULT_PATH
|
dPath: DEFAULT_PATH
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { phrase, seed, dPath, pass } = this.state;
|
const { phrase, seed, dPath, pass } = this.state;
|
||||||
const isValidMnemonic = validateMnemonic(phrase);
|
const isValidMnemonic = validateMnemonic(phrase);
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ export default class MnemonicDecrypt extends Component {
|
||||||
value={phrase}
|
value={phrase}
|
||||||
onChange={this.onMnemonicChange}
|
onChange={this.onMnemonicChange}
|
||||||
placeholder={translateRaw('x_Mnemonic')}
|
placeholder={translateRaw('x_Mnemonic')}
|
||||||
rows="4"
|
rows={4}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
|
@ -72,45 +73,47 @@ export default class MnemonicDecrypt extends Component {
|
||||||
seed={seed}
|
seed={seed}
|
||||||
dPath={dPath}
|
dPath={dPath}
|
||||||
dPaths={DPATHS.MNEMONIC}
|
dPaths={DPATHS.MNEMONIC}
|
||||||
onCancel={this._handleCancel}
|
onCancel={this.handleCancel}
|
||||||
onConfirmAddress={this._handleUnlock}
|
onConfirmAddress={this.handleUnlock}
|
||||||
onPathChange={this._handlePathChange}
|
onPathChange={this.handlePathChange}
|
||||||
walletType={translateRaw('x_Mnemonic')}
|
walletType={translateRaw('x_Mnemonic')}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPasswordChange = (e: SyntheticInputEvent) => {
|
public onPasswordChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||||
this.setState({ pass: e.target.value });
|
this.setState({ pass: (e.target as HTMLInputElement).value });
|
||||||
};
|
};
|
||||||
|
|
||||||
onMnemonicChange = (e: SyntheticInputEvent) => {
|
public onMnemonicChange = (e: React.SyntheticEvent<HTMLTextAreaElement>) => {
|
||||||
this.setState({ phrase: e.target.value });
|
this.setState({ phrase: (e.target as HTMLTextAreaElement).value });
|
||||||
};
|
};
|
||||||
|
|
||||||
onDWModalOpen = (e: SyntheticInputEvent) => {
|
public onDWModalOpen = (e: React.SyntheticEvent<HTMLButtonElement>) => {
|
||||||
const { phrase, pass } = this.state;
|
const { phrase, pass } = this.state;
|
||||||
|
|
||||||
if (!validateMnemonic(phrase)) return;
|
if (!validateMnemonic(phrase)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let seed = mnemonicToSeed(phrase.trim(), pass).toString('hex');
|
const seed = mnemonicToSeed(phrase.trim(), pass).toString('hex');
|
||||||
this.setState({ seed });
|
this.setState({ seed });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleCancel = () => {
|
private handleCancel = () => {
|
||||||
this.setState({ seed: '' });
|
this.setState({ seed: '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
_handlePathChange = (dPath: string) => {
|
private handlePathChange = (dPath: string) => {
|
||||||
this.setState({ dPath });
|
this.setState({ dPath });
|
||||||
};
|
};
|
||||||
|
|
||||||
_handleUnlock = (address, index) => {
|
private handleUnlock = (address, index) => {
|
||||||
const { phrase, pass, dPath } = this.state;
|
const { phrase, pass, dPath } = this.state;
|
||||||
|
|
||||||
this.props.onUnlock({
|
this.props.onUnlock({
|
|
@ -1,13 +1,12 @@
|
||||||
// @flow
|
import { isValidEncryptedPrivKey, isValidPrivKey } from 'libs/validators';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import translate, { translateRaw } from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import { isValidPrivKey, isValidEncryptedPrivKey } from 'libs/validators';
|
|
||||||
|
|
||||||
export type PrivateKeyValue = {
|
export interface PrivateKeyValue {
|
||||||
key: string,
|
key: string;
|
||||||
password: string,
|
password: string;
|
||||||
valid: boolean
|
valid: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
function fixPkey(key) {
|
function fixPkey(key) {
|
||||||
if (key.indexOf('0x') === 0) {
|
if (key.indexOf('0x') === 0) {
|
||||||
|
@ -16,14 +15,14 @@ function fixPkey(key) {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
type validated = {
|
interface Validated {
|
||||||
fixedPkey: string,
|
fixedPkey: string;
|
||||||
isValidPkey: boolean,
|
isValidPkey: boolean;
|
||||||
isPassRequired: boolean,
|
isPassRequired: boolean;
|
||||||
valid: boolean
|
valid: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
function validatePkeyAndPass(pkey: string, pass: string): validated {
|
function validatePkeyAndPass(pkey: string, pass: string): Validated {
|
||||||
const fixedPkey = fixPkey(pkey);
|
const fixedPkey = fixPkey(pkey);
|
||||||
const validPkey = isValidPrivKey(fixedPkey);
|
const validPkey = isValidPrivKey(fixedPkey);
|
||||||
const validEncPkey = isValidEncryptedPrivKey(fixedPkey);
|
const validEncPkey = isValidEncryptedPrivKey(fixedPkey);
|
||||||
|
@ -46,13 +45,13 @@ function validatePkeyAndPass(pkey: string, pass: string): validated {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class PrivateKeyDecrypt extends Component {
|
export default class PrivateKeyDecrypt extends Component {
|
||||||
props: {
|
public props: {
|
||||||
value: PrivateKeyValue,
|
value: PrivateKeyValue;
|
||||||
onChange: (value: PrivateKeyValue) => void,
|
onChange(value: PrivateKeyValue): void;
|
||||||
onUnlock: () => void
|
onUnlock(): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { key, password } = this.props.value;
|
const { key, password } = this.props.value;
|
||||||
const { isValidPkey, isPassRequired } = validatePkeyAndPass(key, password);
|
const { isValidPkey, isPassRequired } = validatePkeyAndPass(key, password);
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ export default class PrivateKeyDecrypt extends Component {
|
||||||
onChange={this.onPkeyChange}
|
onChange={this.onPkeyChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
placeholder={translateRaw('x_PrivKey2')}
|
placeholder={translateRaw('x_PrivKey2')}
|
||||||
rows="4"
|
rows={4}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{isValidPkey &&
|
{isValidPkey &&
|
||||||
|
@ -97,17 +96,17 @@ export default class PrivateKeyDecrypt extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPkeyChange = (e: SyntheticInputEvent) => {
|
public onPkeyChange = (e: React.SyntheticEvent<HTMLTextAreaElement>) => {
|
||||||
const pkey = e.target.value;
|
const pkey = (e.target as HTMLInputElement).value;
|
||||||
const pass = this.props.value.password;
|
const pass = this.props.value.password;
|
||||||
const { fixedPkey, valid } = validatePkeyAndPass(pkey, pass);
|
const { fixedPkey, valid } = validatePkeyAndPass(pkey, pass);
|
||||||
|
|
||||||
this.props.onChange({ ...this.props.value, key: fixedPkey, valid });
|
this.props.onChange({ ...this.props.value, key: fixedPkey, valid });
|
||||||
};
|
};
|
||||||
|
|
||||||
onPasswordChange = (e: SyntheticInputEvent) => {
|
public onPasswordChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||||
const pkey = this.props.value.key;
|
const pkey = this.props.value.key;
|
||||||
const pass = e.target.value;
|
const pass = (e.target as HTMLInputElement).value;
|
||||||
const { valid } = validatePkeyAndPass(pkey, pass);
|
const { valid } = validatePkeyAndPass(pkey, pass);
|
||||||
|
|
||||||
this.props.onChange({
|
this.props.onChange({
|
||||||
|
@ -117,7 +116,7 @@ export default class PrivateKeyDecrypt extends Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onKeyDown = (e: SyntheticKeyboardEvent) => {
|
public onKeyDown = (e: any) => {
|
||||||
if (e.keyCode === 13) {
|
if (e.keyCode === 13) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
|
@ -1,24 +1,25 @@
|
||||||
// @flow
|
import DPATHS from 'config/dpaths';
|
||||||
import './Trezor.scss';
|
import TrezorWallet from 'libs/wallet/trezor';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import translate from 'translations';
|
import translate, { translateRaw } from 'translations';
|
||||||
import TrezorConnect from 'vendor/trezor-connect';
|
import TrezorConnect from 'vendor/trezor-connect';
|
||||||
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
import DeterministicWalletsModal from './DeterministicWalletsModal';
|
||||||
import TrezorWallet from 'libs/wallet/trezor';
|
import './Trezor.scss';
|
||||||
import DPATHS from 'config/dpaths.js';
|
|
||||||
const DEFAULT_PATH = DPATHS.TREZOR[0].value;
|
const DEFAULT_PATH = DPATHS.TREZOR[0].value;
|
||||||
|
|
||||||
type State = {
|
interface Props {
|
||||||
publicKey: string,
|
onUnlock(param: any): void;
|
||||||
chainCode: string,
|
}
|
||||||
dPath: string,
|
interface State {
|
||||||
error: ?string,
|
publicKey: string;
|
||||||
isLoading: boolean
|
chainCode: string;
|
||||||
};
|
dPath: string;
|
||||||
|
error: string | null;
|
||||||
|
isLoading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export default class TrezorDecrypt extends Component {
|
export default class TrezorDecrypt extends Component<Props, State> {
|
||||||
props: { onUnlock: any => void };
|
public state: State = {
|
||||||
state: State = {
|
|
||||||
publicKey: '',
|
publicKey: '',
|
||||||
chainCode: '',
|
chainCode: '',
|
||||||
dPath: DEFAULT_PATH,
|
dPath: DEFAULT_PATH,
|
||||||
|
@ -26,50 +27,7 @@ export default class TrezorDecrypt extends Component {
|
||||||
isLoading: false
|
isLoading: false
|
||||||
};
|
};
|
||||||
|
|
||||||
_handlePathChange = (dPath: string) => {
|
public render() {
|
||||||
this._handleConnect(dPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleConnect = (dPath: string = this.state.dPath) => {
|
|
||||||
this.setState({
|
|
||||||
isLoading: true,
|
|
||||||
error: null
|
|
||||||
});
|
|
||||||
|
|
||||||
TrezorConnect.getXPubKey(
|
|
||||||
dPath,
|
|
||||||
res => {
|
|
||||||
if (res.success) {
|
|
||||||
this.setState({
|
|
||||||
dPath,
|
|
||||||
publicKey: res.publicKey,
|
|
||||||
chainCode: res.chainCode,
|
|
||||||
isLoading: false
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
error: res.error,
|
|
||||||
isLoading: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'1.5.2'
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleCancel = () => {
|
|
||||||
this.setState({
|
|
||||||
publicKey: '',
|
|
||||||
chainCode: '',
|
|
||||||
dPath: DEFAULT_PATH
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_handleUnlock = (address: string, index: number) => {
|
|
||||||
this.props.onUnlock(new TrezorWallet(address, this.state.dPath, index));
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { dPath, publicKey, chainCode, error, isLoading } = this.state;
|
const { dPath, publicKey, chainCode, error, isLoading } = this.state;
|
||||||
const showErr = error ? 'is-showing' : '';
|
const showErr = error ? 'is-showing' : '';
|
||||||
|
|
||||||
|
@ -77,7 +35,7 @@ export default class TrezorDecrypt extends Component {
|
||||||
<section className="TrezorDecrypt col-md-4 col-sm-6">
|
<section className="TrezorDecrypt col-md-4 col-sm-6">
|
||||||
<button
|
<button
|
||||||
className="TrezorDecrypt-decrypt btn btn-primary btn-lg"
|
className="TrezorDecrypt-decrypt btn btn-primary btn-lg"
|
||||||
onClick={() => this._handleConnect()}
|
onClick={this.handleNullConnect}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
>
|
>
|
||||||
{isLoading ? 'Unlocking...' : translate('ADD_Trezor_scan')}
|
{isLoading ? 'Unlocking...' : translate('ADD_Trezor_scan')}
|
||||||
|
@ -113,12 +71,60 @@ export default class TrezorDecrypt extends Component {
|
||||||
chainCode={chainCode}
|
chainCode={chainCode}
|
||||||
dPath={dPath}
|
dPath={dPath}
|
||||||
dPaths={DPATHS.TREZOR}
|
dPaths={DPATHS.TREZOR}
|
||||||
onCancel={this._handleCancel}
|
onCancel={this.handleCancel}
|
||||||
onConfirmAddress={this._handleUnlock}
|
onConfirmAddress={this.handleUnlock}
|
||||||
onPathChange={this._handlePathChange}
|
onPathChange={this.handlePathChange}
|
||||||
walletType={translate('x_Trezor', true)}
|
walletType={translateRaw('x_Trezor')}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handlePathChange = (dPath: string) => {
|
||||||
|
this.handleConnect(dPath);
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleConnect = (dPath: string = this.state.dPath): void => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: true,
|
||||||
|
error: null
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: type vendor file
|
||||||
|
(TrezorConnect as any).getXPubKey(
|
||||||
|
dPath,
|
||||||
|
res => {
|
||||||
|
if (res.success) {
|
||||||
|
this.setState({
|
||||||
|
dPath,
|
||||||
|
publicKey: res.publicKey,
|
||||||
|
chainCode: res.chainCode,
|
||||||
|
isLoading: false
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
error: res.error,
|
||||||
|
isLoading: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'1.5.2'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleCancel = () => {
|
||||||
|
this.setState({
|
||||||
|
publicKey: '',
|
||||||
|
chainCode: '',
|
||||||
|
dPath: DEFAULT_PATH
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleUnlock = (address: string, index: number) => {
|
||||||
|
this.props.onUnlock(new TrezorWallet(address, this.state.dPath, index));
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleNullConnect(): void {
|
||||||
|
return this.handleConnect();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,11 +2,13 @@ import React, { Component } from 'react';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
|
|
||||||
export default class ViewOnlyDecrypt extends Component {
|
export default class ViewOnlyDecrypt extends Component {
|
||||||
render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<section className="col-md-4 col-sm-6">
|
<section className="col-md-4 col-sm-6">
|
||||||
<div id="selectedUploadKey">
|
<div id="selectedUploadKey">
|
||||||
<h4>{translate('ADD_Radio_2_alt')}</h4>
|
<h4>
|
||||||
|
{translate('ADD_Radio_2_alt')}
|
||||||
|
</h4>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<input type="file" id="fselector" />
|
<input type="file" id="fselector" />
|
||||||
|
@ -14,7 +16,7 @@ export default class ViewOnlyDecrypt extends Component {
|
||||||
<a
|
<a
|
||||||
className="btn-file marg-v-sm"
|
className="btn-file marg-v-sm"
|
||||||
id="aria1"
|
id="aria1"
|
||||||
tabIndex="0"
|
tabIndex={0}
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
{translate('ADD_Radio_2_short')}
|
{translate('ADD_Radio_2_short')}
|
|
@ -1,22 +1,24 @@
|
||||||
// @flow
|
import {
|
||||||
|
setWallet,
|
||||||
|
unlockKeystore,
|
||||||
|
UnlockKeystoreAction,
|
||||||
|
unlockMnemonic,
|
||||||
|
UnlockMnemonicAction,
|
||||||
|
unlockPrivateKey,
|
||||||
|
UnlockPrivateKeyAction
|
||||||
|
} from 'actions/wallet';
|
||||||
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
import map from 'lodash/map';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
import translate from 'translations';
|
import translate from 'translations';
|
||||||
import KeystoreDecrypt from './Keystore';
|
import KeystoreDecrypt from './Keystore';
|
||||||
import PrivateKeyDecrypt from './PrivateKey';
|
|
||||||
import type { PrivateKeyValue } from './PrivateKey';
|
|
||||||
import MnemonicDecrypt from './Mnemonic';
|
|
||||||
import LedgerNanoSDecrypt from './LedgerNano';
|
import LedgerNanoSDecrypt from './LedgerNano';
|
||||||
|
import MnemonicDecrypt from './Mnemonic';
|
||||||
|
import PrivateKeyDecrypt, { PrivateKeyValue } from './PrivateKey';
|
||||||
import TrezorDecrypt from './Trezor';
|
import TrezorDecrypt from './Trezor';
|
||||||
import ViewOnlyDecrypt from './ViewOnly';
|
import ViewOnlyDecrypt from './ViewOnly';
|
||||||
import map from 'lodash/map';
|
|
||||||
import {
|
|
||||||
unlockPrivateKey,
|
|
||||||
unlockKeystore,
|
|
||||||
unlockMnemonic,
|
|
||||||
setWallet
|
|
||||||
} from 'actions/wallet';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import isEmpty from 'lodash/isEmpty';
|
|
||||||
|
|
||||||
const WALLETS = {
|
const WALLETS = {
|
||||||
'keystore-file': {
|
'keystore-file': {
|
||||||
|
@ -26,7 +28,8 @@ const WALLETS = {
|
||||||
file: '',
|
file: '',
|
||||||
password: ''
|
password: ''
|
||||||
},
|
},
|
||||||
unlock: unlockKeystore
|
unlock: unlockKeystore,
|
||||||
|
disabled: false
|
||||||
},
|
},
|
||||||
'private-key': {
|
'private-key': {
|
||||||
lid: 'x_PrivKey2',
|
lid: 'x_PrivKey2',
|
||||||
|
@ -35,13 +38,15 @@ const WALLETS = {
|
||||||
key: '',
|
key: '',
|
||||||
password: ''
|
password: ''
|
||||||
},
|
},
|
||||||
unlock: unlockPrivateKey
|
unlock: unlockPrivateKey,
|
||||||
|
disabled: false
|
||||||
},
|
},
|
||||||
'mnemonic-phrase': {
|
'mnemonic-phrase': {
|
||||||
lid: 'x_Mnemonic',
|
lid: 'x_Mnemonic',
|
||||||
component: MnemonicDecrypt,
|
component: MnemonicDecrypt,
|
||||||
initialParams: {},
|
initialParams: {},
|
||||||
unlock: unlockMnemonic
|
unlock: unlockMnemonic,
|
||||||
|
disabled: false
|
||||||
},
|
},
|
||||||
'ledger-nano-s': {
|
'ledger-nano-s': {
|
||||||
lid: 'x_Ledger',
|
lid: 'x_Ledger',
|
||||||
|
@ -52,7 +57,8 @@ const WALLETS = {
|
||||||
lid: 'x_Trezor',
|
lid: 'x_Trezor',
|
||||||
component: TrezorDecrypt,
|
component: TrezorDecrypt,
|
||||||
initialParams: {},
|
initialParams: {},
|
||||||
unlock: setWallet
|
unlock: setWallet,
|
||||||
|
disabled: false
|
||||||
},
|
},
|
||||||
'view-only': {
|
'view-only': {
|
||||||
lid: 'View with Address Only',
|
lid: 'View with Address Only',
|
||||||
|
@ -63,22 +69,25 @@ const WALLETS = {
|
||||||
|
|
||||||
type UnlockParams = {} | PrivateKeyValue;
|
type UnlockParams = {} | PrivateKeyValue;
|
||||||
|
|
||||||
type State = {
|
interface Props {
|
||||||
selectedWalletKey: string,
|
// FIXME
|
||||||
value: UnlockParams
|
dispatch: Dispatch<
|
||||||
};
|
UnlockKeystoreAction | UnlockMnemonicAction | UnlockPrivateKeyAction
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
export class WalletDecrypt extends Component {
|
interface State {
|
||||||
props: {
|
selectedWalletKey: string;
|
||||||
// FIXME
|
value: UnlockParams;
|
||||||
dispatch: (action: any) => void
|
}
|
||||||
};
|
|
||||||
state: State = {
|
export class WalletDecrypt extends Component<Props, State> {
|
||||||
|
public state: State = {
|
||||||
selectedWalletKey: 'keystore-file',
|
selectedWalletKey: 'keystore-file',
|
||||||
value: WALLETS['keystore-file'].initialParams
|
value: WALLETS['keystore-file'].initialParams
|
||||||
};
|
};
|
||||||
|
|
||||||
getDecryptionComponent() {
|
public getDecryptionComponent() {
|
||||||
const { selectedWalletKey, value } = this.state;
|
const { selectedWalletKey, value } = this.state;
|
||||||
const selectedWallet = WALLETS[selectedWalletKey];
|
const selectedWallet = WALLETS[selectedWalletKey];
|
||||||
|
|
||||||
|
@ -95,7 +104,7 @@ export class WalletDecrypt extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildWalletOptions() {
|
public buildWalletOptions() {
|
||||||
return map(WALLETS, (wallet, key) => {
|
return map(WALLETS, (wallet, key) => {
|
||||||
const isSelected = this.state.selectedWalletKey === key;
|
const isSelected = this.state.selectedWalletKey === key;
|
||||||
|
|
||||||
|
@ -119,20 +128,22 @@ export class WalletDecrypt extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDecryptionChoiceChange = (event: SyntheticInputEvent) => {
|
public handleDecryptionChoiceChange = (
|
||||||
const wallet = WALLETS[event.target.value];
|
event: React.SyntheticEvent<HTMLInputElement>
|
||||||
|
) => {
|
||||||
|
const wallet = WALLETS[(event.target as HTMLInputElement).value];
|
||||||
|
|
||||||
if (!wallet) {
|
if (!wallet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedWalletKey: event.target.value,
|
selectedWalletKey: (event.target as HTMLInputElement).value,
|
||||||
value: wallet.initialParams
|
value: wallet.initialParams
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const decryptionComponent = this.getDecryptionComponent();
|
const decryptionComponent = this.getDecryptionComponent();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -146,14 +157,14 @@ export class WalletDecrypt extends Component {
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{decryptionComponent}
|
{decryptionComponent}
|
||||||
{!!this.state.value.valid &&
|
{!!(this.state.value as PrivateKeyValue).valid &&
|
||||||
<section className="col-md-4 col-sm-6">
|
<section className="col-md-4 col-sm-6">
|
||||||
<h4 id="uploadbtntxt-wallet">
|
<h4 id="uploadbtntxt-wallet">
|
||||||
{translate('ADD_Label_6')}
|
{translate('ADD_Label_6')}
|
||||||
</h4>
|
</h4>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<a
|
<a
|
||||||
tabIndex="0"
|
tabIndex={0}
|
||||||
role="button"
|
role="button"
|
||||||
className="btn btn-primary btn-block"
|
className="btn btn-primary btn-block"
|
||||||
onClick={this.onUnlock}
|
onClick={this.onUnlock}
|
||||||
|
@ -166,11 +177,11 @@ export class WalletDecrypt extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (value: UnlockParams) => {
|
public onChange = (value: UnlockParams) => {
|
||||||
this.setState({ value });
|
this.setState({ value });
|
||||||
};
|
};
|
||||||
|
|
||||||
onUnlock = (payload: any) => {
|
public onUnlock = (payload: any) => {
|
||||||
// some components (TrezorDecrypt) don't take an onChange prop, and thus this.state.value will remain unpopulated.
|
// some components (TrezorDecrypt) don't take an onChange prop, and thus this.state.value will remain unpopulated.
|
||||||
// in this case, we can expect the payload to contain the unlocked wallet info.
|
// in this case, we can expect the payload to contain the unlocked wallet info.
|
||||||
const unlockValue =
|
const unlockValue =
|
|
@ -1,5 +1,3 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
export { default as Header } from './Header';
|
export { default as Header } from './Header';
|
||||||
export { default as Footer } from './Footer';
|
export { default as Footer } from './Footer';
|
||||||
export { default as Root } from './Root';
|
export { default as Root } from './Root';
|
|
@ -1,38 +1,31 @@
|
||||||
// @flow
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
type Props<T> = {
|
interface Props<T> {
|
||||||
value: T,
|
value: T;
|
||||||
options: T[],
|
options: T[];
|
||||||
ariaLabel: string,
|
ariaLabel: string;
|
||||||
formatTitle: (option: T) => any,
|
extra?: any;
|
||||||
extra?: any,
|
formatTitle(option: T): any;
|
||||||
onChange: (value: T) => void
|
onChange(value: T): void;
|
||||||
};
|
}
|
||||||
|
|
||||||
type State = {
|
interface State {
|
||||||
expanded: boolean
|
expanded: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class DropdownComponent<T: *> extends Component<
|
export default class DropdownComponent<T> extends Component<Props<T>, State> {
|
||||||
void,
|
public state = {
|
||||||
Props<T>,
|
|
||||||
State
|
|
||||||
> {
|
|
||||||
props: Props<T>;
|
|
||||||
|
|
||||||
state = {
|
|
||||||
expanded: false
|
expanded: false
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { options, value, ariaLabel, extra } = this.props;
|
const { options, value, ariaLabel, extra } = this.props;
|
||||||
const { expanded } = this.state;
|
const { expanded } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={`dropdown ${expanded ? 'open' : ''}`}>
|
<span className={`dropdown ${expanded ? 'open' : ''}`}>
|
||||||
<a
|
<a
|
||||||
tabIndex="0"
|
tabIndex={0}
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
|
@ -62,11 +55,11 @@ export default class DropdownComponent<T: *> extends Component<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
formatTitle(option: any) {
|
public formatTitle(option: any) {
|
||||||
return this.props.formatTitle(option);
|
return this.props.formatTitle(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleExpanded = () => {
|
public toggleExpanded = () => {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return {
|
return {
|
||||||
expanded: !state.expanded
|
expanded: !state.expanded
|
||||||
|
@ -74,7 +67,7 @@ export default class DropdownComponent<T: *> extends Component<
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onChange = (value: any) => {
|
public onChange = (value: any) => {
|
||||||
this.props.onChange(value);
|
this.props.onChange(value);
|
||||||
this.setState({ expanded: false });
|
this.setState({ expanded: false });
|
||||||
};
|
};
|
|
@ -1,13 +1,11 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { toDataUrl } from 'ethereum-blockies';
|
import { toDataUrl } from 'ethereum-blockies';
|
||||||
import { isValidETHAddress } from 'libs/validators';
|
import { isValidETHAddress } from 'libs/validators';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
address: string,
|
address: string;
|
||||||
size?: string
|
size?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default function Identicon(props: Props) {
|
export default function Identicon(props: Props) {
|
||||||
const size = props.size || '4rem';
|
const size = props.size || '4rem';
|
|
@ -1,61 +1,83 @@
|
||||||
// @flow
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import closeIcon from 'assets/images/icon-x.svg';
|
import closeIcon from 'assets/images/icon-x.svg';
|
||||||
|
import React, { Component } from 'react';
|
||||||
import './Modal.scss';
|
import './Modal.scss';
|
||||||
|
|
||||||
type Props = {
|
export interface IButton {
|
||||||
isOpen?: boolean,
|
text: string;
|
||||||
title: string,
|
type?:
|
||||||
buttons: {
|
| 'default'
|
||||||
text: string,
|
| 'primary'
|
||||||
type?:
|
| 'success'
|
||||||
| 'default'
|
| 'info'
|
||||||
| 'primary'
|
| 'warning'
|
||||||
| 'success'
|
| 'danger'
|
||||||
| 'info'
|
| 'link';
|
||||||
| 'warning'
|
disabled?: boolean;
|
||||||
| 'danger'
|
onClick?(): void;
|
||||||
| 'link',
|
}
|
||||||
disabled?: boolean,
|
interface Props {
|
||||||
onClick?: () => void
|
isOpen?: boolean;
|
||||||
}[],
|
title: string;
|
||||||
handleClose: () => void,
|
disableButtons?: boolean;
|
||||||
disableButtons?: boolean,
|
children: any;
|
||||||
children: any
|
buttons: IButton[];
|
||||||
};
|
handleClose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
export default class Modal extends Component {
|
export default class Modal extends Component<Props, {}> {
|
||||||
props: Props;
|
public componentDidMount() {
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.updateBodyClass();
|
this.updateBodyClass();
|
||||||
document.addEventListener('keydown', this._escapeListner);
|
document.addEventListener('keydown', this.escapeListner);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
public componentDidUpdate() {
|
||||||
this.updateBodyClass();
|
this.updateBodyClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBodyClass() {
|
public updateBodyClass() {
|
||||||
// $FlowFixMe
|
|
||||||
document.body.classList.toggle('no-scroll', !!this.props.isOpen);
|
document.body.classList.toggle('no-scroll', !!this.props.isOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
document.removeEventListener('keydown', this._escapeListner);
|
document.removeEventListener('keydown', this.escapeListner);
|
||||||
// $FlowFixMe
|
|
||||||
document.body.classList.remove('no-scroll');
|
document.body.classList.remove('no-scroll');
|
||||||
}
|
}
|
||||||
|
|
||||||
_escapeListner = (ev: KeyboardEvent) => {
|
public render() {
|
||||||
|
const { isOpen, title, children, buttons, handleClose } = this.props;
|
||||||
|
const hasButtons = buttons && buttons.length;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={`Modalshade ${isOpen ? 'is-open' : ''}`} />
|
||||||
|
<div className={`Modal ${isOpen ? 'is-open' : ''}`}>
|
||||||
|
<div className="Modal-header">
|
||||||
|
<h2 className="Modal-header-title">
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
<button className="Modal-header-close" onClick={handleClose}>
|
||||||
|
<img className="Modal-header-close-icon" src={closeIcon} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="Modal-content">
|
||||||
|
{isOpen && children}
|
||||||
|
</div>
|
||||||
|
{hasButtons &&
|
||||||
|
<div className="Modal-footer">
|
||||||
|
{this.renderButtons()}
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private escapeListner = (ev: KeyboardEvent) => {
|
||||||
// Don't trigger if they hit escape while on an input
|
// Don't trigger if they hit escape while on an input
|
||||||
if (ev.target) {
|
if (ev.target) {
|
||||||
if (
|
if (
|
||||||
ev.target.tagName === 'INPUT' ||
|
(ev.target as HTMLElement).tagName === 'INPUT' ||
|
||||||
ev.target.tagName === 'SELECT' ||
|
(ev.target as HTMLElement).tagName === 'SELECT' ||
|
||||||
ev.target.tagName === 'TEXTAREA' ||
|
(ev.target as HTMLElement).tagName === 'TEXTAREA' ||
|
||||||
ev.target.isContentEditable
|
(ev.target as HTMLElement).isContentEditable
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +88,7 @@ export default class Modal extends Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_renderButtons = () => {
|
private renderButtons = () => {
|
||||||
const { disableButtons, buttons } = this.props;
|
const { disableButtons, buttons } = this.props;
|
||||||
|
|
||||||
return buttons.map((btn, idx) => {
|
return buttons.map((btn, idx) => {
|
||||||
|
@ -88,32 +110,4 @@ export default class Modal extends Component {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
|
||||||
const { isOpen, title, children, buttons, handleClose } = this.props;
|
|
||||||
const hasButtons = buttons && buttons.length;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className={`Modalshade ${isOpen ? 'is-open' : ''}`} />
|
|
||||||
<div className={`Modal ${isOpen ? 'is-open' : ''}`}>
|
|
||||||
<div className="Modal-header">
|
|
||||||
<h2 className="Modal-header-title">
|
|
||||||
{title}
|
|
||||||
</h2>
|
|
||||||
<button className="Modal-header-close" onClick={handleClose}>
|
|
||||||
<img className="Modal-header-close-icon" src={closeIcon} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="Modal-content">
|
|
||||||
{isOpen && children}
|
|
||||||
</div>
|
|
||||||
{hasButtons &&
|
|
||||||
<div className="Modal-footer">
|
|
||||||
{this._renderButtons()}
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,48 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
type AAttributes = {
|
|
||||||
charset?: string,
|
|
||||||
coords?: string,
|
|
||||||
download?: string,
|
|
||||||
href: string,
|
|
||||||
hreflang?: string,
|
|
||||||
media?: string,
|
|
||||||
name?: string,
|
|
||||||
rel?:
|
|
||||||
| 'alternate'
|
|
||||||
| 'author'
|
|
||||||
| 'bookmark'
|
|
||||||
| 'external'
|
|
||||||
| 'help'
|
|
||||||
| 'license'
|
|
||||||
| 'next'
|
|
||||||
| 'nofollow'
|
|
||||||
| 'noreferrer'
|
|
||||||
| 'noopener'
|
|
||||||
| 'prev'
|
|
||||||
| 'search'
|
|
||||||
| 'tag',
|
|
||||||
rev?: string,
|
|
||||||
shape?: 'default' | 'rect' | 'circle' | 'poly',
|
|
||||||
target?: '_blank' | '_parent' | '_self' | '_top',
|
|
||||||
type?: string
|
|
||||||
};
|
|
||||||
|
|
||||||
type NewTabLinkProps = {
|
|
||||||
content?: React.Element<any> | string,
|
|
||||||
children?: React.Element<any> | string,
|
|
||||||
rest?: AAttributes
|
|
||||||
};
|
|
||||||
|
|
||||||
const NewTabLink = ({
|
|
||||||
/* eslint-disable */
|
|
||||||
content, // ESLINT: prop-types validation error, to be fixed in #122
|
|
||||||
children /* eslint-enable */,
|
|
||||||
...rest
|
|
||||||
}: NewTabLinkProps) =>
|
|
||||||
<a target="_blank" rel="noopener" {...rest}>
|
|
||||||
{content || children} {/* Keep content for short-hand text insertion */}
|
|
||||||
</a>;
|
|
||||||
|
|
||||||
export default NewTabLink;
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface AAttributes {
|
||||||
|
charset?: string;
|
||||||
|
coords?: string;
|
||||||
|
download?: string;
|
||||||
|
href: string;
|
||||||
|
hreflang?: string;
|
||||||
|
media?: string;
|
||||||
|
name?: string;
|
||||||
|
rel?:
|
||||||
|
| 'alternate'
|
||||||
|
| 'author'
|
||||||
|
| 'bookmark'
|
||||||
|
| 'external'
|
||||||
|
| 'help'
|
||||||
|
| 'license'
|
||||||
|
| 'next'
|
||||||
|
| 'nofollow'
|
||||||
|
| 'noreferrer'
|
||||||
|
| 'noopener'
|
||||||
|
| 'prev'
|
||||||
|
| 'search'
|
||||||
|
| 'tag';
|
||||||
|
rev?: string;
|
||||||
|
shape?: 'default' | 'rect' | 'circle' | 'poly';
|
||||||
|
target?: '_blank' | '_parent' | '_self' | '_top';
|
||||||
|
type?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NewTabLinkProps extends AAttributes {
|
||||||
|
content?: React.ReactElement<any> | string;
|
||||||
|
children?: React.ReactElement<any> | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NewTabLink = ({ content, children, ...rest }: NewTabLinkProps) =>
|
||||||
|
<a target="_blank" rel="noopener" {...rest}>
|
||||||
|
{content || children} {/* Keep content for short-hand text insertion */}
|
||||||
|
</a>;
|
||||||
|
|
||||||
|
export default NewTabLink;
|
|
@ -1,59 +1,36 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
|
||||||
import QRCodeLib from 'qrcode';
|
import QRCodeLib from 'qrcode';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
// FIXME should store limited amount if history
|
// FIXME should store limited amount if history
|
||||||
// data -> qr cache
|
// data -> qr cache
|
||||||
const cache: { [key: string]: string } = {};
|
const cache: { [key: string]: string } = {};
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
data: string
|
data: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
type State = {
|
interface State {
|
||||||
qr?: string
|
qr?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class QRCode extends React.Component {
|
export default class QRCode extends React.Component<Props, State> {
|
||||||
props: Props;
|
public state: State = {}
|
||||||
state: State = {};
|
public componentWillMount() {
|
||||||
|
console.error(this.props.data)
|
||||||
componentWillMount() {
|
|
||||||
// Start generating QR codes immediately
|
// Start generating QR codes immediately
|
||||||
this._generateQrCode(this.props.data);
|
this.generateQrCode(this.props.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
|
console.error(this.props.data)
|
||||||
|
|
||||||
// Regenerate QR codes if props change
|
// Regenerate QR codes if props change
|
||||||
if (nextProps.data !== this.props.data) {
|
if (nextProps.data !== this.props.data) {
|
||||||
this._generateQrCode(nextProps.data);
|
this.generateQrCode(nextProps.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_generateQrCode(value: string) {
|
public render() {
|
||||||
if (cache[value]) {
|
|
||||||
this.setState({ qr: cache[value] });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QRCodeLib.toDataURL(
|
|
||||||
value,
|
|
||||||
{
|
|
||||||
color: {
|
|
||||||
dark: '#000',
|
|
||||||
light: '#fff'
|
|
||||||
},
|
|
||||||
margin: 0,
|
|
||||||
errorCorrectionLevel: 'H'
|
|
||||||
},
|
|
||||||
(err, qr) => {
|
|
||||||
if (err) return;
|
|
||||||
cache[value] = qr;
|
|
||||||
this.setState({ qr });
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { qr } = this.state;
|
const { qr } = this.state;
|
||||||
if (!qr) {
|
if (!qr) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -68,4 +45,30 @@ export default class QRCode extends React.Component {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private generateQrCode(value: string) {
|
||||||
|
if (cache[value]) {
|
||||||
|
this.setState({ qr: cache[value] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.error(value, 'Value')
|
||||||
|
QRCodeLib.toDataURL(
|
||||||
|
value,
|
||||||
|
{
|
||||||
|
color: {
|
||||||
|
dark: '#000',
|
||||||
|
light: '#fff'
|
||||||
|
},
|
||||||
|
margin: 0,
|
||||||
|
errorCorrectionLevel: 'H'
|
||||||
|
},
|
||||||
|
(err, qr) => {
|
||||||
|
if (err) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cache[value] = qr;
|
||||||
|
this.setState({ qr });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,9 @@
|
||||||
// @flow
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import type { Element } from 'react';
|
import Spinner from './Spinner';
|
||||||
|
|
||||||
const DEFAULT_BUTTON_TYPE = 'primary';
|
const DEFAULT_BUTTON_TYPE = 'primary';
|
||||||
const DEFAULT_BUTTON_SIZE = 'lg';
|
const DEFAULT_BUTTON_SIZE = 'lg';
|
||||||
|
|
||||||
import Spinner from './Spinner';
|
|
||||||
|
|
||||||
type ButtonType =
|
type ButtonType =
|
||||||
| 'default'
|
| 'default'
|
||||||
| 'primary'
|
| 'primary'
|
||||||
|
@ -16,26 +13,24 @@ type ButtonType =
|
||||||
| 'danger';
|
| 'danger';
|
||||||
type ButtonSize = 'lg' | 'sm' | 'xs';
|
type ButtonSize = 'lg' | 'sm' | 'xs';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
onClick: () => any,
|
text: React.ReactElement<any> | string;
|
||||||
text: Element<*> | string,
|
loading?: boolean;
|
||||||
loading?: boolean,
|
disabled?: boolean;
|
||||||
disabled?: boolean,
|
loadingText?: string;
|
||||||
loadingText?: string,
|
size?: ButtonSize;
|
||||||
size?: ButtonSize,
|
type?: ButtonType;
|
||||||
type?: ButtonType
|
onClick(): any;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class SimpleButton extends Component {
|
export default class SimpleButton extends Component<Props, {}> {
|
||||||
props: Props;
|
public computedClass = () => {
|
||||||
|
|
||||||
computedClass = () => {
|
|
||||||
return `btn btn-${this.props.size || DEFAULT_BUTTON_TYPE} btn-${this.props
|
return `btn btn-${this.props.size || DEFAULT_BUTTON_TYPE} btn-${this.props
|
||||||
.type || DEFAULT_BUTTON_SIZE}`;
|
.type || DEFAULT_BUTTON_SIZE}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
let { loading, disabled, loadingText, text, onClick } = this.props;
|
const { loading, disabled, loadingText, text, onClick } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
|
@ -1,33 +1,32 @@
|
||||||
// @flow
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
value?: string,
|
value?: string;
|
||||||
options: string[],
|
options: string[];
|
||||||
onChange: (value: string) => void
|
onChange(value: string): void;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class SimpleDropDown extends Component {
|
interface State {
|
||||||
props: Props;
|
expanded: boolean;
|
||||||
state: {
|
}
|
||||||
expanded: boolean
|
export default class SimpleDropDown extends Component<Props, State> {
|
||||||
} = {
|
public state = {
|
||||||
expanded: false
|
expanded: false
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleExpanded = () => {
|
public toggleExpanded = () => {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return { expanded: !state.expanded };
|
return { expanded: !state.expanded };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onClick = (event: SyntheticInputEvent) => {
|
public onClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
|
||||||
const value = event.target.getAttribute('data-value') || '';
|
const value = (event.target as HTMLAnchorElement).getAttribute('data-value') || '';
|
||||||
this.props.onChange(value);
|
this.props.onChange(value);
|
||||||
this.setState({ expanded: false });
|
this.setState({ expanded: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
const { options, value } = this.props;
|
const { options, value } = this.props;
|
||||||
const { expanded } = this.state;
|
const { expanded } = this.state;
|
||||||
return (
|
return (
|
|
@ -1,16 +1,13 @@
|
||||||
// @flow
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
value?: string,
|
value?: string;
|
||||||
options: string[],
|
options: string[];
|
||||||
onChange: (event: SyntheticInputEvent) => void
|
onChange(event: React.SyntheticEvent<HTMLSpanElement>): void;
|
||||||
};
|
}
|
||||||
|
|
||||||
export default class SimpleSelect extends Component {
|
export default class SimpleSelect extends Component<Props, {}> {
|
||||||
props: Props;
|
public render() {
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
value={this.props.value || this.props.options[0]}
|
value={this.props.value || this.props.options[0]}
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
type size = 'lg' | '2x' | '3x' | '4x' | '5x';
|
type Size = 'lg' | '2x' | '3x' | '4x' | '5x';
|
||||||
|
|
||||||
type SpinnerProps = {
|
interface SpinnerProps {
|
||||||
size?: size
|
size?: Size;
|
||||||
};
|
}
|
||||||
|
|
||||||
const Spinner = ({ size = 'fa-' }: SpinnerProps) => {
|
const Spinner = ({ size = 'fa-' }: SpinnerProps) => {
|
||||||
return <i className={`fa fa-spinner fa-spin fa-${size ? size : 'fw'}`} />;
|
return <i className={`fa fa-spinner fa-spin fa-${size ? size : 'fw'}`} />;
|
|
@ -1,30 +1,23 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import translate from 'translations';
|
|
||||||
import WalletDecrypt from 'components/WalletDecrypt';
|
import WalletDecrypt from 'components/WalletDecrypt';
|
||||||
import type { IWallet } from 'libs/wallet/IWallet';
|
import { IWallet } from 'libs/wallet/IWallet';
|
||||||
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import type { State } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
|
import translate from 'translations';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
title: string,
|
title: string;
|
||||||
wallet: IWallet
|
wallet: IWallet;
|
||||||
};
|
}
|
||||||
|
interface State {
|
||||||
export class UnlockHeader extends React.Component {
|
expanded: boolean;
|
||||||
props: Props;
|
}
|
||||||
static propTypes = {
|
export class UnlockHeader extends React.Component<Props, State> {
|
||||||
title: PropTypes.string.isRequired
|
public state = {
|
||||||
};
|
|
||||||
|
|
||||||
state: {
|
|
||||||
expanded: boolean
|
|
||||||
} = {
|
|
||||||
expanded: !this.props.wallet
|
expanded: !this.props.wallet
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props) {
|
public componentDidUpdate(prevProps: Props) {
|
||||||
if (this.props.wallet && this.props.wallet !== prevProps.wallet) {
|
if (this.props.wallet && this.props.wallet !== prevProps.wallet) {
|
||||||
this.setState({ expanded: false });
|
this.setState({ expanded: false });
|
||||||
}
|
}
|
||||||
|
@ -35,7 +28,7 @@ export class UnlockHeader extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<article className="collapse-container">
|
<article className="collapse-container">
|
||||||
<div onClick={this.toggleExpanded}>
|
<div onClick={this.toggleExpanded}>
|
||||||
|
@ -54,14 +47,14 @@ export class UnlockHeader extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleExpanded = () => {
|
public toggleExpanded = () => {
|
||||||
this.setState(state => {
|
this.setState(state => {
|
||||||
return { expanded: !state.expanded };
|
return { expanded: !state.expanded };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state: State) {
|
function mapStateToProps(state: AppState) {
|
||||||
return {
|
return {
|
||||||
wallet: state.wallet.inst
|
wallet: state.wallet.inst
|
||||||
};
|
};
|
|
@ -1,8 +1,6 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
export { default as Dropdown } from './Dropdown';
|
export { default as Dropdown } from './Dropdown';
|
||||||
export { default as Identicon } from './Identicon';
|
export { default as Identicon } from './Identicon';
|
||||||
export { default as Modal } from './Modal';
|
export { default as Modal } from './Modal';
|
||||||
export { default as UnlockHeader } from './UnlockHeader';
|
export { default as UnlockHeader } from './UnlockHeader';
|
||||||
export { default as QRCode } from './QRCode';
|
export { default as QRCode } from './QRCode';
|
||||||
export { default as NewTabLink } from './NewTabLink.jsx';
|
export { default as NewTabLink } from './NewTabLink';
|
|
@ -1,4 +1,4 @@
|
||||||
import { ETHTxExplorer, BTCTxExplorer } from './data';
|
import { BTCTxExplorer, ETHTxExplorer } from './data';
|
||||||
|
|
||||||
type SupportedDestinationKind = 'ETH' | 'BTC' | 'REP';
|
type SupportedDestinationKind = 'ETH' | 'BTC' | 'REP';
|
||||||
|
|
||||||
|
@ -16,16 +16,16 @@ const buffers = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// rate must be BTC[KIND]
|
// rate must be BTC[KIND]
|
||||||
export function kindMin(
|
export function generateKindMin(
|
||||||
BTCKINDRate: number,
|
BTCKINDRate: number,
|
||||||
kind: SupportedDestinationKind
|
kind: SupportedDestinationKind
|
||||||
): number {
|
): number {
|
||||||
const kindMin = BTCKINDRate * BTCMin;
|
const kindMinVal = BTCKINDRate * BTCMin;
|
||||||
return kindMin + kindMin * buffers[kind];
|
return kindMinVal + kindMinVal * buffers[kind];
|
||||||
}
|
}
|
||||||
|
|
||||||
// rate must be BTC[KIND]
|
// rate must be BTC[KIND]
|
||||||
export function kindMax(
|
export function generateKindMax(
|
||||||
BTCKINDRate: number,
|
BTCKINDRate: number,
|
||||||
kind: SupportedDestinationKind
|
kind: SupportedDestinationKind
|
||||||
): number {
|
): number {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue