UNPKG

@conflux-dev/conflux-address-js

Version:

The encoder and decoder for Conflux Network address

249 lines (191 loc) 9.39 kB
"use strict"; function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArrayLimit(arr, i) { var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]); if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } var _require = require('./base32'), ALPHABET = _require.ALPHABET, ALPHABET_MAP = _require.ALPHABET_MAP, polyMod = _require.polyMod, convertBit = _require.convertBit; var CONST = require('../const'); var _require2 = require('../utils'), isHexString = _require2.isHexString, hexToBytes = _require2.hexToBytes, decodeUTF8 = _require2.decodeUTF8; var VERSION_BYTE = 0; var NET_ID_LIMIT = 0xFFFFFFFF; function encodeNetId(netId) { if (!Number.isInteger(netId)) { throw new Error('netId should be passed as an integer'); } if (netId < 0 || netId > NET_ID_LIMIT) { throw new Error('netId should be passed as in range [0, 0xFFFFFFFF]'); } switch (netId) { case CONST.NETID_TEST: return CONST.PREFIX_CFXTEST; case CONST.NETID_MAIN: return CONST.PREFIX_CFX; default: return "".concat(CONST.PREFIX_NET).concat(netId); } } function isValidNetId(netId) { return /^([1-9]\d*)$/.test(netId) && Number(netId) <= NET_ID_LIMIT; } function decodeNetId(payload) { switch (payload) { case CONST.PREFIX_CFXTEST: return CONST.NETID_TEST; case CONST.PREFIX_CFX: return CONST.NETID_MAIN; default: { var prefix = payload.slice(0, 3); var netId = payload.slice(3); if (prefix !== CONST.PREFIX_NET || !isValidNetId(netId)) { throw new Error("netId prefix should be passed by 'cfx', 'cfxtest' or 'net[n]' "); } if (Number(netId) === CONST.NETID_TEST || Number(netId) === CONST.NETID_MAIN) { throw new Error('net1 or net1029 are invalid'); } return Number(netId); } } } function getAddressType(hexAddress) { if (hexAddress.length < 1) { throw new Error('Empty payload in address'); } switch (hexAddress[0] & 0xf0) { case 0x10: return CONST.TYPE_USER; case 0x80: return CONST.TYPE_CONTRACT; case 0x00: var _iterator = _createForOfIteratorHelper(hexAddress), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var x = _step.value; if (x !== 0x00) { return CONST.TYPE_BUILTIN; } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return CONST.TYPE_NULL; default: return CONST.TYPE_UNKNOWN; // throw new Error('hexAddress should start with 0x0, 0x1 or 0x8') } } function encode(hexAddress, netId) { var verbose = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (isHexString(hexAddress)) { hexAddress = hexToBytes(hexAddress.slice(2)); } if (!(hexAddress instanceof Uint8Array)) { throw new Error('hexAddress should be passed as a Uint8Array'); } if (hexAddress.length < 20) { throw new Error('hexAddress should be at least 20 bytes'); } var addressType = getAddressType(hexAddress).toUpperCase(); var netName = encodeNetId(netId).toUpperCase(); var netName5Bits = decodeUTF8(netName).map(function (_byte) { return _byte & 31; }); var payload5Bits = convertBit([VERSION_BYTE].concat(_toConsumableArray(hexAddress)), 8, 5, true); var checksumBigInt = polyMod([].concat(_toConsumableArray(netName5Bits), [0], _toConsumableArray(payload5Bits), [0, 0, 0, 0, 0, 0, 0, 0])); var checksumBytes = hexToBytes(checksumBigInt.toString(16).padStart(10, '0'), 'hex'); var checksum5Bits = convertBit(checksumBytes, 8, 5, true); var payload = payload5Bits.map(function (_byte2) { return ALPHABET[_byte2]; }).join(''); var checksum = checksum5Bits.map(function (_byte3) { return ALPHABET[_byte3]; }).join(''); return verbose ? "".concat(netName, ":TYPE.").concat(addressType, ":").concat(payload).concat(checksum) : "".concat(netName, ":").concat(payload).concat(checksum).toLowerCase(); } function decode(address) { // don't allow mixed case var lowered = address.toLowerCase(); var uppered = address.toUpperCase(); if (address !== lowered && address !== uppered) { throw new Error('Mixed-case address ' + address); } var _address$toUpperCase$ = address.toUpperCase().match(/^([^:]+):(.+:)?(.{34})(.{8})$/), _address$toUpperCase$2 = _slicedToArray(_address$toUpperCase$, 5), netName = _address$toUpperCase$2[1], shouldHaveType = _address$toUpperCase$2[2], payload = _address$toUpperCase$2[3], checksum = _address$toUpperCase$2[4]; var prefix5Bits = decodeUTF8(netName).map(function (_byte4) { return _byte4 & 31; }); var payload5Bits = []; var _iterator2 = _createForOfIteratorHelper(payload), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _char = _step2.value; payload5Bits.push(ALPHABET_MAP[_char]); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } var checksum5Bits = []; var _iterator3 = _createForOfIteratorHelper(checksum), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var _char2 = _step3.value; checksum5Bits.push(ALPHABET_MAP[_char2]); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } var _convertBit = convertBit(payload5Bits, 5, 8), _convertBit2 = _toArray(_convertBit), version = _convertBit2[0], addressBytes = _convertBit2.slice(1); if (version !== VERSION_BYTE) { throw new Error('Can not recognize version byte'); } var hexAddress = new Uint8Array(addressBytes); var netId = decodeNetId(netName.toLowerCase()); var type = getAddressType(hexAddress); if (shouldHaveType && "type.".concat(type, ":") !== shouldHaveType.toLowerCase()) { throw new Error('Type of address doesn\'t match'); } var bigInt = polyMod([].concat(_toConsumableArray(prefix5Bits), [0], payload5Bits, checksum5Bits)); if (Number(bigInt)) { throw new Error("Invalid checksum for ".concat(address)); } return { hexAddress: hexAddress, netId: netId, type: type }; } module.exports = { encode: encode, decode: decode };