All files / src/common utils.ts

100% Statements 41/41
100% Branches 12/12
100% Functions 8/8
100% Lines 34/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 995x 5x                       5x           5x 181x 7x 7x       5x   152x 2x   150x   152x     5x         142x 142x 140x   140x 3x             137x       5x       142x   142x 140x       2x         5x       108x       104x 104x     5x 8x   5x 6x     5x       64x    
import { BigNumber } from "ethers";
import {
  BytesLike,
  arrayify,
  formatBytes32String,
  hexlify,
  isHexString,
  keccak256,
  parseUnits,
  toUtf8Bytes,
  zeroPad,
} from "ethers/lib/utils";
 
const ZERO_EX_PREFIX_LENGTH = 2; // length of string "0x"
 
export type NumberLike = number | string;
 
export type ConvertibleToBytes32 = string;
 
export const assert = (condition: boolean, errMsg?: string) => {
  if (!condition) {
    const errText = `Assertion failed` + (errMsg ? `: ${errMsg}` : "");
    throw new Error(errText);
  }
};
 
export const convertStringToBytes32 = (str: string): Uint8Array => {
  let bytes32Str: string;
  if (str.length > 31) {
    bytes32Str = keccak256(isHexString(str) ? str : toUtf8Bytes(str));
  } else {
    bytes32Str = formatBytes32String(str);
  }
  return arrayify(bytes32Str);
};
 
export const convertNumberToBytes = (
  value: NumberLike,
  decimals: number,
  byteSize: number
): Uint8Array => {
  const stringifiedNumber = convertNumberToString(value, decimals);
  const bigNumberValue = parseUnits(stringifiedNumber, decimals);
  const bytesValue = arrayify(bigNumberValue.toHexString());
 
  if (byteSize < bytesValue.length) {
    throw new Error(
      `Overflow: ` +
        `value: ${value}, ` +
        `decimals: ${decimals}, ` +
        `byteSize: ${byteSize}`
    );
  } else {
    return zeroPad(bytesValue, byteSize);
  }
};
 
export const convertNumberToString = (
  value: NumberLike,
  decimals: number
): string => {
  const stringifiedNumber = Number(value).toFixed(decimals);
 
  if (!stringifiedNumber.includes("e")) {
    return stringifiedNumber;
  }
  // js for numbers >1e20 uses scientific notation,
  // which is not supported by BigNumber.js
  return Number(stringifiedNumber).toLocaleString("fullwide", {
    useGrouping: false,
  });
};
 
export const convertIntegerNumberToBytes = (
  value: NumberLike,
  byteSize: number
): Uint8Array => {
  assert(
    Number.isInteger(Number(value)),
    "convertIntegerNumberToBytes expects integer as input"
  );
  const decimals = 0; // 0 digits after comma
  return convertNumberToBytes(value, decimals, byteSize);
};
 
export const convertBytesToNumber = (bytes: Uint8Array): number =>
  BigNumber.from(bytes).toNumber();
 
export const hexlifyWithout0xPrefix = (value: BytesLike): string => {
  return hexlify(value).slice(ZERO_EX_PREFIX_LENGTH);
};
 
export function useDefaultIfUndefined<T>(
  value: T | undefined,
  defaultValue: T
): T {
  return value === undefined ? defaultValue : value;
}