@unique-nft/utils
Version:
A tiny library to work with Substrate and Ethereum addresses and do some more
207 lines (201 loc) • 7.12 kB
JavaScript
import "./chunk-N4PTXCJY.mjs";
import {
Address,
Address_exports
} from "./chunk-6B63RM6C.mjs";
import {
__export
} from "./chunk-SMH5LAMQ.mjs";
// 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
});
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
};
export {
Royalties,
RoyaltyType
};
//# sourceMappingURL=royalties.mjs.map