npm package: @snowballmoney/mns-sdk
Description: This SDK provides a clean and type-safe way to interact with your Snowstorm public API. 
Author: Your Name
Latest version: 1.1.0

# Snowstorm SDK

[![npm version](https://img.shields.io/npm/v/@snowballmoney/mns-sdk.svg)](https://www.npmjs.com/package/@snowballmoney/mns-sdk)

A TypeScript SDK for interacting with the Snowstorm naming service API. Snowstorm is a modular naming service that allows resolution between blockchain addresses and human-readable names across different chains. It uses [@snowballmoney/chain-agnostic-utils](https://www.npmjs.com/package/@snowballmoney/chain-agnostic-utils) for standardized blockchain network identification.

## Features

- Full TypeScript support with type definitions
- Cross-chain identity resolution using CAIP-2 standard
- Integration with @snowballmoney/chain-agnostic-utils for network identification
- Batch operations support
- Partner search API with pagination support
- API key authentication for partner endpoints
- Automatic error handling
- Caching support
- CAIP2 standard compliance

## Installation

```bash
npm install @snowballmoney/mns-sdk @snowballmoney/chain-agnostic-utils
# or
yarn add @snowballmoney/mns-sdk @snowballmoney/chain-agnostic-utils
```

## Quick Start

```typescript
import { SnowstormSDK } from '@snowballmoney/mns-sdk';
import { NETWORKS } from '@snowballmoney/chain-agnostic-utils';

// Initialize the SDK
const sdk = new SnowstormSDK();

// Get an identity name for an address using CAIP2 network ID
const identity = await sdk.getIdentityName(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  NETWORKS.MOVEMENT.TESTNET
);
```

## Usage

### Initialization

```typescript
import { SnowstormSDK } from '@snowballmoney/mns-sdk';

const sdk = new SnowstormSDK({
  baseUrl: 'https://api.modular.name/api/public', // optional
  timeout: 5000, // optional, defaults to 10000ms
  apiKey: 'your-api-key', // optional, required for partner search API
});
```

### Single Resolution

```typescript
import { NETWORKS } from '@snowballmoney/chain-agnostic-utils';

// Get identity name by address
const identityName = await sdk.getIdentityName(
  '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  NETWORKS.MOVEMENT.TESTNET
);

// Get address by identity name
const identityAddress = await sdk.getIdentityAddress(
  'alice.snow',
  NETWORKS.MOVEMENT.TESTNET
);

// Get identity metadata
const metadata = await sdk.getIdentityMetadata('alice.snow');
```

### Batch Operations

```typescript
import { NETWORKS } from '@snowballmoney/chain-agnostic-utils';

// Batch resolve names for multiple addresses
const batchNames = await sdk.getIdentityNames({
  addresses: [
    '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
    '0x123...',
  ],
  caip2Id: NETWORKS.MOVEMENT.TESTNET,
});

// Batch resolve addresses for multiple names
const batchAddresses = await sdk.getIdentityAddresses({
  names: ['alice.snow', 'bob.snow'],
  caip2Id: NETWORKS.MOVEMENT.TESTNET,
});
```

### Using Wildcard CAIP2 IDs

You can use wildcard CAIP2 IDs to query across all networks in a namespace:

```typescript
import { NETWORKS } from '@snowballmoney/chain-agnostic-utils';

const allNetworks = await sdk.getIdentityNames({
  addresses: ['0x742d35...'],
  caip2Id: 'move-mvmt:*', // Query all Movement networks
});
```

### Partner Search API

Search for identities across multiple naming services with pagination support. Requires an API key.

#### Configuration with API Key

```typescript
import { SnowstormSDK } from '@snowballmoney/mns-sdk';

// Option 1: Global API key configuration (recommended)
const sdk = new SnowstormSDK({
  apiKey: 'snow-key-hash-...',
});

// Option 2: Per-method API key
const sdk = new SnowstormSDK();
const results = await sdk.searchIdentityByName('vitalik', {
  page: 1,
  perPage: 10,
  apiKey: 'snow-key-hash-...',
});

// Option 3: Custom base URL for staging/testing
const stagingSdk = new SnowstormSDK({
  baseUrl: 'https://staging.modular.name/',
  apiKey: 'staging-api-key',
});
```

#### Search Usage

```typescript
// Basic search (uses default pagination: page 1, perPage 10)
const results = await sdk.searchIdentityByName('vitalik');

// Search with custom pagination
const results = await sdk.searchIdentityByName('alice', {
  page: 2,
  perPage: 20,
});

// Access search results
results.results.forEach(identity => {
  console.log(`Name: ${identity.name}`);
  console.log(`Owner: ${identity.ownerAddress}`);
  console.log(`Provider: ${identity.providerName}`);
  console.log(`Expires: ${identity.expireAt}`);
  
  // Multichain addresses
  identity.multichainAddresses.forEach(addr => {
    console.log(`  ${addr.chainName}: ${addr.address}`);
  });
  
  // Social profiles and metadata
  identity.txtRecords.forEach(record => {
    console.log(`  ${record.type}: ${record.value}`);
  });
});

// Pagination information
console.log(`Page ${results.pagination.page} of ${results.pagination.totalPages}`);
console.log(`Total results: ${results.pagination.total}`);
```

#### Search Response Structure

```typescript
interface IdentitySearchResponse {
  results: IdentitySearchResult[];
  pagination: {
    page: number;
    perPage: number;
    total: number;
    totalPages: number;
  };
}

interface IdentitySearchResult {
  name: string;
  ownerAddress: string;
  source: string;
  provider: string;
  providerName: string;
  logoURI: string;
  url: string;
  caip2Id: string;
  expireAt: string;
  registeredAt: string;
  multichainAddresses: MultichainAddress[];
  txtRecords: TxtRecordSearchResult[];
}
```

### Error Handling

The SDK provides a custom `SnowstormError` class for proper error handling:

```typescript
try {
  const identity = await sdk.getIdentityName(address, caip2Id);
} catch (error) {
  if (error instanceof SnowstormError) {
    console.error('API Error:', {
      message: error.message,
      status: error.status,
      code: error.code,
    });
  } else {
    console.error('Unexpected error:', error);
  }
}
```

## API Reference

### Methods

#### `getIdentityName(address: string, caip2Id: CAIP2ID): Promise<IdentityName>`
Get the identity name associated with an address.

#### `getIdentityAddress(name: string, caip2Id: CAIP2ID): Promise<IdentityAddress>`
Get the address associated with an identity name.

#### `getIdentityMetadata(name: string): Promise<IdentityMetadata>`
Get metadata associated with an identity.

#### `getIdentityNames(params: GetIdentityNamesByAddressesRequest): Promise<BatchIdentityNames>`
Batch resolve names for multiple addresses.

#### `getIdentityAddresses(params: GetIdentityAddressesByNamesRequest): Promise<BatchIdentityAddresses>`
Batch resolve addresses for multiple names.

#### `searchIdentityByName(query: string, options?: SearchIdentityOptions): Promise<IdentitySearchResponse>`
Search for identities across multiple naming services. Requires API key.

**Parameters:**
- `query` - Search query string
- `options` - Optional search parameters
  - `page` - Page number (default: 1)
  - `perPage` - Results per page (default: 10)
  - `apiKey` - API key override (optional if configured globally)

### Types

```typescript
type CAIP2ID = string; // e.g. "move-mvmt:testnet"

interface IdentityName {
  name: string;
  owner: string;
}

interface IdentityAddress {
  owner: string;
  resolverAddress: string;
  caip2Id?: CAIP2ID;
  subIdentities?: SubIdentity[];
}

interface IdentityMetadata {
  metadata: Array<{
    key: string;
    value: string;
  }>;
}
```

## CAIP2 ID Format

CAIP2 IDs follow the format: `namespace:reference`

The SDK uses [@snowballmoney/chain-agnostic-utils](https://www.npmjs.com/package/@snowballmoney/chain-agnostic-utils) for standardized network identification. Examples:
- `move-mvmt:testnet` - Movement testnet
- `move-mvmt:mainnet` - Movement mainnet
- `move-mvmt:*` - All Movement networks

## Development

```bash
# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Generate documentation
npm run docs
```

## Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.

## License

MIT License - see the [LICENSE](LICENSE) file for details.