hex-strings.ts 3.46 KB
Newer Older
1
/* Imports: External */
2 3
import { BigNumber } from '@ethersproject/bignumber'
import { isHexString, hexZeroPad } from '@ethersproject/bytes'
4 5 6

/**
 * Removes "0x" from start of a string if it exists.
7
 *
8 9 10 11 12 13 14 15 16 17 18 19
 * @param str String to modify.
 * @returns the string without "0x".
 */
export const remove0x = (str: string): string => {
  if (str === undefined) {
    return str
  }
  return str.startsWith('0x') ? str.slice(2) : str
}

/**
 * Adds "0x" to the start of a string if necessary.
20
 *
21 22 23 24 25 26 27 28 29 30 31 32
 * @param str String to modify.
 * @returns the string with "0x".
 */
export const add0x = (str: string): string => {
  if (str === undefined) {
    return str
  }
  return str.startsWith('0x') ? str : '0x' + str
}

/**
 * Casts a hex string to a buffer.
33
 *
34 35 36 37 38 39 40 41 42 43 44 45 46
 * @param inp Input to cast to a buffer.
 * @return Input cast as a buffer.
 */
export const fromHexString = (inp: Buffer | string): Buffer => {
  if (typeof inp === 'string' && inp.startsWith('0x')) {
    return Buffer.from(inp.slice(2), 'hex')
  }

  return Buffer.from(inp)
}

/**
 * Casts an input to a hex string.
47
 *
48 49 50 51 52 53 54 55 56 57 58
 * @param inp Input to cast to a hex string.
 * @return Input cast as a hex string.
 */
export const toHexString = (inp: Buffer | string | number | null): string => {
  if (typeof inp === 'number') {
    return BigNumber.from(inp).toHexString()
  } else {
    return '0x' + fromHexString(inp).toString('hex')
  }
}

59 60 61 62 63 64
/**
 * Casts a number to a hex string without zero padding.
 *
 * @param n Number to cast to a hex string.
 * @return Number cast as a hex string.
 */
65 66 67 68
export const toRpcHexString = (n: number | BigNumber): string => {
  let num
  if (typeof n === 'number') {
    num = '0x' + n.toString(16)
69
  } else {
70 71 72 73 74 75
    num = n.toHexString()
  }

  if (num === '0x0') {
    return num
  } else {
76
    // BigNumber pads a single 0 to keep hex length even
77
    return num.replace(/^0x0/, '0x')
78 79 80
  }
}

81 82 83 84 85 86 87
/**
 * Zero pads a hex string if str.length !== 2 + length * 2. Pads to length * 2.
 *
 * @param str Hex string to pad
 * @param length Half the length of the desired padded hex string
 * @return Hex string with length of 2 + length * 2
 */
88 89 90 91 92 93 94 95
export const padHexString = (str: string, length: number): string => {
  if (str.length === 2 + length * 2) {
    return str
  } else {
    return '0x' + str.slice(2).padStart(length * 2, '0')
  }
}

96 97 98 99 100 101 102 103 104
/**
 * Casts an input to hex string without '0x' prefix with conditional padding.
 * Hex string will always start with a 0.
 *
 * @param val Input to cast to a hex string.
 * @param len Desired length to pad hex string. Ignored if less than hex string length.
 * @return Hex string with '0' prefix
 */
export const encodeHex = (val: any, len: number): string =>
105
  remove0x(BigNumber.from(val).toHexString()).padStart(len, '0')
106

107 108 109 110 111 112 113 114
/**
 * Case insensitive hex string equality check
 *
 * @param stringA Hex string A
 * @param stringB Hex string B
 * @throws {Error} Inputs must be valid hex strings
 * @return True if equal
 */
115
export const hexStringEquals = (stringA: string, stringB: string): boolean => {
116
  if (!isHexString(stringA)) {
117 118 119
    throw new Error(`input is not a hex string: ${stringA}`)
  }

120
  if (!isHexString(stringB)) {
121 122 123 124 125
    throw new Error(`input is not a hex string: ${stringB}`)
  }

  return stringA.toLowerCase() === stringB.toLowerCase()
}
126

127 128 129 130 131 132
/**
 * Casts a number to a 32-byte, zero padded hex string.
 *
 * @param value Number to cast to a hex string.
 * @return Number cast as a hex string.
 */
133
export const bytes32ify = (value: number | BigNumber): string => {
134
  return hexZeroPad(BigNumber.from(value).toHexString(), 32)
135
}