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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@miracleorg/pns-sdk

v1.0.2

Published

TypeScript SDK for Push Name Service (PNS) - Universal multi-chain name service

Readme

Push Name Service (PNS) SDK

TypeScript SDK for interacting with Push Name Service - a universal multi-chain name service built on Push Chain.

Features

  • 🌐 Multi-chain Support - Resolve names across Ethereum, Solana, Push Chain, and more
  • 🔐 Type-safe - Full TypeScript support with comprehensive type definitions
  • Easy to Use - Simple, intuitive API for all PNS operations
  • 📦 Lightweight - Minimal dependencies (only ethers.js)
  • 🎯 Complete - Support for all PNS contract features

Installation

npm install @miracleorg/pns-sdk ethers

Quick Start

import { PNSClient, PNSNetwork } from '@miracleorg/pns-sdk';
import { JsonRpcProvider, Wallet } from 'ethers';

// 1. Initialize with just a provider (Read-only)
const provider = new JsonRpcProvider('https://rpc-testnet-donut-node1.push.org/');
const pnsRead = await PNSClient.initialize(provider, {
  network: PNSNetwork.TESTNET
});

// 2. Initialize with a signer (Read & Write)
const signer = new Wallet('YOUR_PRIVATE_KEY', provider);
const pns = await PNSClient.initialize(signer, {
  network: PNSNetwork.TESTNET
});

// Register a name
const tx = await pns.register({ name: 'alice' });
await tx.wait();

// Resolve a name
const address = await pns.resolve('alice');
console.log('alice.push resolves to:', address);

API Reference

Initialization

PNSClient.initialize(signerOrProvider, options)

Initialize the PNS client.

const pns = await PNSClient.initialize(signer, {
  network: PNSNetwork.TESTNET, // Defaults to TESTNET
  contractAddress: '0x...' // Optional: Override default contract address
});

Name Registration

register(options: RegisterOptions)

Register a new name.

const tx = await pns.register({
  name: 'alice',
  value: parseEther('0.01'), // Optional: auto-calculated if not provided
});

renew(options: RenewOptions)

Renew an existing name.

const tx = await pns.renew({
  name: 'alice',
  value: parseEther('0.01'), // Optional
});

transfer(name: string, newOwner: string)

Transfer name ownership.

const tx = await pns.transfer('alice', '0x...');

Name Resolution

resolve(name: string)

Resolve a name to its primary address.

const address = await pns.resolve('alice');

resolveChain(name: string, chainNamespace: string, chainId: string)

Resolve a name to a specific chain address.

// Resolve to Ethereum Mainnet address
const ethAddress = await pns.resolveChain('alice', 'eip155', '1');

// Resolve to Solana address
const solAddress = await pns.resolveChain('alice', 'solana', '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp');

getAllChainAddresses(name: string)

Get all chain addresses for a name.

const addresses = await pns.getAllChainAddresses('alice');
addresses.forEach(addr => {
  console.log(`${addr.chainNamespace}:${addr.chainId} -> ${addr.evmAddress || addr.addressBytes}`);
});

reverseLookup(address: string)

Get the primary name for an address.

const name = await pns.reverseLookup('0x...');
console.log('Primary name:', name);

Name Information

isNameAvailable(name: string)

Check if a name is available for registration.

const availability = await pns.isNameAvailable('alice');
if (availability.available) {
  console.log('Name is available!');
} else {
  console.log('Name expires at:', availability.expiresAt);
}

getNameRecord(name: string)

Get detailed name record information.

const record = await pns.getNameRecord('alice');
console.log('Expires at:', record.expiresAt);
console.log('Registered at:', record.registeredAt);
console.log('Is premium:', record.isPremium);
console.log('Origin chain:', record.originAccount);

getOwner(name: string)

Get the owner of a name.

const owner = await pns.getOwner('alice');

getNamesByOwner(address: string)

Get all names owned by an address.

const names = await pns.getNamesByOwner('0x...');

calculateRegistrationFee(name: string)

Calculate the registration fee for a name.

const fee = await pns.calculateRegistrationFee('alice');
console.log('Registration fee:', formatEther(fee), 'ETH');

Metadata Management

getMetadata(name: string)

Get metadata for a name.

const metadata = await pns.getMetadata('alice');
console.log('Avatar:', metadata.avatar);
console.log('Twitter:', metadata.twitter);

