npm package: @polymerdao/polymer-api-client
Description: TypeScript client library for interacting with Polymer's proof API and blockchain verification
Author: Polymer Labs
Latest version: 0.3.0

# Polymer API Client

TypeScript client library for interacting with Polymer's proof API and blockchain verification. Provides a complete SDK for requesting proofs, verifying cryptographic signatures, and accessing blockchain data.

[![npm version](https://badge.fury.io/js/@polymerdao%2Fpolymer-api-client.svg)](https://www.npmjs.com/package/@polymerdao/polymer-api-client)

## 🚀 Installation

```bash
npm install @polymerdao/polymer-api-client
```

## 🎯 Quick Start

```typescript
import { PolymerOpenRpcClient, ProofVerifier, ChainlistClient } from '@polymerdao/polymer-api-client';

// Initialize the client
const client = new PolymerOpenRpcClient('your-api-key', 'https://api.polymer.zone/v1');

// Request a proof
const proofRequest = await client.proofRequest({
  srcChainId: 1, // Ethereum
  globalLogIndex: 12345,
  srcBlockNumber: 19000000
});

// Query proof status
const status = await client.proofQueryJob({ id: proofRequest.jobId });

// Verify a proof
const verifier = new ProofVerifier('0x4632e987c6f31d6351e39324dec6f1404af56209', 444);
const isValid = await verifier.verifyProof(proofData);
```

## 📚 API Reference

### PolymerOpenRpcClient

Main client for interacting with Polymer's API.

```typescript
import { PolymerOpenRpcClient } from '@polymerdao/polymer-api-client';

const client = new PolymerOpenRpcClient(apiKey, baseUrl);
```

#### Proof Methods

**Request a proof:**
```typescript
const request = await client.proofRequest({
  srcChainId: number,        // Source chain ID (e.g., 1 for Ethereum)
  globalLogIndex: number,    // Global log index of the event
  srcBlockNumber: number     // Block number containing the event
});
// Returns: { jobId: number, status: string }
```

**Query proof job:**
```typescript
const status = await client.proofQueryJob({
  id: number                 // Job ID from proof request
});
// Returns: { jobId: number, status: string, proof?: string, ... }
```

**Query with filters:**
```typescript
const results = await client.proofQueryWithFilter({
  chainId?: number,
  status?: string,
  limit?: number,
  offset?: number
});
```

**Get job statistics:**
```typescript
const stats = await client.proofQueryJobStats();
```

#### Execution Methods

**Submit execution request:**
```typescript
const execution = await client.executeRequest({
  proofRequest: {
    srcChainId: 11155420,         // Optional: request proof generation on the fly
    srcBlockNumber: 29540611,
    globalLogIndex: 5,
  },
  executeRequest: {
    destChainId: 84532,
    destContractAddress: '0xdda9a457771534eDba705E1D79B1ed0f732d642E',
    methodSignature: 'setValueFromSource(string,bytes,bytes)',
    args: ['tester', '0x1234', '$proof'], // '$proof' is replaced with the generated proof bytes
    gasLimit: 1_000_000,
  },
  // Alternatively, omit proofRequest and provide a pre-generated proof:
  // proof: 'base64_proof_payload'
});
```

**Query execution:**
```typescript
const status = await client.executeQuery({
  id: number                 // Execution job ID
});
```

#### Info Methods

**Get connected chains:**
```typescript
const chains = await client.infoGetConnectedChains();
```

**Get client updates:**
```typescript
const updates = await client.infoGetClientUpdates();
```

### ProofVerifier

Cryptographic proof verification utilities.

```typescript
import { ProofVerifier } from '@polymerdao/polymer-api-client';

const verifier = new ProofVerifier(
  validationKey,     // Ethereum address for ECDSA verification
  polymerChainId     // Polymer chain ID (default: 444)
);
```

**Verify a proof:**
```typescript
const isValid = await verifier.verifyProof(proofData);
// Returns: boolean
```

**Parse proof data:**
```typescript
const parsed = verifier.parseProof(proofData);
// Returns: { appHash: string, peptideHeight: number, signature: {...}, ... }
```

**Verify ECDSA signature:**
```typescript
const isValidSig = verifier.verifySignature(messageHash, signature, expectedAddress);
```

### ChainlistClient

Client for accessing blockchain RPC endpoints and chain information.

```typescript
import { ChainlistClient } from '@polymerdao/polymer-api-client';

const chainlist = new ChainlistClient();
```

**Get chain information:**
```typescript
const chains = await chainlist.getChains();
// Returns: Array of chain objects with RPC endpoints
```

**Get RPC endpoints for a chain:**
```typescript
const rpcs = await chainlist.getChainRpcs('ethereum');
// Returns: Array of RPC endpoint objects
```

**Execute RPC call:**
```typescript
const result = await chainlist.executeRpc(
  'ethereum',           // Chain name
  'eth_getBlockByNumber', // RPC method
  ['latest', false]     // Method parameters
);
```

**Cache management:**
```typescript
// Get cache statistics
const stats = chainlist.getCacheStats();

// Clear cache
chainlist.clearCache();
```

## 🔧 Configuration

### Environment Setup

```typescript
// Using environment variables
process.env.POLYMER_API_KEY = 'your-api-key';
process.env.POLYMER_API_BASE = 'https://api.polymer.zone/v1';

const client = new PolymerOpenRpcClient(
  process.env.POLYMER_API_KEY!,
  process.env.POLYMER_API_BASE
);
```

### Custom Configuration

```typescript
const client = new PolymerOpenRpcClient(
  'your-api-key',
  'https://staging.polymer.zone/v1',  // Custom API base
  {
    timeout: 30000,                    // 30 second timeout
    retries: 3,                        // Retry failed requests
    headers: {                         // Custom headers
      'User-Agent': 'MyApp/1.0'
    }
  }
);
```

## 📊 Examples

### Complete Proof Workflow

```typescript
import { PolymerOpenRpcClient, ProofVerifier } from '@polymerdao/polymer-api-client';

async function completeProofWorkflow() {
  const client = new PolymerOpenRpcClient('your-api-key');
  const verifier = new ProofVerifier('0x4632e987c6f31d6351e39324dec6f1404af56209', 444);

  // 1. Request proof
  const request = await client.proofRequest({
    srcChainId: 1,           // Ethereum
    globalLogIndex: 12345,   
    srcBlockNumber: 19000000
  });

  console.log(`Proof requested: Job ID ${request.jobId}`);

  // 2. Poll for completion
  let status;
  do {
    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
    status = await client.proofQueryJob({ id: request.jobId });
    console.log(`Status: ${status.status}`);
  } while (status.status === 'pending');

  // 3. Verify proof if completed
  if (status.status === 'completed' && status.proof) {
    const isValid = await verifier.verifyProof(status.proof);
    console.log(`Proof valid: ${isValid}`);
    
    // Parse proof details
    const parsed = verifier.parseProof(status.proof);
    console.log('Proof details:', parsed);
  }
}
```

### Cross-Chain Execution

```typescript
async function executecrossChain() {
  const client = new PolymerOpenRpcClient('your-api-key');

  // Prepare execution envelope
  const envelope = {
    proof: 'base64_encoded_proof_data',
    executeRequest: {
      destChainId: 137,  // Polygon
      destContractAddress: '0x...', // Target contract
      methodSignature: 'setProof(bytes)',
      args: ['$proof'], // '$proof' gets replaced with proof bytes
    }
  };

  // Submit execution
  const execution = await client.executeRequest(envelope);
  console.log(`Execution submitted: ${execution.jobId}`);

  // Monitor execution
  const result = await client.executeQuery({ id: execution.jobId });
  console.log('Execution result:', result);
}
```

### Blockchain Data Access

```typescript
async function accessBlockchainData() {
  const chainlist = new ChainlistClient();

  // Get latest Ethereum block
  const latestBlock = await chainlist.executeRpc(
    'ethereum',
    'eth_getBlockByNumber',
    ['latest', false]
  );

  console.log('Latest block:', latestBlock);

  // Get contract events
  const logs = await chainlist.executeRpc(
    'ethereum',
    'eth_getLogs',
    [{
      fromBlock: '0x1234567',
      toBlock: 'latest',
      address: '0x...',
      topics: ['0x...']
    }]
  );

  console.log('Contract events:', logs);
}
```

### Error Handling

```typescript
import { PolymerApiError } from '@polymerdao/polymer-api-client';

async function handleErrors() {
  try {
    const client = new PolymerOpenRpcClient('invalid-key');
    await client.proofRequest({ srcChainId: 1, globalLogIndex: 1, srcBlockNumber: 1 });
  } catch (error) {
    if (error instanceof PolymerApiError) {
      console.error('API Error:', error.message);
      console.error('Status Code:', error.statusCode);
      console.error('Response:', error.response);
    } else {
      console.error('Unexpected error:', error);
    }
  }
}
```

## 🧪 Testing

```bash
# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run specific test file
npm test -- chainlist.test.ts
```

### Example Test

```typescript
import { PolymerOpenRpcClient } from '@polymerdao/polymer-api-client';

describe('PolymerOpenRpcClient', () => {
  it('should request a proof', async () => {
    const client = new PolymerOpenRpcClient('test-key');
    
    // Mock the API call
    const mockResponse = { jobId: 123, status: 'pending' };
    jest.spyOn(client, 'proofRequest').mockResolvedValue(mockResponse);

    const result = await client.proofRequest({
      srcChainId: 1,
      globalLogIndex: 12345,
      srcBlockNumber: 19000000
    });

    expect(result.jobId).toBe(123);
    expect(result.status).toBe('pending');
  });
});
```

## 🔧 Development

### Building from Source

```bash
# Clone the monorepo
git clone https://github.com/polymerdao/mcp-polymer.git
cd mcp-polymer/packages/api-client

# Install dependencies
npm install

# Build
npm run build

# Generate client from OpenRPC spec
npm run generate-client
```

### Project Structure

```
src/
├── index.ts              # Main exports
├── client.ts             # PolymerOpenRpcClient implementation
├── verification.ts       # ProofVerifier implementation
├── chainlist.ts          # ChainlistClient implementation
├── types.ts              # TypeScript type definitions
└── generated-client.ts   # Auto-generated from OpenRPC spec
```

### Code Generation

The client includes auto-generated methods from Polymer's OpenRPC specification:

```bash
# Regenerate client methods
npm run generate-client
```

## 📄 Type Definitions

### Core Types

```typescript
interface ProofRequest {
  srcChainId: number;
  globalLogIndex: number;
  srcBlockNumber: number;
}

interface ProofResponse {
  jobId: number;
  status: 'pending' | 'completed' | 'failed';
  proof?: string;
  error?: string;
}

interface ExecuteEnvelope {
  proof: string;
  executeRequest: {
    chainId: number;
    payload: string;
  };
}

interface ChainInfo {
  chainId: number;
  name: string;
  rpc: string[];
  nativeCurrency: {
    name: string;
    symbol: string;
    decimals: number;
  };
}
```

## 🤝 Contributing

See the [main repository README](../../README.md) for contribution guidelines.

### Adding New Features

1. Add feature to appropriate client class
2. Update type definitions in `types.ts`
3. Add tests for new functionality
4. Update this README with examples

## 📄 License

Apache 2.0 License - see [LICENSE](../../LICENSE) for details.