UNPKG

@riverfl0w/dune-client

Version:

A TypeScript client for querying the Dune API, designed to simplify the integration of Dune's powerful analytics into your projects.

330 lines (317 loc) 11 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { BaseClient: () => BaseClient, CancelQueryResponse: () => CancelExecutionResponse_default, DuneClient: () => DuneClient, DuneError: () => DuneError, ErrorResponse: () => ErrorResponse_default, ExecuteQueryResponse: () => ExecuteQueryResponse_default, ExecutionClient: () => ExecutionClient, ExecutionResultResponse: () => ExecutionResultsResponse_default, ExecutionStatusResponse: () => ExecutionStatusResponse_default, QueryClient: () => QueryClient, ResultMetadata: () => ResultMetadata_default }); module.exports = __toCommonJS(src_exports); // src/DuneError.ts var DuneError = class extends Error { }; // src/schemas/ErrorResponse.ts var import_zod = require("zod"); var ErrorResponse = import_zod.z.object({ error: import_zod.z.string() }); var ErrorResponse_default = ErrorResponse; // src/clients/BaseClient.ts var MAX_RATE_LIMIT_DELAY = 6e4; var BaseClient = class { constructor(apiKey) { this.apiKey = apiKey; } base = "https://api.dune.com/api"; async call({ path, searchParams, schema, delay = 0, ...options }) { if (searchParams) { const search = searchParams.toString(); if (search.length > 0) { path += `?${search}`; } } const response = await fetch(`${this.base}${path}`, { ...options, headers: { ...options.headers, "x-dune-api-key": this.apiKey } }); const data = await response.json(); const hasError = await ErrorResponse_default.safeParseAsync(data); if (hasError.success) { if (hasError.data.error.match(/too many requests/)) { await new Promise((resolve) => setTimeout(resolve, delay)); if (delay < MAX_RATE_LIMIT_DELAY) { const newDelay = (delay + Math.floor(Math.random() * 1e3)) * 2; return this.call({ path, searchParams, schema, delay: newDelay, ...options }); } } throw new DuneError(hasError.data.error); } return await schema.parseAsync(data); } }; // src/schemas/CancelExecutionResponse.ts var import_zod2 = require("zod"); var CancelExecutionResponse = import_zod2.z.object({ success: import_zod2.z.boolean() }); var CancelExecutionResponse_default = CancelExecutionResponse; // src/schemas/ExecutionResultsResponse.ts var import_zod4 = require("zod"); // src/schemas/ResultMetadata.ts var import_zod3 = require("zod"); var ResultMetadata = import_zod3.z.object({ column_names: import_zod3.z.array(import_zod3.z.string()), result_set_bytes: import_zod3.z.number().int().nonnegative(), total_row_count: import_zod3.z.number().int().nonnegative(), datapoint_count: import_zod3.z.number().int().nonnegative(), pending_time_millis: import_zod3.z.number().int().nonnegative(), execution_time_millis: import_zod3.z.number().int().nonnegative() }); var ResultMetadata_default = ResultMetadata; // src/schemas/ExecutionResultsResponse.ts var ExecutionResultsResponse = import_zod4.z.object({ execution_id: import_zod4.z.string(), query_id: import_zod4.z.number(), is_execution_finished: import_zod4.z.boolean() }).and( import_zod4.z.discriminatedUnion("state", [ import_zod4.z.object({ state: import_zod4.z.literal("QUERY_STATE_FAILED"), submitted_at: import_zod4.z.string().datetime(), expires_at: import_zod4.z.string().datetime(), execution_started_at: import_zod4.z.string().datetime(), execution_ended_at: import_zod4.z.string().datetime(), error: import_zod4.z.object({ type: import_zod4.z.string(), message: import_zod4.z.string(), metadata: import_zod4.z.record(import_zod4.z.unknown()) }) }), import_zod4.z.object({ state: import_zod4.z.literal("QUERY_STATE_COMPLETED"), submitted_at: import_zod4.z.string().datetime(), expires_at: import_zod4.z.string().datetime(), execution_started_at: import_zod4.z.string().datetime(), execution_ended_at: import_zod4.z.string().datetime(), result: import_zod4.z.object({ rows: import_zod4.z.array(import_zod4.z.record(import_zod4.z.unknown())), metadata: ResultMetadata_default }) }), import_zod4.z.object({ state: import_zod4.z.literal("QUERY_STATE_CANCELLED"), submitted_at: import_zod4.z.string().datetime(), expires_at: import_zod4.z.string().datetime(), cancelled_at: import_zod4.z.string().datetime() }), import_zod4.z.object({ state: import_zod4.z.literal("QUERY_STATE_EXPIRED") // TODO: Add more fields }) ]) ); var ExecutionResultsResponse_default = ExecutionResultsResponse; // src/schemas/ExecutionStatusResponse.ts var import_zod5 = require("zod"); var ExecutionStatusResponse = import_zod5.z.object({ execution_id: import_zod5.z.string(), query_id: import_zod5.z.number(), is_execution_finished: import_zod5.z.boolean() }).and( import_zod5.z.discriminatedUnion("state", [ import_zod5.z.object({ state: import_zod5.z.literal("QUERY_STATE_PENDING"), queue_position: import_zod5.z.number().int().nonnegative().optional(), submitted_at: import_zod5.z.string().datetime() }), import_zod5.z.object({ state: import_zod5.z.literal("QUERY_STATE_EXECUTING"), submitted_at: import_zod5.z.string().datetime(), execution_started_at: import_zod5.z.string().datetime() }), import_zod5.z.object({ state: import_zod5.z.literal("QUERY_STATE_FAILED"), submitted_at: import_zod5.z.string().datetime(), expires_at: import_zod5.z.string().datetime(), execution_started_at: import_zod5.z.string().datetime(), execution_ended_at: import_zod5.z.string().datetime() }), import_zod5.z.object({ state: import_zod5.z.literal("QUERY_STATE_COMPLETED"), submitted_at: import_zod5.z.string().datetime(), expires_at: import_zod5.z.string().datetime(), execution_started_at: import_zod5.z.string().datetime(), execution_ended_at: import_zod5.z.string().datetime(), result_metadata: ResultMetadata_default }), import_zod5.z.object({ state: import_zod5.z.literal("QUERY_STATE_CANCELLED"), submitted_at: import_zod5.z.string().datetime(), expires_at: import_zod5.z.string().datetime(), cancelled_at: import_zod5.z.string().datetime() }), import_zod5.z.object({ state: import_zod5.z.literal("QUERY_STATE_EXPIRED") // TODO: Add more fields }) ]) ); var ExecutionStatusResponse_default = ExecutionStatusResponse; // src/clients/ExecutionClient.ts var ExecutionClient = class extends BaseClient { /** * Get the status of an execution. * @see https://dune.com/docs/api/api-reference/get-results/execution-status/ */ status({ execution_id }) { return this.call({ method: "GET", path: `/v1/execution/${execution_id}/status`, schema: ExecutionStatusResponse_default }); } /** * Cancel an execution. * @see https://dune.com/docs/api/api-reference/execute-queries/cancel-execution/ */ cancel({ execution_id }) { return this.call({ method: "POST", path: `/v1/execution/${execution_id}/cancel`, schema: CancelExecutionResponse_default }); } /** * Get the results of an execution. * @see https://dune.com/docs/api/api-reference/get-results/execution-status/ */ results({ execution_id }) { return this.call({ method: "GET", path: `/v1/execution/${execution_id}/results`, schema: ExecutionResultsResponse_default }); } }; // src/schemas/ExecuteQueryResponse.ts var import_zod6 = require("zod"); var ExecuteQueryResponse = import_zod6.z.object({ execution_id: import_zod6.z.string() }).and( import_zod6.z.discriminatedUnion("state", [ import_zod6.z.object({ state: import_zod6.z.literal("QUERY_STATE_PENDING") }), import_zod6.z.object({ state: import_zod6.z.literal("QUERY_STATE_EXECUTING") }) ]) ); var ExecuteQueryResponse_default = ExecuteQueryResponse; // src/clients/QueryClient.ts var QueryClient = class extends BaseClient { /** * Execute am existing Dune query. * @see https://dune.com/docs/api/api-reference/execute-queries/execute-query-id/ */ execute({ query_id, ...options }) { return this.call({ method: "POST", path: `/v1/query/${query_id}/execute`, schema: ExecuteQueryResponse_default, body: JSON.stringify(options) }); } /** * Get the latedst results of a Dune query. This method does NOT execute the query. * @see https://dune.com/docs/api/api-reference/get-results/latest-results/ */ results({ query_id, ignore_max_datapoints_per_request }) { const searchParams = new URLSearchParams(); if (ignore_max_datapoints_per_request) { searchParams.set("ignore_max_datapoints_per_request", "true"); } return this.call({ method: "GET", path: `/v1/query/${query_id}/results`, searchParams, schema: ExecutionResultsResponse_default }); } }; // src/DuneClient.ts var DuneClient = class { execution; query; constructor(apiKey) { this.execution = new ExecutionClient(apiKey); this.query = new QueryClient(apiKey); } /** * Convenience method to refresh the results of a query. * It will wait for the query to finish and return the results. * @param param0 * @returns */ async refresh({ cooldown = 500, ...args }) { const { execution_id } = await this.query.execute(args); for (; ; ) { const { state } = await this.execution.status({ execution_id }); if (state === "QUERY_STATE_PENDING" || state === "QUERY_STATE_EXECUTING") { await new Promise((resolve) => setTimeout(resolve, cooldown)); continue; } break; } return await this.execution.results({ execution_id }); } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BaseClient, CancelQueryResponse, DuneClient, DuneError, ErrorResponse, ExecuteQueryResponse, ExecutionClient, ExecutionResultResponse, ExecutionStatusResponse, QueryClient, ResultMetadata }); //# sourceMappingURL=index.cjs.map