1import * as bip39 from 'bip39';
2import * as ob from 'urbit-ob';
3import { identity, includes } from 'lodash';
5import { isValidAddress, ETH_ZERO_ADDR, ETH_ZERO_ADDR_SHORT } from './wallet';
6import patp2dec from './patp2dec';
7import { patpStringLength } from './lib';
8import { MIN_GALAXY, MAX_GALAXY } from './constants';
10// NOTE: do not use the /g modifier for these regexes
11// https://stackoverflow.com/a/21373261
12// https://stackoverflow.com/a/1520853
14// via: https://emailregex.com/
15const emailRegExp = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
17// is this 64 hex chars?
18const plain64CharHexValue = /[0-9A-Fa-f]{64}/;
20// is this only hex values with a 0x prefix?
21const isHexString = /0x[0-9A-Fa-f]/;
23// Wraps single validation functions in a controlled and predictable way.
24export const simpleValidatorWrapper = ({
30 // If a previous validation has already failed, skip this validation and
31 // return the prev message to the next stage in the validation function chain.
32 // Failed validations should drop all the way down the chain and drop out of
34 if (!prevMessage.pass) {
38 // Run the validator and return the result.
39 const pass = validator(prevMessage.data);
40 const data = pass ? transform(prevMessage.data) : prevMessage.data;
42 return newMessage(data, pass, !pass && error);
51// Creates a new validation message in a uniform way.
52const newMessage = (data, pass, error) => ({
55 // Has the data passed validation?
57 // If data has failed a validator, the error message goes here.
61// A validator that always passes.
62export const kDefaultValidator = data => newMessage(data, true, null);
64// Validates a bip39 mnemonic
65export const validateMnemonic = m =>
66 simpleValidatorWrapper({
68 validator: d => bip39.validateMnemonic(d),
69 error: 'This is not a valid mnemonic.',
72// Checks an empty field
73export const validateNotEmpty = m =>
74 simpleValidatorWrapper({
83 error: 'This field is required.',
86// Checks if a patp is a valid galaxy
87export const validateGalaxy = m =>
88 simpleValidatorWrapper({
94 return point >= MIN_GALAXY && point <= MAX_GALAXY;
99 error: 'This is not a valid galaxy.',
102export const validatePoint = m =>
103 simpleValidatorWrapper({
107 return ob.isValidPatp(d);
112 error: 'This is not a valid point.',
115export const validateTicket = m =>
116 simpleValidatorWrapper({
120 return ob.isValidPatq(d);
125 error: 'This is not a valid ticket.',
128export const validateShard = m =>
129 simpleValidatorWrapper({
133 return ob.isValidPatq(d);
138 error: 'This is not a valid shard.',
141export const validateOneOf = (options = []) => m =>
142 simpleValidatorWrapper({
144 validator: d => includes(options, d),
145 error: `Is not a valid option.`,
148export const validateHexString = m =>
149 simpleValidatorWrapper({
151 validator: d => isHexString.test(d),
152 error: 'This is not a valid hex string.',
156export const validateNetworkKey = m =>
157 simpleValidatorWrapper({
159 validator: d => plain64CharHexValue.test(d),
160 error: 'This is not a valid network key.',
164export const validateNetworkSeed = m =>
165 simpleValidatorWrapper({
167 validator: d => plain64CharHexValue.test(d),
168 error: 'This is not a valid network seed.',
171// Checks if a string is a valid ethereum address
172export const validateEthereumAddress = m =>
173 simpleValidatorWrapper({
175 validator: d => isValidAddress(d),
176 error: 'This is not a valid Ethereum address.',
179export const validateEmail = m =>
180 simpleValidatorWrapper({
182 validator: d => emailRegExp.test(d),
183 error: 'This is not a valid email address.',
186export const validateInt = m =>
187 simpleValidatorWrapper({
189 transform: d => parseInt(d, 10),
198 error: 'This is not a valid number.',
201export const validateExactly = (value, error) => m =>
202 simpleValidatorWrapper({
204 validator: d => d === value,
208export const validateNotAny = (values = []) => m =>
209 simpleValidatorWrapper({
211 validator: d => !values.includes(d),
212 error: `Cannot be ${m.data}.`,
215export const validateLength = l => m =>
216 simpleValidatorWrapper({
220 return d.length === l;
225 error: `Must be exactly ${l} characters.`,
228export const validateHexLength = l => m =>
229 simpleValidatorWrapper({
233 return d.length === l + 2;
238 error: `Must be exactly ${l} hex characters.`,
241export const validateMaximumLength = l => m =>
242 simpleValidatorWrapper({
246 return d.length <= l;
251 error: `Must be ${l} characters or fewer.`,
254export const validateGreaterThan = l => m =>
255 simpleValidatorWrapper({
257 validator: d => d > l,
258 error: `Must be at least ${l}.`,
261export const validateInSet = (set, error) => m =>
262 simpleValidatorWrapper({
264 validator: d => set.has(d),
268export const validateNameInNumberSet = (set, error) => m =>
269 simpleValidatorWrapper({
272 const num = patp2dec(p);
278export const validatePatpByteLength = byteLength => {
279 return validateLength(patpStringLength(byteLength));
282export const validateMaximumPatpByteLength = byteLength => {
283 return validateMaximumLength(patpStringLength(byteLength));
286export const validateNotNullAddress = validateNotAny([
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