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