SDK Generation Guide
Supported Languages: TypeScript, Python, Java, Go, Ruby, PHP Generation Tool: OpenAPI Generator CLI OpenAPI Version: 3.0.3 Last Generated: 2024-01-15
Table of Contents
- Overview
- Prerequisites
- Quick Start
- Language-Specific Guides
- Customization
- Testing
- CI/CD Integration
- Troubleshooting
Overview
What are Generated SDKs?
Generated SDKs (Software Development Kits) are client libraries automatically created from our OpenAPI specification. They provide:
- Type Safety: Full type definitions for requests and responses
- Auto-Completion: IDE support with intelligent code completion
- Consistency: Guaranteed compatibility with the API specification
- Documentation: Inline documentation from OpenAPI descriptions
- Error Handling: Structured error handling and retry logic
- Authentication: Built-in authentication mechanisms
Why Use Generated SDKs?
Benefits:
- Reduce integration time from days to hours
- Eliminate manual API client code
- Automatic updates when API changes
- Consistent patterns across languages
- Built-in best practices
Supported Languages:
- TypeScript/JavaScript (Node.js, Browser)
- Python (3.7+)
- Java (8+)
- Go (1.18+)
- Ruby (2.7+)
- PHP (7.4+)
Prerequisites
Required Tools
- 
OpenAPI Generator CLI # Via npm
 npm install -g @openapitools/openapi-generator-cli
 # Via Homebrew (macOS)
 brew install openapi-generator
 # Via Docker
 docker pull openapitools/openapi-generator-cli
- 
Language-Specific Tools: - TypeScript: Node.js 16+, npm/yarn
- Python: Python 3.7+, pip
- Java: JDK 8+, Maven/Gradle
- Go: Go 1.18+
- Ruby: Ruby 2.7+, Bundler
- PHP: PHP 7.4+, Composer
 
OpenAPI Specification
Ensure you have the OpenAPI specification file:
# Download the latest spec
curl -O https://api.tvl.com/openapi.yaml
# Or use from repository
git clone https://github.com/tvl/api-specs.git
cd api-specs
Quick Start
Generate Your First SDK
Step 1: Install the generator
npm install -g @openapitools/openapi-generator-cli
Step 2: Generate TypeScript SDK
./scripts/generate-sdk.sh typescript
Step 3: Use in your project
import { TvlSdk } from '@tvl/sdk';
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: 'your-api-key'
});
const protocols = await sdk.protocols.getProtocols();
console.log(protocols.data);
One-Command Generation
Generate all SDKs at once:
./scripts/generate-sdk.sh --all
Generate specific language:
./scripts/generate-sdk.sh python -o ./my-sdk
Language-Specific Guides
TypeScript/JavaScript
Generation
# Using the provided script
./scripts/generate-typescript-sdk.sh ./sdk-output
# Or using openapi-generator directly
openapi-generator-cli generate \
  -i openapi.yaml \
  -g typescript-axios \
  -o ./typescript-sdk \
  --additional-properties=npmName=@tvl/sdk,supportsES6=true
