UNPKG

@unique-nft/api

Version:

Definitely typed JS API for the Unique Network blockchain

460 lines (451 loc) 16.5 kB
var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; // src/utils/address/constants.ts var constants_exports = {}; __export(constants_exports, { COLLECTION_ADDRESS_PREFIX: () => COLLECTION_ADDRESS_PREFIX, NESTING_PREFIX: () => NESTING_PREFIX, STATIC_ADDRESSES: () => STATIC_ADDRESSES }); var STATIC_ADDRESSES = { contractHelpers: "0x842899ECF380553E8a4de75bF534cdf6fBF64049", collectionHelpers: "0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F" }; var NESTING_PREFIX = "0xf8238ccfff8ed887463fd5e0"; var COLLECTION_ADDRESS_PREFIX = "0x17c4e6453cc49aaaaeaca894e6d9683e"; // src/utils/address/imports.ts var imports_exports = {}; __export(imports_exports, { base58: () => base58, base64: () => base64, basex: () => basex, blake2b: () => blake2b, keccak_256: () => keccak_256 }); import basex from "base-x"; import { keccak_256 } from "@noble/hashes/sha3"; import { blake2b } from "@noble/hashes/blake2b"; var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var base58 = basex(BASE58_ALPHABET); var base64 = basex(BASE64_ALPHABET); // src/utils/address/stringUtils.ts var stringUtils_exports = {}; __export(stringUtils_exports, { DWORDHexString: () => DWORDHexString, hexStringToString: () => hexStringToString, hexToU8a: () => hexToU8a, parseAndCheckTheNumberIsDWORD: () => parseAndCheckTheNumberIsDWORD, safeJsonParseStringOrHexString: () => safeJsonParseStringOrHexString, str2vec: () => str2vec, strToU8a: () => strToU8a, u8aToHex: () => u8aToHex, vec2str: () => vec2str }); // src/tsUtils.ts var safeJSONParse = (str) => { try { return JSON.parse(str); } catch { return str; } }; // src/utils/address/stringUtils.ts var vec2str = (arr) => { return arr.map((x) => String.fromCharCode(typeof x === "number" ? x : parseInt(x, 10))).join(""); }; var str2vec = (str) => { if (typeof str !== "string") { return str; } return str.split("").map((x) => x.charCodeAt(0)); }; var strToU8a = (str) => new Uint8Array(str2vec(str)); var hexToU8a = (hexString) => Uint8Array.from(((hexString.startsWith("0x") ? hexString.slice(2) : hexString).match(/.{1,2}/g) || []).map((byte) => parseInt(byte, 16))); var u8aToHex = (bytes) => { const arr = bytes instanceof Uint8Array ? Array.from(bytes) : bytes; return "0x" + arr.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), ""); }; var hexStringToString = (hexString) => ((hexString.startsWith("0x") ? hexString.slice(2) : hexString).match(/.{1,2}/g) || []).map((el) => String.fromCharCode(parseInt(el, 16))).join(""); var safeJsonParseStringOrHexString = (stringOrHexString) => { try { return JSON.parse(stringOrHexString); } catch { return safeJSONParse(hexStringToString(stringOrHexString)); } }; var parseAndCheckTheNumberIsDWORD = (n) => { const num = typeof n === "string" ? parseInt(n, 10) : n; if (isNaN(num)) throw new Error(`Passed number is NaN: ${n}`); if (num < 0) throw new Error(`Passed number is less than 0: ${n}`); if (num > 4294967295) throw new Error(`Passed number is more than 2**32: ${n}`); return num; }; var DWORDHexString = { fromNumber: (n) => { return parseAndCheckTheNumberIsDWORD(n).toString(16).padStart(8, "0"); }, toNumber: (s) => { const num = parseInt(s, 16); if (isNaN(num)) throw new Error(`Passed string is not hexadecimal: ${s}`); return num; } }; // src/utils/address/ethereum.ts var unsafeNormalizeEthereumAddress = (address) => { const addr = address.toLowerCase().replace(/^0x/i, ""); const addressHash = u8aToHex(keccak_256(addr)).replace(/^0x/i, ""); let checksumAddress = "0x"; for (let i = 0; i < addr.length; i++) { checksumAddress += parseInt(addressHash[i], 16) > 7 ? addr[i].toUpperCase() : addr[i]; } return checksumAddress; }; var normalizeEthereumAddress = (address) => { validate.ethereumAddress(address); return unsafeNormalizeEthereumAddress(address); }; var compareEthereumAddresses = (address1, address2) => { const addr1 = typeof address1 === "string" ? address1 : address1.Ethereum || address1.ethereum; const addr2 = typeof address2 === "string" ? address2 : address2.Ethereum || address2.ethereum; if (!addr1 || !addr2 || !is.ethereumAddress(addr1) || !is.ethereumAddress(addr2)) { return false; } return addr1.toLowerCase() === addr2.toLowerCase(); }; var collectionIdToEthAddress = (collectionId) => { validate.collectionId(collectionId); return unsafeNormalizeEthereumAddress(COLLECTION_ADDRESS_PREFIX + DWORDHexString.fromNumber(collectionId)); }; var ethAddressToCollectionId = (address) => { validate.collectionAddress(address); return DWORDHexString.toNumber(address.slice(-8)); }; var collectionIdAndTokenIdToNestingAddress = (collectionId, tokenId) => { validate.collectionId(collectionId); validate.tokenId(tokenId); return unsafeNormalizeEthereumAddress(NESTING_PREFIX + DWORDHexString.fromNumber(collectionId) + DWORDHexString.fromNumber(tokenId)); }; var nestingAddressToCollectionIdAndTokenId = (address) => { validate.nestingAddress(address); return { collectionId: DWORDHexString.toNumber(address.slice(-16, -8)), tokenId: DWORDHexString.toNumber(address.slice(-8)) }; }; // src/utils/address/substrate.ts var blake2AsU8a = (u8a, dkLen = 32) => { return blake2b(u8a, { dkLen }); }; var u8aConcat = (u8as) => { let offset = 0; let length = 0; for (let i = 0; i < u8as.length; i++) { length += u8as[i].length; } const result = new Uint8Array(length); for (let i = 0; i < u8as.length; i++) { result.set(u8as[i], offset); offset += u8as[i].length; } return result; }; var SS58_PREFIX = new Uint8Array([83, 83, 53, 56, 80, 82, 69]); var sshash = (data) => { return blake2AsU8a(u8aConcat([SS58_PREFIX, data]), 64); }; var checkAddressChecksum = (decoded) => { const ss58Length = decoded[0] & 64 ? 2 : 1; const ss58Decoded = ss58Length === 1 ? decoded[0] : (decoded[0] & 63) << 2 | decoded[1] >> 6 | (decoded[1] & 63) << 8; const isPublicKey = [34 + ss58Length, 35 + ss58Length].includes(decoded.length); const length = decoded.length - (isPublicKey ? 2 : 1); const hash = sshash(decoded.subarray(0, length)); const isValid = (decoded[0] & 128) === 0 && ![46, 47].includes(decoded[0]) && (isPublicKey ? decoded[decoded.length - 2] === hash[0] && decoded[decoded.length - 1] === hash[1] : decoded[decoded.length - 1] === hash[0]); return [isValid, length, ss58Length, ss58Decoded]; }; var normalizeSubstrateAddress = (address, prefix = 42) => { return encodeSubstrateAddress(decodeSubstrateAddress(address).u8a, prefix); }; function encodeSubstrateAddress(key, ss58Format = 42) { const u8a = typeof key === "string" ? hexToU8a(key) : typeof key === "bigint" ? hexToU8a(key.toString(16)) : key; if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) { throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`); } const allowedDecodedLengths = [1, 2, 4, 8, 32, 33]; if (!allowedDecodedLengths.includes(u8a.length)) { throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(", ")}`); } const u8aPrefix = ss58Format < 64 ? new Uint8Array([ss58Format]) : new Uint8Array([ (ss58Format & 252) >> 2 | 64, ss58Format >> 8 | (ss58Format & 3) << 6 ]); const input = u8aConcat([u8aPrefix, u8a]); return base58.encode(u8aConcat([ input, sshash(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1) ])); } function decodeSubstrateAddress(address, ignoreChecksum, ss58Format = -1) { let realError = null; try { const decoded = base58.decode(address); const allowedEncodedLengths = [3, 4, 6, 10, 35, 36, 37, 38]; if (!allowedEncodedLengths.includes(decoded.length)) { realError = new Error(`key length is not valid, decoded key length is ${decoded.length}, valid values are ${allowedEncodedLengths.join(", ")}`); throw realError; } const [isValid, endPos, ss58Length, ss58Decoded] = checkAddressChecksum(decoded); if (!ignoreChecksum && !isValid) { realError = new Error(`Invalid decoded address checksum`); throw realError; } if (![-1, ss58Decoded].includes(ss58Format)) { realError = new Error(`Expected ss58Format ${ss58Format}, received ${ss58Decoded}`); throw realError; } const publicKey = decoded.slice(ss58Length, endPos); const hex = u8aToHex(publicKey); return { u8a: publicKey, hex, bigint: BigInt(hex) }; } catch (error) { throw realError ? realError : new Error(`Decoding ${address}: ${error.message}`); } } var compareSubstrateAddresses = (address1, address2) => { const addr1 = typeof address1 === "string" ? address1 : address1.Substrate || address1.substrate; const addr2 = typeof address2 === "string" ? address2 : address2.Substrate || address2.substrate; if (!addr1 || !addr2) { return false; } try { const decoded1 = decodeSubstrateAddress(addr1); const decoded2 = decodeSubstrateAddress(addr2); return decoded1.bigint === decoded2.bigint; } catch (e) { return false; } }; var addressToEvm = (address, ignoreChecksum) => { const truncated = decodeSubstrateAddress(address, ignoreChecksum).u8a.subarray(0, 20); return normalizeEthereumAddress(u8aToHex(truncated)); }; var EVM_PREFIX_U8A = new Uint8Array([101, 118, 109, 58]); var evmToAddress = (evmAddress, ss58Format = 42) => { validate.ethereumAddress(evmAddress); const message = u8aConcat([EVM_PREFIX_U8A, hexToU8a(evmAddress)]); return encodeSubstrateAddress(blake2AsU8a(message), ss58Format); }; // src/utils/address/crossAccountId.ts var guessAddressAndExtractItNormalizedSafe = (address) => { if (typeof address === "object") { if (is.substrateAddressObject(address)) return normalize.substrateAddress(address.Substrate); else if (is.substrateAddressObjectUncapitalized(address)) return normalize.substrateAddress(address.substrate); else if (is.ethereumAddressObject(address)) return normalizeEthereumAddress(address.Ethereum); else if (is.ethereumAddressObjectUncapitalized(address)) return normalizeEthereumAddress(address.ethereum); else return null; } if (typeof address === "string") { if (is.substrateAddress(address)) return normalizeSubstrateAddress(address); else if (is.ethereumAddress(address)) return normalizeEthereumAddress(address); else return null; } return null; }; var guessAddressAndExtractItNormalized = (address) => { const result = guessAddressAndExtractItNormalizedSafe(address); if (!result) { throw new Error(`Passed address is not a valid address string or object: ${JSON.stringify(address).slice(0, 100)}`); } return result; }; var addressToCrossAccountId = (address) => { if (is.substrateAddress(address)) { return { Substrate: address }; } else if (is.ethereumAddress(address)) { return { Ethereum: address }; } throw new Error(`Passed address ${address} is not substrate nor ethereum address`); }; var addressToCrossAccountIdNormalized = (address) => { if (is.substrateAddress(address)) { return { Substrate: normalize.substrateAddress(address) }; } else if (is.ethereumAddress(address)) { return { Ethereum: normalize.ethereumAddress(address) }; } throw new Error(`Passed address ${address} is not substrate nor ethereum address`); }; var substrateNormalizedWithMirrorIfEthereum = (address) => { const addressObject = addressToCrossAccountId(address); return addressObject.Substrate ? normalizeSubstrateAddress(addressObject.Substrate) : mirror.ethereumToSubstrate(addressObject.Ethereum); }; // src/utils/address/index.ts var ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/; var validate = { substrateAddress: (address) => { decodeSubstrateAddress(address); return true; }, ethereumAddress: (address) => { if (!is.ethereumAddress(address)) { throw new Error(`address "${address}" is not valid ethereum address`); } return true; }, collectionAddress: (address) => { if (!is.collectionAddress(address)) { throw new Error(`address ${address} is not a collection address`); } return true; }, nestingAddress: (address) => { if (!is.nestingAddress(address)) { throw new Error(`address ${address} is not a nesting address`); } return true; }, collectionId: (collectionId) => { if (!is.collectionId(collectionId)) { throw new Error(`collectionId should be a number between 0 and 0xffffffff`); } return true; }, tokenId: (tokenId) => { if (!is.tokenId(tokenId)) { throw new Error(`collectionId should be a number between 0 and 0xffffffff`); } return true; } }; var is = { substrateAddress: (address) => { try { decodeSubstrateAddress(address); return true; } catch { return false; } }, ethereumAddress: (address) => { return typeof address === "string" && address.length === 42 && !!address.match(ETH_ADDRESS_REGEX); }, collectionAddress: (address) => { return is.ethereumAddress(address) && address.toLowerCase().startsWith(COLLECTION_ADDRESS_PREFIX); }, nestingAddress: (address) => { return is.ethereumAddress(address) && address.toLowerCase().startsWith(NESTING_PREFIX); }, collectionId: (collectionId) => { return !(typeof collectionId !== "number" || isNaN(collectionId) || collectionId < 0 || collectionId > 4294967295); }, tokenId: (tokenId) => { return !(typeof tokenId !== "number" || isNaN(tokenId) || tokenId < 0 || tokenId > 4294967295); }, crossAccountId(obj) { return is.substrateAddressObject(obj) || is.ethereumAddressObject(obj); }, crossAccountIdUncapitalized(obj) { return is.substrateAddressObjectUncapitalized(obj) || is.ethereumAddressObjectUncapitalized(obj); }, substrateAddressObject(obj) { return typeof obj === "object" && typeof obj?.Substrate === "string" && is.substrateAddress(obj.Substrate); }, ethereumAddressObject(obj) { return typeof obj === "object" && typeof obj?.Ethereum === "string" && is.ethereumAddress(obj.Ethereum); }, substrateAddressObjectUncapitalized(obj) { return typeof obj === "object" && typeof obj?.substrate === "string" && is.substrateAddress(obj.substrate); }, ethereumAddressObjectUncapitalized(obj) { return typeof obj === "object" && typeof obj?.ethereum === "string" && is.ethereumAddress(obj.ethereum); } }; var collection = { idToAddress: collectionIdToEthAddress, addressToId: ethAddressToCollectionId }; var nesting = { idsToAddress: collectionIdAndTokenIdToNestingAddress, addressToIds: nestingAddressToCollectionIdAndTokenId }; var to = { crossAccountId: addressToCrossAccountId, crossAccountIdNormalized: addressToCrossAccountIdNormalized, substrateNormalizedOrMirrorIfEthereum: substrateNormalizedWithMirrorIfEthereum }; var extract = { normalizedAddressFromObject: guessAddressAndExtractItNormalized, normalizedAddressFromObjectSafe: guessAddressAndExtractItNormalizedSafe, crossAccountIdFromObject: (obj) => { return addressToCrossAccountId(guessAddressAndExtractItNormalized(obj)); }, crossAccountIdFromObjectNormalized: (obj) => { return addressToCrossAccountId(guessAddressAndExtractItNormalized(obj)); } }; var mirror = { substrateToEthereum: addressToEvm, ethereumToSubstrate: evmToAddress }; var normalize = { substrateAddress: normalizeSubstrateAddress, ethereumAddress: normalizeEthereumAddress }; var compare = { substrateAddresses: compareSubstrateAddresses, ethereumAddresses: compareEthereumAddresses }; var substrate = { encode: encodeSubstrateAddress, decode: decodeSubstrateAddress, compare: compareSubstrateAddresses }; var Address = { constants: constants_exports, is, validate, collection, nesting, to, extract, mirror, normalize, compare, substrate, algorithms: imports_exports, StringUtils: stringUtils_exports }; export { Address, stringUtils_exports as StringUtils, imports_exports as algorithms, collection, compare, constants_exports as constants, extract, is, mirror, nesting, normalize, substrate, to, validate }; //# sourceMappingURL=address.mjs.map