npm package: @leaps-develop/sdk
Description: Official TypeScript SDK for Leaps Layer REST API
Latest version: 0.1.0

# @leaps-layer/sdk

Official TypeScript SDK for the Leaps Layer REST API.

## Installation

```bash
pnpm add @leaps-layer/sdk
```

## Quick Start

```typescript
import LeapsLayer from '@leaps-layer/sdk'

const client = new LeapsLayer({
  apiKey: process.env.LEAPS_LAYER_API_KEY!,
})

// Mint an NFT and wait for confirmation
const result = await client.actions.mintAndWait({
  to: '0x1234567890abcdef1234567890abcdef12345678',
  title: 'Event Ticket #1',
  imageBase64: 'data:image/png;base64,...',
  properties: [{ name: 'tier', value: 'VIP' }],
  soulBound: true,
})

console.log(`Confirmed! TX: ${result.txHash}`)
```

## Client Options

```typescript
const client = new LeapsLayer({
  apiKey: 'sk_live_xxx',      // Required: API key
  baseUrl: 'https://...',     // Optional: API base URL
  timeout: 30000,             // Optional: Request timeout in ms (default: 30000)
  maxRetries: 2,              // Optional: Max retry count (default: 2)
})
```

## API Reference

### Actions

All action methods return `ActionResult` with an `operationId`. Use `xxxAndWait()` variants to wait for confirmation.

```typescript
// Mint
const result = await client.actions.mint({
  to: '0x...',
  title: 'My NFT',
  imageBase64: 'data:image/png;base64,...',
  description: 'Optional description',
  tokenId: 1,                                   // Optional: auto-generated if omitted
  properties: [{ name: 'key', value: 'val' }],  // Optional
  soulBound: true,                               // Optional: default false
})

// Mint and wait for confirmation
const confirmed = await client.actions.mintAndWait(params)

// Burn
await client.actions.burn({ tokenId: 1 })
await client.actions.burnAndWait({ tokenId: 1 })

// Redeem
await client.actions.redeem({
  tokenId: 1,
  redemptionId: '0x...',  // bytes32
  memo: 'Optional memo',
})
await client.actions.redeemAndWait(params)

// Pause / Unpause
await client.actions.pause()
await client.actions.pauseAndWait()
await client.actions.unpause()
await client.actions.unpauseAndWait()
```

### Contract

```typescript
const address = await client.contract.getAddress()
// { contractAddress: '0x...', networkId: 'amoy' }

const owner = await client.contract.getOwner()
// { owner: '0x...' }

const status = await client.contract.getStatus()
// { paused: false, totalSupply: 100, maxSupply: 1000 }
```

### Tokens

```typescript
const metadata = await client.tokens.getMetadata(1)
// { tokenId, tokenURI, name, description, image, attributes }

const state = await client.tokens.getState(1)
// { tokenId, owner, burned }
```

### Operations

```typescript
// Get operation status
const op = await client.operations.get('op-xxx')

// Wait for completion with custom options
const completed = await client.operations.wait('op-xxx', {
  interval: 3000,     // Poll every 3s (default: 2000)
  maxAttempts: 20,    // Max polls (default: 30)
})
```

### Transactions

```typescript
const tx = await client.transactions.get('0xabc...')
// { txHash, type, status, fromAddress, toAddress, blockNumber, confirmedAt, createdAt }
```

## Error Handling

```typescript
import { ConflictError, NotFoundError, AuthenticationError } from '@leaps-layer/sdk'

try {
  await client.actions.pause()
} catch (e) {
  if (e instanceof ConflictError) {
    console.log('Already paused')
  } else if (e instanceof AuthenticationError) {
    console.log('Invalid API key')
  } else if (e instanceof NotFoundError) {
    console.log('Resource not found')
  }
}
```

Error hierarchy:

```
LeapsLayerError
├── ApiError (HTTP errors)
│   ├── AuthenticationError (401)
│   ├── PermissionError (403)
│   ├── NotFoundError (404)
│   └── ConflictError (409)
├── TimeoutError
└── ConnectionError
```

## Idempotency

Prevent duplicate operations using idempotency keys:

```typescript
await client.actions.mint(params, {
  idempotencyKey: 'order-12345',
})
```

POST requests with an idempotency key are safe to retry. Without one, POST requests are not retried.

## Retry Strategy

- Exponential backoff: 500ms base, factor 2, with jitter
- Retryable status codes: 408, 429, 500, 502, 503, 504
- GET requests: always retried
- POST requests: retried only with `idempotencyKey`
- Default max retries: 2

## TypeScript

All types are exported for use in your application:

```typescript
import type {
  MintParams,
  BurnParams,
  RedeemParams,
  ActionResult,
  OperationResponse,
  ContractStatusResponse,
  TokenMetadataResponse,
  TokenStateResponse,
  TransactionResponse,
} from '@leaps-layer/sdk'
```

## Requirements

- Node.js >= 18 (uses global `fetch`)
- TypeScript >= 5.0 (recommended)