dune-api-client
Version:
A minimal TypeScript client for interacting with the Dune API.
86 lines (85 loc) • 3.18 kB
JavaScript
export class Dune {
API_KEY;
BASE_URL = 'https://api.dune.com/api/v1';
constructor(API_KEY) {
if (!API_KEY) {
throw new Error('Dune API key is required');
}
this.API_KEY = API_KEY;
}
/**
* Wrapper to handle HTTP requests with clean typing
* @param endpoint API endpoint
* @returns Dune response
*/
async fetchDune(method, endpoint, body) {
const res = await fetch(endpoint, {
method,
headers: {
'x-dune-api-key': this.API_KEY,
},
body: method === 'POST' ? JSON.stringify(body) : undefined,
});
const json = await res.json();
if (json.error) {
return json;
}
return { data: json };
}
/**
* Execute a query
* @param query_id Dune query id
* @returns Execution id and state
*/
async execute(query_id, options) {
const endpoint = this.BASE_URL + '/query/' + query_id + '/execute';
const body = { query_parameters: options?.params };
return await this.fetchDune('POST', endpoint, body);
}
/**
* Cancel an execution
* @param execution_id Dune execution id
* @returns Success of cancellation
*/
async cancel(execution_id) {
const endpoint = this.BASE_URL + '/execution/' + execution_id + '/cancel';
return await this.fetchDune('POST', endpoint);
}
/**
* Check the status of an execution
* @param execution_id Dune execution id
* @returns Status of execution
*/
async status(execution_id) {
const endpoint = this.BASE_URL + '/execution/' + execution_id + '/status';
return await this.fetchDune('GET', endpoint);
}
/**
* Fetch the results of an execution
* @param exec_or_query_id Dune execution id or query id
* @returns Results of execution, including row data if available
*/
async results(exec_or_query_id, options) {
const isIdNumber = /^\d+$/.test(exec_or_query_id.toString());
let endpoint;
if (isIdNumber) {
// If `exec_or_query_id` is a number, we want the latest query results
// Since this is a GET request, the params need to be in the URL query string
// https://dune.com/docs/api/api-reference/get-results/latest-results/
const searchParams = new URLSearchParams();
if (options?.params) {
for (const [key, value] of Object.entries(options.params)) {
const formattedKey = 'params.' + key;
const formattedValue = value instanceof Date ? value.toISOString() : value.toString();
searchParams.append(formattedKey, formattedValue);
}
}
endpoint = `${this.BASE_URL}/query/${exec_or_query_id}/results?${searchParams}`;
}
else {
// If `exec_or_query_id` is a string, we want the results of a specific execution
endpoint = this.BASE_URL + '/execution/' + exec_or_query_id + '/results';
}
return await this.fetchDune('GET', endpoint);
}
}