@unique-nft/api
Version:
Definitely typed JS API for the Unique Network blockchain
460 lines (451 loc) • 16.5 kB
JavaScript
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