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:
parent
ea3ad58d48
commit
bf3dd1cfde
@ -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,61 +77,71 @@ 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);
|
||||||
|
|
||||||
const response = await TrezorConnect.ethereumVerifyMessage({
|
if (hasError) {
|
||||||
device: {
|
dispatch({
|
||||||
path: selected.path,
|
type: SIGN_VERIFY.ERROR,
|
||||||
instance: selected.instance,
|
inputName: 'verifyAddress',
|
||||||
state: selected.state,
|
message: validateAddress(address),
|
||||||
},
|
});
|
||||||
address,
|
}
|
||||||
message,
|
|
||||||
signature,
|
|
||||||
hex,
|
|
||||||
useEmptyPassphrase: selected.useEmptyPassphrase,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response && response.success) {
|
if (!hasError) {
|
||||||
dispatch({
|
const response = await TrezorConnect.ethereumVerifyMessage({
|
||||||
type: NOTIFICATION.ADD,
|
device: {
|
||||||
payload: {
|
path: selected.path,
|
||||||
type: 'success',
|
instance: selected.instance,
|
||||||
title: 'Verify success',
|
state: selected.state,
|
||||||
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));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
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({
|
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 => {
|
||||||
|
@ -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';
|
@ -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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 = {
|
||||||
|
@ -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={
|
||||||
verifyAddress,
|
() => {
|
||||||
verifyMessage,
|
if (errors.length <= 0) {
|
||||||
verifySignature,
|
signVerifyActions.verify(
|
||||||
)}
|
verifyAddress,
|
||||||
|
verifyMessage,
|
||||||
|
verifySignature,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
>Verify
|
>Verify
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
</RowButtons>
|
</RowButtons>
|
||||||
|
Loading…
Reference in New Issue
Block a user