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

@getsafle/unified-id-sdk

v1.0.3

Published

JavaScript SDK for Unified ID registration and management

Readme

Unified ID SDK

A functional JavaScript SDK for Unified ID registration and management.

Features

  • 📝 Unified ID Registration: Register new unified IDs with cryptographic signatures
  • 🔗 Secondary Address Management: Add and remove secondary addresses
  • Class-based Design: Easy-to-use UnifiedIdSDK class
  • 🔒 Security: EIP-191 compliant signatures and secure nonce management
  • 🔍 Comprehensive Utility Functions: Check contract states, validate addresses, and verify data

Installation

npm install unified-id-sdk

Quick Integration Checklist

  1. Initialize the SDK with config (see below)
  2. Use SDK utility functions for nonce and signature hash
  3. Sign the hash with your wallet or signing method
  4. Call the SDK class methods for API actions

SDK Initialization

You must provide all config values explicitly. There are no defaults or environment variable fallbacks. The contract address is set automatically based on environment and chainId.

const UnifiedIdSDK = require('unified-id-sdk');

const config = {
  baseURL: 'safle_api_base_url',           // API base URL (required)
  authToken: 'your-bearer-token-here',           // Auth token (required)
  chainId: 11155111,                             // Blockchain chain ID (required, e.g. Sepolia)
  environment: 'testnet'                         // 'testnet' or 'mainnet' (required)
};

const sdk = new UnifiedIdSDK(config);

If any config value is missing or invalid, the SDK will throw an error.

Environment and Chain ID Validation

  • environment must be either 'testnet' or 'mainnet'.
  • The chainId must match the allowed values for the selected environment.
  • The contract address is set automatically; do not provide it manually.

Usage Examples

Note: For all flows, you must sign the hash returned by createSignatureMessage using your preferred wallet or signing method (e.g., MetaMask, ethers.js, hardware wallet, etc.).

1. Register a New Unified ID

Step 1: Generate the signature hash

const { getNonce, createSignatureMessage } = require('unified-id-sdk');
const nonce = await getNonce('my-unified-id', config, 'https://sepolia.infura.io/v3/YOUR_PROJECT_ID');
const hash = createSignatureMessage('register', {
  unifiedId: 'my-unified-id',
  userAddress: '0xUSER_ADDRESS',
  nonce: Number(nonce)
});

Step 2: Sign the hash

  • Dapp/user must sign the hash using their wallet.

Step 3: Call the SDK method

const result = await sdk.registerUnifiedId({
  unifiedId: 'my-unified-id',
  userAddress: '0xUSER_ADDRESS',
  nonce: Number(nonce),
  signature // <- the signature from the user
});

2. Add a Secondary Address

Step 1: Generate the signature hash

const nonce = await getNonce('my-unified-id', config, 'https://sepolia.infura.io/v3/YOUR_PROJECT_ID');
const hash = createSignatureMessage('register', {
  unifiedId: 'my-unified-id',
  userAddress: '0xSECONDARY_ADDRESS',
  nonce: Number(nonce)
});

Step 2: Sign the hash

  • Both the primary and secondary wallets must sign the hash.
  • Pass both signatures to the SDK method below.

Step 3: Call the SDK method

const result = await sdk.addSecondaryAddress({
  unifiedId: 'my-unified-id',
  secondaryAddress: '0xSECONDARY_ADDRESS',
  nonce: Number(nonce),
  primarySignature,   // <- signature from primary wallet
  secondarySignature  // <- signature from secondary wallet
});

3. Remove a Secondary Address

Step 1: Generate the signature hash

const nonce = await getNonce('my-unified-id', config, 'https://sepolia.infura.io/v3/YOUR_PROJECT_ID');
const hash = createSignatureMessage('removeSecondary', {
  unifiedId: 'my-unified-id',
  secondaryAddress: '0xSECONDARY_ADDRESS',
  nonce: Number(nonce)
});

Step 2: Sign the hash

  • The primary wallet must sign the hash.

Step 3: Call the SDK method

const result = await sdk.removeSecondaryAddress({
  unifiedId: 'my-unified-id',
  secondaryAddress: '0xSECONDARY_ADDRESS',
  nonce: Number(nonce),
  signature // <- signature from primary wallet
});

4. Update Unified ID

Step 1: Generate the signature hash

const nonce = await getNonce('old-unified-id', config, 'https://sepolia.infura.io/v3/YOUR_PROJECT_ID');
const hash = createSignatureMessage('updateUnifiedId', {
  oldUnifiedId: 'old-unified-id',
  newUnifiedId: 'new-unified-id',
  nonce: Number(nonce)
});

Step 2: Sign the hash

  • The primary wallet must sign the hash

Step 3: Call the SDK method

const result = await sdk.updateUnifiedId({
  oldUnifiedId: 'old-unified-id',
  newUnifiedId: 'new-unified-id',
  nonce: Number(nonce),
  signature // <- signature from primary wallet
});

5. Change Primary Address

Step 1: Generate the signature hash

const nonce = await getNonce('my-unified-id', config, 'https://sepolia.infura.io/v3/YOUR_PROJECT_ID');
const hash = createSignatureMessage('primaryChange', {
  unifiedId: 'my-unified-id',
  newAddress: '0xNEW_PRIMARY_ADDRESS',
  nonce: Number(nonce)
});

Step 2: Sign the hash

  • Both the current and new primary wallets must sign the hash.
  • Pass both signatures to the SDK method below.

Step 3: Call the SDK method

const result = await sdk.changePrimaryAddress({
  unifiedId: 'my-unified-id',
  newAddress: '0xNEW_PRIMARY_ADDRESS',
  nonce: Number(nonce),
  currentPrimarySignature, // <- signature from current primary wallet
  newPrimarySignature     // <- signature from new primary wallet
});

