PrivateKey.tsx
1 import React, { PureComponent } from 'react'; 2 3 import translate, { translateRaw } from 'translations'; 4 import { isValidEncryptedPrivKey, isValidPrivKey } from 'libs/validators'; 5 import { stripHexPrefix } from 'libs/formatters'; 6 import { TogglablePassword } from 'components'; 7 import { Input } from 'components/ui'; 8 9 export interface PrivateKeyValue { 10 key: string; 11 password: string; 12 valid: boolean; 13 } 14 15 interface Validated { 16 fixedPkey: string; 17 isValidPkey: boolean; 18 isPassRequired: boolean; 19 valid: boolean; 20 } 21 22 function validatePkeyAndPass(pkey: string, pass: string): Validated { 23 const fixedPkey = stripHexPrefix(pkey).trim(); 24 const validPkey = isValidPrivKey(fixedPkey); 25 const validEncPkey = isValidEncryptedPrivKey(fixedPkey); 26 const isValidPkey = validPkey || validEncPkey; 27 28 let isValidPass = false; 29 30 if (validPkey) { 31 isValidPass = true; 32 } else if (validEncPkey) { 33 isValidPass = pass.length > 0; 34 } 35 36 return { 37 fixedPkey, 38 isValidPkey, 39 isPassRequired: validEncPkey, 40 valid: isValidPkey && isValidPass 41 }; 42 } 43 44 interface Props { 45 value: PrivateKeyValue; 46 onChange(value: PrivateKeyValue): void; 47 onUnlock(): void; 48 } 49 50 export class PrivateKeyDecrypt extends PureComponent<Props> { 51 public render() { 52 const { key, password } = this.props.value; 53 const { isValidPkey, isPassRequired } = validatePkeyAndPass(key, password); 54 const unlockDisabled = !isValidPkey || (isPassRequired && !password.length); 55 56 return ( 57 <form id="selectedTypeKey" onSubmit={this.unlock}> 58 <div className="input-group-wrapper"> 59 <label className="input-group"> 60 <TogglablePassword 61 value={key} 62 rows={4} 63 placeholder={translateRaw('X_PRIVKEY2')} 64 isValid={isValidPkey} 65 onChange={this.onPkeyChange} 66 onEnter={this.props.onUnlock} 67 /> 68 </label> 69 </div> 70 {isValidPkey && 71 isPassRequired && ( 72 <div className="input-group-wrapper"> 73 <label className="input-group"> 74 <div className="input-group-header">{translate('ADD_LABEL_3')}</div> 75 <Input 76 isValid={password.length > 0} 77 value={password} 78 onChange={this.onPasswordChange} 79 onKeyDown={this.onKeyDown} 80 placeholder={translateRaw('INPUT_PASSWORD_LABEL')} 81 type="password" 82 /> 83 </label> 84 </div> 85 )} 86 <button className="btn btn-block btn-primary" disabled={unlockDisabled}> 87 {translate('ADD_LABEL_6_SHORT')} 88 </button> 89 </form> 90 ); 91 } 92 93 private onPkeyChange = (e: React.FormEvent<HTMLTextAreaElement | HTMLInputElement>) => { 94 const pkey = e.currentTarget.value; 95 const pass = this.props.value.password; 96 const { fixedPkey, valid } = validatePkeyAndPass(pkey, pass); 97 98 this.props.onChange({ ...this.props.value, key: fixedPkey, valid }); 99 }; 100 101 private onPasswordChange = (e: React.FormEvent<HTMLInputElement>) => { 102 // NOTE: Textareas don't support password type, so we replace the value 103 // with an equal length number of dots. On change, we replace 104 const pkey = this.props.value.key; 105 const pass = e.currentTarget.value; 106 const { valid } = validatePkeyAndPass(pkey, pass); 107 108 this.props.onChange({ 109 ...this.props.value, 110 password: pass, 111 valid 112 }); 113 }; 114 115 private onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => { 116 if (e.keyCode === 13) { 117 this.unlock(e); 118 } 119 }; 120 121 private unlock = (e: React.SyntheticEvent<HTMLElement>) => { 122 e.preventDefault(); 123 e.stopPropagation(); 124 this.props.onUnlock(); 125 }; 126 }