1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-28 03:08:30 +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 {
GetState, Dispatch, ThunkAction, AsyncAction,
} from 'flowtype';
import { validateAddress } from 'utils/ethUtils';
import * as NOTIFICATION from 'actions/constants/notification';
import * as SIGN_VERIFY from './constants/signVerify';
@ -15,11 +16,19 @@ export type SignVerifyAction = {
type: typeof SIGN_VERIFY.CLEAR_VERIFY,
} | {
type: typeof SIGN_VERIFY.INPUT_CHANGE,
name: string,
inputName: string,
value: string
} | {
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 = (
@ -55,13 +64,6 @@ const sign = (
title: 'Sign error',
message: response.payload.error,
cancelable: true,
actions: [{
label: 'Try again',
callback: () => {
dispatch(sign(path, message, hex));
},
},
],
},
});
}
@ -75,61 +77,71 @@ const verify = (
): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
const selected = getState().wallet.selectedDevice;
if (!selected) return;
const hasError = validateAddress(address);
const response = await TrezorConnect.ethereumVerifyMessage({
device: {
path: selected.path,
instance: selected.instance,
state: selected.state,
},
address,
message,
signature,
hex,
useEmptyPassphrase: selected.useEmptyPassphrase,
});
if (hasError) {
dispatch({
type: SIGN_VERIFY.ERROR,
inputName: 'verifyAddress',
message: validateAddress(address),
});
}
if (response && response.success) {
dispatch({
type: NOTIFICATION.ADD,
payload: {
type: 'success',
title: 'Verify success',
message: 'signature is valid',
cancelable: true,
},
});
} else {
dispatch({
type: NOTIFICATION.ADD,
payload: {
type: 'error',
title: 'Verify error',
message: response.payload.error,
cancelable: true,
actions: [
{
label: 'Try again',
callback: () => {
dispatch(verify(address, message, signature, hex));
},
},
],
if (!hasError) {
const response = await TrezorConnect.ethereumVerifyMessage({
device: {
path: selected.path,
instance: selected.instance,
state: selected.state,
},
address,
message,
signature,
hex,
useEmptyPassphrase: selected.useEmptyPassphrase,
});
if (response && response.success) {
dispatch({
type: NOTIFICATION.ADD,
payload: {
type: 'success',
title: 'Verify success',
message: 'signature is valid',
cancelable: true,
},
});
} else {
dispatch({
type: NOTIFICATION.ADD,
payload: {
type: 'error',
title: 'Verify error',
message: response.payload.error,
cancelable: true,
},
});
}
}
};
const inputChange = (name: string, value: string): ThunkAction => (dispatch: Dispatch): void => {
const inputChange = (inputName: string, value: string): ThunkAction => (dispatch: Dispatch): void => {
dispatch({
type: SIGN_VERIFY.INPUT_CHANGE,
name,
inputName,
value,
});
dispatch({
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 => {

View File

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

View File

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

View File

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