@stacks/bns
Version:
Library for working with the Stacks Blockchain Naming System BNS.
328 lines • 14.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BNS_CONTRACT_NAME = void 0;
exports.canRegisterName = canRegisterName;
exports.getNamespacePrice = getNamespacePrice;
exports.getNamePrice = getNamePrice;
exports.buildPreorderNamespaceTx = buildPreorderNamespaceTx;
exports.buildRevealNamespaceTx = buildRevealNamespaceTx;
exports.buildImportNameTx = buildImportNameTx;
exports.buildReadyNamespaceTx = buildReadyNamespaceTx;
exports.buildPreorderNameTx = buildPreorderNameTx;
exports.buildRegisterNameTx = buildRegisterNameTx;
exports.buildUpdateNameTx = buildUpdateNameTx;
exports.buildTransferNameTx = buildTransferNameTx;
exports.buildRevokeNameTx = buildRevokeNameTx;
exports.buildRenewNameTx = buildRenewNameTx;
const common_1 = require("@stacks/common");
const transactions_1 = require("@stacks/transactions");
const utils_1 = require("./utils");
exports.BNS_CONTRACT_NAME = 'bns';
async function makeBnsContractCall(options) {
const txOptions = {
contractAddress: options.network.bootAddress,
contractName: exports.BNS_CONTRACT_NAME,
functionName: options.functionName,
functionArgs: options.functionArgs,
publicKey: options.publicKey,
validateWithAbi: false,
network: options.network,
postConditions: options.postConditions,
};
return (0, transactions_1.makeUnsignedContractCall)(txOptions);
}
async function callReadOnlyBnsFunction(options) {
return (0, transactions_1.fetchCallReadOnlyFunction)({
...options,
contractAddress: options.network.bootAddress,
contractName: exports.BNS_CONTRACT_NAME,
});
}
async function canRegisterName({ fullyQualifiedName, network, }) {
const bnsFunctionName = 'can-name-be-registered';
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error('Cannot register a subdomain using registerName');
}
const randomPrivateKey = (0, transactions_1.makeRandomPrivKey)();
const randomAddress = (0, transactions_1.getAddressFromPrivateKey)(randomPrivateKey);
return callReadOnlyBnsFunction({
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) {
return responseCV.value.type === transactions_1.ClarityType.BoolTrue;
}
else {
return false;
}
});
}
async function getNamespacePrice({ namespace, network, }) {
const bnsFunctionName = 'get-namespace-price';
const randomPrivateKey = (0, transactions_1.makeRandomPrivKey)();
const randomAddress = (0, transactions_1.getAddressFromPrivateKey)(randomPrivateKey);
return callReadOnlyBnsFunction({
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 BigInt(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 name price');
}
const randomPrivateKey = (0, transactions_1.makeRandomPrivKey)();
const randomAddress = (0, transactions_1.getAddressFromPrivateKey)(randomPrivateKey);
return callReadOnlyBnsFunction({
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) {
if (responseCV.value.type === transactions_1.ClarityType.Int || responseCV.value.type === transactions_1.ClarityType.UInt) {
return BigInt(responseCV.value.value);
}
else {
throw new Error('Response did not contain a number');
}
}
else {
const errorResponse = responseCV;
throw new Error((0, transactions_1.cvToString)(errorResponse.value));
}
});
}
async function buildPreorderNamespaceTx({ namespace, salt, stxToBurn, publicKey, network, }) {
const bnsFunctionName = 'namespace-preorder';
const saltedNamespaceBytes = (0, common_1.utf8ToBytes)(`${namespace}${salt}`);
const hashedSaltedNamespace = (0, transactions_1.hash160)(saltedNamespaceBytes);
const burnSTXPostCondition = {
type: 'stx-postcondition',
address: (0, transactions_1.publicKeyToAddress)(network.addressVersion.singleSig, publicKey),
condition: 'eq',
amount: (0, common_1.intToBigInt)(stxToBurn),
};
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [(0, transactions_1.bufferCV)(hashedSaltedNamespace), (0, transactions_1.uintCV)(stxToBurn)],
publicKey,
network,
postConditions: [burnSTXPostCondition],
});
}
async function buildRevealNamespaceTx({ namespace, salt, priceFunction, lifetime, namespaceImportAddress, publicKey, network, }) {
const bnsFunctionName = 'namespace-reveal';
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [
(0, transactions_1.bufferCVFromString)(namespace),
(0, transactions_1.bufferCVFromString)(salt),
(0, transactions_1.uintCV)(priceFunction.base),
(0, transactions_1.uintCV)(priceFunction.coefficient),
(0, transactions_1.uintCV)(priceFunction.b1),
(0, transactions_1.uintCV)(priceFunction.b2),
(0, transactions_1.uintCV)(priceFunction.b3),
(0, transactions_1.uintCV)(priceFunction.b4),
(0, transactions_1.uintCV)(priceFunction.b5),
(0, transactions_1.uintCV)(priceFunction.b6),
(0, transactions_1.uintCV)(priceFunction.b7),
(0, transactions_1.uintCV)(priceFunction.b8),
(0, transactions_1.uintCV)(priceFunction.b9),
(0, transactions_1.uintCV)(priceFunction.b10),
(0, transactions_1.uintCV)(priceFunction.b11),
(0, transactions_1.uintCV)(priceFunction.b12),
(0, transactions_1.uintCV)(priceFunction.b13),
(0, transactions_1.uintCV)(priceFunction.b14),
(0, transactions_1.uintCV)(priceFunction.b15),
(0, transactions_1.uintCV)(priceFunction.b16),
(0, transactions_1.uintCV)(priceFunction.nonAlphaDiscount),
(0, transactions_1.uintCV)(priceFunction.noVowelDiscount),
(0, transactions_1.uintCV)(lifetime),
(0, transactions_1.standardPrincipalCV)(namespaceImportAddress),
],
publicKey,
network,
});
}
async function buildImportNameTx({ namespace, name, beneficiary, zonefile, publicKey, network, }) {
const bnsFunctionName = 'name-import';
const zonefileHash = (0, utils_1.getZonefileHash)(zonefile);
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [
(0, transactions_1.bufferCVFromString)(namespace),
(0, transactions_1.bufferCVFromString)(name),
(0, transactions_1.standardPrincipalCV)(beneficiary),
(0, transactions_1.bufferCV)(zonefileHash),
],
publicKey,
network,
});
}
async function buildReadyNamespaceTx({ namespace, publicKey, network, }) {
const bnsFunctionName = 'namespace-ready';
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace)],
publicKey,
network,
});
}
async function buildPreorderNameTx({ fullyQualifiedName, salt, stxToBurn, publicKey, network, }) {
const bnsFunctionName = 'name-preorder';
const { subdomain } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error('Cannot preorder a subdomain using preorderName()');
}
const saltedNamesBytes = (0, common_1.utf8ToBytes)(`${fullyQualifiedName}${salt}`);
const hashedSaltedName = (0, transactions_1.hash160)(saltedNamesBytes);
const burnSTXPostCondition = {
type: 'stx-postcondition',
address: (0, transactions_1.publicKeyToAddress)(network.addressVersion.singleSig, publicKey),
condition: 'eq',
amount: (0, common_1.intToBigInt)(stxToBurn),
};
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [(0, transactions_1.bufferCV)(hashedSaltedName), (0, transactions_1.uintCV)(stxToBurn)],
publicKey,
network,
postConditions: [burnSTXPostCondition],
});
}
async function buildRegisterNameTx({ fullyQualifiedName, salt, zonefile, publicKey, network, }) {
const bnsFunctionName = 'name-register';
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error('Cannot register a subdomain using registerName()');
}
const zonefileHash = (0, utils_1.getZonefileHash)(zonefile);
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [
(0, transactions_1.bufferCVFromString)(namespace),
(0, transactions_1.bufferCVFromString)(name),
(0, transactions_1.bufferCVFromString)(salt),
(0, transactions_1.bufferCV)(zonefileHash),
],
network,
publicKey,
});
}
async function buildUpdateNameTx({ fullyQualifiedName, zonefile, publicKey, network, }) {
const bnsFunctionName = 'name-update';
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error('Cannot update a subdomain using updateName()');
}
const zonefileHash = (0, utils_1.getZonefileHash)(zonefile);
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace), (0, transactions_1.bufferCVFromString)(name), (0, transactions_1.bufferCV)(zonefileHash)],
publicKey,
network,
});
}
async function buildTransferNameTx({ fullyQualifiedName, newOwnerAddress, zonefile, publicKey, network, }) {
const bnsFunctionName = 'name-transfer';
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error('Cannot transfer a subdomain using transferName()');
}
const functionArgs = [
(0, transactions_1.bufferCVFromString)(namespace),
(0, transactions_1.bufferCVFromString)(name),
(0, transactions_1.standardPrincipalCV)(newOwnerAddress),
zonefile ? (0, transactions_1.someCV)((0, transactions_1.bufferCV)((0, utils_1.getZonefileHash)(zonefile))) : (0, transactions_1.noneCV)(),
];
const postConditionSender = {
type: 'nft-postcondition',
address: (0, transactions_1.publicKeyToAddress)(network.addressVersion.singleSig, publicKey),
condition: 'sent',
asset: `${network.bootAddress}.bns::names`,
assetId: (0, transactions_1.tupleCV)({
name: (0, transactions_1.bufferCVFromString)(name),
namespace: (0, transactions_1.bufferCVFromString)(namespace),
}),
};
const postConditionReceiver = {
type: 'nft-postcondition',
address: newOwnerAddress,
condition: 'not-sent',
asset: `${network.bootAddress}.bns::names`,
assetId: (0, transactions_1.tupleCV)({
name: (0, transactions_1.bufferCVFromString)(name),
namespace: (0, transactions_1.bufferCVFromString)(namespace),
}),
};
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs,
publicKey,
network,
postConditions: [postConditionSender, postConditionReceiver],
});
}
async function buildRevokeNameTx({ fullyQualifiedName, publicKey, network, }) {
const bnsFunctionName = 'name-revoke';
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error('Cannot revoke a subdomain using revokeName()');
}
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs: [(0, transactions_1.bufferCVFromString)(namespace), (0, transactions_1.bufferCVFromString)(name)],
publicKey,
network,
});
}
async function buildRenewNameTx({ fullyQualifiedName, stxToBurn, newOwnerAddress, zonefile, publicKey, network, }) {
const bnsFunctionName = 'name-renewal';
const { subdomain, namespace, name } = (0, utils_1.decodeFQN)(fullyQualifiedName);
if (subdomain) {
throw new Error('Cannot renew a subdomain using renewName()');
}
const functionArgs = [
(0, transactions_1.bufferCVFromString)(namespace),
(0, transactions_1.bufferCVFromString)(name),
(0, transactions_1.uintCV)(stxToBurn),
newOwnerAddress ? (0, transactions_1.someCV)((0, transactions_1.standardPrincipalCV)(newOwnerAddress)) : (0, transactions_1.noneCV)(),
zonefile ? (0, transactions_1.someCV)((0, transactions_1.bufferCV)((0, utils_1.getZonefileHash)(zonefile))) : (0, transactions_1.noneCV)(),
];
const burnSTXPostCondition = {
type: 'stx-postcondition',
address: (0, transactions_1.publicKeyToAddress)(network.addressVersion.singleSig, publicKey),
condition: 'eq',
amount: (0, common_1.intToBigInt)(stxToBurn),
};
return makeBnsContractCall({
functionName: bnsFunctionName,
functionArgs,
publicKey,
network,
postConditions: [burnSTXPostCondition],
});
}
//# sourceMappingURL=index.js.map