on 35c970a help sign in
bridge/src/lib/useInputs.js
221 lines 5.2 kB history raw
1import React, { useCallback, useState, useMemo } from 'react';
2import { AccessoryIcon, useForm } from 'indigo-react';
3import { identity } from 'lodash';
4import * as bip39 from 'bip39';
6import { DEFAULT_HD_PATH } from 'lib/wallet';
7import {
8 validateNotEmpty,
9 validateMnemonic,
10 validatePoint,
11 validateTicket,
12 validateEmail,
13 validateLength,
14 validateHexString,
15 validateOneOf,
16 validateMaximumPatpByteLength,
17} from 'lib/validators';
18import { prependSig } from 'lib/transformers';
20import InputSigil from 'components/InputSigil';
22const EXAMPLE_PRIVATE_KEY =
23 '0xa44de2416ee6beb2f323fab48b432925c9785808d33a6ca6d7ba00b45e9370c3';
25// pulls out the first input from a useForm() call
26function useFirstOf({ inputs, setValue, ...rest }, mapper = identity) {
27 // ask the mapper function for any values to overwrite
28 const input = {
29 ...inputs[0],
30 ...mapper(inputs[0]),
31 };
32 // memoize the setValue callback for manually setting the value
33 // in response to some imperative event
34 const _setValue = useCallback(value => setValue(input.name, value), [
35 setValue,
36 input.name,
37 ]);
39 // provide the first input as the first element
40 // _and_ as the second element to facilitate destructuring
41 // and then provide the pass/error/setValue/etc properties at the end
42 return [
43 input,
44 input,
45 {
46 ...rest,
47 setValue: _setValue,
48 },
49 ];
52export function usePassphraseInput(props) {
53 return useFirstOf(
54 useForm([
55 {
56 type: 'password',
57 autoComplete: 'off',
58 placeholder: 'Passphrase',
59 ...props,
60 },
61 ])
62 );
65export function useHexInput({ length, ...rest }) {
66 return useFirstOf(
67 useForm([
68 {
69 type: 'text', // or password
70 autoComplete: 'off',
71 placeholder: EXAMPLE_PRIVATE_KEY,
72 validators: useMemo(
73 () => [
74 validateHexString,
75 validateLength(length + 2),
76 validateNotEmpty,
77 ],
78 [length]
79 ),
80 ...rest,
81 },
82 ])
83 );
86const kExampleMnemonic = bip39.generateMnemonic();
87const kMnemonicValidators = [validateMnemonic, validateNotEmpty];
88export function useMnemonicInput(props) {
89 return useFirstOf(
90 useForm([
91 {
92 type: 'text',
93 autoComplete: 'off',
94 placeholder: `e.g. ${kExampleMnemonic}`,
95 validators: kMnemonicValidators,
96 ...props,
97 },
98 ])
99 );
102export function useHdPathInput(props) {
103 return useFirstOf(
104 useForm([
105 {
106 type: 'text',
107 autoComplete: 'off',
108 placeholder: `e.g. ${DEFAULT_HD_PATH}`,
109 ...props,
110 },
111 ])
112 );
115const kTicketValidators = [validateTicket, validateNotEmpty];
116//TODO needs to be fancier, displaying sig and dashes instead of •ing all
117const kTicketTransformers = [prependSig];
118export function useTicketInput({ validators = [], deriving = false, ...rest }) {
119 return useFirstOf(
120 useForm([
121 {
122 type: 'password',
123 label: 'Ticket',
124 placeholder: 'e.g. ~ragtyd-modwen-bostec-hinsep',
125 validators: useMemo(() => [...validators, ...kTicketValidators], [
126 validators,
127 ]),
128 transformers: kTicketTransformers,
129 mono: true,
130 ...rest,
131 },
132 ]),
133 ({ error, pass }) => ({
134 accessory: error ? (
135 <AccessoryIcon.Failure />
136 ) : deriving ? (
137 <AccessoryIcon.Pending />
138 ) : pass ? (
139 <AccessoryIcon.Success />
140 ) : null,
141 })
142 );
145const kPointValidators = [
146 validatePoint,
147 validateMaximumPatpByteLength(4),
148 validateNotEmpty,
149];
150const kPointTransformers = [prependSig];
151export function usePointInput(rest) {
152 const [lastValidPoint, setLastValidPoint] = useState('');
153 return useFirstOf(
154 useForm([
155 {
156 type: 'text',
157 label: 'Point',
158 placeholder: 'e.g. ~zod',
159 validators: kPointValidators,
160 transformers: kPointTransformers,
161 mono: true,
162 onValue: setLastValidPoint,
163 ...rest,
164 },
165 ]),
166 ({ error, pass, focused }) => ({
167 accessory: lastValidPoint ? (
168 <InputSigil
169 patp={lastValidPoint}
170 size={44}
171 margin={8}
172 pass={pass}
173 focused={focused}
174 error={error}
175 />
176 ) : null,
177 })
178 );
181export function useCheckboxInput({ initialValue, ...rest }) {
182 return useFirstOf(
183 useForm([
184 {
185 type: 'checkbox',
186 ...rest,
187 },
188 ])
189 );
192export function useSelectInput({ initialValue, options, ...rest }) {
193 return useFirstOf(
194 useForm([
195 {
196 type: 'select',
197 validators: useMemo(
198 () => [
199 validateOneOf(
200 options.map(option => option.value),
201 validateNotEmpty
202 ),
203 ],
204 [options]
205 ),
206 options,
207 initialValue: initialValue || options[0].value,
208 ...rest,
209 },
210 ])
211 );
214const kEmailValidators = [validateEmail, validateNotEmpty];
215export const buildEmailInputConfig = extra => ({
216 type: 'email',
217 autoComplete: 'off',
218 validators: kEmailValidators,
219 initialValue: '',
220 ...extra,
221});