A Rust client for the Dune Analytics API. Execute queries, wait for completion, and deserialize results into your own types.
cargo add dunersYou’ll need the tokio runtime (e.g. tokio with rt-multi-thread and macros).
-
Get an API key from Dune → Settings → API.
-
Set it (or put it in a
.envfile asDUNE_API_KEY=...):export DUNE_API_KEY="your-api-key"
-
Run a query using the
refreshhelper (execute → wait until done → return results):
use duners::{DuneClient, DuneRequestError};
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct Row {
symbol: String,
max_price: f64,
}
#[tokio::main]
async fn main() -> Result<(), DuneRequestError> {
let client = DuneClient::from_env();
let result = client.refresh::<Row>(971694, None, None).await?;
println!("{:?}", result.get_rows());
Ok(())
}The query ID (e.g. 971694) is the number at the end of a Dune query URL: https://dune.com/queries/971694.
DuneClient::new(api_key)— pass the API key directly.DuneClient::from_env()— readsDUNE_API_KEYfrom the environment. If a.envfile exists in the current directory, it is loaded first.
For queries that take parameters, pass a list of Parameter as the second argument to refresh (or execute_query):
use duners::{DuneClient, Parameter};
let params = vec![
Parameter::text("WalletAddress", "0x1234..."),
Parameter::number("MinAmount", "100"),
Parameter::list("Token", "ETH"),
];
let result = client.refresh::<MyRow>(QUERY_ID, Some(params), None).await?;Parameter names must match the names defined in the query on Dune.
Define a struct whose fields match the query’s columns and derive Deserialize. You can use your own types; the API often returns numbers and dates as strings, so use the helpers in parse_utils when needed:
use chrono::{DateTime, Utc};
use duners::parse_utils::{datetime_from_str, f64_from_str};
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct ResultStruct {
text_field: String,
#[serde(deserialize_with = "f64_from_str")]
number_field: f64,
#[serde(deserialize_with = "datetime_from_str")]
date_field: DateTime<Utc>,
list_field: String,
}f64_from_str— for numeric columns that come as strings.datetime_from_str— for date/timestamp columns that come as strings.
For more control (e.g. custom polling or cancellation):
execute_query(query_id, params)— start execution; returns anexecution_id.get_status(execution_id)— check status (Complete,Executing,Pending,Cancelled,Failed).get_results(execution_id)— fetch result rows (only valid when status isComplete).cancel_execution(execution_id)— cancel a running execution.
See the API docs for details and types.
All fallible methods return Result<_, DuneRequestError>. Use ? to propagate. DuneRequestError implements std::error::Error and Display; variants are:
DuneRequestError::Dune(msg)— API returned an error (e.g. invalid API key, query not found).DuneRequestError::Request(msg)— network/HTTP error (e.g. connection failed, timeout).
Full API reference: docs.rs/duners
MIT OR Apache-2.0