string_manipulation.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. "use strict";
  2. /*
  3. This file is part of web3.js.
  4. web3.js is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. web3.js is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with web3.js. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. Object.defineProperty(exports, "__esModule", { value: true });
  16. exports.fromTwosComplement = exports.toTwosComplement = exports.leftPad = exports.rightPad = exports.padRight = exports.padLeft = void 0;
  17. const web3_errors_1 = require("web3-errors");
  18. const web3_validator_1 = require("web3-validator");
  19. const converters_js_1 = require("./converters.js");
  20. /**
  21. * Adds a padding on the left of a string, if value is a integer or bigInt will be converted to a hex string.
  22. * @param value - The value to be padded.
  23. * @param characterAmount - The amount of characters the string should have.
  24. * @param sign - The sign to be added (default is 0).
  25. * @returns The padded string.
  26. *
  27. * @example
  28. * ```ts
  29. *
  30. * console.log(web3.utils.padLeft('0x123', 10));
  31. * >0x0000000123
  32. * ```
  33. */
  34. const padLeft = (value, characterAmount, sign = '0') => {
  35. // To avoid duplicate code and circular dependency we will
  36. // use `padLeft` implementation from `web3-validator`
  37. if (typeof value === 'string') {
  38. if (!(0, web3_validator_1.isHexStrict)(value)) {
  39. return value.padStart(characterAmount, sign);
  40. }
  41. return web3_validator_1.utils.padLeft(value, characterAmount, sign);
  42. }
  43. web3_validator_1.validator.validate(['int'], [value]);
  44. return web3_validator_1.utils.padLeft(value, characterAmount, sign);
  45. };
  46. exports.padLeft = padLeft;
  47. /**
  48. * Adds a padding on the right of a string, if value is a integer or bigInt will be converted to a hex string.
  49. * @param value - The value to be padded.
  50. * @param characterAmount - The amount of characters the string should have.
  51. * @param sign - The sign to be added (default is 0).
  52. * @returns The padded string.
  53. *
  54. * @example
  55. * ```ts
  56. * console.log(web3.utils.padRight('0x123', 10));
  57. * > 0x1230000000
  58. *
  59. * console.log(web3.utils.padRight('0x123', 10, '1'));
  60. * > 0x1231111111
  61. * ```
  62. */
  63. const padRight = (value, characterAmount, sign = '0') => {
  64. if (typeof value === 'string' && !(0, web3_validator_1.isHexStrict)(value)) {
  65. return value.padEnd(characterAmount, sign);
  66. }
  67. web3_validator_1.validator.validate(['int'], [value]);
  68. const hexString = typeof value === 'string' && (0, web3_validator_1.isHexStrict)(value) ? value : (0, converters_js_1.numberToHex)(value);
  69. const prefixLength = hexString.startsWith('-') ? 3 : 2;
  70. return hexString.padEnd(characterAmount + prefixLength, sign);
  71. };
  72. exports.padRight = padRight;
  73. /**
  74. * Adds a padding on the right of a string, if value is a integer or bigInt will be converted to a hex string. @alias `padRight`
  75. */
  76. exports.rightPad = exports.padRight;
  77. /**
  78. * Adds a padding on the left of a string, if value is a integer or bigInt will be converted to a hex string. @alias `padLeft`
  79. */
  80. exports.leftPad = exports.padLeft;
  81. /**
  82. * Converts a negative number into the two’s complement and return a hexstring of 64 nibbles.
  83. * @param value - The value to be converted.
  84. * @param nibbleWidth - The nibble width of the hex string (default is 64).
  85. *
  86. * @returns The hex string of the two’s complement.
  87. *
  88. * @example
  89. * ```ts
  90. * console.log(web3.utils.toTwosComplement(13, 32));
  91. * > 0x0000000000000000000000000000000d
  92. *
  93. * console.log(web3.utils.toTwosComplement('-0x1', 32));
  94. * > 0xffffffffffffffffffffffffffffffff
  95. *
  96. * console.log(web3.utils.toTwosComplement(BigInt('9007199254740992'), 32));
  97. * > 0x00000000000000000020000000000000
  98. * ```
  99. */
  100. const toTwosComplement = (value, nibbleWidth = 64) => {
  101. web3_validator_1.validator.validate(['int'], [value]);
  102. const val = (0, converters_js_1.toNumber)(value);
  103. if (val >= 0)
  104. return (0, exports.padLeft)((0, converters_js_1.toHex)(val), nibbleWidth);
  105. const largestBit = BigInt(2) ** BigInt(nibbleWidth * 4);
  106. if (-val >= largestBit) {
  107. throw new web3_errors_1.NibbleWidthError(`value: ${value}, nibbleWidth: ${nibbleWidth}`);
  108. }
  109. const updatedVal = BigInt(val);
  110. const complement = updatedVal + largestBit;
  111. return (0, exports.padLeft)((0, converters_js_1.numberToHex)(complement), nibbleWidth);
  112. };
  113. exports.toTwosComplement = toTwosComplement;
  114. /**
  115. * Converts the twos complement into a decimal number or big int.
  116. * @param value - The value to be converted.
  117. * @param nibbleWidth - The nibble width of the hex string (default is 64).
  118. * @returns The decimal number or big int.
  119. *
  120. * @example
  121. * ```ts
  122. * console.log(web3.utils.fromTwosComplement(''0x0000000000000000000000000000000d', 32'));
  123. * > 13
  124. *
  125. * console.log(web3.utils.fromTwosComplement('0x00000000000000000020000000000000', 32));
  126. * > 9007199254740992n
  127. * ```
  128. */
  129. const fromTwosComplement = (value, nibbleWidth = 64) => {
  130. web3_validator_1.validator.validate(['int'], [value]);
  131. const val = (0, converters_js_1.toNumber)(value);
  132. if (val < 0)
  133. return val;
  134. const largestBit = Math.ceil(Math.log(Number(val)) / Math.log(2));
  135. if (largestBit > nibbleWidth * 4)
  136. throw new web3_errors_1.NibbleWidthError(`value: "${value}", nibbleWidth: "${nibbleWidth}"`);
  137. // check the largest bit to see if negative
  138. if (nibbleWidth * 4 !== largestBit)
  139. return val;
  140. const complement = BigInt(2) ** (BigInt(nibbleWidth) * BigInt(4));
  141. return (0, converters_js_1.toNumber)(BigInt(val) - complement);
  142. };
  143. exports.fromTwosComplement = fromTwosComplement;
  144. //# sourceMappingURL=string_manipulation.js.map