npm package: @stacknet/keyutils
Description: Reusable components for buying and managing StackNet node keys
Latest version: 0.4.1

# @stacknet/keyutils

Reusable React components and hooks for buying, managing, and selling StackNet Node Keys.

## Install

```bash
pnpm add @stacknet/keyutils
```

Peer dependencies: `react >= 18`, `react-dom >= 18`

## Quick Start

```tsx
import { BuyKeyWidget } from '@stacknet/keyutils/components';

<BuyKeyWidget
  apiBaseUrl=""
  stackId="stk_your_stack_id"
  stackName="My App"
  paymentMethods={['stripe', 'solana']}
  merchantWallet="YOUR_SOLANA_WALLET_ADDRESS"
  maxQuantity={5}
  keyImage="/key-art.png"
  aispImage="/aisp-chip.png"
  onMintSuccess={(result) => console.log('Key generated:', result)}
/>
```

The `BuyKeyWidget` is fully self-contained — it wraps its own `KeyUtilsProvider` and manages all state internally. Zero setup.

## Components

### `BuyKeyWidget`

Main embeddable widget with three tabs: **Buy**, **Use**, **Sell**.

| Prop | Type | Description |
|------|------|-------------|
| `apiBaseUrl` | `string` | Base URL for API calls (use `""` for same-origin) |
| `stackId` | `string` | Stack identifier for payment config |
| `stackName` | `string` | Display name for the originating stack |
| `paymentMethods` | `('stripe' \| 'solana')[]` | Enabled payment methods |
| `merchantWallet` | `string` | Solana wallet address for crypto payments |
| `maxQuantity` | `number` | Max keys per purchase (default: 5) |
| `keyImage` | `string` | Image URL shown above price on Buy tab |
| `keyImageClass` | `string` | CSS class for key image (default: `w-1/2 mx-auto`) |
| `aispImage` | `string` | Image URL shown on Use tab |
| `termsUrl` | `string` | URL for terms link (default: `/terms`) |
| `solanaRpcUrl` | `string` | Solana RPC endpoint (default: mainnet) |
| `defaultTab` | `'buy' \| 'use' \| 'sell'` | Initial active tab |
| `onMintSuccess` | `(result) => void` | Called after successful key generation |
| `onMintError` | `(error) => void` | Called on generation failure |
| `onListingCreated` | `(listing) => void` | Called after marketplace listing |

### `KeyUtilsProvider`

Context provider for using individual components and hooks outside of `BuyKeyWidget`.

```tsx
import { KeyUtilsProvider, KeyList } from '@stacknet/keyutils/components';

<KeyUtilsProvider config={{ apiBaseUrl: '' }}>
  <KeyList getKeyHref="/keys/get" />
</KeyUtilsProvider>
```

### Other Components

| Component | Description |
|-----------|-------------|
| `BuyPanel` | Purchase flow with pricing, quantity, and payment |
| `UsePanel` | Download links with platform detection |
| `SellPanel` | Marketplace listing interface |
| `KeyList` | Displays user's keys with balances |
| `KeyCard` | Single key with expandable ledger |
| `KeyBalanceBar` | Token balance progress bar |
| `SolanaPayButton` | Solana payment via Phantom wallet |
| `MintSuccess` | Post-purchase success display |

All components except `BuyKeyWidget` require a parent `KeyUtilsProvider`.

## Hooks

```tsx
import { usePricing, useKeys, useMintKey, useListKey } from '@stacknet/keyutils/hooks';
```

| Hook | Returns | Description |
|------|---------|-------------|
| `usePricing()` | `{ pricing, loading, error, refresh }` | Live pricing with 60s auto-refresh |
| `useKeys()` | `{ keys, totalBalance, loading, error, refresh }` | User's node keys |
| `useKeyLedger(keyId)` | `{ entries, loading, error, refresh }` | Ledger for a specific key |
| `useMintKey()` | `{ mint, minting, result, error }` | Key generation after payment |
| `useListKey()` | `{ listKey, delistKey, listing, result, error }` | Marketplace list/delist |
| `useStripeCheckout()` | `{ createSession, loading, error }` | Stripe Checkout Session creation |

All hooks require a parent `KeyUtilsProvider`.

## API Proxy Routes

The widget expects these proxy routes on the host app:

| Route | Method | Proxies To |
|-------|--------|------------|
| `/api/keys` | GET | `/api/v2/node-keys` |
| `/api/keys/pricing` | GET | `/api/v2/node-keys/pricing` |
| `/api/keys/mint` | POST | `/api/v2/node-keys/mint` |
| `/api/keys/:id` | GET | `/api/v2/node-keys/:id` |
| `/api/keys/:id/ledger` | GET | `/api/v2/node-keys/:id/ledger` |
| `/api/keys/:id/list` | POST/DELETE | `/api/v2/node-keys/:id/list` |
| `/api/keys/stripe-session` | POST | `/api/v2/node-keys/stripe-session` |

## Sub-path Exports

```ts
import { BuyKeyWidget } from '@stacknet/keyutils/components';
import { usePricing } from '@stacknet/keyutils/hooks';
import type { NodeKeyInfo } from '@stacknet/keyutils/types';
import { cn, formatTokens } from '@stacknet/keyutils/utils';
```

## Build

```bash
pnpm --filter @stacknet/keyutils build
```

## License

MIT