1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-28 11:18:16 +00:00

Fix validation on send

This commit is contained in:
Vladimir Volek 2018-11-27 17:11:46 +01:00
parent ea3ad58d48
commit bf3dd1cfde
5 changed files with 118 additions and 66 deletions

View File

@ -3,6 +3,7 @@ import TrezorConnect from 'trezor-connect';
import type { import type {
GetState, Dispatch, ThunkAction, AsyncAction, GetState, Dispatch, ThunkAction, AsyncAction,
} from 'flowtype'; } from 'flowtype';
import { validateAddress } from 'utils/ethUtils';
import * as NOTIFICATION from 'actions/constants/notification'; import * as NOTIFICATION from 'actions/constants/notification';
import * as SIGN_VERIFY from './constants/signVerify'; import * as SIGN_VERIFY from './constants/signVerify';
@ -15,11 +16,19 @@ export type SignVerifyAction = {
type: typeof SIGN_VERIFY.CLEAR_VERIFY, type: typeof SIGN_VERIFY.CLEAR_VERIFY,
} | { } | {
type: typeof SIGN_VERIFY.INPUT_CHANGE, type: typeof SIGN_VERIFY.INPUT_CHANGE,
name: string, inputName: string,
value: string value: string
} | { } | {
type: typeof SIGN_VERIFY.TOUCH, type: typeof SIGN_VERIFY.TOUCH,
name: string, inputName: string,
} | {
type: typeof SIGN_VERIFY.ERROR,
inputName: string,
message: ?string
} | {
type: typeof SIGN_VERIFY.ERROR,
inputName: string,
message: ?string
} }
const sign = ( const sign = (
@ -55,13 +64,6 @@ const sign = (
title: 'Sign error', title: 'Sign error',
message: response.payload.error, message: response.payload.error,
cancelable: true, cancelable: true,
actions: [{
label: 'Try again',
callback: () => {
dispatch(sign(path, message, hex));
},
},
],
}, },
}); });
} }
@ -75,7 +77,17 @@ const verify = (
): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { ): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const selected = getState().wallet.selectedDevice; const selected = getState().wallet.selectedDevice;
if (!selected) return; if (!selected) return;
const hasError = validateAddress(address);
if (hasError) {
dispatch({
type: SIGN_VERIFY.ERROR,
inputName: 'verifyAddress',
message: validateAddress(address),
});
}
if (!hasError) {
const response = await TrezorConnect.ethereumVerifyMessage({ const response = await TrezorConnect.ethereumVerifyMessage({
device: { device: {
path: selected.path, path: selected.path,
@ -107,29 +119,29 @@ const verify = (
title: 'Verify error', title: 'Verify error',
message: response.payload.error, message: response.payload.error,
cancelable: true, cancelable: true,
actions: [
{
label: 'Try again',
callback: () => {
dispatch(verify(address, message, signature, hex));
},
},
],
}, },
}); });
} }
}
}; };
const inputChange = (name: string, value: string): ThunkAction => (dispatch: Dispatch): void => { const inputChange = (inputName: string, value: string): ThunkAction => (dispatch: Dispatch): void => {
dispatch({ dispatch({
type: SIGN_VERIFY.INPUT_CHANGE, type: SIGN_VERIFY.INPUT_CHANGE,
name, inputName,
value, value,
}); });
dispatch({ dispatch({
type: SIGN_VERIFY.TOUCH, type: SIGN_VERIFY.TOUCH,
name, inputName,
}); });
if (inputName === 'verifyAddress' && validateAddress(value) !== null) {
dispatch({
type: SIGN_VERIFY.ERROR,
inputName,
message: validateAddress(value),
});
}
}; };
const clearSign = (): ThunkAction => (dispatch: Dispatch): void => { const clearSign = (): ThunkAction => (dispatch: Dispatch): void => {

View File

@ -4,3 +4,4 @@ export const INPUT_CHANGE: 'sign__verify__input__change' = 'sign__verify__input_
export const TOUCH: 'sign__verify__input__touch' = 'sign__verify__input__touch'; export const TOUCH: 'sign__verify__input__touch' = 'sign__verify__input__touch';
export const CLEAR_SIGN: 'sign__verify__sign__clear' = 'sign__verify__sign__clear'; export const CLEAR_SIGN: 'sign__verify__sign__clear' = 'sign__verify__sign__clear';
export const CLEAR_VERIFY: 'sign__verify__verify__clear' = 'sign__verify__verify__clear'; export const CLEAR_VERIFY: 'sign__verify__verify__clear' = 'sign__verify__verify__clear';
export const ERROR: 'sign__verify__error' = 'sign__verify__error';

View File

@ -4,6 +4,11 @@ import type { Action } from 'flowtype';
import * as ACCOUNT from 'actions/constants/account'; import * as ACCOUNT from 'actions/constants/account';
import * as ACTION from 'actions/constants/signVerify'; import * as ACTION from 'actions/constants/signVerify';
export type Error = {
inputName: string,
message: ?string,
};
export type State = { export type State = {
signAddress: string, signAddress: string,
signMessage: string, signMessage: string,
@ -11,7 +16,8 @@ export type State = {
verifyAddress: string, verifyAddress: string,
verifyMessage: string, verifyMessage: string,
verifySignature: string, verifySignature: string,
touched: Array<string> touched: Array<string>,
errors: Array<Error>
} }
export const initialState: State = { export const initialState: State = {
@ -22,6 +28,7 @@ export const initialState: State = {
verifyMessage: '', verifyMessage: '',
verifySignature: '', verifySignature: '',
touched: [], touched: [],
errors: [],
}; };
export default (state: State = initialState, action: Action): State => { export default (state: State = initialState, action: Action): State => {
@ -32,18 +39,34 @@ export default (state: State = initialState, action: Action): State => {
signSignature: action.signSignature, signSignature: action.signSignature,
}; };
case ACTION.TOUCH: { case ACTION.ERROR: {
if (!state.touched.includes(action.name)) { const { inputName } = action;
if (!state.errors.some(e => e.inputName === inputName)) {
const error = { inputName, message: action.message };
return { return {
...state, ...state,
touched: [...state.touched, action.name], errors: [...state.errors, error],
}; };
} }
return state; return state;
} }
case ACTION.TOUCH: {
const { inputName } = action;
if (!state.touched.includes(inputName)) {
return {
...state,
touched: [...state.touched, action.inputName],
};
}
return {
...state,
errors: state.errors.filter(error => error.inputName !== inputName),
};
}
case ACTION.INPUT_CHANGE: { case ACTION.INPUT_CHANGE: {
const change = { [action.name]: action.value }; const change = { [action.inputName]: action.value };
return { ...state, ...change }; return { ...state, ...change };
} }

View File

@ -10,6 +10,11 @@ import Component from './index';
type OwnProps = {} type OwnProps = {}
export type Error = {
inputName: string,
message: ?string,
};
export type SignVerifyState = { export type SignVerifyState = {
signSignature: string, signSignature: string,
signAddress: string, signAddress: string,
@ -19,6 +24,7 @@ export type SignVerifyState = {
verifyMessage: string, verifyMessage: string,
verifySignature: string, verifySignature: string,
touched: Array<string>, touched: Array<string>,
errors: Array<Error>
} }
export type StateProps = { export type StateProps = {

View File

@ -3,7 +3,6 @@ import React, { Component } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import Input from 'components/inputs/Input'; import Input from 'components/inputs/Input';
import Textarea from 'components/Textarea'; import Textarea from 'components/Textarea';
import { validateAddress } from 'utils/ethUtils';
import Title from 'views/Wallet/components/Title'; import Title from 'views/Wallet/components/Title';
import Button from 'components/Button'; import Button from 'components/Button';
import Content from 'views/Wallet/components/Content'; import Content from 'views/Wallet/components/Content';
@ -47,6 +46,11 @@ const Verify = styled(Column)`
`; `;
class SignVerify extends Component <Props, SignVerifyState> { class SignVerify extends Component <Props, SignVerifyState> {
getError(inputName: string) {
if (!this.props.signVerify) return null;
return this.props.signVerify.errors.find(e => e.inputName === inputName);
}
handleInputChange = (event: SyntheticInputEvent<Text>) => { handleInputChange = (event: SyntheticInputEvent<Text>) => {
this.props.signVerifyActions.inputChange(event.target.name, event.target.value); this.props.signVerifyActions.inputChange(event.target.name, event.target.value);
} }
@ -66,10 +70,10 @@ class SignVerify extends Component <Props, SignVerifyState> {
verifyAddress, verifyAddress,
verifyMessage, verifyMessage,
verifySignature, verifySignature,
touched, errors,
}, },
} = this.props; } = this.props;
const verifyAddressError = this.getError('verifyAddress');
return ( return (
<Content> <Content>
<Title>Sign & Verify</Title> <Title>Sign & Verify</Title>
@ -130,8 +134,8 @@ class SignVerify extends Component <Props, SignVerifyState> {
value={verifyAddress} value={verifyAddress}
onChange={this.handleInputChange} onChange={this.handleInputChange}
type="text" type="text"
state={(touched.includes('verifyAddress') && validateAddress(verifyAddress)) ? 'error' : null} state={verifyAddressError ? 'error' : null}
bottomText={touched.includes('verifyAddress') ? validateAddress(verifyAddress) : null} bottomText={verifyAddressError ? verifyAddressError.message : null}
isSmallText isSmallText
/> />
</Row> </Row>
@ -165,11 +169,17 @@ class SignVerify extends Component <Props, SignVerifyState> {
>Clear >Clear
</Button> </Button>
<StyledButton <StyledButton
onClick={() => signVerifyActions.verify( onClick={
() => {
if (errors.length <= 0) {
signVerifyActions.verify(
verifyAddress, verifyAddress,
verifyMessage, verifyMessage,
verifySignature, verifySignature,
)} );
}
}
}
>Verify >Verify
</StyledButton> </StyledButton>
</RowButtons> </RowButtons>