Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: cargo clippy --workspace --lib --tests -- -D warnings

- name: cargo test
run: cargo test -p sdk-core --lib
run: cargo test -p quicknode-sdk --lib

python:
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ jobs:
- uses: dtolnay/rust-toolchain@stable

- name: Package crate
run: cargo package -p sdk-core --allow-dirty
run: cargo package -p quicknode-sdk --allow-dirty

- uses: actions/upload-artifact@v4
with:
name: rust-crate
path: target/package/sdk-core-*.crate
path: target/package/quicknode-sdk-*.crate

build-python:
strategy:
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
### Rust
```bash
cargo check # Type check all crates
cargo build -p sdk-core # Build core crate
cargo test -p sdk-core --lib # Run tests (excludes examples)
cargo run --example admin -p sdk-core # Run example (requires QN_API_KEY env var)
cargo build -p quicknode-sdk # Build core crate
cargo test -p quicknode-sdk --lib # Run tests (excludes examples)
cargo run --example admin -p quicknode-sdk # Run example (requires QN_API_KEY env var)
```

### Python
Expand Down
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ macos-build-and-publish version:
echo "Uploaded macOS arm64 artifacts to v{{version}}"

test:
cargo test -p sdk-core --lib
cargo test -p quicknode-sdk --lib

lint:
cargo clippy --workspace --lib --tests -- -D warnings
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 QuickNode, Inc.
Copyright (c) 2026 Quicknode, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
36 changes: 31 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Construct the SDK once, then reach into the four sub-clients (`admin`, `streams`

```rust
// Rust
use sdk_core::{QuickNodeSdk, SdkFullConfig};
use quicknode_sdk::{QuickNodeSdk, SdkFullConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -3388,7 +3388,7 @@ Use the commands in the `Justfile` for the setup and build commands.
```bash
# Core library
cargo check
cargo test -p sdk-core
cargo test -p quicknode-sdk

# Python (from project root)
just python-setup-env
Expand All @@ -3401,7 +3401,7 @@ just node-build
just ruby-build

# Rust
cargo build -p sdk-core
cargo build -p quicknode-sdk
```

### Testing
Expand All @@ -3410,13 +3410,13 @@ cargo build -p sdk-core
just test
```

Runs the Rust unit tests for `sdk-core` using [wiremock](https://github.com/LukeMathWalker/wiremock-rs) to mock HTTP responses — no API key required.
Runs the Rust unit tests for `quicknode-sdk` using [wiremock](https://github.com/LukeMathWalker/wiremock-rs) to mock HTTP responses — no API key required.

### Examples

```bash
# Rust
QN_SDK__API_KEY=replaceme cargo run --example admin -p sdk-core --features rust
QN_SDK__API_KEY=replaceme cargo run --example admin -p quicknode-sdk --features rust

# Python
QN_SDK__API_KEY=replaceme uv run python/examples/admin.py
Expand All @@ -3435,6 +3435,30 @@ QN_SDK__API_KEY=replaceme ruby ruby/examples/streams.rb

### Releasing

The Rust crate (`quicknode-sdk` on crates.io) versions independently from the Python, Node, and Ruby bindings. Its version lives in `crates/core/Cargo.toml`; the bindings share the workspace version in the root `Cargo.toml`.

#### Rust crate only (crates.io)

```bash
# 1. Bump the version in crates/core/Cargo.toml (e.g. 0.1.0 → 0.1.0-alpha.5)
# Pre-release identifiers use SemVer 2.0 syntax: MAJOR.MINOR.PATCH-<id>.<N>
# Examples: 0.1.0-alpha.4, 0.2.0-beta.1, 0.2.0-rc.1

# 2. Commit and push
git commit -am "chore: release quicknode-sdk 0.1.0-alpha.5"
git push

# 3. Validate the tarball (no upload)
cargo publish -p quicknode-sdk --dry-run

# 4. Publish (requires `cargo login` with a crates.io token)
cargo publish -p quicknode-sdk
```

The first publish claims the `quicknode-sdk` name permanently. Published versions are immutable — you cannot overwrite or delete them (only `cargo yank`, which hides but doesn't remove).

#### All bindings together (Python / Node / Ruby)

macOS (Apple Silicon) artifacts are built locally rather than on GitHub Actions to avoid the ~10× runner cost. Linux artifacts are still built by CI on tag push.

```bash
Expand All @@ -3452,6 +3476,8 @@ just macos-build-and-publish 0.2.0

Step 4 requires the [`gh` CLI](https://cli.github.com/) authenticated to the repo. Intel macOS (`x86_64-apple-darwin`) is not shipped — users on Intel Macs install from source.

`just release` does **not** bump the Rust crate version (that's managed separately in `crates/core/Cargo.toml`). If you want the Rust crate to move in lockstep with a binding release, bump it manually in the same commit.

## License

MIT
5 changes: 3 additions & 2 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[package]
name = "sdk-core"
version.workspace = true
name = "quicknode-sdk"
version = "0.1.0-alpha.4"
edition.workspace = true
license.workspace = true
description = "Core library for quicknode sdk"
repository = "https://github.com/quiknode-labs/sdk"
readme = "../../README.md"
keywords = ["quicknode", "blockchain", "web3", "sdk"]
categories = ["api-bindings", "web-programming"]

Expand Down
21 changes: 21 additions & 0 deletions crates/core/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Quicknode, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2 changes: 1 addition & 1 deletion crates/core/examples/admin.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use sdk_core::{admin::GetEndpointsRequest, QuickNodeSdk, SdkFullConfig};
use quicknode_sdk::{admin::GetEndpointsRequest, QuickNodeSdk, SdkFullConfig};

#[tokio::main]
#[allow(clippy::unwrap_used, clippy::expect_used)]
Expand Down
9 changes: 7 additions & 2 deletions crates/core/examples/admin_e2e.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use sdk_core::{
use quicknode_sdk::{
admin::{
BulkAddTagRequest, BulkRemoveTagRequest, BulkUpdateEndpointStatusRequest,
CreateDomainMaskRequest, CreateEndpointRequest, CreateIpRequest, CreateJwtRequest,
Expand Down Expand Up @@ -827,7 +827,12 @@ async fn main() {
.get_endpoints(&GetEndpointsRequest::default())
.await
{
Err(e) if matches!(e.http_kind(), Some(sdk_core::errors::HttpKind::Timeout)) => {
Err(e)
if matches!(
e.http_kind(),
Some(quicknode_sdk::errors::HttpKind::Timeout)
) =>
{
println!("timed out as expected");
}
other => eprintln!("expected timeout, got {other:?}"),
Expand Down
2 changes: 1 addition & 1 deletion crates/core/examples/kvstore_e2e.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashMap;

use sdk_core::{
use quicknode_sdk::{
kvstore::{
AddListItemParams, BulkSetsParams, CreateListParams, CreateSetParams, UpdateListParams,
},
Expand Down
2 changes: 1 addition & 1 deletion crates/core/examples/streams.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use sdk_core::{
use quicknode_sdk::{
streams::{
CreateStreamParams, DestinationAttributes, StreamDataset, StreamMetadataLocation,
StreamRegion, StreamStatus, WebhookAttributes,
Expand Down
2 changes: 1 addition & 1 deletion crates/core/examples/streams_e2e.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{thread, time::Duration};

use sdk_core::{
use quicknode_sdk::{
streams::{
CreateStreamParams, DestinationAttributes, ListStreamsParams, StreamDataset,
StreamMetadataLocation, StreamRegion, StreamStatus, TestFilterParams, UpdateStreamParams,
Expand Down
2 changes: 1 addition & 1 deletion crates/core/examples/webhooks_e2e.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{thread, time::Duration};

use sdk_core::{
use quicknode_sdk::{
webhooks::{
ActivateWebhookParams, CreateWebhookFromTemplateParams, EvmWalletFilterTemplate,
GetWebhooksParams, TemplateArgs, UpdateWebhookParams, WebhookDestinationAttributes,
Expand Down
3 changes: 2 additions & 1 deletion crates/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version.workspace = true
edition.workspace = true
license.workspace = true
description = "Node.js bindings for quicknode sdk"
publish = false

[lints]
workspace = true
Expand All @@ -12,7 +13,7 @@ workspace = true
crate-type = ["cdylib"]

[dependencies]
sdk-core = { path = "../core", features = ["node"] }
quicknode-sdk = { path = "../core", features = ["node"] }
tokio = { version = "1", features = ["rt-multi-thread"] }
napi = { version = "2", features = ["async", "tokio_rt", "serde-json"] }
napi-derive = "2"
Expand Down
2 changes: 1 addition & 1 deletion crates/node/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use napi::{bindgen_prelude::Error, Status};
use sdk_core::errors::{HttpKind, SdkError};
use quicknode_sdk::errors::{HttpKind, SdkError};

// napi-rs can only throw plain napi::Error with a status + message. To give
// callers a typed class hierarchy in JS, we encode the variant as a structured
Expand Down
2 changes: 1 addition & 1 deletion crates/node/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use napi::bindgen_prelude::*;
use napi_derive::napi;
use sdk_core as core;
use quicknode_sdk as core;

mod errors;
mod streams_destination;
Expand Down
2 changes: 1 addition & 1 deletion crates/node/src/streams_destination.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use napi::bindgen_prelude::*;
use napi_derive::napi;
use sdk_core as core;
use quicknode_sdk as core;

// napi(object) cannot represent the flattened DestinationAttributes enum on
// core's stream types, so these wrappers carry it as serde_json::Value.
Expand Down
1 change: 1 addition & 0 deletions crates/python-stubs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name = "sdk-python-stubs"
version.workspace = true
edition.workspace = true
license.workspace = true
publish = false

[lints]
workspace = true
Expand Down
5 changes: 3 additions & 2 deletions crates/python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version.workspace = true
edition.workspace = true
license.workspace = true
description = "Python bindings for Quicknode SDK"
publish = false

[lints]
workspace = true
Expand All @@ -13,10 +14,10 @@ name = "_core"
crate-type = ["cdylib", "rlib"]

[features]
extension-module = ["pyo3/extension-module", "sdk-core/extension-module"]
extension-module = ["pyo3/extension-module", "quicknode-sdk/extension-module"]

[dependencies]
sdk-core = { path = "../core", features = ["python"] }
quicknode-sdk = { path = "../core", features = ["python"] }
pyo3 = { workspace = true }
pyo3-async-runtimes = { workspace = true, features = ["tokio-runtime"] }
pyo3-stub-gen = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/python/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use pyo3::{
exceptions::{PyException, PyValueError},
prelude::*,
};
use sdk_core::errors::{HttpKind, SdkError};
use quicknode_sdk::errors::{HttpKind, SdkError};

// Invalid-argument parse errors for user-supplied strings (enum values, etc.)
// stay as PyValueError — they're argument errors, not SDK errors.
Expand Down
2 changes: 1 addition & 1 deletion crates/python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use pyo3_stub_gen::{
define_stub_info_gatherer,
derive::{gen_stub_pyclass, gen_stub_pymethods},
};
use sdk_core as core;
use quicknode_sdk as core;

mod errors;
mod streams_destination;
Expand Down
2 changes: 1 addition & 1 deletion crates/python/src/streams_destination.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use pyo3::prelude::*;
use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods};
use sdk_core::streams::{
use quicknode_sdk::streams::{
AddressBookConfig, AzureAttributes, ClickhouseAttributes, DestinationAttributes,
KafkaAttributes, ListStreamsResponse, MongoAttributes, MysqlAttributes, PageInfo,
PostgresAttributes, RedisAttributes, S3Attributes, SnowflakeAttributes, Stream,
Expand Down
3 changes: 2 additions & 1 deletion crates/ruby/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version.workspace = true
edition.workspace = true
license.workspace = true
description = "Ruby bindings for quicknode sdk"
publish = false

[lints]
workspace = true
Expand All @@ -13,7 +14,7 @@ name = "quicknode_sdk"
crate-type = ["cdylib"]

[dependencies]
sdk-core = { path = "../core", features = ["ruby"] }
quicknode-sdk = { path = "../core", features = ["ruby"] }
magnus = { workspace = true }
tokio = { version = "1", features = ["rt-multi-thread"] }
serde_json = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion crates/ruby/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use magnus::{
exception::ExceptionClass, prelude::*, value::Opaque, Object, RModule, RObject, Ruby, Value,
};
use sdk_core::errors::{HttpKind, SdkError};
use quicknode_sdk::errors::{HttpKind, SdkError};
use std::sync::OnceLock;

// Class handles are captured at #[magnus::init] time. OnceLock<Opaque<T>> is
Expand Down
2 changes: 1 addition & 1 deletion crates/ruby/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use magnus::{
function, method, prelude::*, r_hash::ForEach, symbol::Symbol, Error, RArray, RHash, Ruby,
};
use sdk_core as core;
use quicknode_sdk as core;

mod errors;

Expand Down
Loading