github.com/ethereum-optimism/optimism@v1.7.2/packages/core-utils/src/common/hex-strings.ts (about) 1 /* Imports: External */ 2 import { BigNumber } from '@ethersproject/bignumber' 3 import { isHexString, hexZeroPad } from '@ethersproject/bytes' 4 5 /** 6 * Removes "0x" from start of a string if it exists. 7 * 8 * @param str String to modify. 9 * @returns the string without "0x". 10 */ 11 export const remove0x = (str: string): string => { 12 if (str === undefined) { 13 return str 14 } 15 return str.startsWith('0x') ? str.slice(2) : str 16 } 17 18 /** 19 * Adds "0x" to the start of a string if necessary. 20 * 21 * @param str String to modify. 22 * @returns the string with "0x". 23 */ 24 export const add0x = (str: string): string => { 25 if (str === undefined) { 26 return str 27 } 28 return str.startsWith('0x') ? str : '0x' + str 29 } 30 31 /** 32 * Casts a hex string to a buffer. 33 * 34 * @param inp Input to cast to a buffer. 35 * @return Input cast as a buffer. 36 */ 37 export const fromHexString = (inp: Buffer | string): Buffer => { 38 if (typeof inp === 'string' && inp.startsWith('0x')) { 39 return Buffer.from(inp.slice(2), 'hex') 40 } 41 42 return Buffer.from(inp) 43 } 44 45 /** 46 * Casts an input to a hex string. 47 * 48 * @param inp Input to cast to a hex string. 49 * @return Input cast as a hex string. 50 */ 51 export const toHexString = (inp: Buffer | string | number | null): string => { 52 if (typeof inp === 'number') { 53 return BigNumber.from(inp).toHexString() 54 } else { 55 return '0x' + fromHexString(inp).toString('hex') 56 } 57 } 58 59 /** 60 * Casts a number to a hex string without zero padding. 61 * 62 * @param n Number to cast to a hex string. 63 * @return Number cast as a hex string. 64 */ 65 export const toRpcHexString = (n: number | BigNumber): string => { 66 let num 67 if (typeof n === 'number') { 68 num = '0x' + n.toString(16) 69 } else { 70 num = n.toHexString() 71 } 72 73 if (num === '0x0') { 74 return num 75 } else { 76 // BigNumber pads a single 0 to keep hex length even 77 return num.replace(/^0x0/, '0x') 78 } 79 } 80 81 /** 82 * Zero pads a hex string if str.length !== 2 + length * 2. Pads to length * 2. 83 * 84 * @param str Hex string to pad 85 * @param length Half the length of the desired padded hex string 86 * @return Hex string with length of 2 + length * 2 87 */ 88 export const padHexString = (str: string, length: number): string => { 89 if (str.length === 2 + length * 2) { 90 return str 91 } else { 92 return '0x' + str.slice(2).padStart(length * 2, '0') 93 } 94 } 95 96 /** 97 * Casts an input to hex string without '0x' prefix with conditional padding. 98 * Hex string will always start with a 0. 99 * 100 * @param val Input to cast to a hex string. 101 * @param len Desired length to pad hex string. Ignored if less than hex string length. 102 * @return Hex string with '0' prefix 103 */ 104 export const encodeHex = (val: any, len: number): string => 105 remove0x(BigNumber.from(val).toHexString()).padStart(len, '0') 106 107 /** 108 * Case insensitive hex string equality check 109 * 110 * @param stringA Hex string A 111 * @param stringB Hex string B 112 * @throws {Error} Inputs must be valid hex strings 113 * @return True if equal 114 */ 115 export const hexStringEquals = (stringA: string, stringB: string): boolean => { 116 if (!isHexString(stringA)) { 117 throw new Error(`input is not a hex string: ${stringA}`) 118 } 119 120 if (!isHexString(stringB)) { 121 throw new Error(`input is not a hex string: ${stringB}`) 122 } 123 124 return stringA.toLowerCase() === stringB.toLowerCase() 125 } 126 127 /** 128 * Casts a number to a 32-byte, zero padded hex string. 129 * 130 * @param value Number to cast to a hex string. 131 * @return Number cast as a hex string. 132 */ 133 export const bytes32ify = (value: number | BigNumber): string => { 134 return hexZeroPad(BigNumber.from(value).toHexString(), 32) 135 }