1import { some } from 'lodash';
10 validateMaximumPatpByteLength,
14 validateEthereumAddress,
18 validateNotNullAddress,
23} from 'lib/validators';
24import { isPromise } from 'lib/isPromise';
26const PRIVATE_KEY_CHAR_LENGTH = 64; // 64 hex characters
27const ADDRESS_CHAR_LENGTH = 40; // 40 hex characters
29// iterate over validators, exiting early if there's an error
30const buildValidator = (validators = [], validate) => value => {
31 for (const validator of validators) {
33 const error = validator(value);
44 // the final validate function can optionally return a promise
45 return validate(value);
49// maps a validator across an array of values
50export const buildArrayValidator = validator => values => {
51 const errorsOrPromises = values.map(validator);
52 if (some(errorsOrPromises, isPromise)) {
53 return Promise.all(errorsOrPromises);
56 return errorsOrPromises;
59// error object has errors if some of its fields are
60// 1) an array with any defined values
61// 2) any defined values
62export const hasErrors = iter =>
63 some(iter, v => (Array.isArray(v) ? hasErrors(v) : v !== undefined));
65export const buildPatqValidator = (validators = []) =>
66 buildValidator([validateNotEmpty, validatePatq, ...validators]);
67export const buildShardValidator = (validators = []) =>
68 buildValidator([validateShard, ...validators]);
69export const buildAnyMnemonicValidator = () =>
70 buildValidator([validateNotEmpty]);
71export const buildMnemonicValidator = () =>
72 buildValidator([validateNotEmpty, validateMnemonic]);
73export const buildCheckboxValidator = mustBe =>
75 validateOneOf(mustBe !== undefined ? [mustBe] : [true, false]),
77export const buildPassphraseValidator = () => buildValidator([]);
78// TODO: validate hdpath format
79export const buildHdPathValidator = () => buildValidator([validateHdPath]);
80export const buildPointValidator = (size = 4, validators = []) =>
83 validateMaximumPatpByteLength(size),
87export const buildSelectValidator = options =>
88 buildValidator([validateOneOf(options.map(option => option.value))]);
89export const buildHexValidator = length =>
94 validateHexLength(length),
96export const buildPrivateKeyValidator = () =>
100 validateLength(PRIVATE_KEY_CHAR_LENGTH),
102export const buildUploadValidator = () => buildValidator([validateNotEmpty]);
103export const buildAddressValidator = () =>
108 validateHexLength(ADDRESS_CHAR_LENGTH),
109 validateNotNullAddress,
110 validateEthereumAddress,
112export const buildNumberValidator = (min = 0, max = null) => {
113 let validators = [validateGreaterThan(min)];
115 validators.push(validateLessThan(max));
117 return buildValidator(validators);
120export const buildEmailValidator = validate =>
121 buildValidator([validateNotEmpty, validateEmail], validate);
123export const buildEmailArrayValidator = () =>
124 buildValidator([validateUnique, buildArrayValidator(buildEmailValidator())]);
126export const buildPsbtValidator = btcWallet => buildValidator([validatePsbt]);
128// the form validator is the composition of all of the field validators
129// plus an additional form validator function
130export const composeValidator = (
131 fieldValidators = {},
132 // the default form validator just returns field-level validations
133 formValidator = (values, errors) => errors
135 const names = Object.keys(fieldValidators);
137 const fieldLevelValidators = names.map(name => value =>
138 fieldValidators[name](value)
141 // async reduce errors per-field into an errors object
142 const fieldLevelValidator = values => {
143 const errorsOrPromises = names.map((name, i) =>
144 fieldLevelValidators[i](values[name])
147 const reduce = errors =>
149 (memo, name, i) => ({
156 if (some(errorsOrPromises, isPromise)) {
157 // if any of these results are a promise, await them all then reduce
158 return Promise.all(errorsOrPromises).then(reduce);
161 // otherwise return immediately
162 return reduce(errorsOrPromises);
165 // the final-form `validate` function
166 // NOTE: if we return a Promise to final-form it will toggle the `validating`
167 // state, which is expected. If our promise resolves immediately, however,
168 // that means our `validating` state flickers the UI and it looks pretty bad.
169 // The solution is to conditionally return a promise only when necessary.
171 // ask for field-level errors
172 const errorsOrPromise = fieldLevelValidator(values);
174 // pass the current values and their validity to the form-level validator
175 // that can implement conditional logic and more complex validations
176 const runFormValidator = errors => formValidator(values, errors);
178 if (isPromise(errorsOrPromise)) {
179 // if promise, promise
180 return errorsOrPromise.then(runFormValidator);
183 // otherwise, it's an errors object
184 return runFormValidator(errorsOrPromise);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list