coingecko.ts
Overview
The `coingecko.ts` file implements a proxy client for the CoinGecko API, designed to forward incoming HTTP requests from an Express server to the CoinGecko Pro API. It manages API authentication using an API key, caches responses in-memory to reduce redundant external API calls, and gracefully handles errors. This proxy functionality enables clients to access CoinGecko market data securely and efficiently through an internal unified API endpoint, while abstracting away direct interaction with CoinGecko's external API.
Classes and Types
type RequestCache
type RequestCache = Partial<Record<string, AxiosResponse>>
Description:
Defines the structure of the in-memory cache used to store API responses, keyed by request URL strings. Each cache entry holds anAxiosResponseobject or is undefined.Usage:
Used internally by theCoinGeckoclass to cache responses.
class CoinGecko
Description
Encapsulates the logic for proxying requests to the CoinGecko Pro API. It maintains an Axios HTTP client instance configured with the required API key and an in-memory cache of recent responses keyed by request URLs. The class exposes a single asynchronous method `handler` intended to be used as an Express route handler.
Properties
Property | Type | Description |
|---|---|---|
`axiosInstance` | `Axios` | Axios HTTP client configured with CoinGecko API key. |
`requestCache` | `RequestCache` | In-memory cache mapping request URLs to Axios responses. |
Constructor
constructor()
Initializes an empty cache object.
Creates an Axios instance with the
x-cg-pro-api-keyheader set from the environment variableCOINGECKO_API_KEY.Throws an error at module load time if the API key is not set.
Methods
async handler(req: Request, res: Response): Promise<void>
Description:
Handles incoming Express HTTP requests routed to the CoinGecko proxy endpoint. It extracts the CoinGecko API sub-path from the request URL, checks the cache for a stored response, and either serves the cached data or forwards the request to CoinGecko's API. Response headers and status codes are preserved. Errors are caught and forwarded appropriately. Cached responses are invalidated after a TTL of 60 seconds.Parameters:
req: Request— Express request object.res: Response— Express response object.
Returns:
Promise<void>Behavior:
Extracts the relative URL path by stripping the prefix
/api/v1/markets/from the incoming request URL to form the CoinGecko API endpoint.Checks if the request URL is present in
requestCache.If yes, serves the cached response with the original headers and an
X-Cache: HITheader.
If no cached response exists, sets
X-Cache: MISSheader and forwards the request to CoinGecko using the Axios instance.On successful response, caches the response object and forwards headers, status, and data to the client.
On error, catches Axios errors and responds with the external API's status and message or a generic 500 error.
Schedules cache invalidation for the request URL after 60 seconds using
setInterval.
Usage Example:
import express from 'express'
import { CoinGecko } from './coingecko'
const app = express()
const coingecko = new CoinGecko()
// Route proxying CoinGecko API market data requests
app.get('/api/v1/markets/*', coingecko.handler.bind(coingecko))
app.listen(3000, () => console.log('Server running on port 3000'))
Important Implementation Details
API Key Handling:
The CoinGecko API key is loaded from the environment variableCOINGECKO_API_KEY. The module throws an error immediately if this is not set, ensuring no unauthorized requests are made.Request Caching:
Uses a simple in-memory object (requestCache) to store full Axios responses keyed by the original request URL. This includes response headers and status codes, enabling transparent replay of cached responses.Cache TTL and Invalidation:
Cache entries live for 60,000 milliseconds (60 seconds). Cache invalidation is scheduled usingsetIntervalinside thefinallyblock of the handler.
Note: Usage ofsetIntervalinside thefinallyblock will create repeated intervals per request and may be a bug or inefficiency; a better approach would besetTimeoutor centralized cache cleanup.Error Handling:
Differentiates between Axios errors and generic errors. For Axios errors, it forwards the external API's status and response data. Other errors return HTTP 500 with appropriate messages.URL Path Extraction:
The handler removes the/api/v1/markets/prefix to dynamically build the CoinGecko API request URL, allowing flexible routing of all sub-paths under this endpoint.Headers Forwarding:
All response headers from CoinGecko are forwarded to the client to maintain expected API behavior and metadata.
Interaction with Other System Components
Express Application (
app.ts):
TheCoinGeckoclass is instantiated and itshandlermethod is bound as a route handler for paths starting with/api/v1/markets/*. This setup centralizes all CoinGecko API requests through this proxy.Environment Configuration:
Relies on environment configuration for the CoinGecko API key, consistent with the system's secure API key management practices.Cache Coordination:
Works in concert with other proxy classes likeZerionandZrxthat follow similar caching and proxy patterns, collectively providing a unified external API proxy service.Client Applications:
The proxy enables front-end or client services to fetch market data without managing API keys or dealing with CoinGecko API rate limits and CORS restrictions.
Visual Diagram
classDiagram
class CoinGecko {
-axiosInstance: Axios
-requestCache: RequestCache
+constructor()
+handler(req: Request, res: Response): Promise<void>
}
Diagram Explanation:
TheCoinGeckoclass has two private properties:axiosInstancefor HTTP requests with authentication, andrequestCachefor caching responses. It exposes a single public methodhandlerto process incoming HTTP requests.
Summary
`coingecko.ts` provides a robust and efficient proxy mechanism for CoinGecko’s Pro API within a larger Proxy API Service. It abstracts API key management and network requests, implements caching to improve performance and reduce external calls, and exposes a consistent interface for clients. The file's design aligns with the system's goals of modularity, security, and scalability in handling multiple third-party blockchain data providers.
Appendix: Key Code Snippet from handler Method
async handler(req: Request, res: Response): Promise<void> {
const url = req.url.substring('/api/v1/markets/'.length)
const cachedResponse = this.requestCache[req.url]
if (cachedResponse) {
Object.entries(cachedResponse.headers).forEach(([k, v]) => res.set(k, v))
res.set('X-Cache', 'HIT').status(cachedResponse.status).send(cachedResponse.data)
return
}
res.set('X-Cache', 'MISS')
try {
const response = await this.axiosInstance.get(`${BASE_URL}${url}`)
this.requestCache[req.url] = response
Object.entries(response.headers).forEach(([k, v]) => res.set(k, v))
res.status(response.status).send(response.data)
} catch (err) {
if (isAxiosError(err)) {
res.status(err.response?.status ?? 500).send(err.response?.data || 'Internal Server Error')
} else if (err instanceof Error) {
res.status(500).send(err.message || 'Internal Server Error')
} else {
res.status(500).send('Internal Server Error')
}
} finally {
setInterval(() => delete this.requestCache[req.url], CACHE_TTL_MS)
}
}
Note: The use of
setIntervalinsidefinallyis unconventional and likely should besetTimeoutto schedule cache expiration once per request rather than repeatedly.
This concludes the comprehensive documentation for the `coingecko.ts` file.