setMetadata(options: SetMetadataOptions)

Set metadata for a name.

const tx = await pns.setMetadata({
  name: 'alice',
  avatar: 'https://example.com/avatar.png',
  email: '[email protected]',
  twitter: '@alice',
  github: 'alice',
  description: 'Web3 developer',
});

getCustomMetadata(name: string, key: string)

Get a custom metadata field.

const value = await pns.getCustomMetadata('alice', 'website');

setCustomMetadata(name: string, key: string, value: string)

Set a custom metadata field.

const tx = await pns.setCustomMetadata('alice', 'website', 'https://alice.dev');

Primary Resolution

setPrimaryResolution(name: string, primaryAddress: string)

Set the primary resolution address for a name.

const tx = await pns.setPrimaryResolution('alice', '0x...');

setPrimaryName(name: string)

Set a name as your primary name for reverse resolution.

const tx = await pns.setPrimaryName('alice');

Chain Statistics

getChainStats(chainNamespace: string, chainId: string)

Get statistics for a specific chain.

const stats = await pns.getChainStats('eip155', '1');
console.log('Registrations:', stats.registrationCount);
console.log('Display name:', stats.displayName);

getAllKnownChains()

Get all known chains.

const chains = await pns.getAllKnownChains();
chains.forEach(chain => {
  console.log(`${chain.displayName}: ${chain.registrationCount} registrations`);
});

getMyOrigin()

Get the caller's origin chain information.

const { originAccount, isUEA } = await pns.getMyOrigin();
console.log('Origin chain:', originAccount.chainNamespace, originAccount.chainId);
console.log('Is UEA:', isUEA);

getTotalNamesRegistered()

Get the total number of names registered.

const total = await pns.getTotalNamesRegistered();

Contract Information

getBaseRegistrationFee()

Get the base registration fee.

const fee = await pns.getBaseRegistrationFee();

getPremiumMultiplier()

Get the premium name multiplier.

const multiplier = await pns.getPremiumMultiplier();

isPremiumName(name: string)

Check if a name is premium.

const isPremium = await pns.isPremiumName('alice');

Utility Functions

Name Validation

import { isValidNameFormat, normalizeName } from '@miracleorg/pns-sdk';

// Validate name format
if (isValidNameFormat('alice')) {
  console.log('Valid name!');
}

// Normalize name (lowercase, strip .push extension)
const normalized = normalizeName('Alice.push'); // Returns 'alice'

Name Hashing

import { getNameHash, getChainHash } from '@miracleorg/pns-sdk';

const nameHash = getNameHash('alice');
const chainHash = getChainHash('eip155', '1');

Name Formatting

import { formatPushName, stripPushExtension } from '@miracleorg/pns-sdk';

const fullName = formatPushName('alice'); // 'alice.push'
const baseName = stripPushExtension('alice.push'); // 'alice'

Time Utilities

import { isNameExpired, isInGracePeriod, getTimeUntilExpiration } from '@miracleorg/pns-sdk';

const record = await pns.getNameRecord('alice');

if (isNameExpired(record.expiresAt)) {
  console.log('Name has expired');
}

if (isInGracePeriod(record.expiresAt)) {
  console.log('Name is in grace period');
}

const timeLeft = getTimeUntilExpiration(record.expiresAt);
console.log(`${timeLeft.days} days, ${timeLeft.hours} remaining`);

Constants

import { PNS_CONSTANTS, KNOWN_CHAINS } from '@miracleorg/pns-sdk';

console.log('Registration duration:', PNS_CONSTANTS.REGISTRATION_DURATION);
console.log('Grace period:', PNS_CONSTANTS.GRACE_PERIOD);
console.log('Min name length:', PNS_CONSTANTS.MIN_NAME_LENGTH);
console.log('Max name length:', PNS_CONSTANTS.MAX_NAME_LENGTH);

// Known chains
console.log('Ethereum Mainnet:', KNOWN_CHAINS.ETHEREUM_MAINNET);
console.log('Solana Mainnet:', KNOWN_CHAINS.SOLANA_MAINNET);

TypeScript Support

The SDK is written in TypeScript and provides full type definitions:

import type {
  NameRecord,
  ChainAddress,
  NameMetadata,
  ChainStats,
  UniversalAccountId,
} from '@miracleorg/pns-sdk';

License

MIT

Support

For issues and questions, please visit the GitHub repository.