Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

BNS v2

BNS (Bitcoin Name System) v2 extension for name resolution, registration, and management on Stacks.

Setup

import { createPublicClient, createWalletClient, http, mainnet } from "@secondlayer/stacks";
import { privateKeyToAccount } from "@secondlayer/stacks/accounts";
import { bns } from "@secondlayer/stacks/bns";
 
// Read-only client
const client = createPublicClient({
  chain: mainnet,
  transport: http(),
}).extend(bns());
 
// Wallet client (for registration/transfers)
const wallet = createWalletClient({
  account: privateKeyToAccount("0x..."),
  chain: mainnet,
  transport: http(),
}).extend(bns());

Resolve Names

// Name -> address
const owner = await client.bns.resolveName("alice.btc");
 
// Address -> primary name
const name = await client.bns.getPrimaryName("SP2J6...");
 
// Check availability
const available = await client.bns.canRegister("bob.btc");
// `true` only means the contract call itself resolved to "name unknown" —
// network/HTTP failures throw instead of being reported as "available".
 
// Get price (microSTX)
const price = await client.bns.getNamePrice("bob.btc");
 
// Get NFT token ID
const id = await client.bns.getNameId("alice.btc");

Register Names

Two registration paths:

Fast Claim (instant, snipeable)

const txid = await wallet.bns.claimFast({
  name: "bob.btc",
  recipient: account.address,
});

Secure Registration (2-step, front-run proof)

// Step 1: Preorder (commits salted hash)
const { txid, salt } = await wallet.bns.preorder({ name: "bob.btc" });
 
// Wait ~10 minutes (1 Bitcoin block)
 
// Step 2: Register (reveals name)
await wallet.bns.register({ name: "bob.btc", salt });

Manage Names

// Transfer
await wallet.bns.transfer({
  name: "alice.btc",
  recipient: "SP3FBR...",
});
 
// Set primary name
await wallet.bns.setPrimary({ name: "alice.btc" });

Zonefiles

// Read zonefile
const zonefile = await client.bns.getZonefile("alice.btc");
if (zonefile) console.log(new TextDecoder().decode(zonefile));
// `null` only means the contract genuinely has no zonefile set — network/HTTP
// failures throw instead of being reported as "no zonefile".
 
// Update zonefile
await wallet.bns.updateZonefile({
  name: "alice.btc",
  zonefile: "$ORIGIN alice.btc\n$TTL 3600\n...",
});
 
// Clear zonefile
await wallet.bns.revokeZonefile("alice.btc");

Namespace

All methods accept fully-qualified names (alice.btc) or bare names (alice, defaults to .btc).