bns-v2-sdk
Version:
The official BNS V2 SDK for interacting with Stacks Blockchain
741 lines (740 loc) • 35 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLastTokenId = getLastTokenId;
exports.getRenewalHeight = getRenewalHeight;
exports.canResolveName = canResolveName;
exports.getOwner = getOwner;
exports.getOwnerById = getOwnerById;
exports.getIdFromBns = getIdFromBns;
exports.getBnsFromId = getBnsFromId;
exports.canRegisterName = canRegisterName;
exports.getNamespacePrice = getNamespacePrice;
exports.getNamePrice = getNamePrice;
exports.canNamespaceBeRegistered = canNamespaceBeRegistered;
exports.getNamespaceProperties = getNamespaceProperties;
exports.getNameInfo = getNameInfo;
exports.getPrimaryName = getPrimaryName;
exports.fetchUserOwnedNames = fetchUserOwnedNames;
exports.resolveNameZonefile = resolveNameZonefile;
exports.getZonefileRaw = getZonefileRaw;
exports.getZonefileProfile = getZonefileProfile;
const transactions_1 = require("@stacks/transactions");
const axios_1 = __importDefault(require("axios"));
const utils_1 = require("./utils");
const config_1 = require("./config");
const callersHelper_1 = require("./callersHelper");
const debug_1 = require("./debug");
const API_BASE_URL = "https://api.bnsv2.com";
const callApi = async (endpoint, network) => {
try {
const networkPrefix = network === "testnet" ? "/testnet" : "";
const url = `${API_BASE_URL}${networkPrefix}${endpoint}`;
debug_1.debug.log("Making API call to:", url);
const response = await axios_1.default.get(url);
return response.data;
}
catch (error) {
debug_1.debug.error("API call failed:", error);
throw error;
}
};
async function getLastTokenId({ network, }) {
try {
const response = await callApi("/token/last-id", network);
return response.last_token_id;
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-last-token-id",
senderAddress: randomAddress,
functionArgs: [],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.UInt) {
return responseCV.value.value;
}
throw new Error("Response did not contain a UInt");
}
if (responseCV.type === transactions_1.ClarityType.ResponseErr) {
throw new Error((0, transactions_1.cvToString)(responseCV.value));
}
throw new Error(`Unexpected Clarity Value type: ${(0, transactions_1.getCVTypeString)(responseCV)}`);
}
}
async function getRenewalHeight({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/names/${fullyQualifiedName}/renewal`, network);
return BigInt(response.renewal_height);
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot get renewal height for a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const nameId = await getIdFromBns({ fullyQualifiedName, network });
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-renewal-height",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.uintCV)(nameId)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.UInt) {
return responseCV.value.value;
}
throw new Error("Response did not contain a UInt");
}
if (responseCV.type === transactions_1.ClarityType.ResponseErr) {
throw new Error((0, transactions_1.cvToString)(responseCV.value));
}
throw new Error(`Unexpected Clarity Value type: ${(0, transactions_1.getCVTypeString)(responseCV)}`);
}
}
async function canResolveName({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/names/${fullyQualifiedName}/can-resolve`, network);
return {
renewal: BigInt(response.renewal_height),
owner: response.owner,
};
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot check resolution for a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "can-resolve-name",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace), (0, transactions_1.bufferCVFromString)(name)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk &&
responseCV.value.type === transactions_1.ClarityType.Tuple) {
const renewalCV = responseCV.value.value["renewal"];
const ownerCV = responseCV.value.value["owner"];
if (renewalCV.type === transactions_1.ClarityType.UInt &&
(ownerCV.type === transactions_1.ClarityType.PrincipalStandard ||
ownerCV.type === transactions_1.ClarityType.PrincipalContract)) {
return {
renewal: renewalCV.value,
owner: (0, transactions_1.cvToString)(ownerCV),
};
}
throw new Error("Unexpected data types in response tuple");
}
throw new Error("Invalid response from contract");
}
}
async function getOwner({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/names/${fullyQualifiedName}/owner`, network);
return response.owner;
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot check resolution for a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-owner-name",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCVFromString)(namespace)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.OptionalSome) {
if (responseCV.value.value.type === transactions_1.ClarityType.PrincipalStandard ||
responseCV.value.value.type === transactions_1.ClarityType.PrincipalContract) {
return (0, transactions_1.cvToString)(responseCV.value.value);
}
throw new Error("Owner is not a principal");
}
if (responseCV.value.type === transactions_1.ClarityType.OptionalNone) {
return null;
}
}
throw new Error("Invalid response from contract");
}
}
async function getOwnerById({ id, network, }) {
try {
const response = await callApi(`/tokens/${id}/owner`, network);
return response.owner;
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-owner",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.uintCV)(id)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.OptionalSome) {
if (responseCV.value.value.type === transactions_1.ClarityType.PrincipalStandard ||
responseCV.value.value.type === transactions_1.ClarityType.PrincipalContract) {
return (0, transactions_1.cvToString)(responseCV.value.value);
}
throw new Error("Owner is not a principal");
}
if (responseCV.value.type === transactions_1.ClarityType.OptionalNone) {
return null;
}
}
throw new Error("Invalid response from contract");
}
}
async function getIdFromBns({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/names/${fullyQualifiedName}/id`, network);
return BigInt(response.id);
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot get info for a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-id-from-bns",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCVFromString)(namespace)],
network,
});
if (responseCV.type === transactions_1.ClarityType.OptionalSome) {
if (responseCV.value.type === transactions_1.ClarityType.UInt) {
return responseCV.value.value;
}
throw new Error("Response did not contain a UInt");
}
if (responseCV.type === transactions_1.ClarityType.OptionalNone) {
throw new Error("Name not found");
}
throw new Error(`Unexpected Clarity Value type: ${(0, transactions_1.getCVTypeString)(responseCV)}`);
}
}
async function getBnsFromId({ id, network, }) {
try {
const response = await callApi(`/tokens/${id}/name`, network);
return {
name: response.name,
namespace: response.namespace,
};
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-bns-from-id",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.uintCV)(id)],
network,
});
if (responseCV.type === transactions_1.ClarityType.OptionalSome) {
if (responseCV.value.type === transactions_1.ClarityType.Tuple) {
const nameCV = responseCV.value.value["name"];
const namespaceCV = responseCV.value.value["namespace"];
return {
name: nameCV.value.toString(),
namespace: nameCV.value.toString(),
};
}
throw new Error("Response did not contain a Tuple");
}
if (responseCV.type === transactions_1.ClarityType.OptionalNone) {
return null;
}
throw new Error(`Unexpected Clarity Value type: ${(0, transactions_1.getCVTypeString)(responseCV)}`);
}
}
async function canRegisterName({ fullyQualifiedName, network, }) {
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot register a subdomain using registerName");
}
try {
const response = await callApi(`/names/${namespace}/${name}/can-register`, network);
return response.can_register;
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
return fallbackContractCall(name, namespace, network);
}
}
async function fallbackContractCall(name, namespace, network) {
const randomAddress = (0, utils_1.generateRandomAddress)();
debug_1.debug.log("Falling back to contract call:", { name, namespace, network });
return (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-bns-info",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCVFromString)(namespace)],
network,
}).then((responseCV) => {
if (responseCV.type === transactions_1.ClarityType.OptionalSome) {
debug_1.debug.log("Name exists in contract");
return false;
}
else if (responseCV.type === transactions_1.ClarityType.OptionalNone) {
debug_1.debug.log("Name available in contract");
return true;
}
else {
throw new Error(`Unexpected response type: ${responseCV.type}`);
}
});
}
async function getNamespacePrice({ namespace, network, }) {
const bnsFunctionName = "get-namespace-price";
const randomAddress = (0, utils_1.generateRandomAddress)();
return (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: bnsFunctionName,
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace)],
network,
}).then((responseCV) => {
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.Int ||
responseCV.value.type === transactions_1.ClarityType.UInt) {
return responseCV.value.value;
}
else {
throw new Error("Response did not contain a number");
}
}
else if (responseCV.type === transactions_1.ClarityType.ResponseErr) {
throw new Error((0, transactions_1.cvToString)(responseCV.value));
}
else {
throw new Error(`Unexpected Clarity Value type: ${(0, transactions_1.getCVTypeString)(responseCV)}`);
}
});
}
async function getNamePrice({ fullyQualifiedName, network, }) {
const bnsFunctionName = "get-name-price";
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot get subdomain price");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
return (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: bnsFunctionName,
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace), (0, transactions_1.bufferCVFromString)(name)],
network,
})
.then((responseCV) => {
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
const responseOkValue = responseCV.value;
if (responseOkValue.type === transactions_1.ClarityType.ResponseOk) {
const nestedResponseOkValue = responseOkValue.value;
if (nestedResponseOkValue.type === transactions_1.ClarityType.Int ||
nestedResponseOkValue.type === transactions_1.ClarityType.UInt) {
return nestedResponseOkValue.value;
}
else {
throw new Error("Nested response did not contain a number");
}
}
else if (responseOkValue.type === transactions_1.ClarityType.Int ||
responseOkValue.type === transactions_1.ClarityType.UInt) {
return responseOkValue.value;
}
else {
throw new Error("Response did not contain a number");
}
}
else {
const errorResponse = responseCV;
throw new Error((0, transactions_1.cvToString)(errorResponse.value));
}
})
.catch((error) => {
throw error;
});
}
async function canNamespaceBeRegistered({ namespace, network, }) {
const bnsFunctionName = "can-namespace-be-registered";
const randomAddress = (0, utils_1.generateRandomAddress)();
return (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: bnsFunctionName,
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace)],
network,
}).then((responseCV) => {
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.BoolTrue) {
return true;
}
else if (responseCV.value.type === transactions_1.ClarityType.BoolFalse) {
return false;
}
else {
throw new Error("Response did not contain a boolean");
}
}
else if (responseCV.type === transactions_1.ClarityType.ResponseErr) {
throw new Error((0, transactions_1.cvToString)(responseCV.value));
}
else {
throw new Error(`Unexpected Clarity Value type: ${(0, transactions_1.getCVTypeString)(responseCV)}`);
}
});
}
async function getNamespaceProperties({ namespace, network, }) {
try {
const response = await callApi(`/namespaces/${namespace}`, network);
const namespaceData = response.namespace;
return {
namespace: namespace,
properties: {
"namespace-manager": namespaceData.namespace_manager || null,
"manager-transferable": namespaceData.manager_transferable,
"manager-frozen": namespaceData.manager_frozen || false,
"namespace-import": namespaceData.namespace_import,
"revealed-at": BigInt(namespaceData.revealed_at || 0),
"launched-at": namespaceData.launched_at
? BigInt(namespaceData.launched_at)
: null,
lifetime: BigInt(namespaceData.lifetime || 0),
"can-update-price-function": namespaceData.can_update_price_function,
"price-function": {
base: BigInt(namespaceData.price_function_base),
coefficient: BigInt(namespaceData.price_function_coeff),
b1: BigInt(namespaceData.price_function_buckets[0] || 0),
b2: BigInt(namespaceData.price_function_buckets[1] || 0),
b3: BigInt(namespaceData.price_function_buckets[2] || 0),
b4: BigInt(namespaceData.price_function_buckets[3] || 0),
b5: BigInt(namespaceData.price_function_buckets[4] || 0),
b6: BigInt(namespaceData.price_function_buckets[5] || 0),
b7: BigInt(namespaceData.price_function_buckets[6] || 0),
b8: BigInt(namespaceData.price_function_buckets[7] || 0),
b9: BigInt(namespaceData.price_function_buckets[8] || 0),
b10: BigInt(namespaceData.price_function_buckets[9] || 0),
b11: BigInt(namespaceData.price_function_buckets[10] || 0),
b12: BigInt(namespaceData.price_function_buckets[11] || 0),
b13: BigInt(namespaceData.price_function_buckets[12] || 0),
b14: BigInt(namespaceData.price_function_buckets[13] || 0),
b15: BigInt(namespaceData.price_function_buckets[14] || 0),
b16: BigInt(namespaceData.price_function_buckets[15] || 0),
nonAlphaDiscount: BigInt(namespaceData.price_function_nonalpha_discount),
noVowelDiscount: BigInt(namespaceData.price_function_no_vowel_discount),
},
},
};
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-namespace-properties",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk &&
responseCV.value.type === transactions_1.ClarityType.Tuple) {
const namespaceCV = responseCV.value.value["namespace"];
const propertiesCV = responseCV.value.value["properties"];
const properties = propertiesCV.value;
return {
namespace: namespaceCV.value.toString(),
properties: {
"namespace-manager": properties["namespace-manager"].type === transactions_1.ClarityType.OptionalNone
? null
: (0, transactions_1.cvToString)(properties["namespace-manager"].value),
"manager-transferable": properties["manager-transferable"].type ===
transactions_1.ClarityType.BoolTrue,
"manager-frozen": properties["manager-frozen"].type ===
transactions_1.ClarityType.BoolTrue,
"namespace-import": (0, transactions_1.cvToString)(properties["namespace-import"]),
"revealed-at": properties["revealed-at"].value,
"launched-at": properties["launched-at"].type === transactions_1.ClarityType.OptionalNone
? null
: properties["launched-at"].value.value,
lifetime: properties["lifetime"].value,
"can-update-price-function": properties["can-update-price-function"].type ===
transactions_1.ClarityType.BoolTrue,
"price-function": (0, utils_1.parsePriceFunction)(properties["price-function"].value),
},
};
}
throw new Error("Invalid response from contract");
}
}
async function getNameInfo({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/names/${fullyQualifiedName}`, network);
const data = response.data;
return {
owner: data.owner,
registeredAt: data.registered_at ? BigInt(data.registered_at) : null,
renewalHeight: BigInt(data.renewal_height || 0),
stxBurn: BigInt(data.stx_burn || 0),
importedAt: data.imported_at ? BigInt(data.imported_at) : null,
preorderedBy: data.preordered_by,
hashedSaltedFqnPreorder: data.hashedSaltedFqnPreorder,
};
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot get info for a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: "get-bns-info",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCVFromString)(namespace)],
network,
});
if (responseCV.type === transactions_1.ClarityType.OptionalSome &&
responseCV.value.type === transactions_1.ClarityType.Tuple) {
const tupleCV = responseCV.value;
const properties = tupleCV.value;
return {
owner: (0, transactions_1.cvToString)(properties.owner),
registeredAt: properties["registered-at"].type === transactions_1.ClarityType.OptionalNone
? null
: properties["registered-at"].value.value,
renewalHeight: properties["renewal-height"].value,
stxBurn: properties["stx-burn"].value,
importedAt: properties["imported-at"].type === transactions_1.ClarityType.OptionalNone
? null
: properties["imported-at"].value.value,
preorderedBy: properties["preordered-by"].type === transactions_1.ClarityType.OptionalNone
? null
: (0, transactions_1.cvToString)(properties["preordered-by"].value),
hashedSaltedFqnPreorder: properties["hashed-salted-fqn-preorder"].type ===
transactions_1.ClarityType.OptionalNone
? null
: properties["hashed-salted-fqn-preorder"].value.toString(),
};
}
throw new Error("Invalid response from contract");
}
}
async function getPrimaryName({ address, network, }) {
const bnsFunctionName = "get-primary";
const randomAddress = (0, utils_1.generateRandomAddress)();
return (0, callersHelper_1.bnsV2ReadOnlyCall)({
functionName: bnsFunctionName,
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.standardPrincipalCV)(address)],
network,
}).then((responseCV) => {
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.Tuple) {
const nameCV = responseCV.value.value["name"];
const namespaceCV = responseCV.value.value["namespace"];
return {
name: Buffer.from(nameCV.value, "hex").toString(),
namespace: Buffer.from(namespaceCV.value, "hex").toString(),
};
}
else if (responseCV.value.type === transactions_1.ClarityType.OptionalSome) {
const innerValue = responseCV.value.value;
if (innerValue.type === transactions_1.ClarityType.Tuple) {
const nameCV = innerValue.value["name"];
const namespaceCV = innerValue.value["namespace"];
return {
name: Buffer.from(nameCV.value, "hex").toString(),
namespace: Buffer.from(namespaceCV.value, "hex").toString(),
};
}
}
throw new Error("Unexpected response structure");
}
else if (responseCV.type === transactions_1.ClarityType.ResponseErr) {
if ((0, transactions_1.cvToString)(responseCV.value) === "u131") {
return null;
}
throw new Error((0, transactions_1.cvToString)(responseCV.value));
}
else {
throw new Error(`Unexpected Clarity Value type: ${(0, transactions_1.getCVTypeString)(responseCV)}`);
}
});
}
async function fetchUserOwnedNames({ senderAddress, network, }) {
try {
let allNames = [];
let offset = 0;
const limit = 50;
while (true) {
const response = await callApi(`/names/address/${senderAddress}/valid?limit=${limit}&offset=${offset}`, network);
allNames = allNames.concat(response.names);
if (response.names.length < limit || allNames.length >= response.total) {
break;
}
offset += limit;
}
return allNames.map((name) => ({
name: name.name_string,
namespace: name.namespace_string,
}));
}
catch (error) {
debug_1.debug.error("API call failed, falling back to contract call:", error);
const contractAddress = (0, config_1.getBnsContractAddress)(network);
const assetIdentifier = `${contractAddress}.${config_1.BnsContractName}::BNS-V2`;
const apiUrl = network === "mainnet"
? "https://api.hiro.so"
: "https://api.testnet.hiro.so";
let allAssets = [];
let offset = 0;
const limit = 50;
while (true) {
const response = await axios_1.default.get(`${apiUrl}/extended/v1/tokens/nft/holdings?principal=${senderAddress}&asset_identifiers=${assetIdentifier}&limit=${limit}&offset=${offset}`);
const assets = response.data.results.map((asset) => parseInt(asset.value.repr.slice(1)));
allAssets = allAssets.concat(assets);
if (response.data.total <= offset + limit) {
break;
}
offset += limit;
}
const bnsPromises = allAssets.map((id) => getBnsFromId({ id: BigInt(id), network }));
const bnsResults = await Promise.all(bnsPromises);
return bnsResults
.filter((result) => result !== null)
.map((result) => ({
name: (0, utils_1.asciiToUtf8)(result.name),
namespace: (0, utils_1.asciiToUtf8)(result.namespace),
}))
.sort((a, b) => {
if (a.namespace !== b.namespace) {
return a.namespace.localeCompare(b.namespace);
}
return a.name.localeCompare(b.name);
});
}
}
async function resolveNameZonefile({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/resolve-name/${fullyQualifiedName}`, network);
return response.zonefile || null;
}
catch (error) {
if (axios_1.default.isAxiosError(error) && error.response?.status === 404) {
return null;
}
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot resolve a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.zonefileReadOnlyCall)({
functionName: "resolve-name",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCVFromString)(namespace)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.OptionalSome &&
responseCV.value.value.type === transactions_1.ClarityType.Buffer) {
const zonefileString = Buffer.from(responseCV.value.value.value).toString("utf8");
return (0, utils_1.parseZonefile)(zonefileString);
}
if (responseCV.value.type === transactions_1.ClarityType.OptionalNone) {
return null;
}
}
throw new Error("Invalid response from contract");
}
}
async function getZonefileRaw({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/zonefile/${fullyQualifiedName}/raw`, network);
return response.zonefile || null;
}
catch (error) {
if (axios_1.default.isAxiosError(error) && error.response?.status === 404) {
return null;
}
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot get raw zonefile for a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.zonefileReadOnlyCall)({
functionName: "resolve-name",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCVFromString)(namespace)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.OptionalSome &&
responseCV.value.value.type === transactions_1.ClarityType.Buffer) {
const zonefileString = Buffer.from(responseCV.value.value.value).toString("utf8");
try {
return JSON.parse(zonefileString);
}
catch {
return zonefileString;
}
}
if (responseCV.value.type === transactions_1.ClarityType.OptionalNone) {
return null;
}
}
throw new Error("Invalid response from contract");
}
}
async function getZonefileProfile({ fullyQualifiedName, network, }) {
try {
const response = await callApi(`/zonefile/${fullyQualifiedName}/profile`, network);
return response.profile || null;
}
catch (error) {
if (axios_1.default.isAxiosError(error) && error.response?.status === 404) {
return null;
}
debug_1.debug.error("API call failed, falling back to contract call:", error);
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error("Cannot get profile zonefile for a subdomain");
}
const randomAddress = (0, utils_1.generateRandomAddress)();
const responseCV = await (0, callersHelper_1.zonefileReadOnlyCall)({
functionName: "resolve-name",
senderAddress: randomAddress,
functionArgs: [(0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCVFromString)(namespace)],
network,
});
if (responseCV.type === transactions_1.ClarityType.ResponseOk) {
if (responseCV.value.type === transactions_1.ClarityType.OptionalSome &&
responseCV.value.value.type === transactions_1.ClarityType.Buffer) {
const zonefileString = Buffer.from(responseCV.value.value.value).toString("utf8");
try {
const parsed = JSON.parse(zonefileString);
return (0, utils_1.createFormattedZonefileData)(parsed);
}
catch (error) {
debug_1.debug.error("Failed to parse zonefile as profile format:", error);
return null;
}
}
if (responseCV.value.type === transactions_1.ClarityType.OptionalNone) {
return null;
}
}
throw new Error("Invalid response from contract");
}
}