npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bonfida/spl-name-service

v4.0.1

Published

<p align="center"> <img width="200" src="https://www.sns.id/assets/logo/brand.svg" alt="SNS logo" /> </p>

Readme

SNS JavaScript SDK

npm MIT License

JavaScript SDK for resolving Solana Name Service (SNS) domains, reading records and ownership data, and constructing SNS transaction instructions with @solana/web3.js 1.x.

Migrating from v3? This release is not fully backward compatible. Review the changelog for breaking changes and migration notes.

Installation

npm install @bonfida/spl-name-service @solana/web3.js

The SDK has a peer dependency on @solana/web3.js ^1.98.2. Supply a web3.js Connection for RPC operations. While Node.js is the primary tested environment, browser applications are fully supported via compatible bundlers.

Read APIs fetch and decode account data. Mutation bindings return TransactionInstruction, Promise<TransactionInstruction>, or Promise<TransactionInstruction[]>. Add the returned instruction(s) to a transaction, set its fee payer and recent blockhash, collect the signatures required by its account metas, and submit that transaction through your application.

Subpath Imports

While the root entry point remains available, applications can also use subpath imports:

import { getPrimaryDomain } from "@bonfida/spl-name-service/address";
import { resolve, safeResolve } from "@bonfida/spl-name-service/domain";
import { getMultipleRecords, Record } from "@bonfida/spl-name-service/record";

Supported subpaths are address, bindings, constants, domain, errors, instructions, nft, record, states, twitter, types, and utils.

Quick Start

Resolve A Domain

import { Connection } from "@solana/web3.js";
import { resolve } from "@bonfida/spl-name-service/domain";

const connection = new Connection("https://your-rpc-endpoint.example");
const owner = await resolve(connection, "mydomain.sns"); // Or use `safeResolve`.

console.log(owner.toBase58());

Get A Primary Domain

import { Connection, PublicKey } from "@solana/web3.js";
import { getPrimaryDomain } from "@bonfida/spl-name-service/address";

const connection = new Connection("https://your-rpc-endpoint.example");
const wallet = new PublicKey("<WALLET_ADDRESS>");
const primaryDomain = await getPrimaryDomain(connection, wallet);

console.log(`${primaryDomain.reverse}.sns`, primaryDomain.stale);

List Domains For An Owner

import { Connection, PublicKey } from "@solana/web3.js";
import { getSnsDomainsForOwner } from "@bonfida/spl-name-service/address";

const connection = new Connection("https://your-rpc-endpoint.example");
const wallet = new PublicKey("<WALLET_ADDRESS>");
const domains = await getSnsDomainsForOwner(connection, wallet);

console.log(domains.map(({ domain }) => `${domain}.sns`));

Domain Inputs And Resolution

Use the form required by each API rather than normalizing names yourself:

| API family | Required input | Scope | | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------- | | High-level reads such as resolve, safeResolve, getRecord, and getMultipleRecords | Full suffixed name, for example mydomain.sns | .sns; legacy .sol reads have the transition rule below | | Top-level writes such as registration, transfer, burn, and background changes | Canonical lowercase mydomain.sns | Exactly one label before .sns | | Record writes | Canonical lowercase mydomain.sns or sub.mydomain.sns | Top-level domain or one-level subdomain | | Subdomain creation | Canonical lowercase sub.mydomain.sns | Exactly one subdomain level | | Derivation and raw name-account helpers | TLD-trimmed or raw input, for example mydomain or sub.mydomain | Follow each low-level helper's account-format contract |

High-level .sol reads use the legacy SNS-backed path only before finalized slot 452,825,395. At and after that slot, .sol is rejected. .sol writes are not supported.

API Reference

Resolution

  • resolve — resolves a .sns domain, or a legacy .sol domain while the transition path remains available.

    resolve(connection: Connection, domain: string, config?: ResolveConfig): Promise<PublicKey>
  • safeResolve — follows resolve, but when SRS-backed .sol resolution is enabled, it also checks the SNS-backed target and throws SnsSolResolutionMismatchError if the addresses differ.

    safeResolve(connection: Connection, domain: string, config?: ResolveConfig): Promise<PublicKey>

