# LLM Context

````markdown
# MNEE SDK Complete Reference

This document provides comprehensive documentation for the MNEE SDK, designed to give LLMs full context for working with the SDK.

## Table of Contents

1. [Setup and Configuration](#setup-and-configuration)
2. [Core Methods](#core-methods)
3. [Batch Operations](#batch-operations)
4. [HD Wallet](#hd-wallet)
5. [Type Definitions](#type-definitions)
6. [Webhook Support](#webhook-support)

## Setup and Configuration

### Installation and Initialization

```typescript
import Mnee from '@mnee/ts-sdk';

// Initialize MNEE SDK
const mnee = new Mnee({ 
  environment: 'production', // or 'sandbox' (required)
  apiKey: 'your-api-key'     // optional but recommended
});

// All types are also exported from the main module
import { 
  MNEEBalance, 
  MNEEUtxo, 
  TransferResponse,
  HDWallet 
  // ... and more
} from '@mnee/ts-sdk';
```

#### SdkConfig Type

```typescript
type SdkConfig = {
  environment: 'production' | 'sandbox';
  apiKey?: string;
};
```

### Configuration

The `config()` method retrieves the current MNEE service configuration including fee structure and system addresses.

```typescript
const config = await mnee.config();
```

#### Response Structure

```typescript
interface MNEEConfig {
  approver: string;      // Cosigner public key
  feeAddress: string;    // Fee collection address
  burnAddress: string;   // Burn operations address
  mintAddress: string;   // Mint operations address
  fees: FeeTier[];       // Fee structure tiers
}

interface FeeTier {
  min: number;    // Minimum amount (atomic units)
  max: number;    // Maximum amount (atomic units)
  fee: number;    // Fee amount (atomic units)
}
```

## Core Methods

### Balance Operations

#### Single Address Balance

```typescript
const balance = await mnee.balance('address');
// Returns: { address: string, amount: number, decimalAmount: number }
```

#### Multiple Address Balances

```typescript
const balances = await mnee.balances(['address1', 'address2']);
// Returns: MNEEBalance[]
```

### UTXO Operations

```typescript
// Single address (returns up to 10 UTXOs by default)
const utxos = await mnee.getUtxos('address');

// With pagination
const utxos = await mnee.getUtxos('address', 0, 100, 'desc');
// Parameters: address, page, size (max 1000), order ('asc' | 'desc')

// Multiple addresses
const utxos = await mnee.getUtxos(['address1', 'address2'], 0, 50);
// Returns: MNEEUtxo[]

// Get just enough UTXOS for a specific amount (optimized for transfers)
const requiredAmount = mnee.toAtomicAmount(5.0); // Convert 5 MNEE to atomic units
const enoughUtxos = await mnee.getEnoughUtxos('address', requiredAmount); // Returns: MNEEUtxo[] - stops fetching once sufficient amount is reached

// Get all Utxos for an address (comprehensive wallet view)
const allUtxos = await mnee.getAllUtxos('address'); // Returns: MNEEUtxo[] - fetchtes every UTXO for the address

```

#### UTXO Structure (BSV21)

```typescript
interface MNEEUtxo {
  txid: string;
  vout: number;
  outpoint: string;  // "txid_vout"
  satoshis: number;
  accSats: number;
  script: string;
  owners: string[];
  data: {
    types: string[];
    insc: {
      json: any;
      text: string;
      words: string[];
      file: {
        hash: string;
        size: number;
        type: string;
      };
    };
    map: { [key: string]: any };
    b: {
      hash: string;
      size: number;
      type: string;
    };
    sigmas: Array<{ algorithm: string; address: string; signature: string; index?: number }>;
    list: {
      payout: Array<{ address: string; value: number }>;
      lock: { until: number };
    };
    bsv20: { [key: string]: any };
    bsv21: {
      id: string;    // Token ID
      p: string;     // Protocol
      op: string;    // Operation
      amt: number;   // Amount in atomic units
      sym: string;   // Symbol
      icon: string;  // Icon URL
      dec: number;   // Decimals
    };
  };
}
```

### Transfer Operations

#### Simple Transfer

```typescript
const recipients: SendMNEE[] = [
  { address: 'recipient1', amount: 10.5 },
  { address: 'recipient2', amount: 5.25 }
];

const response = await mnee.transfer(
  recipients, 
  'sender-private-key-wif',
  { broadcast: true, callbackUrl: 'https://your-api.com/webhook' }  // optional
);
// Returns: TransferResponse

// Get transaction ID from status
const status = await mnee.getTxStatus(response.ticketId);
console.log('Transaction ID:', status.tx_id);
```

#### Multi-Source Transfer

```typescript
const options: TransferMultiOptions = {
  inputs: [
    { txid: 'txid1', vout: 0, wif: 'wif1' },
    { txid: 'txid2', vout: 1, wif: 'wif2' }
  ],
  recipients: [
    { address: 'recipient1', amount: 15.75 },
    { address: 'recipient2', amount: 8.50 }
  ],
  changeAddress: 'change-address' // optional
};

const response = await mnee.transferMulti(options, { broadcast: true });
// Returns: TransferResponse

// Get transaction ID from status
const status = await mnee.getTxStatus(response.ticketId);
console.log('Transaction ID:', status.tx_id);
```

#### Transfer Response

```typescript
interface TransferResponse {
  ticketId?: string;  // Ticket ID for tracking (only if broadcast is true)
  rawtx?: string;     // The raw transaction hex (only if broadcast is false)
}
```

#### Transaction Status

```typescript
const status = await mnee.getTxStatus(ticketId);
// Returns: TransferStatus

interface TransferStatus {
  id: string;
  tx_id: string;
  tx_hex: string;
  action_requested: 'transfer';
  status: 'BROADCASTING' | 'SUCCESS' | 'MINED' | 'FAILED';
  createdAt: string;
  updatedAt: string;
  errors: string | null;
}
```

### Transaction Validation

```typescript
const isValid = await mnee.validateMneeTx(rawTxHex);
// Or with expected recipients
const isValid = await mnee.validateMneeTx(rawTxHex, recipients);
// Returns: boolean
```

### Submit Raw Transaction

```typescript
const response = await mnee.submitRawTx(rawTxHex, {
  broadcast: true,
  callbackUrl: 'https://your-api.com/webhook'  // optional
});
// Returns: TransferResponse with ticketId

// Get transaction ID from status
const status = await mnee.getTxStatus(response.ticketId);
console.log('Transaction ID:', status.tx_id);
```

### Unit Conversion

```typescript
// Convert MNEE to atomic units (1 MNEE = 100,000 atomic)
const atomic = mnee.toAtomicAmount(1.5);  // Returns: 150000

// Convert atomic units to MNEE
const mneeAmount = mnee.fromAtomicAmount(150000);  // Returns: 1.5
```

### Transaction History

#### Single Address History

```typescript
const history = await mnee.recentTxHistory(address, fromScore, limit);
// Returns: TxHistoryResponse
```

#### Multiple Address Histories

```typescript
const params: AddressHistoryParams[] = [
  { address: 'address1', limit: 100 },
  { address: 'address2', fromScore: 850000, limit: 50 }
];
const histories = await mnee.recentTxHistories(params);
// Returns: TxHistoryResponse[]
```

#### History Response Structure

```typescript
interface TxHistoryResponse {
  address: string;
  history: TxHistory[];
  nextScore: number;
}

interface TxHistory {
  txid: string;
  height: number;          // 0 for unconfirmed
  status: 'confirmed' | 'unconfirmed';
  type: 'send' | 'receive';
  amount: number;          // Atomic units
  counterparties: Array<{ address: string; amount: number }>;
  fee: number;
  score: number;           // For pagination
}
```

### Transaction Parsing

#### Parse by Transaction ID

```typescript
const parsed = await mnee.parseTx(txid);
// With extended data
const parsed = await mnee.parseTx(txid, { includeRaw: true });
// Returns: ParseTxResponse | ParseTxExtendedResponse
```

#### Parse from Raw Transaction

```typescript
const parsed = await mnee.parseTxFromRawTx(rawTxHex);
// With extended data
const parsed = await mnee.parseTxFromRawTx(rawTxHex, { includeRaw: true });
```

#### Parse Response Structure

```typescript
interface ParseTxResponse {
  txid: string;
  environment: 'production' | 'sandbox';
  type: string;  // 'transfer', 'burn', etc.
  inputs: Array<{ address: string; amount: number }>;
  outputs: Array<{ address: string; amount: number }>;
  isValid: boolean;
  inputTotal: string;   // String to preserve precision
  outputTotal: string;  // String to preserve precision
}

interface ParseTxExtendedResponse extends ParseTxResponse {
  raw: {
    txHex: string;
    inputs: Array<{
      txid: string;
      vout: number;
      scriptSig: string;
      sequence: number;
      satoshis: number;
      address: string;
      tokenData: any;
    }>;
    outputs: Array<{
      value: number;
      scriptPubKey: string;
      address: string;
      tokenData: any;
    }>;
    version: number;
    lockTime: number;
    size: number;
    hash: string;
  };
}
```

### Script Parsing

#### Parse Inscription

```typescript
import { Script } from '@bsv/sdk';

const script = Script.fromHex('...');
const inscription = mnee.parseInscription(script);
// Returns: Inscription | undefined
```

#### Parse Cosigner Scripts

```typescript
const scripts = [Script.fromHex('...'), Script.fromHex('...')];
const cosigners = mnee.parseCosignerScripts(scripts);
// Returns: ParsedCosigner[]
```

#### Inscription Structure

```typescript
interface Inscription {
  file?: {
    hash: string;
    size: number;
    type: string;
    content: number[];
  };
  fields?: { [key: string]: any };
  parent?: string;
}

interface ParsedCosigner {
  cosigner: string;  // Public key
  address: string;   // Bitcoin address
}
```

## Batch Operations

### Setup

```typescript
const batch = mnee.batch();
```

### Batch Configuration

```typescript
interface BatchOptions {
  chunkSize?: number;         // Max items per API call (default: 20)
  requestsPerSecond?: number; // Rate limit (default: 3)
  continueOnError?: boolean;  // Continue on error (default: false)
  maxRetries?: number;        // Max retries per chunk (default: 3)
  retryDelay?: number;        // Retry delay in ms (default: 1000)
  onProgress?: (completed: number, total: number, errors: number) => void;
}
```

### Batch Methods

#### Get UTXOs

```typescript
const result = await batch.getUtxos(addresses, options);
// Returns: BatchResult<BatchUtxoResult>
```

#### Get Balances

```typescript
const result = await batch.getBalances(addresses, options);
// Returns: BatchResult<MNEEBalance>
```

#### Get Transaction Histories

```typescript
const params = addresses.map(addr => ({ address: addr, limit: 100 }));
const result = await batch.getTxHistories(params, options);
// Returns: BatchResult<TxHistoryResponse>
```

#### Parse Transactions

```typescript
const result = await batch.parseTx(txids, {
  parseOptions: { includeRaw: true },
  ...batchOptions
});
// Returns: BatchResult<BatchParseTxResult>
```

### Batch Response Structure

```typescript
interface BatchResult<T> {
  results: T[];
  errors: BatchError[];
  totalProcessed: number;
  totalErrors: number;
}

interface BatchError {
  items: string[];
  error: {
    message: string;
    code?: string;
  };
  retryCount: number;
}

interface BatchUtxoResult {
  address: string;
  utxos: MNEEUtxo[];
}

interface BatchParseTxResult {
  txid: string;
  parsed: ParseTxResponse | ParseTxExtendedResponse;
}
```

## HD Wallet

### Setup

```typescript
import Mnee, { HDWallet } from '@mnee/ts-sdk';

const mnee = new Mnee({ 
  environment: 'production',  // required
  apiKey: 'your-api-key'      // optional but recommended
});
```

### Static Methods

```typescript
// Static methods can be accessed via Mnee.HDWallet or imported HDWallet
import Mnee, { HDWallet } from '@mnee/ts-sdk';

// Generate new mnemonic (12 words)
const mnemonic = HDWallet.generateMnemonic();
// or
const mnemonic = Mnee.HDWallet.generateMnemonic();

// Validate mnemonic
const isValid = HDWallet.isValidMnemonic(mnemonic);
// or
const isValid = Mnee.HDWallet.isValidMnemonic(mnemonic);
```

### Create HD Wallet

```typescript
const hdWallet = mnee.HDWallet(mnemonic, {
  derivationPath: "m/44'/236'/0'",  // BIP44 path
  cacheSize: 1000                    // Optional cache size
});
```

### Derive Addresses

#### Single Address

```typescript
// Receive address (change = false)
const addressInfo = hdWallet.deriveAddress(0, false);
// Change address (change = true)
const changeInfo = hdWallet.deriveAddress(0, true);

// AddressInfo structure
{
  address: string;      // Bitcoin address
  privateKey: string;   // WIF format
  path: string;         // Full derivation path
}
```

#### Multiple Addresses

```typescript
const addresses = await hdWallet.deriveAddresses(0, 10, false);
// Returns: AddressInfo[]
```

### Get Private Keys

```typescript
// Get private keys for specific addresses
const result = hdWallet.getPrivateKeysForAddresses(addresses, {
  maxScanReceive: 10000,
  maxScanChange: 10000,
  scanStrategy: 'parallel'  // or 'sequential'
});
// Returns: { privateKeys: {}, paths: {} }

// Simplified version
const privateKeys = hdWallet.getPrivateKeys(addresses, options);
// Returns: { [address: string]: string }
```

### Scan with Gap Limit

```typescript
const checkAddressUsed = async (address) => {
  const balance = await mnee.balance(address);
  return balance.amount > 0;
};

const discovered = await hdWallet.scanAddressesWithGapLimit(
  checkAddressUsed,
  {
    gapLimit: 20,
    scanChange: true,
    maxScan: 10000
  }
);
// Returns: { receive: AddressInfo[], change: AddressInfo[] }
```

### Cache Management

```typescript
hdWallet.clearCache();
const cacheSize = hdWallet.getCacheSize();
```

## Important Notes

### Unit System
- 1 MNEE = 100,000 atomic units
- All blockchain operations use atomic units
- User-facing amounts should be in MNEE (decimal)
- SDK methods expecting amounts use MNEE values (not atomic)

### Address Validation
- Bitcoin addresses starting with 1, 3, or bc1
- Invalid addresses in batch operations are handled based on `continueOnError` setting

### Error Handling

The SDK throws standard JavaScript Error objects with descriptive messages. Common error scenarios:

#### Initialization Errors
- `"Invalid environment. Must be either 'production' or 'sandbox'"` - Invalid environment parameter
- `"MNEE API key cannot be an empty string"` - Empty API key provided
- `"Invalid API key"` - API key authentication failed

#### Validation Errors
- `"Invalid Bitcoin address: <address>"` - Address format validation failed
- `"No valid Bitcoin addresses provided"` - No valid addresses in batch
- `"Invalid transaction ID: empty or not a string"` - Invalid transaction ID format
- `"Invalid transaction ID format: <txid>"` - Transaction ID not 64 hex characters

#### Batch Operation Errors
- `"Input must be an array of addresses"` - Non-array input to batch methods
- `"Input must be an array of transaction IDs"` - Non-array input to parseTx
- `"Max retries exceeded"` - Batch operation failed after all retries

#### HD Wallet Errors
- `"Invalid mnemonic phrase"` - Invalid BIP39 mnemonic
- `"Failed to derive private key for path: <path>"` - Derivation failure
- `"Could not find private keys for <n> address(es)"` - Address not found in HD wallet scan

#### Transfer/Submit Errors (POST methods)
- `"Config not fetched"` - Failed to get cosigner configuration
- `"Insufficient MNEE balance"` - Not enough tokens for transfer
- `"Failed to broadcast transaction"` - Cosigner rejected transaction
- `"Failed to submit raw transaction"` - Submit raw tx failed

#### Error Handling Patterns

```typescript
// Basic error handling
try {
  const result = await mnee.transfer(recipients, wif);
} catch (error) {
  console.error('Transfer failed:', error.message);
}

// Batch operations with continueOnError
const result = await batch.getBalances(addresses, {
  continueOnError: true  // Continue processing on errors
});

// Check for partial failures
if (result.errors.length > 0) {
  result.errors.forEach(error => {
    console.log(`Failed addresses: ${error.items.join(', ')}`);
    console.log(`Error: ${error.error.message}`);
  });
}

// Handle API authentication errors
try {
  const result = await mnee.transfer(recipients, wif);
} catch (error) {
  if (error.message === 'Invalid API key') {
    // Handle authentication failure (401/403)
  } else if (error.message.includes('HTTP error! status:')) {
    // Handle other HTTP errors
  }
}
```

Note: When methods make POST requests to the cosigner API (transfer, transferMulti, submitRawTx), they handle HTTP 401/403 as "Invalid API key" and other HTTP errors as "HTTP error! status: {code}".

## Webhook Support

Transactions can be tracked via webhook callbacks for real-time status updates.

### Webhook Response Format

```typescript
interface TransferWebhookResponse {
  id: string;              // The ticket ID
  tx_id: string;           // The blockchain transaction ID
  tx_hex: string;          // The raw transaction hex
  action_requested: 'transfer';  // Always 'transfer' for MNEE transactions
  callback_url: string;    // Your webhook URL (for verification)
  status: 'BROADCASTING' | 'SUCCESS' | 'MINED' | 'FAILED';
  createdAt: string;       // ISO timestamp when ticket was created
  updatedAt: string;       // ISO timestamp of this update
  errors: string | null;   // Error details if status is FAILED
}
```

### Using Webhooks

```typescript
// Transfer with webhook
const response = await mnee.transfer(recipients, wif, {
  broadcast: true,
  callbackUrl: 'https://your-api.com/webhook'
});

// TransferMulti with webhook
const response = await mnee.transferMulti(options, {
  broadcast: true,
  callbackUrl: 'https://your-api.com/webhook'
});

// Submit raw transaction with webhook
const response = await mnee.submitRawTx(rawTxHex, {
  broadcast: true,
  callbackUrl: 'https://your-api.com/webhook'
});
```

### Webhook Status Flow

- **BROADCASTING** → Transaction is being broadcast to the network
- **SUCCESS** → Transaction successfully broadcast and accepted by the network
- **MINED** → Transaction has been mined into a block
- **FAILED** → Transaction failed (check `errors` field for details)

### Performance
- Batch operations automatically chunk requests
- Rate limiting prevents API throttling
- Progress callbacks report chunk completion, not individual items
- HD wallet caches derived addresses for performance

### Security
- Never store private keys or mnemonics in plain text
- Use WIF format for private keys
- HD wallet follows BIP32/BIP44 standards
- Cosigner validation available via config and script parsing
````


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mnee.io/dev-tools/llm-context.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
