UNPKG

ox

Version:

Ethereum Standard Library

116 lines 3.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InvalidChecksumError = exports.InvalidInputError = exports.InvalidAddressError = void 0; exports.assert = assert; exports.checksum = checksum; exports.from = from; exports.fromPublicKey = fromPublicKey; exports.isEqual = isEqual; exports.validate = validate; const Bytes = require("./Bytes.js"); const Caches = require("./Caches.js"); const Errors = require("./Errors.js"); const Hash = require("./Hash.js"); const PublicKey = require("./PublicKey.js"); const addressRegex = /^0x[a-fA-F0-9]{40}$/; function assert(value, options = {}) { const { strict = true } = options; if (!addressRegex.test(value)) throw new InvalidAddressError({ address: value, cause: new InvalidInputError(), }); if (strict) { if (value.toLowerCase() === value) return; if (checksum(value) !== value) throw new InvalidAddressError({ address: value, cause: new InvalidChecksumError(), }); } } function checksum(address) { if (Caches.checksum.has(address)) return Caches.checksum.get(address); assert(address, { strict: false }); const hexAddress = address.substring(2).toLowerCase(); const hash = Hash.keccak256(Bytes.fromString(hexAddress), { as: 'Bytes' }); const characters = hexAddress.split(''); for (let i = 0; i < 40; i += 2) { if (hash[i >> 1] >> 4 >= 8 && characters[i]) { characters[i] = characters[i].toUpperCase(); } if ((hash[i >> 1] & 0x0f) >= 8 && characters[i + 1]) { characters[i + 1] = characters[i + 1].toUpperCase(); } } const result = `0x${characters.join('')}`; Caches.checksum.set(address, result); return result; } function from(address, options = {}) { const { checksum: checksumVal = false } = options; assert(address); if (checksumVal) return checksum(address); return address; } function fromPublicKey(publicKey, options = {}) { const address = Hash.keccak256(`0x${PublicKey.toHex(publicKey).slice(4)}`).substring(26); return from(`0x${address}`, options); } function isEqual(addressA, addressB) { assert(addressA, { strict: false }); assert(addressB, { strict: false }); return addressA.toLowerCase() === addressB.toLowerCase(); } function validate(address, options = {}) { const { strict = true } = options ?? {}; try { assert(address, { strict }); return true; } catch { return false; } } class InvalidAddressError extends Errors.BaseError { constructor({ address, cause }) { super(`Address "${address}" is invalid.`, { cause, }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'Address.InvalidAddressError' }); } } exports.InvalidAddressError = InvalidAddressError; class InvalidInputError extends Errors.BaseError { constructor() { super('Address is not a 20 byte (40 hexadecimal character) value.'); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'Address.InvalidInputError' }); } } exports.InvalidInputError = InvalidInputError; class InvalidChecksumError extends Errors.BaseError { constructor() { super('Address does not match its checksum counterpart.'); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: 'Address.InvalidChecksumError' }); } } exports.InvalidChecksumError = InvalidChecksumError; //# sourceMappingURL=Address.js.map