Configuration Options
# Environment variables
export PACKAGE_NAME="@myorg/tvl-sdk"
export PACKAGE_VERSION="1.0.0"
export OPENAPI_SPEC="./custom-spec.yaml"
./scripts/generate-typescript-sdk.sh
Installation & Usage
Install:
cd typescript-sdk
npm install
npm run build
Usage:
import { TvlSdk } from '@tvl/sdk';
// Initialize
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: process.env.TVL_API_KEY,
  timeout: 30000,
  retryAttempts: 3
});
// Use the SDK
async function getProtocols() {
  try {
    const response = await sdk.protocols.getProtocols();
    return response.data;
  } catch (error) {
    console.error('API Error:', error.message);
    throw error;
  }
}
Advanced Configuration
Custom Interceptors:
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: 'your-api-key',
  onRequest: (config) => {
    console.log('Request:', config.url);
    config.headers['X-Custom-Header'] = 'value';
    return config;
  },
  onResponse: (response) => {
    console.log('Response:', response.status);
    return response;
  },
  onError: (error) => {
    console.error('Error:', error);
    // Custom error handling (e.g., send to monitoring)
  }
});
Authentication:
// API Key authentication
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: 'your-api-key'
});
// Update API key at runtime
sdk.updateConfig({ apiKey: 'new-api-key' });
Error Handling:
import { TvlSdk } from '@tvl/sdk';
const sdk = new TvlSdk({ apiKey: 'your-api-key' });
try {
  const protocol = await sdk.protocols.getProtocolById({ id: 'uniswap' });
} catch (error) {
  if (error.status === 404) {
    console.log('Protocol not found');
  } else if (error.status === 429) {
    console.log('Rate limit exceeded');
  } else {
    console.error('Unexpected error:', error);
  }
}
Type Safety
import { TvlSdk, Protocol, ProtocolTvlHistory } from '@tvl/sdk';
const sdk = new TvlSdk({ apiKey: 'your-api-key' });
// Type-safe responses
const protocol: Protocol = await sdk.protocols.getProtocolById({
  id: 'uniswap'
});
// Type-safe requests
const history: ProtocolTvlHistory[] = await sdk.protocols.getProtocolTvlHistory({
  id: 'uniswap',
  startDate: '2024-01-01',
  endDate: '2024-12-31'
});
// Auto-completion for all properties
console.log(protocol.name);
console.log(protocol.totalValueLocked);
console.log(protocol.chains);
Publishing to npm
# Build the package
npm run build
# Test locally
npm link
# Publish to npm
npm login
npm publish --access public
# Or to a private registry
npm publish --registry https://registry.your-org.com
Python
Generation
# Using the provided script
./scripts/generate-python-sdk.sh ./sdk-output
# Or using openapi-generator directly
openapi-generator-cli generate \
  -i openapi.yaml \
  -g python \
  -o ./python-sdk \
  --additional-properties=packageName=tvl_sdk,library=asyncio
Configuration Options
# Environment variables
export PACKAGE_NAME="tvl-sdk"
export PACKAGE_VERSION="1.0.0"
export OPENAPI_SPEC="./openapi.yaml"
./scripts/generate-python-sdk.sh
Installation & Usage
Install:
cd python-sdk
pip install -r requirements.txt
python setup.py install
# Or for development
pip install -e .
Basic Usage:
from tvl_sdk import TvlSdk
# Initialize
sdk = TvlSdk(
    base_url="https://api.tvl.com/v1",
    api_key="your-api-key",
    timeout=30,
    retry_attempts=3
)
# Get protocols
protocols = sdk.protocols.get_protocols()
print(protocols)
# Get specific protocol
protocol = sdk.protocols.get_protocol_by_id(id="uniswap")
print(f"Protocol: {protocol.name}")
print(f"TVL: ${protocol.total_value_locked:,.2f}")
Async/Await Support
import asyncio
from tvl_sdk import AsyncTvlSdk
async def main():
    # Use async context manager
    async with AsyncTvlSdk(
        base_url="https://api.tvl.com/v1",
        api_key="your-api-key"
    ) as sdk:
        # Fetch multiple endpoints concurrently
        protocols_task = sdk.protocols.get_protocols()
        chains_task = sdk.chains.get_chains()
        protocols, chains = await asyncio.gather(
            protocols_task,
            chains_task
        )
        print(f"Protocols: {len(protocols)}")
        print(f"Chains: {len(chains)}")
# Run async code
asyncio.run(main())
Type Hints with Pydantic
from tvl_sdk import TvlSdk, Protocol, ProtocolTvlHistory
from typing import List
from datetime import date
sdk = TvlSdk(api_key="your-api-key")
# Type-safe responses
protocol: Protocol = sdk.protocols.get_protocol_by_id(id="uniswap")
# Type-safe requests
history: List[ProtocolTvlHistory] = sdk.protocols.get_protocol_tvl_history(
    id="uniswap",
    start_date=date(2024, 1, 1),
    end_date=date(2024, 12, 31)
)
# Pydantic models provide validation
print(protocol.name)  # IDE auto-completion
print(protocol.total_value_locked)
Error Handling
from tvl_sdk import TvlSdk, ApiException
sdk = TvlSdk(api_key="your-api-key")
try:
    protocol = sdk.protocols.get_protocol_by_id(id="invalid")
except ApiException as e:
    print(f"API Error: {e.status} - {e.reason}")
    print(f"Body: {e.body}")
    if e.status == 404:
        print("Protocol not found")
    elif e.status == 429:
        print("Rate limit exceeded")
Custom Configuration
from tvl_sdk import TvlSdk
# Custom error handler
def handle_error(error):
    print(f"Error occurred: {error}")
    # Send to monitoring service
    # send_to_sentry(error)
sdk = TvlSdk(
    base_url="https://api.tvl.com/v1",
    api_key="your-api-key",
    timeout=60,
    retry_attempts=5,
    retry_delay=2.0,
    on_error=handle_error
)
# Update configuration at runtime
sdk.update_config(
    api_key="new-api-key",
    timeout=90
)
Publishing to PyPI
# Build the package
python setup.py sdist bdist_wheel
# Test with TestPyPI
twine upload --repository testpypi dist/*
# Install from TestPyPI
pip install --index-url https://test.pypi.org/simple/ tvl-sdk
# Publish to PyPI
twine upload dist/*
Java
Generation
openapi-generator-cli generate \
  -i openapi.yaml \
  -g java \
  -o ./java-sdk \
  --additional-properties=\
groupId=com.tvl,\
artifactId=tvl-sdk,\
invokerPackage=com.tvl.client,\
apiPackage=com.tvl.api,\
modelPackage=com.tvl.model,\
library=okhttp-gson
Maven Setup
pom.xml:
<dependency>
    <groupId>com.tvl</groupId>
    <artifactId>tvl-sdk</artifactId>
    <version>1.0.0</version>
</dependency>
Gradle Setup
build.gradle:
dependencies {
    implementation 'com.tvl:tvl-sdk:1.0.0'
}
Usage Examples
import com.tvl.client.ApiClient;
import com.tvl.client.Configuration;
import com.tvl.api.ProtocolsApi;
import com.tvl.model.Protocol;
public class TvlExample {
    public static void main(String[] args) {
        // Configure API client
        ApiClient client = Configuration.getDefaultApiClient();
        client.setBasePath("https://api.tvl.com/v1");
        client.setApiKey("your-api-key");
        // Create API instance
        ProtocolsApi api = new ProtocolsApi(client);
        try {
            // Get all protocols
            List<Protocol> protocols = api.getProtocols();
            // Get specific protocol
            Protocol protocol = api.getProtocolById("uniswap");
            System.out.println("Protocol: " + protocol.getName());
            System.out.println("TVL: $" + protocol.getTotalValueLocked());
        } catch (ApiException e) {
            System.err.println("API Error: " + e.getCode());
            System.err.println("Response: " + e.getResponseBody());
        }
    }
}
Go
Generation
openapi-generator-cli generate \
  -i openapi.yaml \
  -g go \
  -o ./go-sdk \
  --additional-properties=\
packageName=tvlsdk,\
packageVersion=1.0.0
Module Setup
cd go-sdk
go mod init github.com/yourusername/tvl-sdk
go mod tidy
Usage Examples
package main
import (
    "context"
    "fmt"
    "github.com/yourusername/tvl-sdk"
)
func main() {
    // Configure client
    cfg := tvlsdk.NewConfiguration()
    cfg.Servers = tvlsdk.ServerConfigurations{
        {
            URL: "https://api.tvl.com/v1",
        },
    }
    cfg.AddDefaultHeader("X-API-Key", "your-api-key")
    // Create client
    client := tvlsdk.NewAPIClient(cfg)
    ctx := context.Background()
    // Get protocols
    protocols, resp, err := client.ProtocolsApi.GetProtocols(ctx).Execute()
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    fmt.Printf("Status: %d\n", resp.StatusCode)
    fmt.Printf("Protocols: %d\n", len(protocols))
    // Get specific protocol
    protocol, _, err := client.ProtocolsApi.GetProtocolById(ctx, "uniswap").Execute()
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    fmt.Printf("Protocol: %s\n", protocol.Name)
    fmt.Printf("TVL: $%.2f\n", protocol.TotalValueLocked)
}
Customization
Custom Templates
Create Custom Template Directory
mkdir -p ./custom-templates/typescript-axios
Override API Template
Use Custom Templates
openapi-generator-cli generate \
  -i openapi.yaml \
  -g typescript-axios \
  -o ./sdk \
  -t ./custom-templates/typescript-axios
Configuration Files
Create Config File
# openapi-generator-config.yaml
generatorName: typescript-axios
inputSpec: openapi.yaml
outputDir: ./generated-sdk
additionalProperties:
  npmName: "@tvl/sdk"
  npmVersion: "1.0.0"
  supportsES6: true
  withInterfaces: true
globalProperties:
  models: true
  apis: true
  supportingFiles: true
# Custom template location
templateDir: ./custom-templates
Generate with Config
openapi-generator-cli generate -c openapi-generator-config.yaml
Adding Middleware/Interceptors
TypeScript Example
// middleware/logger.ts
export function createLoggerMiddleware() {
  return {
    onRequest: (config: any) => {
      console.log(`[${new Date().toISOString()}] ${config.method?.toUpperCase()} ${config.url}`);
      return config;
    },
    onResponse: (response: any) => {
      console.log(`[${new Date().toISOString()}] ${response.status} ${response.config.url}`);
      return response;
    }
  };
}
// usage
import { TvlSdk } from '@tvl/sdk';
import { createLoggerMiddleware } from './middleware/logger';
const logger = createLoggerMiddleware();
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: 'your-api-key',
  ...logger
});
Python Example
# middleware/logger.py
import logging
from datetime import datetime
logger = logging.getLogger(__name__)
def log_request(request):
    logger.info(f"[{datetime.now().isoformat()}] {request.method} {request.url}")
    return request
def log_response(response):
    logger.info(f"[{datetime.now().isoformat()}] {response.status_code} {response.url}")
    return response
# usage
from tvl_sdk import TvlSdk
from middleware.logger import log_request, log_response
sdk = TvlSdk(
    base_url="https://api.tvl.com/v1",
    api_key="your-api-key",
    on_request=log_request,
    on_response=log_response
)
Custom Error Handling
TypeScript
class TvlApiError extends Error {
  constructor(
    message: string,
    public status: number,
    public code: string,
    public data: any
  ) {
    super(message);
    this.name = 'TvlApiError';
  }
}
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: 'your-api-key',
  onError: (error) => {
    throw new TvlApiError(
      error.message,
      error.status,
      error.code,
      error.data
    );
  }
});
Python
class TvlApiError(Exception):
    def __init__(self, message, status, code, data):
        super().__init__(message)
        self.status = status
        self.code = code
        self.data = data
def handle_error(error):
    raise TvlApiError(
        str(error),
        getattr(error, 'status', None),
        getattr(error, 'code', None),
        getattr(error, 'body', None)
    )
sdk = TvlSdk(
    base_url="https://api.tvl.com/v1",
    api_key="your-api-key",
    on_error=handle_error
)
Testing Generated SDKs
Unit Testing
TypeScript (Jest)
// __tests__/sdk.test.ts
import { TvlSdk } from '@tvl/sdk';
import axios from 'axios';
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
describe('TvlSdk', () => {
  let sdk: TvlSdk;
  beforeEach(() => {
    sdk = new TvlSdk({
      baseURL: 'https://api.tvl.com/v1',
      apiKey: 'test-api-key'
    });
  });
  test('should fetch protocols', async () => {
    const mockProtocols = [
      { id: 'uniswap', name: 'Uniswap', tvl: 1000000 }
    ];
    mockedAxios.get.mockResolvedValue({
      data: mockProtocols,
      status: 200
    });
    const protocols = await sdk.protocols.getProtocols();
    expect(protocols.data).toEqual(mockProtocols);
  });
  test('should handle errors', async () => {
    mockedAxios.get.mockRejectedValue({
      response: { status: 404, data: { message: 'Not found' } }
    });
    await expect(sdk.protocols.getProtocolById({ id: 'invalid' }))
      .rejects.toThrow();
  });
});
Python (pytest)
# tests/test_sdk.py
import pytest
from unittest.mock import Mock, patch
from tvl_sdk import TvlSdk, ApiException
@pytest.fixture
def sdk():
    return TvlSdk(
        base_url="https://api.tvl.com/v1",
        api_key="test-api-key"
    )
def test_get_protocols(sdk):
    with patch.object(sdk.protocols, 'get_protocols') as mock_get:
        mock_get.return_value = [
            {"id": "uniswap", "name": "Uniswap", "tvl": 1000000}
        ]
        protocols = sdk.protocols.get_protocols()
        assert len(protocols) == 1
        assert protocols[0]["name"] == "Uniswap"
def test_error_handling(sdk):
    with patch.object(sdk.protocols, 'get_protocol_by_id') as mock_get:
        mock_get.side_effect = ApiException(status=404, reason="Not found")
        with pytest.raises(ApiException) as exc_info:
            sdk.protocols.get_protocol_by_id(id="invalid")
        assert exc_info.value.status == 404
Integration Testing
Mock Server Setup
// mock-server.js
const express = require('express');
const app = express();
app.get('/v1/protocols', (req, res) => {
  res.json([
    { id: 'uniswap', name: 'Uniswap', tvl: 1000000 },
    { id: 'aave', name: 'Aave', tvl: 2000000 }
  ]);
});
app.get('/v1/protocols/:id', (req, res) => {
  const { id } = req.params;
  if (id === 'uniswap') {
    res.json({ id: 'uniswap', name: 'Uniswap', tvl: 1000000 });
  } else {
    res.status(404).json({ error: 'Not found' });
  }
});
app.listen(3000, () => {
  console.log('Mock server running on port 3000');
});
Integration Test
// integration/sdk.integration.test.ts
import { TvlSdk } from '@tvl/sdk';
describe('SDK Integration Tests', () => {
  let sdk: TvlSdk;
  beforeAll(() => {
    // Point to mock server
    sdk = new TvlSdk({
      baseURL: 'http://localhost:3000/v1',
      apiKey: 'test-key'
    });
  });
  test('should fetch protocols from mock server', async () => {
    const protocols = await sdk.protocols.getProtocols();
    expect(protocols.data).toHaveLength(2);
    expect(protocols.data[0].name).toBe('Uniswap');
  });
  test('should handle 404 errors', async () => {
    await expect(
      sdk.protocols.getProtocolById({ id: 'nonexistent' })
    ).rejects.toMatchObject({
      status: 404
    });
  });
});
CI/CD Integration
Auto-Generate on OpenAPI Changes
GitHub Actions
# .github/workflows/generate-sdks.yml
name: Generate SDKs
on:
  push:
    paths:
      - 'openapi.yaml'
      - 'openapi/**'
    branches:
      - main
jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install OpenAPI Generator
        run: npm install -g @openapitools/openapi-generator-cli
      - name: Generate TypeScript SDK
        run: ./scripts/generate-typescript-sdk.sh ./sdks/typescript
      - name: Generate Python SDK
        run: ./scripts/generate-python-sdk.sh ./sdks/python
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v5
        with:
          commit-message: 'chore: regenerate SDKs'
          title: 'Auto-generated SDK updates'
          body: 'SDKs regenerated from OpenAPI spec changes'
          branch: sdk-updates
Version Management
Semantic Versioning Script
#!/bin/bash
# scripts/version-sdk.sh
VERSION_FILE="./VERSION"
CURRENT_VERSION=$(cat $VERSION_FILE)
# Parse version
IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION"
MAJOR="${VERSION_PARTS[0]}"
MINOR="${VERSION_PARTS[1]}"
PATCH="${VERSION_PARTS[2]}"
# Increment based on argument
case $1 in
  major)
    MAJOR=$((MAJOR + 1))
    MINOR=0
    PATCH=0
    ;;
  minor)
    MINOR=$((MINOR + 1))
    PATCH=0
    ;;
  patch)
    PATCH=$((PATCH + 1))
    ;;
  *)
    echo "Usage: $0 {major|minor|patch}"
    exit 1
    ;;
esac
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
echo $NEW_VERSION > $VERSION_FILE
echo "Version updated: $CURRENT_VERSION -> $NEW_VERSION"
# Update package files
export PACKAGE_VERSION=$NEW_VERSION
./scripts/generate-sdk.sh --all
Publishing Workflow
TypeScript to npm
# .github/workflows/publish-typescript-sdk.yml
name: Publish TypeScript SDK
on:
  release:
    types: [created]
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
          registry-url: 'https://registry.npmjs.org'
      - name: Install dependencies
        working-directory: ./sdks/typescript
        run: npm install
      - name: Build
        working-directory: ./sdks/typescript
        run: npm run build
      - name: Publish to npm
        working-directory: ./sdks/typescript
        run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Python to PyPI
# .github/workflows/publish-python-sdk.yml
name: Publish Python SDK
on:
  release:
    types: [created]
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.9'
      - name: Install dependencies
        run: |
          pip install build twine
      - name: Build package
        working-directory: ./sdks/python
        run: python -m build
      - name: Publish to PyPI
        working-directory: ./sdks/python
        run: twine upload dist/*
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
SDK Usage Examples
Complete TypeScript Example
import { TvlSdk } from '@tvl/sdk';
// Initialize SDK
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: process.env.TVL_API_KEY,
  timeout: 30000,
  retryAttempts: 3,
  retryDelay: 1000
});
// Example 1: Get all protocols
async function getAllProtocols() {
  try {
    const response = await sdk.protocols.getProtocols();
    console.log(`Found ${response.data.length} protocols`);
    response.data.forEach(protocol => {
      console.log(`${protocol.name}: $${protocol.totalValueLocked.toLocaleString()}`);
    });
    return response.data;
  } catch (error) {
    console.error('Failed to fetch protocols:', error.message);
    throw error;
  }
}
// Example 2: Get protocol with pagination
async function getProtocolsWithPagination() {
  let page = 1;
  let hasMore = true;
  const allProtocols = [];
  while (hasMore) {
    const response = await sdk.protocols.getProtocols({
      page,
      limit: 100
    });
    allProtocols.push(...response.data);
    hasMore = response.data.length === 100;
    page++;
  }
  return allProtocols;
}
// Example 3: Error handling
async function getProtocolSafely(id: string) {
  try {
    const protocol = await sdk.protocols.getProtocolById({ id });
    return protocol.data;
  } catch (error) {
    if (error.status === 404) {
      console.log(`Protocol ${id} not found`);
      return null;
    } else if (error.status === 429) {
      console.log('Rate limit exceeded, waiting...');
      await new Promise(resolve => setTimeout(resolve, 5000));
      return getProtocolSafely(id); // Retry
    } else {
      throw error;
    }
  }
}
// Example 4: Parallel requests
async function getMultipleProtocols(ids: string[]) {
  const promises = ids.map(id =>
    sdk.protocols.getProtocolById({ id })
      .then(res => res.data)
      .catch(err => null)
  );
  return Promise.all(promises);
}
// Example 5: Stream processing
async function* streamProtocols() {
  let page = 1;
  let hasMore = true;
  while (hasMore) {
    const response = await sdk.protocols.getProtocols({
      page,
      limit: 50
    });
    for (const protocol of response.data) {
      yield protocol;
    }
    hasMore = response.data.length === 50;
    page++;
  }
}
// Usage
(async () => {
  // Get all protocols
  await getAllProtocols();
  // Get with pagination
  const allProtocols = await getProtocolsWithPagination();
  console.log(`Total protocols: ${allProtocols.length}`);
  // Get multiple protocols
  const protocols = await getMultipleProtocols(['uniswap', 'aave', 'compound']);
  console.log('Fetched protocols:', protocols.filter(p => p !== null).length);
  // Stream processing
  for await (const protocol of streamProtocols()) {
    console.log(`Processing: ${protocol.name}`);
    // Process each protocol
  }
})();
Complete Python Example
import asyncio
from typing import List, AsyncGenerator
from tvl_sdk import TvlSdk, AsyncTvlSdk, Protocol, ApiException
# Initialize SDK
sdk = TvlSdk(
    base_url="https://api.tvl.com/v1",
    api_key="your-api-key",
    timeout=30,
    retry_attempts=3,
    retry_delay=1.0
)
# Example 1: Get all protocols
def get_all_protocols() -> List[Protocol]:
    try:
        protocols = sdk.protocols.get_protocols()
        print(f"Found {len(protocols)} protocols")
        for protocol in protocols:
            print(f"{protocol.name}: ${protocol.total_value_locked:,.2f}")
        return protocols
    except ApiException as e:
        print(f"Failed to fetch protocols: {e.reason}")
        raise
# Example 2: Get protocols with pagination
def get_protocols_with_pagination() -> List[Protocol]:
    page = 1
    all_protocols = []
    while True:
        protocols = sdk.protocols.get_protocols(
            page=page,
            limit=100
        )
        all_protocols.extend(protocols)
        if len(protocols) < 100:
            break
        page += 1
    return all_protocols
# Example 3: Error handling
def get_protocol_safely(protocol_id: str):
    try:
        protocol = sdk.protocols.get_protocol_by_id(id=protocol_id)
        return protocol
    except ApiException as e:
        if e.status == 404:
            print(f"Protocol {protocol_id} not found")
            return None
        elif e.status == 429:
            print("Rate limit exceeded, waiting...")
            import time
            time.sleep(5)
            return get_protocol_safely(protocol_id)  # Retry
        else:
            raise
# Example 4: Async parallel requests
async def get_multiple_protocols_async(ids: List[str]):
    async with AsyncTvlSdk(
        base_url="https://api.tvl.com/v1",
        api_key="your-api-key"
    ) as sdk:
        tasks = []
        for protocol_id in ids:
            task = sdk.protocols.get_protocol_by_id(id=protocol_id)
            tasks.append(task)
        results = await asyncio.gather(*tasks, return_exceptions=True)
        protocols = []
        for result in results:
            if isinstance(result, Exception):
                print(f"Error: {result}")
            else:
                protocols.append(result)
        return protocols
# Example 5: Async stream processing
async def stream_protocols_async() -> AsyncGenerator[Protocol, None]:
    async with AsyncTvlSdk(
        base_url="https://api.tvl.com/v1",
        api_key="your-api-key"
    ) as sdk:
        page = 1
        while True:
            protocols = await sdk.protocols.get_protocols(
                page=page,
                limit=50
            )
            for protocol in protocols:
                yield protocol
            if len(protocols) < 50:
                break
            page += 1
# Example 6: Context manager for cleanup
class TvlAnalyzer:
    def __init__(self, api_key: str):
        self.sdk = TvlSdk(
            base_url="https://api.tvl.com/v1",
            api_key=api_key
        )
    def analyze_protocol(self, protocol_id: str):
        protocol = self.sdk.protocols.get_protocol_by_id(id=protocol_id)
        history = self.sdk.protocols.get_protocol_tvl_history(
            id=protocol_id,
            start_date="2024-01-01",
            end_date="2024-12-31"
        )
        return {
            "name": protocol.name,
            "current_tvl": protocol.total_value_locked,
            "historical_data": history,
            "growth": self._calculate_growth(history)
        }
    def _calculate_growth(self, history):
        if len(history) < 2:
            return 0
        start_tvl = history[0].tvl
        end_tvl = history[-1].tvl
        return ((end_tvl - start_tvl) / start_tvl) * 100
# Usage
if __name__ == "__main__":
    # Sync examples
    protocols = get_all_protocols()
    all_protocols = get_protocols_with_pagination()
    print(f"Total protocols: {len(all_protocols)}")
    # Safe fetch
    protocol = get_protocol_safely("uniswap")
    if protocol:
        print(f"Found: {protocol.name}")
    # Async examples
    async def main():
        # Parallel fetch
        protocols = await get_multiple_protocols_async([
            "uniswap", "aave", "compound"
        ])
        print(f"Fetched {len(protocols)} protocols")
        # Stream processing
        async for protocol in stream_protocols_async():
            print(f"Processing: {protocol.name}")
            # Process each protocol
    asyncio.run(main())
    # Analyzer
    analyzer = TvlAnalyzer(api_key="your-api-key")
    analysis = analyzer.analyze_protocol("uniswap")
    print(f"Growth: {analysis['growth']:.2f}%")
Troubleshooting
Common Issues
1. OpenAPI Generator Not Found
Error:
openapi-generator-cli: command not found
Solution:
# Install via npm
npm install -g @openapitools/openapi-generator-cli
# Or via Homebrew
brew install openapi-generator
# Verify installation
openapi-generator-cli version
2. Invalid OpenAPI Specification
Error:
Validation error: ...
Solution:
# Validate spec
openapi-generator-cli validate -i openapi.yaml
# Use --skip-validate-spec flag
./scripts/generate-sdk.sh typescript --skip-validate
3. TypeScript Compilation Errors
Error:
TS2304: Cannot find name 'Promise'
Solution:
// Update tsconfig.json
{
  "compilerOptions": {
    "lib": ["ES2018", "DOM"],
    "target": "ES2018"
  }
}
4. Python Import Errors
Error:
ModuleNotFoundError: No module named 'tvl_sdk'
Solution:
# Install in development mode
pip install -e .
# Or install normally
python setup.py install
# Verify installation
python -c "import tvl_sdk; print(tvl_sdk.__version__)"
5. Authentication Failures
Error:
401 Unauthorized
Solution:
// Check API key format
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: process.env.TVL_API_KEY // Ensure this is set
});
// Verify API key is being sent
sdk.updateConfig({
  onRequest: (config) => {
    console.log('Headers:', config.headers);
    return config;
  }
});
6. Rate Limiting
Error:
429 Too Many Requests
Solution:
// Increase retry delay
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: 'your-api-key',
  retryAttempts: 5,
  retryDelay: 2000, // 2 seconds
  onError: (error) => {
    if (error.status === 429) {
      const retryAfter = error.headers?.['retry-after'];
      console.log(`Rate limited. Retry after: ${retryAfter}s`);
    }
  }
});
Debug Mode
TypeScript
// Enable debug logging
const sdk = new TvlSdk({
  baseURL: 'https://api.tvl.com/v1',
  apiKey: 'your-api-key',
  onRequest: (config) => {
    console.log('REQUEST:', {
      method: config.method,
      url: config.url,
      headers: config.headers,
      data: config.data
    });
    return config;
  },
  onResponse: (response) => {
    console.log('RESPONSE:', {
      status: response.status,
      headers: response.headers,
      data: response.data
    });
    return response;
  },
  onError: (error) => {
    console.error('ERROR:', {
      message: error.message,
      status: error.status,
      data: error.data
    });
  }
});
Python
import logging
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
sdk = TvlSdk(
    base_url="https://api.tvl.com/v1",
    api_key="your-api-key",
    on_error=lambda e: logging.error(f"API Error: {e}")
)
Getting Help
If you encounter issues not covered here:
- Check the documentation: https://docs.tvl.com
- Search existing issues: https://github.com/tvl/sdks/issues
- Join our Discord: https://discord.gg/tvl
- Contact support: support@tvl.com
Resources
Official Links
- API Documentation: https://api.tvl.com/docs
- OpenAPI Specification: https://api.tvl.com/openapi.yaml
- GitHub Repository: https://github.com/tvl/sdks
- npm Package: https://www.npmjs.com/package/@tvl/sdk
- PyPI Package: https://pypi.org/project/tvl-sdk/
External Resources
- OpenAPI Generator: https://openapi-generator.tech
- OpenAPI Specification: https://swagger.io/specification/
- REST API Best Practices: https://restfulapi.net
Community
- Discord: https://discord.gg/tvl
- Twitter: https://twitter.com/tvl
- Blog: https://blog.tvl.com
Changelog
Version 1.0.0 (2024-01-15)
- Initial release
- Support for TypeScript, Python, Java, Go, Ruby, PHP
- Retry logic and error handling
- Async support for TypeScript and Python
- Type safety and validation
- Comprehensive documentation
Need help? Contact us at support@tvl.com or open an issue on GitHub.