@@ -1,6 +1,6 @@
1import * as bip39 from 'bip39';
1import * as bip39 from 'bip39';
2import * as ob from 'urbit-ob';
2import * as ob from 'urbit-ob';
3−import { identity, includes } from 'lodash';
3+import { includes } from 'lodash';
5import { isValidAddress, ETH_ZERO_ADDR, ETH_ZERO_ADDR_SHORT } from './wallet';
5import { isValidAddress, ETH_ZERO_ADDR, ETH_ZERO_ADDR_SHORT } from './wallet';
6import patp2dec from './patp2dec';
6import patp2dec from './patp2dec';
@@ -14,274 +14,83 @@ import { MIN_GALAXY, MAX_GALAXY } from './constants';
14// via: https://emailregex.com/
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,}))$/;
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?
18−const plain64CharHexValue = /[0-9A-Fa-f]{64}/;
20// is this only hex values with a 0x prefix?
17// is this only hex values with a 0x prefix?
21const isHexString = /0x[0-9A-Fa-f]/;
18const isHexString = /0x[0-9A-Fa-f]/;
23−// Wraps single validation functions in a controlled and predictable way.
24−export const simpleValidatorWrapper = ({
26− transform = identity,
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.
52−const 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.
62−export const kDefaultValidator = data => newMessage(data, true, null);
64// Validates a bip39 mnemonic
20// Validates a bip39 mnemonic
65−export const validateMnemonic = m =>
21+export const validateMnemonic = v =>
66− simpleValidatorWrapper({
68− validator: d => bip39.validateMnemonic(d),
69− error: 'This is not a valid mnemonic.',
22+ !bip39.validateMnemonic(v) && 'This is not a valid mnemonic.';
72// Checks an empty field
24// Checks an empty field
73−export const validateNotEmpty = m =>
25+export const validateNotEmpty = v =>
74− simpleValidatorWrapper({
83− error: 'This field is required.',
26+ v.length === 0 && 'This field is required.';
86// Checks if a patp is a valid galaxy
28// Checks if a patp is a valid galaxy
87−export const validateGalaxy = m =>
29+export const validateGalaxy = v => {
88− simpleValidatorWrapper({
93− point = patp2dec(d);
31+ const point = patp2dec(v);
94− return point >= MIN_GALAXY && point <= MAX_GALAXY;
32+ const isValidGalaxy = point >= MIN_GALAXY && point <= MAX_GALAXY;
95− } catch (e) {
33+ if (!isValidGalaxy) {
96− return false;
34+ throw new Error();
99− error: 'This is not a valid galaxy.',
37+ return 'This is not a valid galaxy.';
102−export const validatePoint = m =>
103− simpleValidatorWrapper({
107− return ob.isValidPatp(d);
112− error: 'This is not a valid point.',
115−export const validateTicket = m =>
116− simpleValidatorWrapper({
120− return ob.isValidPatq(d);
125− error: 'This is not a valid ticket.',
128−export const validateShard = m =>
129− simpleValidatorWrapper({
133− return ob.isValidPatq(d);
138− error: 'This is not a valid shard.',
141−export const validateOneOf = (options = []) => m =>
142− simpleValidatorWrapper({
144− validator: d => includes(options, d),
145− error: `Is not a valid option.`,
148−export const validateHexString = m =>
149− simpleValidatorWrapper({
151− validator: d => isHexString.test(d),
152− error: 'This is not a valid hex string.',
156−export const validateNetworkKey = m =>
157− simpleValidatorWrapper({
159− validator: d => plain64CharHexValue.test(d),
160− error: 'This is not a valid network key.',
163−// @deprecate
41+export const validatePoint = v => {
164−export const validateNetworkSeed = m =>
42+ try {
165− simpleValidatorWrapper({
43+ if (!ob.isValidPatp(v)) {
166− prevMessage: m,
44+ throw new Error();
167− validator: d => plain64CharHexValue.test(d),
45+ }
168− error: 'This is not a valid network seed.',
47+ return 'This is not a valid point.';
171−// Checks if a string is a valid ethereum address
51+export const validatePatq = v => {
172−export const validateEthereumAddress = m =>
52+ try {
173− simpleValidatorWrapper({
53+ if (!ob.isValidPatq(v)) {
174− prevMessage: m,
54+ throw new Error();
175− validator: d => isValidAddress(d),
55+ }
176− error: 'This is not a valid Ethereum address.',
57+ return 'This is not a valid ticket.';
179−export const validateEmail = m =>
61+export const validateOneOf = (options = []) => v =>
180− simpleValidatorWrapper({
62+ !includes(options, v) && 'Is not a valid option.';
182− validator: d => emailRegExp.test(d),
183− error: 'This is not a valid email address.',
186−export const validateInt = m =>
64+export const validateHexString = v =>
187− simpleValidatorWrapper({
189− transform: d => parseInt(d, 10),
198− error: 'This is not a valid number.',
65+ !isHexString.test(v) && 'This is not a valid hex string.';
201−export const validateExactly = (value, error) => m =>
67+export const validateEthereumAddress = v =>
202− simpleValidatorWrapper({
68+ !isValidAddress(v) && 'This is not a valid Ethereum address.';
204− validator: d => d === value,
208−export const validateNotAny = (values = []) => m =>
70+export const validateEmail = v =>
209− simpleValidatorWrapper({
71+ !emailRegExp.test(v) && 'This is not a valid email address.';
211− validator: d => !values.includes(d),
212− error: `Cannot be ${m.data}.`,
215−export const validateLength = l => m =>
73+export const validateExactly = (value, error) => v => v !== value && error;
216− simpleValidatorWrapper({
220− return d.length === l;
225− error: `Must be exactly ${l} characters.`,
228−export const validateHexLength = l => m =>
75+export const validateNotAny = (values = []) => v =>
229− simpleValidatorWrapper({
76+ values.includes(v) && `Cannot be ${v}.`;
233− return d.length === l + 2;
238− error: `Must be exactly ${l} hex characters.`,
241−export const validateMaximumLength = l => m =>
78+export const validateLength = l => v =>
242− simpleValidatorWrapper({
246− return d.length <= l;
251− error: `Must be ${l} characters or fewer.`,
79+ v.length !== l && `Must be exactly ${l} characters.`;
254−export const validateGreaterThan = l => m =>
81+export const validateHexLength = l => v =>
255− simpleValidatorWrapper({
82+ v.length !== l + 2 && `Must be exactly ${l} hex characters.`;
257− validator: d => d > l,
258− error: `Must be at least ${l}.`,
261−export const validateInSet = (set, error) => m =>
84+export const validateMaximumLength = l => v =>
262− simpleValidatorWrapper({
85+ v.length > l && `Must be ${l} characters or fewer.`;
264− validator: d => set.has(d),
268−export const validateNameInNumberSet = (set, error) => m =>
87+export const validateGreaterThan = l => v =>
269− simpleValidatorWrapper({
88+ !(v > l) && `Must be at least ${l}.`;
272− const num = patp2dec(p);
273− return set.has(num);
278−export const validatePatpByteLength = byteLength => {
90+export const validateInSet = (set, error) => v => !set.has(v) && error;
279− return validateLength(patpStringLength(byteLength));
282−export const validateMaximumPatpByteLength = byteLength => {
92+export const validateMaximumPatpByteLength = byteLength =>
283− return validateMaximumLength(patpStringLength(byteLength));
93+ validateMaximumLength(patpStringLength(byteLength));
286export const validateNotNullAddress = validateNotAny([
95export const validateNotNullAddress = validateNotAny([
287 ETH_ZERO_ADDR,
96 ETH_ZERO_ADDR,