Skip to content

feat(sql): add SQL client to SDK#46

Merged
johnpmitsch merged 1 commit into
mainfrom
dx-5876-add-sql-client-to-sdk
Jun 25, 2026
Merged

feat(sql): add SQL client to SDK#46
johnpmitsch merged 1 commit into
mainfrom
dx-5876-add-sql-client-to-sdk

Conversation

@johnpmitsch

Copy link
Copy Markdown
Collaborator

Adds a new sql sub-client to the SDK across all four languages (Rust core, Python, Node, Ruby). It wraps the public Quicknode SQL REST API with two methods:

  • query — run a SQL query against a cluster; returns typed rows plus query stats (rows, credits, elapsed).
  • get_schema / getSchema — fetch a cluster's table schema (chain, tables, columns, row counts).

Query result rows come back as native dynamic objects keyed by column name (dict in Python, plain object in Node, IndifferentHash in Ruby, an indexable row in Rust).

Wired through every layer: core config (ResolvedSqlConfig), the four binding crates, the five READMEs, and the type stubs (.pyi, sdk.d.ts, index.d.ts, .rbs).

Closes DX-5876

Usage

Rust

use quicknode_sdk::{sql::QueryParams, QuicknodeSdk, SdkFullConfig};

let qn = QuicknodeSdk::new(&SdkFullConfig::from_env()?)?;

let resp = qn.sql.query(&QueryParams {
    query: "SELECT action_type, user FROM hyperliquid_system_actions \
            ORDER BY block_time DESC LIMIT 3".to_string(),
    cluster_id: "hyperliquid-core-mainnet".to_string(),
}).await?;

println!("{} rows, {} credits", resp.rows, resp.credits);
if let Some(row) = resp.data.first() {
    println!("action_type: {}", row["action_type"]);
}

let schema = qn.sql.get_schema("hyperliquid-core-mainnet").await?;
println!("{} ({} tables)", schema.chain, schema.tables.len());

Python

from quicknode_sdk import QuicknodeSdk

qn = QuicknodeSdk.from_env()

resp = await qn.sql.query(
    query=(
        "SELECT action_type, user FROM hyperliquid_system_actions "
        "ORDER BY block_time DESC LIMIT 3"
    ),
    cluster_id="hyperliquid-core-mainnet",
)
print(f"{resp.rows} rows, {resp.credits} credits")
if resp.data:
    # rows are native dicts keyed by column name
    print(resp.data[0]["action_type"])

schema = await qn.sql.get_schema("hyperliquid-core-mainnet")
print(f"{schema.chain} ({len(schema.tables)} tables)")

Node.js

import { QuicknodeSdk } from "@quicknode/sdk";

const qn = QuicknodeSdk.fromEnv();

const resp = await qn.sql.query(
  "SELECT action_type, user FROM hyperliquid_system_actions " +
    "ORDER BY block_time DESC LIMIT 3",
  "hyperliquid-core-mainnet",
);
console.log(`${resp.rows} rows, ${resp.credits} credits`);
if (resp.data.length > 0) {
  // rows are plain objects keyed by column name
  console.log(resp.data[0].action_type);
}

const schema = await qn.sql.getSchema("hyperliquid-core-mainnet");
console.log(`${schema.chain} (${schema.tables.length} tables)`);

Ruby

require "quicknode_sdk"

qn = QuicknodeSdk::SDK.from_env

resp = qn.sql.query(
  query: "SELECT action_type, user FROM hyperliquid_system_actions " \
         "ORDER BY block_time DESC LIMIT 3",
  cluster_id: "hyperliquid-core-mainnet"
)
puts "#{resp[:rows]} rows, #{resp[:credits]} credits"
# rows are IndifferentHash, access with [] or dig
puts resp[:data].first[:action_type] if resp[:data].first

schema = qn.sql.get_schema(cluster_id: "hyperliquid-core-mainnet")
puts "#{schema[:chain]} (#{schema[:tables].length} tables)"

Adds a sql sub-client exposing query and get_schema against the public
Quicknode SQL REST API. Query rows are returned as native dynamic
objects keyed by column name in each language.

Wired through core config (ResolvedSqlConfig), the four binding crates,
the five READMEs, and the type stubs.
@johnpmitsch johnpmitsch merged commit 3903797 into main Jun 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants