on 82b5914 help sign in
bridge/src/components/Inputs.js
242 lines 5.8 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 InputSigil from 'components/InputSigil';
8import { DEFAULT_HD_PATH } from 'lib/wallet';
9import {
10 validateNotEmpty,
11 validateMnemonic,
12 validatePoint,
13 validateTicket,
14 validateEmail,
15 validateLength,
16 validateHexString,
17 validateOneOf,
18} from 'lib/validators';
19import { prependSig } from 'lib/transformers';
21const EXAMPLE_PRIVATE_KEY =
22 '0xa44de2416ee6beb2f323fab48b432925c9785808d33a6ca6d7ba00b45e9370c3';
24// const RequiredInput = advancedInput({
25// WrappedComponent: Input,
26// validators: [validateNotEmpty],
27// });
29// const NetworkKeyInput = advancedInput({
30// WrappedComponent: Input,
31// validators: [validateNotEmpty, validateNetworkKey],
32// });
34// const NetworkSeedInput = advancedInput({
35// WrappedComponent: Input,
36// validators: [validateNotEmpty, validateNetworkSeed],
37// });
39// const AddressInput = advancedInput({
40// WrappedComponent: Input,
41// validators: [validateEthereumAddress, validateNotEmpty],
42// });
44// const GalaxyInput = advancedInput({
45// WrappedComponent: Input,
46// validators: [validateGalaxy, validateNotEmpty],
47// transformers: [prependSig],
48// });
50// pulls out the first input from a useForm() call
51function useFirstOf({ inputs, setValue, ...rest }, mapper = identity) {
52 // ask the mapper function for any values to overwrite
53 const input = {
54 ...inputs[0],
55 ...mapper(inputs[0]),
56 };
57 // memoize the setValue callback for manually setting the value
58 // in response to some imperative event
59 const _setValue = useCallback(value => setValue(input.name, value), [
60 setValue,
61 input.name,
62 ]);
64 // provide the first input as the first element
65 // _and_ as the second element to facilitate destructuring
66 // and then provide the pass/error/setValue/etc properties at the end
67 return [
68 input,
69 input,
70 {
71 ...rest,
72 setValue: _setValue,
73 },
74 ];
77export function usePassphraseInput(props) {
78 return useFirstOf(
79 useForm([
80 {
81 type: 'password',
82 autoComplete: 'off',
83 placeholder: 'Passphrase',
84 ...props,
85 },
86 ])
87 );
90export function useHexInput({ length, ...rest }) {
91 return useFirstOf(
92 useForm([
93 {
94 type: 'text', // or password
95 autoComplete: 'off',
96 placeholder: EXAMPLE_PRIVATE_KEY,
97 validators: useMemo(
98 () => [
99 validateHexString,
100 validateLength(length + 2),
101 validateNotEmpty,
102 ],
103 [length]
104 ),
105 ...rest,
106 },
107 ])
108 );
111const kExampleMnemonic = bip39.generateMnemonic();
112const kMnemonicValidators = [validateMnemonic, validateNotEmpty];
113export function useMnemonicInput(props) {
114 return useFirstOf(
115 useForm([
116 {
117 type: 'text',
118 autoComplete: 'off',
119 placeholder: `e.g. ${kExampleMnemonic}`,
120 validators: kMnemonicValidators,
121 ...props,
122 },
123 ])
124 );
127export function useHdPathInput(props) {
128 return useFirstOf(
129 useForm([
130 {
131 type: 'text',
132 autoComplete: 'off',
133 placeholder: `e.g. ${DEFAULT_HD_PATH}`,
134 ...props,
135 },
136 ])
137 );
140const kTicketValidators = [validateTicket, validateNotEmpty];
141const kTicketTransformers = [prependSig];
142//TODO needs to be fancier, displaying sig and dashes instead of •ing all
143export function useTicketInput({ validators = [], deriving = false, ...rest }) {
144 return useFirstOf(
145 useForm([
146 {
147 type: 'password',
148 label: 'Ticket',
149 placeholder: '~ragtyd-modwen-bostec-hinsep',
150 validators: useMemo(() => [...validators, ...kTicketValidators], [
151 validators,
152 ]),
153 transformers: kTicketTransformers,
154 mono: true,
155 ...rest,
156 },
157 ]),
158 ({ error, pass }) => ({
159 accessory: error ? (
160 <AccessoryIcon.Failure />
161 ) : deriving ? (
162 <AccessoryIcon.Pending />
163 ) : pass ? (
164 <AccessoryIcon.Success />
165 ) : null,
166 })
167 );
170const kPointValidators = [validatePoint, validateNotEmpty];
171const kPointTransformers = [prependSig];
172export function usePointInput(rest) {
173 const [lastValidPoint, setLastValidPoint] = useState('');
174 return useFirstOf(
175 useForm([
176 {
177 type: 'text',
178 label: 'Point',
179 placeholder: 'e.g. ~zod',
180 validators: kPointValidators,
181 transformers: kPointTransformers,
182 mono: true,
183 onValue: setLastValidPoint,
184 ...rest,
185 },
186 ]),
187 ({ error, pass, focused }) => ({
188 accessory: lastValidPoint ? (
189 <InputSigil
190 patp={lastValidPoint}
191 size={44}
192 margin={8}
193 pass={pass}
194 focused={focused}
195 error={error}
196 />
197 ) : null,
198 })
199 );
202export function useCheckboxInput({ initialValue, ...rest }) {
203 return useFirstOf(
204 useForm([
205 {
206 type: 'checkbox',
207 ...rest,
208 },
209 ])
210 );
213export function useSelectInput({ initialValue, options, ...rest }) {
214 return useFirstOf(
215 useForm([
216 {
217 type: 'select',
218 validators: useMemo(
219 () => [
220 validateOneOf(
221 options.map(option => option.value),
222 validateNotEmpty
223 ),
224 ],
225 [options]
226 ),
227 options,
228 initialValue: initialValue || options[0].value,
229 ...rest,
230 },
231 ])
232 );
235const kEmailValidators = [validateEmail, validateNotEmpty];
236export const buildEmailInputConfig = extra => ({
237 type: 'email',
238 autoComplete: 'off',
239 validators: kEmailValidators,
240 initialValue: '',
241 ...extra,
242});