# Betfair Exchange API Client

A comprehensive TypeScript library for interfacing with the Betfair Exchange API, including betting, accounts, heartbeat, and streaming functionality.

## Features

- Complete typing for all Betfair API requests and responses
- Support for the Betting API, Accounts API, and Heartbeat API
- Stream API client for real-time market and order data
- Authentication via interactive and non-interactive methods
- Comprehensive error handling
- Machine Comprehensible Project (MCP) file for enhanced IDE support

## Installation

```bash
npm install betfair-exchange-api
```

## MCP Support

This package includes a Machine Comprehensible Project (MCP) file that provides enhanced IDE support and documentation. Upon installation, the MCP file is automatically copied to your project root directory.

The MCP file contains:
- Detailed API documentation
- Type definitions
- Method signatures and parameters
- Event documentation for the Stream API
- Component relationships and architecture

If you're using an MCP-compatible IDE (like Cursor), you'll get enhanced:
- Code completion
- Documentation
- Type inference
- Method suggestions

The MCP file is automatically installed via the package's postinstall script. If you need to manually copy it:

```bash
cp node_modules/betfair-exchange-api/betfair-exchange-api.mcp ./
```

## Authentication

Before using the API, you need to authenticate with your Betfair credentials:

```typescript
import { BetfairClient } from 'betfair-exchange-api';

// Initialize with your application key
const client = new BetfairClient('YOUR_APP_KEY');

// Interactive authentication (username/password)
await client.authenticateInteractive('username', 'password');

// OR Non-interactive (certificate) authentication
await client.authenticateNonInteractive(
  'username', 
  'password', 
  'path/to/certificate.crt', 
  'path/to/private.key'
);
```

## Betting API Examples

### List all available sports (event types)

```typescript
const eventTypes = await client.betting.listEventTypes({});
console.log(eventTypes);
```

### List soccer events for today

```typescript
const now = new Date();
const tomorrow = new Date();
tomorrow.setDate(now.getDate() + 1);

const soccerFilter = {
  eventTypeIds: ['1'], // 1 = Soccer
  marketStartTime: {
    from: now.toISOString(),
    to: tomorrow.toISOString()
  }
};

const events = await client.betting.listEvents(soccerFilter);
console.log(events);
```

### Get market catalog for an event

```typescript
const marketFilter = {
  eventIds: ['31520581'] // Replace with your event ID
};

const markets = await client.betting.listMarketCatalogue(
  marketFilter,
  ['MARKET_DESCRIPTION', 'RUNNER_DESCRIPTION', 'RUNNER_METADATA'],
  undefined,
  25 // Maximum 1000 results
);

console.log(markets);
```

### Get market prices

```typescript
const priceProjection = {
  priceData: ['EX_BEST_OFFERS', 'EX_TRADED'],
  virtualise: true
};

const marketBooks = await client.betting.listMarketBook(
  ['1.179082418'], // Replace with your market ID
  priceProjection
);

console.log(marketBooks);
```

### Place a bet

```typescript
const placeInstruction = {
  orderType: 'LIMIT',
  selectionId: 12345678, // Replace with your selection ID
  side: 'BACK',
  limitOrder: {
    size: 2.0,
    price: 3.0,
    persistenceType: 'LAPSE'
  }
};

const response = await client.betting.placeOrders(
  '1.179082418', // Replace with your market ID
  [placeInstruction],
  'my_customer_ref' // Optional customer reference
);

console.log(response);
```

### List current orders

```typescript
const currentOrders = await client.betting.listCurrentOrders();
console.log(currentOrders);
```

## Accounts API Examples

### Get account details

```typescript
const accountDetails = await client.accounts.getAccountDetails();
console.log(accountDetails);
```

### Get account funds

```typescript
const accountFunds = await client.accounts.getAccountFunds();
console.log(accountFunds);
```

### Get account statement

```typescript
const statement = await client.accounts.getAccountStatement(
  undefined, // locale
  0, // fromRecord
  100, // recordCount
  {
    from: '2023-01-01T00:00:00Z',
    to: '2023-01-31T23:59:59Z'
  } // itemDateRange
);

console.log(statement);
```

## Heartbeat API Example

```typescript
// Set up the heartbeat with a 60 second timeout
const heartbeatReport = await client.heartbeat.heartbeat(60);
console.log(heartbeatReport);
```

## Stream API Examples

The Stream API provides real-time updates for markets and orders.

```typescript
import { BetfairStreamClient } from 'betfair-exchange-api';

// Create stream client with your credentials
const streamClient = new BetfairStreamClient('YOUR_APP_KEY', 'YOUR_SESSION_TOKEN');

// Set up event handlers
streamClient.on('connected', () => {
  console.log('Connected to Betfair Stream API');
});

streamClient.on('disconnected', () => {
  console.log('Disconnected from Betfair Stream API');
});

streamClient.on('marketChange', (marketChange) => {
  console.log('Market data update:', marketChange);
});

streamClient.on('orderChange', (orderChange) => {
  console.log('Order data update:', orderChange);
});

// Connect to the stream
streamClient.connect();

// After authentication succeeds, subscribe to markets
streamClient.subscribeToMarkets(
  {
    eventTypeIds: ['1'], // Soccer
    marketTypes: ['MATCH_ODDS']
  },
  {
    fields: ['EX_BEST_OFFERS', 'EX_TRADED'],
    ladderLevels: 3
  }
);

// Subscribe to orders
streamClient.subscribeToOrders({
  includeOverallPosition: true
});

// When finished
streamClient.disconnect();
```

## Session Management

```typescript
// Keep your session alive
const keepAliveResult = await client.keepAlive();

// Logout when done
const logoutResult = await client.logout();
```

## Error Handling

All API methods throw exceptions when they fail. It's recommended to use try/catch blocks to handle errors appropriately:

```typescript
try {
  const markets = await client.betting.listMarketCatalogue(marketFilter);
  // Process markets
} catch (error) {
  console.error('API Error:', error.message);
}
```

## Notes

- Remember to manage your session with keepAlive to prevent it from expiring
- Be aware of API request limits to avoid getting rate limited
- The Stream API requires an active and valid session token

## License

MIT

## Credits

This library is an unofficial implementation of the Betfair Exchange API. Betfair and all related trademarks are the property of The Sporting Exchange Limited.
