on 5a30d53 help sign in
bridge/src/lib/validators.ts
154 lines 4.4 kB history raw
1import * as bip39 from 'bip39';
2import * as bitcoin from 'bitcoinjs-lib';
3import ob from 'urbit-ob';
4import { includes } from 'lodash';
6import { isValidAddress } from './utils/address';
7import { patp2dec } from './patp2dec';
8import { patpStringLength } from './lib';
9import {
10 ETH_ZERO_ADDR,
11 ETH_ZERO_ADDR_SHORT,
12 MIN_GALAXY,
13 MAX_GALAXY,
14} from './constants';
15import { ticketFromSegments } from 'form/formatters';
17// NOTE: do not use the /g modifier for these regexes
18// https://stackoverflow.com/a/21373261
19// https://stackoverflow.com/a/1520853
21// via: https://emailregex.com/
22const 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,}))$/;
24// validate only strings that use hex characters
25const isHexString = /[0-9A-Fa-f]/;
27// validate only strings that are prefixed with 0x
28const isHexPrefixed = /^0x/;
30// Validates a bip39 mnemonic
31export const validateMnemonic = v =>
32 !bip39.validateMnemonic(v) && 'This is not a valid mnemonic.';
34const isHdPath = /^m(\/[0-9]+'?)*$/;
35export const validateHdPath = v =>
36 !isHdPath.test(v) && 'Invalid HD derivation path.';
38// Checks an empty field
39export const validateNotEmpty = v =>
40 (v === undefined || v.length === 0) && 'This field is required.';
42// Checks if a patp is a valid galaxy
43export const validateGalaxy = v => {
44 try {
45 const point = patp2dec(v);
46 const isValidGalaxy = point >= MIN_GALAXY && point <= MAX_GALAXY;
47 if (!isValidGalaxy) {
48 throw new Error();
49 }
50 } catch {
51 return 'This is not a valid galaxy.';
52 }
53};
55export const validatePoint = v => {
56 try {
57 if (!ob.isValidPatp(v)) {
58 throw new Error();
59 }
60 } catch {
61 return 'This is not a valid point.';
62 }
63};
65export const validatePatq = v => {
66 try {
67 if (!ob.isValidPatq(v)) {
68 throw new Error();
69 }
70 } catch {
71 return 'This is not a valid ticket.';
72 }
73};
75export const validateShard = v => {
76 try {
77 if (v !== undefined && v !== '' && !ob.isValidPatq(v)) {
78 throw new Error();
79 }
80 } catch {
81 return 'This is not a valid shard.';
82 }
83};
85export const validateOneOf = (options = []) => v =>
86 !includes(options, v) && 'Is not a valid option.';
88export const validateHexString = v =>
89 !isHexString.test(v) && 'This is not a valid hex string.';
91export const validateHexPrefix = v =>
92 !isHexPrefixed.test(v) && 'Must include 0x prefix.';
94export const validateEthereumAddress = v =>
95 !isValidAddress(v) && 'This is not a valid Ethereum address.';
97export const validateEmail = v =>
98 !emailRegExp.test(v) && 'This is not a valid email address.';
100export const validateExactly = (value, error) => v => v !== value && error;
102export const validateNotAny = (values = []) => v =>
103 values.includes(v) && `Cannot be ${v}.`;
105export const validateLength = l => v =>
106 v.length !== l && `Must be exactly ${l} characters.`;
108export const validateHexLength = l => v =>
109 v.length !== l + 2 && `Must be exactly ${l} hex characters.`;
111export const validateMaximumLength = l => v =>
112 v.length > l && `Must be ${l} characters or fewer.`;
114export const validateMinimumLength = l => v =>
115 v.length < l && `Must be ${l} characters or more.`;
117export const validateGreaterThan = l => v =>
118 !(v > l) && `Must be greater than ${l}.`;
120export const validateLessThan = l => v => !(v < l) && `Must be less than ${l}`;
122export const validateInSet = (set, error) => v => !set.has(v) && error;
124export const validateMaximumPatpByteLength = byteLength =>
125 validateMaximumLength(patpStringLength(byteLength));
127export const validateMinimumPatpByteLength = byteLength =>
128 validateMinimumLength(patpStringLength(byteLength));
130export const validateNotNullAddress = validateNotAny([
131 ETH_ZERO_ADDR,
132 ETH_ZERO_ADDR_SHORT,
133]);
135export const validateUnique = arr => {
136 const res = [...new Set(arr)].length !== arr.length && 'Must be unique';
137 return res;
138};
140export const validateChild = ourShip => ship =>
141 ourShip !== ob.sein(ship) && `This point is not a child of ${ourShip}.`;
143export const validatePsbt = base64 => {
144 try {
145 bitcoin.Psbt.fromBase64(base64);
146 } catch (e) {
147 return 'Invalid Partially Signed Bitcoin Transaction';
148 }
149};
151export const validateSegmentedTicket = (segments: string[]) => {
152 const ticket = ticketFromSegments(segments);
153 return validatePatq(ticket);
154};