Record Reads And Validation

  • getRecord — fetches and verifies one V2 record.

    getRecord(connection: Connection, domain: string, record: Record, options?: { deserialize?: boolean }): Promise<RecordResult>
  • getMultipleRecords — returns results in input order; a missing record account is undefined at its corresponding index.

    getMultipleRecords(connection: Connection, domain: string, records: Record[], options?: { deserialize?: boolean }): Promise<(RecordResult | undefined)[]>

The following standalone helpers do not come from RecordResult:

  • getRecordV1Key / getRecordV2Key — derive record account keys from a TLD-trimmed domain such as mydomain.

    getRecordV1Key(domain: string, record: Record): PublicKey
    getRecordV2Key(domain: string, record: Record): PublicKey
  • serializeRecordContent / deserializeRecordContent — encode content for storage, or decode stored content.

    serializeRecordContent(content: string, record: Record): Buffer
    deserializeRecordContent(content: Buffer, record: Record): string
  • verifyStaleness — independently fetches and checks a V2 record's staleness validation.

    verifyStaleness(connection: Connection, record: Record, domain: string): Promise<boolean>
  • verifyRightOfAssociation — independently fetches and checks a V2 record's right-of-association validation.

    verifyRightOfAssociation(connection: Connection, record: Record, domain: string, verifier?: Buffer): Promise<boolean>

Record Writes

Each function below synchronously returns one TransactionInstruction:

  • createRecord

    createRecord(domain: string, record: Record, content: string, owner: PublicKey, payer: PublicKey): TransactionInstruction
  • updateRecord

    updateRecord(domain: string, record: Record, content: string, owner: PublicKey, payer: PublicKey): TransactionInstruction
  • deleteRecord

    deleteRecord(domain: string, record: Record, owner: PublicKey, payer: PublicKey): TransactionInstruction
  • setRecordStalenessVerifier

    setRecordStalenessVerifier(domain: string, record: Record, owner: PublicKey, payer: PublicKey, verifier: PublicKey): TransactionInstruction
  • setRecordRoaVerifier

    setRecordRoaVerifier(domain: string, record: Record, owner: PublicKey, payer: PublicKey, verifier: PublicKey): TransactionInstruction
  • validateRecordRoa

    validateRecordRoa(domain: string, record: Record, owner: PublicKey, payer: PublicKey, verifier: PublicKey): TransactionInstruction
  • validateRecordRoaEthereumsignature is 64 bytes and expectedPubkey is a 20-byte Ethereum address.

    validateRecordRoaEthereum(domain: string, record: Record, owner: PublicKey, payer: PublicKey, signature: Buffer, expectedPubkey: Buffer): TransactionInstruction

Registration And Lifecycle

Registration is limited to a lowercase top-level .sns name. Return shapes differ by operation:

  • registerDomain — returns the registration instruction and may prepend an idempotent referrer associated-token-account instruction. The selected mint must have a configured Pyth price feed.

    registerDomain(domain: string, space: number, buyer: PublicKey, buyerTokenAccount: PublicKey, mint?: PublicKey, referrerKey?: PublicKey): Promise<TransactionInstruction[]>
  • registerDomainWithNft — returns one Wolves-NFT registration instruction. Derive nameAccount and reverseLookupAccount before calling it.

    registerDomainWithNft(domain: string, space: number, nameAccount: PublicKey, reverseLookupAccount: PublicKey, buyer: PublicKey, nftSource: PublicKey, nftMint: PublicKey): TransactionInstruction
  • transferDomain — retrieves the current owner and returns one transfer instruction.

    transferDomain(connection: Connection, domain: string, newOwner: PublicKey): Promise<TransactionInstruction>
  • burnDomain — returns one burn instruction; target receives reclaimed lamports.

    burnDomain(domain: string, owner: PublicKey, target: PublicKey): TransactionInstruction
  • setPrimaryDomain — returns one instruction for an already derived domain account.

    setPrimaryDomain(connection: Connection, nameAccount: PublicKey, owner: PublicKey): Promise<TransactionInstruction>
  • setBackground — returns the instructions required to set an issued custom background.

    setBackground(connection: Connection, domain: string, bg: CustomBg, owner: PublicKey): Promise<TransactionInstruction[]>

