npm package: @miracleorg/pns-sdk
Description: TypeScript SDK for Push Name Service (PNS) - Universal multi-chain name service
Author: Push Protocol
Latest version: 1.0.2

# 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

```bash
npm install @miracleorg/pns-sdk ethers
```

## Quick Start

```typescript
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.

```typescript
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.

```typescript
const tx = await pns.register({
  name: 'alice',
  value: parseEther('0.01'), // Optional: auto-calculated if not provided
});
```

#### `renew(options: RenewOptions)`

Renew an existing name.

```typescript
const tx = await pns.renew({
  name: 'alice',
  value: parseEther('0.01'), // Optional
});
```

#### `transfer(name: string, newOwner: string)`

Transfer name ownership.

```typescript
const tx = await pns.transfer('alice', '0x...');
```

### Name Resolution

#### `resolve(name: string)`

Resolve a name to its primary address.

```typescript
const address = await pns.resolve('alice');
```

#### `resolveChain(name: string, chainNamespace: string, chainId: string)`

Resolve a name to a specific chain address.

```typescript
// 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.

```typescript
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.

```typescript
const name = await pns.reverseLookup('0x...');
console.log('Primary name:', name);
```

### Name Information

#### `isNameAvailable(name: string)`

Check if a name is available for registration.

```typescript
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.

```typescript
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.

```typescript
const owner = await pns.getOwner('alice');
```

#### `getNamesByOwner(address: string)`

Get all names owned by an address.

```typescript
const names = await pns.getNamesByOwner('0x...');
```

#### `calculateRegistrationFee(name: string)`

Calculate the registration fee for a name.

```typescript
const fee = await pns.calculateRegistrationFee('alice');
console.log('Registration fee:', formatEther(fee), 'ETH');
```

### Metadata Management

#### `getMetadata(name: string)`

Get metadata for a name.

```typescript
const metadata = await pns.getMetadata('alice');
console.log('Avatar:', metadata.avatar);
console.log('Twitter:', metadata.twitter);
```

#### `setMetadata(options: SetMetadataOptions)`

Set metadata for a name.

```typescript
const tx = await pns.setMetadata({
  name: 'alice',
  avatar: 'https://example.com/avatar.png',
  email: 'alice@example.com',
  twitter: '@alice',
  github: 'alice',
  description: 'Web3 developer',
});
```

#### `getCustomMetadata(name: string, key: string)`

Get a custom metadata field.

```typescript
const value = await pns.getCustomMetadata('alice', 'website');
```

#### `setCustomMetadata(name: string, key: string, value: string)`

Set a custom metadata field.

```typescript
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.

```typescript
const tx = await pns.setPrimaryResolution('alice', '0x...');
```

#### `setPrimaryName(name: string)`

Set a name as your primary name for reverse resolution.

```typescript
const tx = await pns.setPrimaryName('alice');
```

### Chain Statistics

#### `getChainStats(chainNamespace: string, chainId: string)`

Get statistics for a specific chain.

```typescript
const stats = await pns.getChainStats('eip155', '1');
console.log('Registrations:', stats.registrationCount);
console.log('Display name:', stats.displayName);
```

#### `getAllKnownChains()`

Get all known chains.

```typescript
const chains = await pns.getAllKnownChains();
chains.forEach(chain => {
  console.log(`${chain.displayName}: ${chain.registrationCount} registrations`);
});
```

#### `getMyOrigin()`

Get the caller's origin chain information.

```typescript
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.

```typescript
const total = await pns.getTotalNamesRegistered();
```

### Contract Information

#### `getBaseRegistrationFee()`

Get the base registration fee.

```typescript
const fee = await pns.getBaseRegistrationFee();
```

#### `getPremiumMultiplier()`

Get the premium name multiplier.

```typescript
const multiplier = await pns.getPremiumMultiplier();
```

#### `isPremiumName(name: string)`

Check if a name is premium.

```typescript
const isPremium = await pns.isPremiumName('alice');
```

## Utility Functions

### Name Validation

```typescript
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

```typescript
import { getNameHash, getChainHash } from '@miracleorg/pns-sdk';

const nameHash = getNameHash('alice');
const chainHash = getChainHash('eip155', '1');
```

### Name Formatting

```typescript
import { formatPushName, stripPushExtension } from '@miracleorg/pns-sdk';

const fullName = formatPushName('alice'); // 'alice.push'
const baseName = stripPushExtension('alice.push'); // 'alice'
```

### Time Utilities

```typescript
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

```typescript
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:

```typescript
import type {
  NameRecord,
  ChainAddress,
  NameMetadata,
  ChainStats,
  UniversalAccountId,
} from '@miracleorg/pns-sdk';
```

## License

MIT

## Support

For issues and questions, please visit the [GitHub repository](https://github.com/push-protocol/pns-sdk).