@polymerdao/polymer-api-client
v0.3.0
Published
TypeScript client library for interacting with Polymer's proof API and blockchain verification
Readme
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.
🚀 Installation
npm install @polymerdao/polymer-api-client🎯 Quick Start
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.
import { PolymerOpenRpcClient } from '@polymerdao/polymer-api-client';
const client = new PolymerOpenRpcClient(apiKey, baseUrl);Proof Methods
Request a proof:
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:
const status = await client.proofQueryJob({
id: number // Job ID from proof request
});
// Returns: { jobId: number, status: string, proof?: string, ... }Query with filters:
const results = await client.proofQueryWithFilter({
chainId?: number,
status?: string,
limit?: number,
offset?: number
});Get job statistics:
const stats = await client.proofQueryJobStats();Execution Methods
Submit execution request:
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:
const status = await client.executeQuery({
id: number // Execution job ID
});Info Methods
Get connected chains:
const chains = await client.infoGetConnectedChains();Get client updates:
const updates = await client.infoGetClientUpdates();ProofVerifier
Cryptographic proof verification utilities.
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:
const isValid = await verifier.verifyProof(proofData);
// Returns: booleanParse proof data:
const parsed = verifier.parseProof(proofData);
// Returns: { appHash: string, peptideHeight: number, signature: {...}, ... }Verify ECDSA signature:
const isValidSig = verifier.verifySignature(messageHash, signature, expectedAddress);ChainlistClient
Client for accessing blockchain RPC endpoints and chain information.
import { ChainlistClient } from '@polymerdao/polymer-api-client';
const chainlist = new ChainlistClient();Get chain information:
const chains = await chainlist.getChains();
// Returns: Array of chain objects with RPC endpointsGet RPC endpoints for a chain:
const rpcs = await chainlist.getChainRpcs('ethereum');
// Returns: Array of RPC endpoint objectsExecute RPC call:
const result = await chainlist.executeRpc(
'ethereum', // Chain name
'eth_getBlockByNumber', // RPC method
['latest', false] // Method parameters
);Cache management:
// Get cache statistics
const stats = chainlist.getCacheStats();
// Clear cache
chainlist.clearCache();🔧 Configuration
Environment Setup
// 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
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
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
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
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
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
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run specific test file
npm test -- chainlist.test.tsExample Test
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
# 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-clientProject 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 specCode Generation
The client includes auto-generated methods from Polymer's OpenRPC specification:
# Regenerate client methods
npm run generate-client📄 Type Definitions
Core Types
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 for contribution guidelines.
Adding New Features
- Add feature to appropriate client class
- Update type definitions in
types.ts - Add tests for new functionality
- Update this README with examples
📄 License
Apache 2.0 License - see LICENSE for details.
