on d27f157 help sign in
bridge/src/lib/useInputs.js
276 lines 6.4 kB history raw
1import React, { useCallback, useMemo } from 'react';
2import { AccessoryIcon, useForm } from 'indigo-react';
3import { identity } from 'lodash';
5import { DEFAULT_HD_PATH } from 'lib/wallet';
6import {
7 validateNotEmpty,
8 validateMnemonic,
9 validatePoint,
10 validateTicket,
11 validateEmail,
12 validateLength,
13 validateHexString,
14 validateOneOf,
15 validateMaximumPatpByteLength,
16 validateEthereumAddress,
17 validateNotNullAddress,
18 validateGreaterThan,
19} from 'lib/validators';
20import { prependSig, convertToNumber } from 'lib/transformers';
22import InputSigil from 'components/InputSigil';
24const PLACEHOLDER_POINT = '~sampel-ponnym';
25const PLACEHOLDER_HD_PATH = DEFAULT_HD_PATH;
26const PLACEHOLDER_MNEMONIC =
27 'example crew supreme gesture quantum web media hazard theory mercy wing kitten';
28const PLACEHOLDER_TICKET = '~sampel-ticlyt-migfun-falmel';
29const PLACEHOLDER_ADDRESS = '0x12345abcdeDB11D175F123F6891AA64F01c24F7d';
30const PLACEHOLDER_PRIVATE_KEY =
31 '0x12345abcdee6beb2f323fab48b432925c9785808d33a6ca6d7ba00b45e9370c3';
33// pulls out the first input from a useForm() call
34function useFirstOf({ inputs, setValue, ...rest }, mapper = identity) {
35 // ask the mapper function for any values to overwrite
36 const input = {
37 ...inputs[0],
38 ...mapper(inputs[0]),
39 };
40 // memoize the setValue callback for manually setting the value
41 // in response to some imperative event
42 const _setValue = useCallback(value => setValue(input.name, value), [
43 setValue,
44 input.name,
45 ]);
47 // provide the first input as the first element
48 // _and_ as the second element to facilitate destructuring
49 // and then provide the pass/error/setValue/etc properties at the end
50 return [
51 input,
52 input,
53 {
54 ...rest,
55 setValue: _setValue,
56 },
57 ];
60export function usePassphraseInput(props) {
61 return useFirstOf(
62 useForm([
63 {
64 type: 'password',
65 autoComplete: 'off',
66 placeholder: 'Passphrase',
67 ...props,
68 },
69 ])
70 );
73export function useHexInput({ length, ...rest }) {
74 return useFirstOf(
75 useForm([
76 {
77 type: 'text', // or password
78 autoComplete: 'off',
79 placeholder: PLACEHOLDER_PRIVATE_KEY,
80 validators: useMemo(
81 () => [
82 validateHexString,
83 validateLength(length + 2),
84 validateNotEmpty,
85 ],
86 [length]
87 ),
88 ...rest,
89 },
90 ])
91 );
94const kMnemonicValidators = [validateMnemonic, validateNotEmpty];
95export function useMnemonicInput(props) {
96 return useFirstOf(
97 useForm([
98 {
99 type: 'textarea',
100 autoComplete: 'off',
101 placeholder: PLACEHOLDER_MNEMONIC,
102 validators: kMnemonicValidators,
103 ...props,
104 },
105 ])
106 );
109export function useHdPathInput(props) {
110 return useFirstOf(
111 useForm([
112 {
113 type: 'text',
114 autoComplete: 'off',
115 placeholder: PLACEHOLDER_HD_PATH,
116 ...props,
117 },
118 ])
119 );
122const kTicketValidators = [validateTicket, validateNotEmpty];
123//TODO needs to be fancier, displaying sig and dashes instead of •ing all
124const kTicketTransformers = [prependSig];
125export function useTicketInput({ validators = [], deriving = false, ...rest }) {
126 return useFirstOf(
127 useForm([
128 {
129 type: 'password',
130 label: 'Ticket',
131 placeholder: PLACEHOLDER_TICKET,
132 validators: useMemo(() => [...validators, ...kTicketValidators], [
133 validators,
134 ]),
135 transformers: kTicketTransformers,
136 mono: true,
137 ...rest,
138 },
139 ]),
140 ({ error, pass }) => ({
141 accessory: error ? (
142 <AccessoryIcon.Failure />
143 ) : deriving ? (
144 <AccessoryIcon.Pending />
145 ) : pass ? (
146 <AccessoryIcon.Success />
147 ) : null,
148 })
149 );
152const kPointTransformers = [prependSig];
153export function usePointInput({ size = 4, validators = [], ...rest }) {
154 const _validators = useMemo(
155 () => [
156 ...validators,
157 validatePoint,
158 validateMaximumPatpByteLength(size),
159 validateNotEmpty,
160 ],
161 [size, validators]
162 );
164 return useFirstOf(
165 useForm([
166 {
167 type: 'text',
168 label: 'Point',
169 placeholder: PLACEHOLDER_POINT,
170 validators: _validators,
171 transformers: kPointTransformers,
172 mono: true,
173 ...rest,
174 },
175 ]),
176 ({ error, pass, focused, value }) => ({
177 accessory: value ? (
178 <InputSigil
179 patp={value}
180 size={44}
181 pass={pass}
182 focused={focused}
183 error={error}
184 />
185 ) : null,
186 })
187 );
190export function useGalaxyInput(props) {
191 return usePointInput({
192 label: 'Galaxy Name',
193 size: 1,
194 ...props,
195 });
198export function useCheckboxInput({ initialValue, ...rest }) {
199 return useFirstOf(
200 useForm([
201 {
202 type: 'checkbox',
203 ...rest,
204 },
205 ])
206 );
209export function useSelectInput({ initialValue, options, ...rest }) {
210 return useFirstOf(
211 useForm([
212 {
213 type: 'select',
214 validators: useMemo(
215 () => [
216 validateOneOf(
217 options.map(option => option.value),
218 validateNotEmpty
219 ),
220 ],
221 [options]
222 ),
223 options,
224 initialValue: initialValue || options[0].value,
225 ...rest,
226 },
227 ])
228 );
231const kAddressValidators = [
232 validateEthereumAddress,
233 validateNotNullAddress,
234 validateNotEmpty,
235];
236export function useAddressInput({ ...rest }) {
237 return useFirstOf(
238 useForm([
239 {
240 type: 'string',
241 label: 'Ethereum Address',
242 placeholder: PLACEHOLDER_ADDRESS,
243 autoComplete: 'off',
244 validators: kAddressValidators,
245 mono: true,
246 ...rest,
247 },
248 ])
249 );
252const kNumberTransformers = [convertToNumber];
253const kNumberValidators = [validateGreaterThan(0)];
254export function useNumberInput({ ...rest }) {
255 return useFirstOf(
256 useForm([
257 {
258 type: 'number',
259 label: 'Number',
260 autoComplete: 'off',
261 transformers: kNumberTransformers,
262 validators: kNumberValidators,
263 ...rest,
264 },
265 ])
266 );
269const kEmailValidators = [validateEmail, validateNotEmpty];
270export const buildEmailInputConfig = extra => ({
271 type: 'email',
272 autoComplete: 'off',
273 validators: kEmailValidators,
274 initialValue: '',
275 ...extra,
276});