# @mercnet/windmill

Windmill integration adapter for MercNet GraphQL API - A simplified interface for Windmill workflows to interact with MercNet's trading data.

## Installation

```bash
npm install @mercnet/windmill
```

## Quick Start

```typescript
import { createClient, createMercNetClient } from '@mercnet/windmill'

// Using the default MercNet endpoint
const client = createMercNetClient({
  token: 'your-auth-token'
})

// Or specify a custom endpoint
const customClient = createClient({
  endpoint: 'https://your-graphql-endpoint.com/graphql',
  token: 'your-auth-token'
})

// Get all markets
const markets = await client.getAllMarkets()

// Get specific market by ID
const market = await client.getMarketById(1)

// Get market by ticker
const btcMarket = await client.getMarketByTicker('BTC')
```

## Features

- **Pre-configured GraphQL Client**: Ready-to-use client with authentication and error handling
- **Type-safe Operations**: Full TypeScript support with generated types
- **Windmill Optimized**: Designed specifically for Windmill workflow integration
- **Utility Functions**: Common trading operations simplified for workflow use
- **Flexible Configuration**: Support for custom endpoints and authentication

## API Reference

### Core Functions

#### `createClient(config: WindmillClientConfig)`

Creates a pre-configured MercNet GraphQL client.

```typescript
const client = createClient({
  endpoint: 'http://graphql.rocketeer.trade/rpc/graphql_query',
  token: 'your-auth-token',
  debug: true,
  retries: 3
})
```

#### `createMercNetClient(config: Partial<WindmillClientConfig>)`

Creates a client with the default MercNet endpoint pre-configured.

```typescript
const client = createMercNetClient({
  token: 'your-auth-token'
})
```

### Market Operations

#### `getAllMarkets()`

Retrieves all available markets.

```typescript
const markets = await client.getAllMarkets()
console.log(`Found ${markets.length} markets`)
```

#### `getMarketById(id: number)`

Retrieves a specific market by its ID.

```typescript
const market = await client.getMarketById(1)
if (market) {
  console.log(`Market: ${market.name} (${market.ticker})`)
}
```

#### `getMarketByTicker(ticker: string)`

Retrieves a market by its ticker symbol.

```typescript
const btcMarket = await client.getMarketByTicker('BTC')
```

#### `getMarketsByStatus(status: string)`

Retrieves all markets with a specific status.

```typescript
const activeMarkets = await client.getMarketsByStatus('active')
```

### Utility Class

#### `WindmillMercNetUtils`

Provides specialized utility functions for common Windmill workflow operations.

```typescript
import { createUtils } from '@mercnet/windmill'

const utils = createUtils({
  endpoint: 'http://graphql.rocketeer.trade/rpc/graphql_query',
  token: 'your-token'
})

// Get only active markets
const activeMarkets = await utils.getActiveMarkets()

// Get market summary for reporting
const summary = await utils.getMarketSummary(1)

// Search markets by ticker pattern
const cryptoMarkets = await utils.searchMarketsByTicker('BTC')

// Get sentiment analysis for all markets
const sentiments = await utils.getMarketsSentiment()
```

## Configuration Options

```typescript
interface WindmillClientConfig {
  /** GraphQL endpoint URL */
  endpoint: string
  /** Authentication token for API access */
  token?: string
  /** Additional headers to include in requests */
  headers?: Record<string, string>
  /** Number of retry attempts for failed requests */
  retries?: number
  /** Enable debug logging */
  debug?: boolean
}
```

## Market Data Structure

```typescript
interface Market {
  id: number
  name?: string | null
  short_name?: string | null
  ticker: string
  price?: string | null
  type?: string | null
  created_at?: string | null
  last_update_at?: string | null
  trend_status?: string | null
  sentiment?: string | null
  sentiment_update_at?: string | null
  market_activity_score_1h?: string | null
  market_activity_score_1d?: string | null
  data?: Record<string, unknown> | null
  status?: string | null
}
```

## Windmill Integration Examples

### Basic Market Data Retrieval

```typescript
// windmill-market-data.ts
import { createMercNetClient } from '@mercnet/windmill'

export async function main(token: string) {
  const client = createMercNetClient({ token })
  
  const markets = await client.getAllMarkets()
  
  return {
    totalMarkets: markets.length,
    activeMarkets: markets.filter(m => m.status === 'active').length,
    markets: markets.map(m => ({
      id: m.id,
      name: m.name,
      ticker: m.ticker,
      price: m.price,
      sentiment: m.sentiment
    }))
  }
}
```

### Market Monitoring Workflow

```typescript
// windmill-market-monitor.ts
import { createUtils } from '@mercnet/windmill'

export async function main(token: string, alertThreshold: number = 5.0) {
  const utils = createUtils({
    endpoint: 'http://graphql.rocketeer.trade/rpc/graphql_query',
    token
  })
  
  const activeMarkets = await utils.getActiveMarkets()
  const alerts = []
  
  for (const market of activeMarkets) {
    const summary = await utils.getMarketSummary(market.id)
    
    if (summary?.activityScore1h && parseFloat(summary.activityScore1h) > alertThreshold) {
      alerts.push({
        ticker: market.ticker,
        activityScore: summary.activityScore1h,
        sentiment: summary.sentiment,
        trend: summary.trend
      })
    }
  }
  
  return {
    timestamp: new Date().toISOString(),
    totalMarkets: activeMarkets.length,
    alertsTriggered: alerts.length,
    alerts
  }
}
```

### Sentiment Analysis Report

```typescript
// windmill-sentiment-report.ts
import { createUtils } from '@mercnet/windmill'

export async function main(token: string) {
  const utils = createUtils({
    endpoint: 'http://graphql.rocketeer.trade/rpc/graphql_query',
    token
  })
  
  const sentiments = await utils.getMarketsSentiment()
  
  const sentimentCounts = sentiments.reduce((acc, market) => {
    const sentiment = market.sentiment || 'unknown'
    acc[sentiment] = (acc[sentiment] || 0) + 1
    return acc
  }, {} as Record<string, number>)
  
  return {
    timestamp: new Date().toISOString(),
    totalMarketsWithSentiment: sentiments.length,
    sentimentBreakdown: sentimentCounts,
    recentUpdates: sentiments
      .filter(m => m.sentimentUpdateAt)
      .sort((a, b) => new Date(b.sentimentUpdateAt!).getTime() - new Date(a.sentimentUpdateAt!).getTime())
      .slice(0, 10)
  }
}
```

## Error Handling

The client includes comprehensive error handling with retry logic and detailed error information:

```typescript
import { MercNetError } from '@mercnet/windmill'

try {
  const markets = await client.getAllMarkets()
} catch (error) {
  if (error instanceof MercNetError) {
    console.error('MercNet API Error:', error.message)
    console.error('Error Code:', error.code)
    console.error('Details:', error.details)
  } else {
    console.error('Unexpected error:', error)
  }
}
```

## TypeScript Support

This package is built with TypeScript and provides full type safety:

```typescript
import type { Market, WindmillClientConfig, GraphQLResponse } from '@mercnet/windmill'

// All operations are fully typed
const client = createMercNetClient({ token: 'your-token' })
const markets: Market[] = await client.getAllMarkets()
```

## Contributing

This package is part of the MercNet v2 monorepo. See the main repository for contribution guidelines.

## License

MIT