/** Account derived from a local private key (mnemonic or raw key). */ type LocalAccount = { type: "local" address: string /** Compressed public key (hex) */ publicKey: string /** Raw ECDSA sign over a hash */ sign(hash: Uint8Array): Uint8Array /** Sign a raw UTF-8 / byte message (`sha256(bytes)`). Not SIP-018. */ signMessage(message: string | Uint8Array): string }; /** Account with a user-provided signing function (sync or async). */ type CustomAccount = { type: "custom" address: string publicKey: string sign(hash: Uint8Array): Promise | Uint8Array }; /** Browser wallet provider interface (e.g. Leather, Xverse). */ type StacksProvider = { request(method: string, params?: any): Promise }; /** Account backed by a browser wallet {@link StacksProvider}. */ type ProviderAccount = { type: "provider" address: string publicKey: string provider: StacksProvider }; /** Allocates mempool-safe sequential nonces across rapid broadcasts from one account. */ type NonceManager = { consume(params: { client: Client address: string }): Promise reset(params: { client: Client address: string }): void | Promise /** * Give back a nonce from {@link NonceManager.consume} whose transaction * was never accepted by the node. No-op unless it is the latest issued. */ release(params: { client: Client address: string nonce: bigint }): void | Promise /** Next nonce that {@link NonceManager.consume} would return without consuming it, or `undefined` if untracked. */ peek(params: { client: Client address: string }): Promise }; /** Full chain descriptor used by clients and transports for network-aware operations. */ type StacksChain = { /** Chain ID (e.g. 0x00000001 for mainnet) */ id: number /** Human-readable name */ name: string /** Network type */ network: "mainnet" | "testnet" /** Transaction version byte for serialization */ transactionVersion: number /** Peer network ID for P2P broadcasting */ peerNetworkId: number /** Address version bytes */ addressVersion: { singleSig: number multiSig: number } /** Magic bytes for network identification */ magicBytes: string /** Boot address (system contracts deployer) */ bootAddress: string /** Native currency info */ nativeCurrency: { name: string symbol: string decimals: number } /** Default RPC URLs */ rpcUrls: { default: { http: string[] ws?: string[] } } /** Block explorer URLs */ blockExplorers?: { default: { name: string url: string } } }; /** Function that sends an HTTP request to a Stacks node API path. */ type RequestFn = (path: string, options?: RequestOptions) => Promise; /** Options for a transport-level HTTP request. */ type RequestOptions = { method?: "GET" | "POST" | "PUT" | "DELETE" body?: unknown headers?: Record /** * Cancel the request from the caller's side. An aborted signal rejects * with the signal's reason immediately and never retries; it is combined * with the transport's own per-attempt timeout. */ signal?: AbortSignal /** * Override the transport's retry budget for this one request. Broadcasts * pass `0`: re-sending a transaction the node may already hold trades a * transient failure for a confusing nonce conflict. */ retryCount?: number }; /** Shared configuration for all transport types. */ type TransportConfig = { url?: string /** * Per-attempt deadline in ms covering headers AND body. A stalled body * rejects with `TimeoutError` instead of hanging. Default 30_000. */ timeout?: number retryCount?: number retryDelay?: number fetchOptions?: RequestInit /** Sent as `x-api-key`. Held in the request closure and stripped from * `Transport.config` so it never prints with the client. */ apiKey?: string }; /** A resolved transport instance with a bound request function. */ type Transport = { type: string request: RequestFn config: TransportConfig destroy?: () => void }; /** Union of all supported account types (local key, custom signer, or browser provider). */ type Account = LocalAccount | CustomAccount | ProviderAccount; /** * Core client instance that holds chain context, transport, and extensible actions. * Created via {@link createClient}, {@link createPublicClient}, or {@link createWalletClient}. */ type Client = Record> = { chain?: StacksChain account?: Account transport: Transport request: RequestFn /** Optional nonce manager for mempool-safe sequential nonces across rapid broadcasts. */ nonceManager?: NonceManager extend: >(fn: (client: Client) => TNew) => Client & TNew } & TExtended; interface FullyQualifiedName { name: string; namespace: string; } interface ClaimFastParams { name: string; namespace?: string; recipient: string; } interface TransferParams { name: string; namespace?: string; recipient: string; } interface SetPrimaryParams { name: string; namespace?: string; } interface PreorderParams { name: string; namespace?: string; salt?: Uint8Array; } interface RegisterParams { name: string; namespace?: string; salt: Uint8Array; } interface UpdateZonefileParams { name: string; namespace?: string; zonefile: string | Uint8Array | null; } declare const BNS_CONTRACTS: { readonly mainnet: { readonly address: "SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF" readonly name: "BNS-V2" } readonly testnet: { readonly address: "ST2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D9SZJQ0M" readonly name: "BNS-V2" } }; declare const ZONEFILE_RESOLVER_CONTRACTS: { readonly mainnet: { readonly address: "SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF" readonly name: "zonefile-resolver" } readonly testnet: { readonly address: "ST2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D9SZJQ0M" readonly name: "zonefile-resolver" } }; /** * Parse a fully qualified name string into components. * Supports: * - "name.namespace" → { name: "name", namespace: "namespace" } * - "name" → { name: "name", namespace: "btc" } (default) */ declare function parseFQN(fqn: string): FullyQualifiedName; /** * Format name components into FQN string. */ declare function formatFQN(name: string, namespace: string): string; /** * Validate name format. * Names must be: * - 1-48 characters * - Lowercase alphanumeric, hyphens, underscores * - Cannot start or end with hyphen/underscore */ declare function validateName(name: string): boolean; /** * Validate namespace format. * Namespaces must be: * - 1-20 characters * - Lowercase alphanumeric */ declare function validateNamespace(namespace: string): boolean; /** * Validate a fully qualified name. */ declare function validateFQN(fqn: string): boolean; /** * Generate a random 20-byte salt for name preorders. * @returns Random Uint8Array of length 20 */ declare function generateSalt(): Uint8Array; /** * Calculate hash160 for name preorder commitment. * Hash format: hash160(name + namespace + salt) * * @param name - BNS name (without namespace) * @param namespace - BNS namespace (e.g., "btc") * @param salt - 20-byte random salt * @returns 20-byte hash160 commitment */ declare function hashPreorder(name: string, namespace: string, salt: Uint8Array): Uint8Array; /** Actions provided by the BNS extension. */ type BnsActions = { bns: { resolveName: (name: string) => Promise getPrimaryName: (address: string) => Promise canRegister: (name: string) => Promise getNamePrice: (name: string) => Promise getNameId: (name: string) => Promise preorder: (params: PreorderParams) => Promise<{ txid: string salt: Uint8Array }> register: (params: RegisterParams) => Promise claimFast: (params: ClaimFastParams) => Promise transfer: (params: TransferParams) => Promise setPrimary: (params: SetPrimaryParams) => Promise getZonefile: (name: string) => Promise updateZonefile: (params: UpdateZonefileParams) => Promise revokeZonefile: (name: string) => Promise } }; /** * BNS v2 extension for Stacks client. * Provides name resolution, registration, and management. * * @example * import { createWalletClient, http, mainnet } from "stacks"; * import { bns } from "stacks/bns"; * import { privateKeyToAccount } from "stacks/accounts"; * * const account = privateKeyToAccount("0x..."); * const client = createWalletClient({ * account, * chain: mainnet, * transport: http(), * }).extend(bns()); * * // Resolve names * const owner = await client.bns.resolveName("alice.btc"); * * // Register names * const txid = await client.bns.claimFast({ * name: "bob.btc", * recipient: account.address, * }); * * // Transfer names * await client.bns.transfer({ * name: "alice.btc", * recipient: "SP3FBR...", * }); */ declare function bns(): (client: Client) => BnsActions; export { validateNamespace, validateName, validateFQN, parseFQN, hashPreorder, generateSalt, formatFQN, bns, ZONEFILE_RESOLVER_CONTRACTS, UpdateZonefileParams, TransferParams, SetPrimaryParams, RegisterParams, PreorderParams, ClaimFastParams, BnsActions, BNS_CONTRACTS };