@colony/purser-core
Version:
A collection of helpers, utils, validators and normalizers to assist the individual purser modules
159 lines (151 loc) • 4.85 kB
Flow
/* @flow */
import { PATH, SPLITTER, MATCH, SIGNATURE } from './defaults';
/**
* Normalize a derivation path passed in as a string
*
* This method assumes the derivation path is already validatated and is in a correct format.
* Use `derivationPathValidator` from `validators` to achieve that.
*
* @method derivationPathNormalizer
*
* @param {string} derivationPath The derivation path to normalize
*
* @return {string} The normalized derivation path
*/
export const derivationPathNormalizer = (derivationPath: string): string => {
const deSerializedDerivationPath: Array<string> = derivationPath.split(
PATH.DELIMITER,
);
return deSerializedDerivationPath
.map((pathSection, index) => {
switch (index) {
/*
* Normalize the header key (letter "m")
*/
case 0: {
const deviationPathHeader = pathSection.split(SPLITTER);
return [
deviationPathHeader[0].toLowerCase(),
/*
* The purpose doesn't need to be normalized, since we check for the exact value (44)
* inside the validator
*/
deviationPathHeader[1],
].join(SPLITTER);
}
/*
* Normalize the Coin type id and the account (they both normalize the same)
*/
/* eslint-disable-next-line no-fallthrough */
case 1:
case 2: {
return parseInt(pathSection, 10).toString();
}
case 3: {
const deviationPathChageIndex = pathSection.split(SPLITTER);
return deviationPathChageIndex
.map(value => parseInt(value, 10))
.slice(0, 2)
.join(SPLITTER);
}
default: {
return pathSection;
}
}
})
.join(PATH.DELIMITER);
};
/**
* Normalize a hex string to have the length of multiple of two.
* Eg: '3' to be '03', `12c` to be `012c`
*
* This is only needed currently for Trezor's service
*
* This method assumes the value path is already validatated.
*
* @method multipleOfTwoHexValueNormalizer
*
* @param {string} hexValue The hex value to normalize
*
* @return {string} The normalized (padded) hex path
*/
export const multipleOfTwoHexValueNormalizer = (hexValue: string): string =>
String(hexValue).padStart(Math.ceil(hexValue.length / 2) * 2, '0');
const stringPrefixNormalizer = (
pattern: RegExp,
str: string,
prefix: boolean = true,
) => {
/*
* Index 1 is the prefix (if it exists), index 2 is the value without a prefix
*/
const matchedAddress = str.match(pattern) || [];
return prefix
? `0x${matchedAddress[2]}`
: matchedAddress[2];
};
/**
* Normalize an Ethereum address
*
* This method assumes the address is already validatated and is in the correct format.
*
* @method addressNormalizer
*
* @param {string} address The address to normalize
* @param {boolean} prefix Should the final value have a prefix?
*
* @return {string} The normalized string
*/
export const addressNormalizer =
stringPrefixNormalizer.bind(null, MATCH.ADDRESS);
/**
* Normalize a hex string sequence.
*
* Transforms it to lower case, and, depending on the prefix argument,
* either add it (`0x`) or remove it
*
* This method assumes the address is already validatated and is in the correct format.
*
* @method hexSequenceNormalizer
*
* @param {string} hexString The hex string sequence to normalize
* @param {boolean} prefix Should the final value have a prefix?
*
* @return {string} The normalized string
*/
export const hexSequenceNormalizer = (
hexString: string,
prefix: boolean = true,
) => stringPrefixNormalizer(MATCH.HEX_STRING, hexString.toLowerCase(), prefix);
/**
* Normalize the recovery param of an Ethereum ECDSA signature.
*
* @NOTE This will only work for Ethereum based signatures since this is using
* the values from EIP-155
*
* This will basically add 27 to the recovery param value if that is either 0 or 1 (odd or even).
* If it's any other value, leave it as it is.
*
* See EIP-155 for the 27 and 28 magic numbers expected in the recovery parameter:
* https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
*
* @method recoveryParamNormalizer
*
* @param {number} recoveryParam The recovery param value to normalize
* (The one extracted from the signature)
*
* @return {number} The normalized recovery param value
*/
export const recoveryParamNormalizer = (recoveryParam: number): number => {
if (typeof recoveryParam !== 'number') {
throw new Error('Recovery param value is not valid');
}
let normalizedRecoveryParam = recoveryParam;
if (recoveryParam === 0) {
normalizedRecoveryParam = SIGNATURE.RECOVERY_ODD;
}
if (recoveryParam === 1) {
normalizedRecoveryParam = SIGNATURE.RECOVERY_EVEN;
}
return normalizedRecoveryParam;
};