UNPKG

@unique-nft/utils

Version:

A tiny library to work with Substrate and Ethereum addresses and do some more

849 lines (831 loc) 32.6 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/Royalties/index.ts var Royalties_exports = {}; __export(Royalties_exports, { Royalties: () => Royalties, RoyaltyType: () => RoyaltyType }); module.exports = __toCommonJS(Royalties_exports); // src/Royalties/types.ts var RoyaltyType = /* @__PURE__ */ ((RoyaltyType2) => { RoyaltyType2["DEFAULT"] = "DEFAULT"; RoyaltyType2["PRIMARY_ONLY"] = "PRIMARY_ONLY"; return RoyaltyType2; })(RoyaltyType || {}); // src/Royalties/utils.ts var utils_exports = {}; __export(utils_exports, { ROYALTIES_PROPERTY: () => ROYALTIES_PROPERTY, encodeAddress: () => encodeAddress, get42Zeros: () => get42Zeros, parseRoyalties: () => parseRoyalties, parseRoyaltyPart: () => parseRoyaltyPart, splitStringEvery: () => splitStringEvery, toLibPart: () => toLibPart }); // src/Address/index.ts var Address_exports = {}; __export(Address_exports, { Address: () => Address, algorithms: () => imports_exports, collection: () => collection, compare: () => compare, constants: () => constants_exports, extract: () => extract, is: () => is, mirror: () => mirror, nesting: () => nesting, normalize: () => normalize, substrate: () => substrate, validate: () => validate }); // src/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/Address/imports.ts var imports_exports = {}; __export(imports_exports, { base58: () => base58, base64: () => base64, basex: () => import_base_x.default, blake2b: () => import_blake2b.blake2b, keccak_256: () => import_sha3.keccak_256 }); var import_base_x = __toESM(require("base-x")); var import_sha3 = require("@noble/hashes/sha3"); var import_blake2b = require("@noble/hashes/blake2b"); var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var base58 = (0, import_base_x.default)(BASE58_ALPHABET); var base64 = (0, import_base_x.default)(BASE64_ALPHABET); // src/Address/ethereum.ts var import_utf_helpers = require("utf-helpers"); var DWORDHexString = { _checkU32: (num) => { if (typeof num !== "number") throw new Error(`Passed number is not a number: ${typeof num}, ${num}`); if (isNaN(num)) throw new Error(`Passed number is NaN: ${num}`); if (num < 0) throw new Error(`Passed number is less than 0: ${num}`); if (num > 4294967295) throw new Error(`Passed number is more than 2**32: ${num}`); if (num !== Math.floor(num)) throw new Error(`Passed number is not an integer number: ${num}`); return num; }, fromNumber: (n) => { return DWORDHexString._checkU32(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 DWORDHexString._checkU32(num); } }; var unsafeNormalizeEthereumAddress = (address) => { const addr = address.toLowerCase().replace(/^0x/i, ""); const addressHash = import_utf_helpers.HexString.fromU8a((0, import_sha3.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/Address/substrate.ts var import_utf_helpers2 = require("utf-helpers"); var blake2AsU8a = (u8a, dkLen = 32) => { return (0, import_blake2b.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, ignoreChecksum = false) => { 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); let isValid = false; if (!ignoreChecksum) { const hash = sshash(decoded.subarray(0, length)); 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" ? import_utf_helpers2.HexString.toU8a(key) : typeof key === "bigint" ? import_utf_helpers2.HexString.toU8a(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 { if (is.substratePublicKey(address)) { return { u8a: import_utf_helpers2.HexString.toU8a(address), bigint: BigInt(address), hex: address, ss58Prefix: 42 }; } else if (address.startsWith("0x")) { throw new Error(`Invalid substrate address, received ${address}. Wrong or mangled public key?`); } 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, ignoreChecksum); 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 = import_utf_helpers2.HexString.fromU8a(publicKey); return { u8a: publicKey, hex, bigint: BigInt(hex), ss58Prefix: ss58Decoded }; } 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(import_utf_helpers2.HexString.fromU8a(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, import_utf_helpers2.HexString.toU8a(evmAddress)]); return encodeSubstrateAddress(blake2AsU8a(message), ss58Format); }; // src/Address/crossAccountId.ts var guessAddressAndExtractCrossAccountIdUnsafe = (rawAddress, normalize2 = false) => { const address = rawAddress; if (typeof address === "object") { if (address.hasOwnProperty("eth") && address.hasOwnProperty("sub")) { const subPublicKey = address.sub.hasOwnProperty("_hex") && typeof address.sub._hex === "string" ? address.sub._hex : address.sub; if (typeof subPublicKey !== "string" || !subPublicKey.startsWith("0x")) { throw new Error(`Substrate public key must be a hex string, got ${subPublicKey}`); } const subBigInt = BigInt(subPublicKey); const ethBigInt = BigInt(address.eth); if (!(Number(subBigInt === 0n) ^ Number(ethBigInt === 0n))) { throw new Error(`One of the addresses must be 0, got eth ${address.eth} and substrate public key ${address.sub}.`); } if (subBigInt === 0n) { return { Ethereum: normalizeEthereumAddress(address.eth) }; } else { return { Substrate: normalizeSubstrateAddress(subPublicKey) }; } } else if (address.hasOwnProperty("Substrate") || address.hasOwnProperty("substrate")) { const substrateAddress = address.hasOwnProperty("Substrate") ? address.Substrate : address.substrate; if (is.substratePublicKey(substrateAddress)) { return { Substrate: normalizeSubstrateAddress(substrateAddress) }; } else if (is.substrateAddress(substrateAddress)) { return { Substrate: normalize2 ? normalizeSubstrateAddress(substrateAddress) : substrateAddress }; } else { throw new Error(`Address ${substrateAddress} is not a valid Substrate address`); } } else if (address.hasOwnProperty("Ethereum") || address.hasOwnProperty("ethereum")) { const ethereumAddress = address.hasOwnProperty("Ethereum") ? address.Ethereum : address.ethereum; validate.ethereumAddress(ethereumAddress); return { Ethereum: normalize2 ? normalizeEthereumAddress(ethereumAddress) : ethereumAddress }; } else { throw new Error(`Address ${address} is not a valid crossAccountId object (should contain "Substrate"/"substrate" or "Ethereum"/"ethereum" field) or EthCrossAccountId (should contain "eth" and "sub" fields)`); } } if (typeof address === "string") { if (is.substrateAddress(address)) return { Substrate: normalize2 ? normalizeSubstrateAddress(address) : address }; else if (is.ethereumAddress(address)) return { Ethereum: normalize2 ? normalizeEthereumAddress(address) : address }; else if (is.substratePublicKey(address)) return { Substrate: normalizeSubstrateAddress(address) }; else { throw new Error(`Address ${address} is not a valid Substrate or Ethereum address`); } } throw new Error(`Address ${address} is not a string or object: ${typeof address}`); }; var guessAddressAndExtractCrossAccountIdSafe = (address, normalize2 = false) => { try { return guessAddressAndExtractCrossAccountIdUnsafe(address, normalize2); } catch { return null; } }; var substrateOrMirrorIfEthereum = (address, normalize2 = false) => { const addressObject = guessAddressAndExtractCrossAccountIdUnsafe(address, normalize2); return addressObject.Substrate ? addressObject.Substrate : mirror.ethereumToSubstrate(addressObject.Ethereum); }; var addressInAnyFormToEnhancedCrossAccountId = (address, ss58Prefix = 42) => { const crossAccountId = guessAddressAndExtractCrossAccountIdUnsafe(address); if (crossAccountId.Ethereum) { const normalized = normalizeEthereumAddress(crossAccountId.Ethereum); return { ...crossAccountId, address: normalized, addressSS58: normalized, substratePublicKey: normalized, isEthereum: true, isSubstrate: false, type: "Ethereum" }; } else { return { ...crossAccountId, address: normalizeSubstrateAddress(crossAccountId.Substrate), addressSS58: normalizeSubstrateAddress(crossAccountId.Substrate, ss58Prefix), substratePublicKey: decodeSubstrateAddress(crossAccountId.Substrate).hex, isEthereum: false, isSubstrate: true, type: "Substrate" }; } }; // src/Address/index.ts var ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/; var SUB_PUBLIC_KEY_REGEX = /^0x[a-fA-F0-9]{64}$/; 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; }, substratePublicKey: (address) => { if (!is.substratePublicKey(address)) { throw new Error(`address "${address}" is not valid substrate public key`); } 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 !is.substratePublicKey(address); } catch { return false; } }, ethereumAddress: (address) => { return typeof address === "string" && address.length === 42 && !!address.match(ETH_ADDRESS_REGEX); }, substratePublicKey: (address) => { return typeof address === "string" && address.length === 66 && !!address.match(SUB_PUBLIC_KEY_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); }, substrateAddressInAnyForm(address) { return typeof address === "string" ? is.substrateAddress(address) : typeof address === "object" && !!address && (is.substrateAddressObject(address) || is.substrateAddressObjectUncapitalized(address)); }, ethereumAddressInAnyForm(address) { return typeof address === "string" ? is.ethereumAddress(address) : typeof address === "object" && !!address && (is.ethereumAddressObject(address) || is.ethereumAddressObjectUncapitalized(address)); }, validAddressInAnyForm(address) { return is.ethereumAddressInAnyForm(address) || is.substrateAddressInAnyForm(address); } }; var collection = { idToAddress: collectionIdToEthAddress, addressToId: ethAddressToCollectionId }; var nesting = { idsToAddress: collectionIdAndTokenIdToNestingAddress, addressToIds: nestingAddressToCollectionIdAndTokenId }; var extract = { address: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId); return crossAccountId.Substrate || crossAccountId.Ethereum; }, addressSafe: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdSafe(addressOrCrossAccountId); return crossAccountId ? crossAccountId.Substrate || crossAccountId.Ethereum : null; }, addressNormalized: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId, true); return crossAccountId.Substrate || crossAccountId.Ethereum; }, addressNormalizedSafe: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdSafe(addressOrCrossAccountId, true); return crossAccountId ? crossAccountId.Substrate || crossAccountId.Ethereum : null; }, addressForScanNormalized: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId, true); return crossAccountId.Substrate || crossAccountId.Ethereum.toLowerCase(); }, addressForScanNormalizedSafe: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdSafe(addressOrCrossAccountId, true); return crossAccountId ? crossAccountId.Substrate || crossAccountId.Ethereum.toLowerCase() : null; }, crossAccountId: (addressOrCrossAccountId) => { return guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId); }, crossAccountIdSafe: (addressOrCrossAccountId) => { return guessAddressAndExtractCrossAccountIdSafe(addressOrCrossAccountId); }, crossAccountIdNormalized: (addressOrCrossAccountId) => { return guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId, true); }, crossAccountIdNormalizedSafe: (addressOrCrossAccountId) => { return guessAddressAndExtractCrossAccountIdSafe(addressOrCrossAccountId, true); }, crossAccountIdUncapitalized: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId); return crossAccountId.Substrate ? { substrate: crossAccountId.Substrate } : { ethereum: crossAccountId.Ethereum }; }, crossAccountIdUncapitalizedSafe: (addressOrCrossAccountId) => { try { return extract.crossAccountIdUncapitalized(addressOrCrossAccountId); } catch { return null; } }, crossAccountIdUncapitalizedNormalized: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId, true); return crossAccountId.Substrate ? { substrate: crossAccountId.Substrate } : { ethereum: crossAccountId.Ethereum }; }, crossAccountIdUncapitalizedNormalizedSafe: (addressOrCrossAccountId) => { try { return extract.crossAccountIdUncapitalizedNormalized(addressOrCrossAccountId); } catch { return null; } }, substrateOrMirrorIfEthereum: (addressOrCrossAccountId) => { return substrateOrMirrorIfEthereum(addressOrCrossAccountId); }, substrateOrMirrorIfEthereumSafe: (addressOrCrossAccountId) => { try { return substrateOrMirrorIfEthereum(addressOrCrossAccountId); } catch { return null; } }, substrateOrMirrorIfEthereumNormalized: (addressOrCrossAccountId) => { return substrateOrMirrorIfEthereum(addressOrCrossAccountId, true); }, substrateOrMirrorIfEthereumNormalizedSafe: (addressOrCrossAccountId) => { try { return substrateOrMirrorIfEthereum(addressOrCrossAccountId, true); } catch { return null; } }, substratePublicKey: (addressOrCrossAccountId) => { const crossAccountId = guessAddressAndExtractCrossAccountIdUnsafe(addressOrCrossAccountId); if (!crossAccountId.Substrate) { throw new Error("Address is not a substrate address"); } return substrate.decode(crossAccountId.Substrate).hex; }, substratePublicKeySafe: (addressOrCrossAccountId) => { try { return extract.substratePublicKey(addressOrCrossAccountId); } catch { return null; } }, enhancedCrossAccountId: (addressInAnyForm, ss58Prefix = 42) => { return addressInAnyFormToEnhancedCrossAccountId(addressInAnyForm, ss58Prefix); }, enhancedCrossAccountIdSafe: (addressInAnyForm, ss58Prefix = 42) => { try { return addressInAnyFormToEnhancedCrossAccountId(addressInAnyForm, ss58Prefix); } catch { return null; } }, ethCrossAccountId: (addressInAnyForm) => { const addressEnhanced = addressInAnyFormToEnhancedCrossAccountId(addressInAnyForm); if (addressEnhanced.Substrate) { return { eth: "0x0000000000000000000000000000000000000000", sub: addressEnhanced.substratePublicKey }; } else { return { eth: addressEnhanced.address, sub: "0x00" }; } }, ethCrossAccountIdSafe: (addressInAnyForm) => { try { return extract.ethCrossAccountId(addressInAnyForm); } catch { return null; } } }; 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, algorithms: imports_exports, is, validate, collection, nesting, extract, mirror, normalize, compare, substrate, utils: { DWORDHexString } }; // src/index.ts var StringUtils = __toESM(require("utf-helpers")); // src/Utils/coin.ts var coin_exports = {}; __reExport(coin_exports, require("coin-format")); // src/index.ts var { HexString: HexString4, Utf8, Utf16 } = StringUtils; // src/Royalties/utils.ts var ROYALTIES_PROPERTY = "royalties"; var get42Zeros = () => "".padStart(42, "0"); var splitStringEvery = (str, every) => { const result = []; for (let i = 0; i < str.length; i += every) { result.push(str.substring(i, i + every)); } return result; }; var encodeAddress = (address) => { if (Address_exports.is.ethereumAddress(address)) { return [ true, Address_exports.normalize.ethereumAddress(address).substring(2).padStart(64, "0").toLowerCase() ]; } return [false, Address_exports.substrate.decode(address).hex.substring(2)]; }; var toLibPart = (part) => { const account = Address_exports.is.ethereumAddress(part.address) ? part.address : Address_exports.mirror.substrateToEthereum(part.address); const value = part.value * 10n ** BigInt(part.decimals - 4); return { account, value }; }; var parseRoyaltyPart = (part) => { part.version = part.version ?? 1; if (1 > part.version || part.version > 127) { throw new Error(`Version must be between 1 and 127, got ${part.version}`); } if (!Number.isInteger(part.version)) { throw new Error(`Version must be an integer, got ${part.version}`); } part.decimals = part.decimals ?? 4; if (0 > part.decimals || part.decimals > 255) { throw new Error(`Decimals must be between 0 and 255, got ${part.decimals}`); } if (!Number.isInteger(part.decimals)) { throw new Error(`Decimals must be an integer, got ${part.decimals}`); } if (!Number.isInteger(part.value) && typeof part.value !== "bigint") { throw new Error(`Value must be an integer or bigint, got ${part.value} (${typeof part.value})`); } if (part.value < 1 || part.value > 2n ** 64n - 1n) { throw new Error( `Value must be between 1 and 18446744073709551615 (uint64), got ${part.value}` ); } part.royaltyType = part.royaltyType ?? "DEFAULT" /* DEFAULT */; if (!RoyaltyType[part.royaltyType]) { throw new Error( `Royalty type must be one of ${Object.keys(RoyaltyType)}, got ${part.royaltyType}` ); } part.address = Address_exports.extract.address(part.address); return part; }; var parseRoyalties = (parts) => { if (!Array.isArray(parts)) { throw new Error("Royalties must be an array"); } return parts.map(parseRoyaltyPart); }; // src/Royalties/calculation.ts var calculateRoyaltyPart = (part, sellPrice) => { const royalty = parseRoyaltyPart(part); return { address: royalty.address, amount: sellPrice * royalty.value / 10n ** BigInt(royalty.decimals) }; }; var calculateRoyalties = (royalties, isPrimarySale, sellPrice) => { return royalties.filter( (r) => isPrimarySale === (r.royaltyType === "PRIMARY_ONLY" /* PRIMARY_ONLY */) ).map((r) => calculateRoyaltyPart(r, sellPrice)); }; // src/Royalties/decoding.ts var decodeRoyaltyPart = (encoded) => { if (encoded.length !== 130) { throw new Error('Invalid royalty part encoding - length is not 32 bytes ("0x" + 64 symbols)'); } const encodedMeta = encoded.slice(2, 66); const encodedAddress = encoded.slice(2 + 64); const version = parseInt(encodedMeta.slice(0, 2), 16); const decimals = parseInt(encodedMeta.slice(46, 46 + 2), 16); const value = BigInt("0x" + encodedMeta.slice(48)); const royaltyType = encodedMeta[44] === "0" ? "DEFAULT" /* DEFAULT */ : "PRIMARY_ONLY" /* PRIMARY_ONLY */; const isEthereum = encodedMeta[45] === "0"; const address = isEthereum ? Address.normalize.ethereumAddress("0x" + encodedAddress.slice(24)) : Address.substrate.encode(encodedAddress); return { version, decimals, value, royaltyType, address }; }; var decodeRoyalties = (encoded) => { if ((encoded.length - 2) % 128 !== 0) { throw new Error("Invalid royalties encoding - length is not multiple of 64 bytes (128 symbols)"); } const parts = splitStringEvery(encoded.substring(2), 128).map( (encoded2) => "0x" + encoded2 ); return parts.map((part) => decodeRoyaltyPart(part)); }; var decodeRoyaltyToV2 = (encoded) => { const royaltyParts = encoded ? decodeRoyalties(encoded) : []; return royaltyParts.map((royaltyPart) => { const royalty = { address: royaltyPart.address, // core idea: given value 2500 with decimals 4, we want to get 2.5 // or 650000 with decimals 6, we want to get 6.5 percent: Number(royaltyPart.value) / Math.pow(10, royaltyPart.decimals - 2) }; if (royaltyPart.royaltyType === "PRIMARY_ONLY" /* PRIMARY_ONLY */) { royalty.isPrimaryOnly = true; } return royalty; }); }; // src/Royalties/encoding.ts var encodeRoyaltyPart = (royaltyPart) => { const part = parseRoyaltyPart(royaltyPart); const version = part.version.toString(16).padStart(2, "0"); const royaltyType = part.royaltyType === "DEFAULT" /* DEFAULT */ ? "0" : "1"; const decimals = part.decimals.toString(16).padStart(2, "0"); const value = part.value.toString(16).padStart(16, "0"); const [isEthereum, address] = encodeAddress(part.address); const addressType = isEthereum ? "0" : "1"; return `0x${version}${get42Zeros()}${royaltyType}${addressType}${decimals}${value}${address}`; }; var encodeRoyalties = (parts) => "0x" + parts.map((part) => encodeRoyaltyPart(part).substring(2)).join(""); var encodeRoyaltyFromV2 = (royalties) => { const royaltiesToEncode = royalties.map((royalty) => { const { address, percent, isPrimaryOnly } = royalty; const valueInPercent = percent * 100; if (valueInPercent % 1 !== 0) throw new Error("Royalty percent value must has maximum 2 decimal places"); return { address, value: BigInt(percent * 100), decimals: 4, royaltyType: isPrimaryOnly ? "PRIMARY_ONLY" /* PRIMARY_ONLY */ : "DEFAULT" /* DEFAULT */, version: 1 }; }); return encodeRoyalties(royaltiesToEncode); }; // src/Royalties/index.ts var Royalties = { part: { calculate: calculateRoyaltyPart, decode: decodeRoyaltyPart, encode: encodeRoyaltyPart, validate: (part) => { parseRoyaltyPart(part); return true; } }, calculate: calculateRoyalties, decode: decodeRoyalties, encode: encodeRoyalties, validate: (royalties) => { parseRoyalties(royalties); return true; }, uniqueV2: { decode: decodeRoyaltyToV2, encode: encodeRoyaltyFromV2 }, utils: utils_exports }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Royalties, RoyaltyType }); //# sourceMappingURL=royalties.js.map