Utility Functions

The SDK provides comprehensive utility functions for checking contract states, validating addresses, and verifying data. These functions can be used both as SDK instance methods and as direct exports.

Core Utility Functions

You can use these functions directly:

const { 
  getProvider, 
  getNonce, 
  createSignatureMessage, 
  createOptions,
  // Contract state utilities
  isValidUnifiedID,
  isPrimaryAddressAlreadyRegistered,
  isSecondaryAddressAlreadyRegistered,
  isUnifiedIDAlreadyRegistered,
  getMasterWalletforUnifiedID,
  getPrimaryWalletforUnifiedID,
  getSecondaryWalletsforUnifiedID,
  getUnifiedIDByPrimaryAddress,
  getRegistrationFees,
  validateSignature
} = require('unified-id-sdk');

SDK Instance Methods

When using the SDK class, you can call utility functions as instance methods:

const sdk = new UnifiedIdSDK(config);

// Check if unified ID is valid
const isValid = await sdk.isValidUnifiedID('example.id', rpcUrl);
console.log('Is valid:', isValid);

// Check if address is registered as primary
const isPrimary = await sdk.isPrimaryAddressAlreadyRegistered('0xPRIMARY_ADDRESS', rpcUrl);
console.log('Is primary:', isPrimary);

// Check if address is registered as secondary
const isSecondary = await sdk.isSecondaryAddressAlreadyRegistered('0xSECONDARY_ADDRESS',rpcUrl);
console.log('Is secondary:', isSecondary);

// Check if unified ID is already registered
const isRegistered = await sdk.isUnifiedIDAlreadyRegistered('example.id', rpcUrl);
console.log('Is registered:', isRegistered);

// Get master wallet for unified ID
const masterWallet = await sdk.getMasterWalletforUnifiedID('example.id', rpcUrl);
console.log('Master wallet:', masterWallet);

// Get primary wallet for unified ID
const primaryWallet = await sdk.getPrimaryWalletforUnifiedID('example.id', rpcUrl);
console.log('Primary wallet:', primaryWallet);

// Get secondary wallets for unified ID
const secondaryWallets = await sdk.getSecondaryWalletsforUnifiedID('example.id', rpcUrl);
console.log('Secondary wallets:', secondaryWallets);

// Get unified ID by primary address
const unifiedId = await sdk.getUnifiedIDByPrimaryAddress('0xPRIMARY_ADDRESS', chainId, rpcUrl);
console.log('Unified ID:', unifiedId);

// Get registration fees for a token
const fees = await sdk.getRegistrationFees('TOKEN_ADDRESS', '1000000000000000000', rpcUrl);
console.log('Registration fees:', fees);

// Validate signature
const isValidSignature = await sdk.validateSignature(data, expectedSigner, signature, rpcUrl);
console.log('Signature valid:', isValidSignature);

Example Use Cases

Pre-validation before registration

// Check if unified ID already exists before attempting registration
const isValid = await sdk.isValidUnifiedID(unifiedId, rpcUrl);
const isRegistered = await sdk.isUnifiedIDAlreadyRegistered(unifiedId, rpcUrl);

if (!isValid || isRegistered) {
  console.log('Unified ID is invalid or already registered');
  return;
}

// Proceed with registration

Address validation

// Check if address is available before adding as secondary
const isPrimary = await sdk.isPrimaryAddressAlreadyRegistered(address, rpcUrl);
const isSecondary = await sdk.isSecondaryAddressAlreadyRegistered(address, rpcUrl);

if (isPrimary || isSecondary) {
  console.log('Address is already registered');
  return;
}

// Proceed with adding secondary address

Wallet information retrieval

// Get all wallet information for a unified ID
const masterWallet = await sdk.getMasterWalletforUnifiedID(unifiedId, rpcUrl);
const primaryWallet = await sdk.getPrimaryWalletforUnifiedID(unifiedId, rpcUrl);
const secondaryWallets = await sdk.getSecondaryWalletsforUnifiedID(unifiedId, rpcUrl);

console.log('Master wallet:', masterWallet);
console.log('Primary wallet:', primaryWallet);
console.log('Secondary wallets:', secondaryWallets);

Signature validation

// Validate a signature for a specific operation
const data = createSignatureMessage('register', {
  unifiedId: 'example.id',
  userAddress: 'USER_ADDRESS',
  nonce: 1
});

const isValid = await sdk.validateSignature(data, expectedSigner, signature, rpcUrl);
console.log('Signature valid:', isValid);

Error Handling

All SDK methods return a result object:

const result = await sdk.registerUnifiedId(params);
if (!result.success) {
  console.error('Error:', result.error);
  console.error('Details:', result.details);
}

Utility functions throw descriptive errors when:

  • Required parameters are missing
  • Contract calls fail
  • Network issues occur
  • Invalid addresses are provided

Example error handling:

try {
  const result = await sdk.isValidUnifiedID(unifiedId, rpcUrl);
  console.log('Result:', result);
} catch (error) {
  console.error('Error checking unified ID:', error.message);
}

Security Considerations

  1. Private Keys: Never expose private keys in client-side code
  2. Network Security: Use HTTPS for all API communications
  3. Token Management: Store authentication tokens securely
  4. Nonce Management: The SDK provides utilities for nonce retrieval
  5. Signature Verification: All signatures follow EIP-191 standards
  6. Address Validation: Always validate addresses before using them in operations

License

MIT License - see LICENSE file for details.

Support

For support and questions, please open an issue on GitHub or contact the development team.