on f4fd597 help sign in
bridge/src/form/Inputs.js
207 lines 5.2 kB history raw
1import React from 'react';
2import { Input, AccessoryIcon } from 'indigo-react';
3import { useField } from 'react-final-form';
4import { some } from 'lodash';
6import {
7 validateNotEmpty,
8 validateTicket,
9 kDefaultValidator,
10 validateMnemonic,
11 validatePoint,
12 validateMaximumPatpByteLength,
13 validateOneOf,
14 validateHexString,
15 validateHexLength,
16} from 'lib/validators';
17import { compose } from 'lib/lib';
18import { prependSig } from 'lib/transformers';
19import { DEFAULT_HD_PATH } from 'lib/wallet';
20import InputSigil from 'components/InputSigil';
22const PLACEHOLDER_POINT = '~sampel-ponnym';
23const PLACEHOLDER_HD_PATH = DEFAULT_HD_PATH;
24const PLACEHOLDER_MNEMONIC =
25 'example crew supreme gesture quantum web media hazard theory mercy wing kitten';
26const PLACEHOLDER_TICKET = '~sampel-ticlyt-migfun-falmel';
27const PLACEHOLDER_ADDRESS = '0x12345abcdeDB11D175F123F6891AA64F01c24F7d';
28const PLACEHOLDER_PRIVATE_KEY =
29 '0x12345abcdee6beb2f323fab48b432925c9785808d33a6ca6d7ba00b45e9370c3';
31const buildValidator = (
32 validators = [],
33 fn = () => undefined
34) => async value => {
35 return (
36 compose(
37 ...validators,
38 kDefaultValidator
39 )(value).error || (await fn(value))
40 );
41};
43export const hasErrors = obj => some(obj, v => v !== undefined);
45export const buildTicketValidator = (validators = []) =>
46 buildValidator([...validators, validateTicket, validateNotEmpty]);
47export const buildMnemonicValidator = () =>
48 buildValidator([validateMnemonic, validateNotEmpty]);
49export const buildCheckboxValidator = () =>
50 buildValidator([validateOneOf([true, false])]);
51export const buildPassphraseValidator = () => buildValidator([]);
52// TODO: validate hdpath format
53export const buildHdPathValidator = () => buildValidator([validateNotEmpty]);
54export const buildPointValidator = (size = 4) =>
55 buildValidator([
56 validatePoint,
57 validateMaximumPatpByteLength(size),
58 validateNotEmpty,
59 ]);
60export const buildSelectValidator = options =>
61 buildValidator([validateOneOf(options.map(option => option.value))]);
62export const buildHexValidator = length =>
63 buildValidator([
64 validateHexLength(length),
65 validateHexString,
66 validateNotEmpty,
67 ]);
68export const buildUploadValidator = () => buildValidator([validateNotEmpty]);
70// the default form validator just returns field-level validations
71const kDefaultFormValidator = (values, errors) => errors;
72export const composeValidator = (
73 fieldValidators = {},
74 formValidator = kDefaultFormValidator
75) => {
76 const names = Object.keys(fieldValidators);
78 const fieldLevelValidators = names.map(name => value =>
79 fieldValidators[name](value)
80 );
82 const fieldLevelValidator = async values => {
83 const errors = await Promise.all(
84 names.map((name, i) => fieldLevelValidators[i](values[name]))
85 );
87 return names.reduce(
88 (memo, name, i) => ({
89 ...memo,
90 [name]: errors[i],
91 }),
92 {}
93 );
94 };
96 return async values => {
97 console.log('validating...');
98 const errors = await fieldLevelValidator(values);
99 return await formValidator(values, errors);
100 };
101};
103export function TicketInput({ name, ...rest }) {
104 const {
105 meta: { valid, error, validating, touched, active },
106 } = useField(name, {
107 subscription: {
108 valid: true,
109 error: true,
110 validating: true,
111 touched: true,
112 active: true,
113 },
114 });
116 return (
117 <Input
118 type="text"
119 name={name}
120 placeholder={PLACEHOLDER_TICKET}
121 accessory={
122 touched && !active && error ? (
123 <AccessoryIcon.Failure />
124 ) : validating ? (
125 <AccessoryIcon.Pending />
126 ) : valid ? (
127 <AccessoryIcon.Success />
128 ) : null
129 }
130 config={{ format: prependSig }}
131 mono
132 {...rest}
133 />
134 );
137export function MnemonicInput({ ...rest }) {
138 return (
139 <Input type="textarea" placeholder={PLACEHOLDER_MNEMONIC} mono {...rest} />
140 );
143export function HdPathInput({ ...rest }) {
144 return (
145 <Input
146 type="text"
147 placeholder={PLACEHOLDER_HD_PATH}
148 autoComplete="off"
149 {...rest}
150 />
151 );
154export function PassphraseInput({ ...rest }) {
155 return (
156 <Input
157 type="password"
158 placeholder="Passphrase"
159 autoComplete="off"
160 {...rest}
161 />
162 );
165export function PointInput({ name, size = 4, ...rest }) {
166 const {
167 input: { value },
168 meta: { active, valid, error },
169 } = useField(name, {
170 subscription: { value: true, active: true, valid: true, error: true },
171 });
173 return (
174 <Input
175 type="text"
176 label="Point"
177 name={name}
178 placeholder={PLACEHOLDER_POINT}
179 accessory={
180 value ? (
181 <InputSigil
182 patp={value}
183 size={44}
184 margin={8}
185 pass={valid}
186 focused={active}
187 error={error}
188 />
189 ) : null
190 }
191 config={{ format: prependSig }}
192 mono
193 {...rest}
194 />
195 );
198export function PrivateKeyInput({ ...rest }) {
199 return (
200 <Input
201 type="text"
202 placeholder={PLACEHOLDER_PRIVATE_KEY}
203 autoComplete="off"
204 {...rest}
205 />
206 );