import React from 'react'; import { Input, AccessoryIcon } from 'indigo-react'; import { useField } from 'react-final-form'; import { some } from 'lodash'; import { validateNotEmpty, validateTicket, kDefaultValidator, validateMnemonic, validatePoint, validateMaximumPatpByteLength, validateOneOf, validateHexString, validateHexLength, validateEthereumAddress, } from 'lib/validators'; import { compose } from 'lib/lib'; import { prependSig } from 'lib/transformers'; import { DEFAULT_HD_PATH } from 'lib/wallet'; import InputSigil from 'components/InputSigil'; const PLACEHOLDER_POINT = '~sampel-ponnym'; const PLACEHOLDER_HD_PATH = DEFAULT_HD_PATH; const PLACEHOLDER_MNEMONIC = 'example crew supreme gesture quantum web media hazard theory mercy wing kitten'; const PLACEHOLDER_TICKET = '~sampel-ticlyt-migfun-falmel'; const PLACEHOLDER_ADDRESS = '0x12345abcdeDB11D175F123F6891AA64F01c24F7d'; const PLACEHOLDER_PRIVATE_KEY = '0x12345abcdee6beb2f323fab48b432925c9785808d33a6ca6d7ba00b45e9370c3'; const buildValidator = ( validators = [], fn = () => undefined ) => async value => { return ( compose( ...validators, kDefaultValidator )(value).error || (await fn(value)) ); }; export const hasErrors = obj => some(obj, v => v !== undefined); export const buildTicketValidator = (validators = []) => buildValidator([...validators, validateTicket, validateNotEmpty]); export const buildMnemonicValidator = () => buildValidator([validateMnemonic, validateNotEmpty]); export const buildCheckboxValidator = mustBe => buildValidator([ validateOneOf(mustBe !== undefined ? [mustBe] : [true, false]), ]); export const buildPassphraseValidator = () => buildValidator([]); // TODO: validate hdpath format export const buildHdPathValidator = () => buildValidator([validateNotEmpty]); export const buildPointValidator = (size = 4) => buildValidator([ validatePoint, validateMaximumPatpByteLength(size), validateNotEmpty, ]); export const buildSelectValidator = options => buildValidator([validateOneOf(options.map(option => option.value))]); export const buildHexValidator = length => buildValidator([ validateHexLength(length), validateHexString, validateNotEmpty, ]); export const buildUploadValidator = () => buildValidator([validateNotEmpty]); export const buildAddressValidator = () => buildValidator([ validateEthereumAddress, validateHexLength(40), validateHexString, validateNotEmpty, ]); // the default form validator just returns field-level validations const kDefaultFormValidator = (values, errors) => errors; export const composeValidator = ( fieldValidators = {}, formValidator = kDefaultFormValidator ) => { const names = Object.keys(fieldValidators); const fieldLevelValidators = names.map(name => value => fieldValidators[name](value) ); const fieldLevelValidator = async values => { const errors = await Promise.all( names.map((name, i) => fieldLevelValidators[i](values[name])) ); return names.reduce( (memo, name, i) => ({ ...memo, [name]: errors[i], }), {} ); }; return async values => { const errors = await fieldLevelValidator(values); return await formValidator(values, errors); }; }; export function TicketInput({ name, ...rest }) { const { meta: { valid, error, validating, touched, active }, } = useField(name, { subscription: { valid: true, error: true, validating: true, touched: true, active: true, }, }); return ( ) : validating ? ( ) : valid ? ( ) : null } config={{ format: prependSig }} mono {...rest} /> ); } export function MnemonicInput({ ...rest }) { return ( ); } export function HdPathInput({ ...rest }) { return ( ); } export function PassphraseInput({ ...rest }) { return ( ); } export function PointInput({ name, size = 4, ...rest }) { const { input: { value }, meta: { active, valid, error }, } = useField(name, { subscription: { value: true, active: true, valid: true, error: true }, }); return ( ) : null } config={{ format: prependSig }} mono {...rest} /> ); } export function HexInput({ ...rest }) { return ( ); } export function AddressInput({ ...rest }) { return ( ); }