# Lending APY Fetcher TypeScript

A production-ready TypeScript library for fetching Annual Percentage Yields (APYs) from DeFi lending protocols. Currently supports Kamino (Solana) and Aave (Ethereum).

## Features

- 🔄 **Concurrent Fetching**: Fetch from multiple protocols simultaneously
- 🛡️ **Error Handling**: Graceful degradation with detailed error types
- 🔧 **Configurable**: No hardcoded values, everything is configurable
- 📊 **Type Safe**: Full TypeScript support with comprehensive types
- 🔌 **Extensible**: Easy to add new protocols via the Protocol interface
- 🎯 **Utility Methods**: Find best APYs, group by tokens, etc.

## Installation

```bash
npm install lending-apy-fetcher-ts
```

## Quick Start

### Simple Usage

```typescript
import { getApys } from 'lending-apy-fetcher-ts';

// Fetch APYs from all protocols
const apys = await getApys();
console.log(apys);
```

### Advanced Usage

```typescript
import { 
  ApyFetcher, 
  AppConfig, 
  getBestApyForToken 
} from 'lending-apy-fetcher-ts';

// Create custom configuration
const config = AppConfig.fromEnvironment();

// Create fetcher instance
const fetcher = new ApyFetcher(config);

// Fetch APYs with error details
const results = await fetcher.fetchApysWithResults();

// Get best APY for a specific token
const bestUsdc = await getBestApyForToken('USDC');
if (bestUsdc) {
  console.log(`Best USDC APY: ${bestUsdc.best_apy.apy}% on ${bestUsdc.best_apy.protocol_name}`);
}

// Group APYs by token
const groupedApys = await fetcher.getApysByToken();
```

## Environment Variables

The library automatically loads `.env` files when imported. Create a `.env` file in your project root:

```bash
# Required: The Graph API key for Aave data
SUBGRAPH_API_KEY=your_subgraph_api_key_here

# Optional: HTTP configuration
API_TIMEOUT=10000
USER_AGENT=lending-apy-fetcher-ts/1.0.0
RETRY_ATTEMPTS=3
RETRY_DELAY=1000
ENABLE_LOGGING=false
```

### Troubleshooting Environment Variables

If your `.env` file isn't being loaded:

1. **Check file location**: The `.env` file must be in your project root (same directory as `package.json`)

2. **Test environment loading**:
   ```javascript
   // Run this test
   node test-env.js
   ```

3. **Manual loading** (if needed):
   ```javascript
   import { initializeEnvironment } from 'lending-apy-fetcher-ts';
   initializeEnvironment(); // Force reload .env
   ```

4. **Check if variables are set**:
   ```javascript
   console.log('SUBGRAPH_API_KEY:', process.env.SUBGRAPH_API_KEY);
   ```

### Getting The Graph API Key

1. Visit [The Graph Studio](https://thegraph.com/studio/)
2. Connect your wallet and create an account
3. Create a new API key or use an existing one
4. Set it as `SUBGRAPH_API_KEY` in your environment

## Supported Protocols

### Kamino (Solana)
- **Lending APYs**: SOL, USDC, USDT, and other major tokens
- **Staking Yields**: LST (Liquid Staking Token) yields
- **Network**: Solana

### Aave (Ethereum)
- **Lending APYs**: WETH, USDC, DAI, USDT, WBTC, wstETH, and more
- **Data Source**: The Graph Protocol
- **Network**: Ethereum

## API Reference

### Core Classes

#### `ApyFetcher`

Main class for fetching APY data from multiple protocols.

```typescript
const fetcher = new ApyFetcher(config?);

// Fetch from all protocols
const apys = await fetcher.fetchApys(gracefulDegradation?);

// Get detailed results per protocol
const results = await fetcher.fetchApysWithResults(gracefulDegradation?);

// Get APYs grouped by token
const grouped = await fetcher.getApysByToken(gracefulDegradation?);

// Get best APY for specific token
const best = await fetcher.getBestApyForToken('USDC', gracefulDegradation?);
```

#### `AppConfig`

Configuration management for the entire library.

```typescript
// Create from environment variables
const config = AppConfig.fromEnvironment();

// Create with custom settings
const config = new AppConfig(
  addressConfig,
  kaminoConfig,
  aaveEthConfig,
  apiConfig,
  subgraphApiKey
);
```

### Data Types

#### `ApyData`

```typescript
interface ApyData {
  token_symbol: string;     // e.g., "USDC"
  apy: number;             // APY as percentage (e.g., 5.25)
  protocol_name: string;   // e.g., "Kamino"
  network: string;         // e.g., "Solana"
  additional_info?: Record<string, any>;
}
```

#### `BestApyResult`

```typescript
interface BestApyResult {
  token_symbol: string;
  best_apy: ApyData;
  all_options: ApyData[];
}
```

### Convenience Functions

```typescript
// Simple APY fetching
const apys = await getApys(config?, gracefulDegradation?);

// With detailed results
const results = await getApysWithResults(config?, gracefulDegradation?);

// Best APY for token
const best = await getBestApyForToken('USDC', config?, gracefulDegradation?);
```

## Adding Custom Protocols

Implement the `Protocol` interface:

```typescript
import { Protocol, ApyData } from 'lending-apy-fetcher-ts';

class MyCustomProtocol implements Protocol {
  name = 'MyProtocol';
  network = 'Ethereum';

  async fetchApys(): Promise<ApyData[]> {
    // Your implementation here
    return [
      {
        token_symbol: 'USDC',
        apy: 6.5,
        protocol_name: this.name,
        network: this.network,
      }
    ];
  }
}

// Add to fetcher
const fetcher = new ApyFetcher();
fetcher.addProtocol(new MyCustomProtocol());
```

## Error Handling

The library provides detailed error types:

```typescript
import { 
  ApyFetcherError, 
  NetworkError, 
  ValidationError, 
  AuthenticationError 
} from 'lending-apy-fetcher-ts';

try {
  const apys = await getApys();
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Authentication failed:', error.message);
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  } else if (error instanceof ValidationError) {
    console.error('Data validation failed:', error.message);
  }
}
```

## Configuration Options

### Address Mapping

The library includes default token address mappings for major tokens across networks. You can add custom mappings:

```typescript
const addressConfig = new AddressConfig();
addressConfig.addMapping('0x123...', 'MY_TOKEN', 'Ethereum');
```

### HTTP Configuration

```typescript
const apiConfig = new ApiConfig(
  10000,        // timeout
  'my-app/1.0', // user agent
  3,            // retry attempts
  1000,         // retry delay
  true          // enable logging
);
```

## Development

```bash
# Install dependencies
npm install

# Build the library
npm run build

# Run tests
npm test

# Run linting
npm run lint

# Format code
npm run format
```

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request. 