Subdomains

  • createSubdomain — returns the name-account creation instruction and, when the reverse account is absent, a reverse-lookup instruction. subdomain must be a lowercase one-level .sns subdomain.

    createSubdomain(connection: Connection, subdomain: string, owner: PublicKey, space?: number, feePayer?: PublicKey): Promise<TransactionInstruction[]>
  • transferSubdomain — returns one transfer instruction. When owner is omitted, the function retrieves the current owner; set isParentOwnerSigner when the parent owner authorizes the transfer.

    transferSubdomain(connection: Connection, subdomain: string, newOwner: PublicKey, isParentOwnerSigner?: boolean, owner?: PublicKey): Promise<TransactionInstruction>
  • findSubdomains — returns reverse-resolved subdomain labels for a parent name-account key.

    findSubdomains(connection: Connection, parentKey: PublicKey): Promise<string[]>

Ownership And Reverse Lookup

  • getSnsDomainKeysForOwner — returns directly registry-owned top-level name-account keys.

    getSnsDomainKeysForOwner(connection: Connection, wallet: PublicKey): Promise<PublicKey[]>
  • getSnsDomainsForOwner — adds TLD-less reverse names to those directly owned keys; it excludes tokenized domains, subdomains, and entries without reverse data.

    getSnsDomainsForOwner(connection: Connection, wallet: PublicKey): Promise<{ domain: string; key: PublicKey }[]>
  • getSnsNftsForOwner — returns tokenized domains with reverse data.

    getSnsNftsForOwner(connection: Connection, owner: PublicKey): Promise<{ domain: string; key: PublicKey; mint: PublicKey }[]>
  • getAllSnsDomains — returns raw top-level registry program accounts whose account.data is sliced to the 32-byte registry-owner field.

    getAllSnsDomains(connection: Connection): Promise<GetProgramAccountsResponse>
  • getPrimaryDomain — returns the primary name-account key, TLD-less reverse name, and stale status.

    getPrimaryDomain(connection: Connection, owner: PublicKey): Promise<{ domain: PublicKey; reverse: string; stale: boolean }>
  • getMultiplePrimaryDomains — returns TLD-less primary names in input order; missing entries are undefined.

    getMultiplePrimaryDomains(connection: Connection, wallets: PublicKey[]): Promise<(string | undefined)[]>
  • reverseLookup — returns one TLD-less reverse name.

    reverseLookup(connection: Connection, nameAccount: PublicKey, parent?: PublicKey): Promise<string>
  • reverseLookupBatch — returns TLD-less names in input order; missing reverse records are undefined.

    reverseLookupBatch(connection: Connection, nameAccounts: PublicKey[]): Promise<(string | undefined)[]>

Advanced APIs

For account-level integrations, the root export also includes derivation and raw name-registry helpers such as getSnsDomainKeySync, getReverseKeySync, getReverseKeyFromDomainKey, getHashedNameSync, getNameAccountKeySync, createNameRegistry, updateNameRegistry, deleteNameRegistry, and createReverse.

NFT helpers and state classes include domain-mint/owner/record retrieval, NameRegistryState, PrimaryDomain, and NFT state exports. CustomBg, getCustomBgKeys, and setBackground support issued custom backgrounds. The devnet export provides devnet-specific bindings and constants. Low-level instruction classes and raw state decoders are also exported for specialized integrations.

Legacy Twitter registry APIs remain exported for advanced compatibility use. They are not part of the recommended domain-resolution or registration path.

Documentation And Migration

License

This project is available under the MIT License.