From dd22992ae1f5c83ab2b32568b31337cc78b43f1d Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 09:40:43 -0400 Subject: [PATCH 01/28] chore: switch reqwest to rustls for cross-compilation support --- crates/core/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 0ebb03f..e5e69b0 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -19,7 +19,7 @@ extension-module = ["pyo3/extension-module"] thiserror = "1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -reqwest = { version = "0.13.2", features = ["json", "query"] } +reqwest = { version = "0.13.2", default-features = false, features = ["json", "query", "rustls", "http2"] } pyo3 = { workspace = true, optional = true, features = ["experimental-async"] } pyo3-async-runtimes = { workspace = true, optional = true, features = ["tokio-runtime"] } napi = { workspace = true, optional = true, features = ["async", "tokio_rt"] } From a9c5007d4535d9573f878362f6c21d6f06b4046d Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 09:51:28 -0400 Subject: [PATCH 02/28] chore: rename napi binary to quicknode-sdk, package to @quicknode/sdk-next --- npm/package.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/npm/package.json b/npm/package.json index faebd25..3030920 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,5 +1,5 @@ { - "name": "@quicknode/sdk", + "name": "@quicknode/sdk-next", "version": "0.1.0", "description": "Quicknode SDK", "main": "sdk.js", @@ -12,13 +12,12 @@ "*.node" ], "napi": { - "binaryName": "my-sdk", + "binaryName": "quicknode-sdk", "targets": [ - "x86_64-apple-darwin", - "aarch64-apple-darwin", "x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu", - "x86_64-pc-windows-msvc" + "x86_64-unknown-linux-musl", + "aarch64-unknown-linux-musl" ] }, "scripts": { From b7cdbdad4102464ddeb32c9e9d92b1e0cb770321 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 09:53:14 -0400 Subject: [PATCH 03/28] chore: add package metadata to sdk-core for crates.io compatibility --- crates/core/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index e5e69b0..a16ed81 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -4,6 +4,9 @@ version.workspace = true edition.workspace = true license.workspace = true description = "Core library for quicknode sdk" +repository = "https://github.com/quiknode-labs/sdk" +keywords = ["quicknode", "blockchain", "web3", "sdk"] +categories = ["api-bindings", "web-programming"] [lints] workspace = true From 649050bc07eb43eec5e47a3327936b452b5a7cf1 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 09:53:57 -0400 Subject: [PATCH 04/28] chore: add Ruby gemspec for release packaging --- ruby/quicknode_sdk.gemspec | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 ruby/quicknode_sdk.gemspec diff --git a/ruby/quicknode_sdk.gemspec b/ruby/quicknode_sdk.gemspec new file mode 100644 index 0000000..526d0a5 --- /dev/null +++ b/ruby/quicknode_sdk.gemspec @@ -0,0 +1,9 @@ +Gem::Specification.new do |s| + s.name = "quicknode_sdk" + s.version = "0.1.0" + s.summary = "QuickNode SDK for Ruby" + s.authors = ["QuickNode"] + s.license = "MIT" + s.files = ["lib/quicknode_sdk.rb"] + s.required_ruby_version = ">= 3.0" +end From 268b1f382acad38ae633ac4d588c2824fbcd9025 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 09:54:39 -0400 Subject: [PATCH 05/28] ci: add release workflow with Rust build job --- .github/workflows/release.yml | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..267c35d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: Release + +on: + pull_request: + push: + tags: + - 'v*' + +jobs: + build-rust: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + + - name: Package crate + run: cargo package -p sdk-core --allow-dirty + + - uses: actions/upload-artifact@v4 + with: + name: rust-crate + path: target/package/sdk-core-*.crate + + release: + needs: [build-rust] + runs-on: ubuntu-latest + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + path: artifacts/ + merge-multiple: true + + - uses: softprops/action-gh-release@v2 + with: + files: artifacts/**/* + generate_release_notes: true + draft: false + prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-beta') }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 71b81c42a420dfe391cbfd59304533df29b58fd6 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:04:47 -0400 Subject: [PATCH 06/28] ci: add Python wheel build job (4 Linux targets) --- .github/workflows/release.yml | 54 ++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 267c35d..96e246b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,8 +22,60 @@ jobs: name: rust-crate path: target/package/sdk-core-*.crate + build-python: + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-unknown-linux-gnu + cross: false + - target: aarch64-unknown-linux-gnu + cross: true + - target: x86_64-unknown-linux-musl + cross: true + - target: aarch64-unknown-linux-musl + cross: true + # Placeholder for future macOS support: + # - target: aarch64-apple-darwin + # runner: macos-14 + # cross: false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install maturin + run: pip install "maturin>=1.5,<2.0" + + - name: Install Zig + if: matrix.cross + uses: goto-bus-stop/setup-zig@v2 + + - name: Build wheel + run: | + maturin build --release \ + --target ${{ matrix.target }} \ + ${{ matrix.cross && '--zig' || '' }} \ + --out dist/ + + - name: Build sdist + if: matrix.target == 'x86_64-unknown-linux-gnu' + run: maturin sdist --out dist/ + + - uses: actions/upload-artifact@v4 + with: + name: python-${{ matrix.target }} + path: dist/* + release: - needs: [build-rust] + needs: [build-rust, build-python] runs-on: ubuntu-latest if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') permissions: From 0f5063954c46ac07fc6a14899b8f8df4cd02e7b0 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:06:57 -0400 Subject: [PATCH 07/28] Small changes --- npm/index.d.ts | 2 +- npm/package-lock.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/npm/index.d.ts b/npm/index.d.ts index ba1dd4e..f1e5ba1 100644 --- a/npm/index.d.ts +++ b/npm/index.d.ts @@ -953,7 +953,7 @@ export interface Webhook { status: string network: string createdAt: string - updatedAt: string + updatedAt?: string templateId?: string notificationEmail?: string /** Destination-specific configuration as a JSON string. */ diff --git a/npm/package-lock.json b/npm/package-lock.json index 5c8dbf0..acac2f0 100644 --- a/npm/package-lock.json +++ b/npm/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@quicknode/sdk", + "name": "@quicknode/sdk-next", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@quicknode/sdk", + "name": "@quicknode/sdk-next", "version": "0.1.0", "license": "MIT", "devDependencies": { From bf1105f1c24f7895ec33b5ce5240df895f0eb6d1 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:09:16 -0400 Subject: [PATCH 08/28] ci: fix maturin cross-compilation by specifying python interpreter --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96e246b..4066307 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -63,6 +63,7 @@ jobs: maturin build --release \ --target ${{ matrix.target }} \ ${{ matrix.cross && '--zig' || '' }} \ + -i python3.11 \ --out dist/ - name: Build sdist From b571f36f5b0c06d57ce943af2a4b030e1c9e1cd8 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:18:35 -0400 Subject: [PATCH 09/28] ci: build Python wheels for 3.10-3.13 across all targets (16 builds) --- .github/workflows/release.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4066307..938c43e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,6 +26,14 @@ jobs: strategy: fail-fast: false matrix: + python-version: ['3.10', '3.11', '3.12', '3.13'] + target: + - x86_64-unknown-linux-gnu + - aarch64-unknown-linux-gnu + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-musl + # Placeholder for future macOS support: + # - aarch64-apple-darwin include: - target: x86_64-unknown-linux-gnu cross: false @@ -35,10 +43,6 @@ jobs: cross: true - target: aarch64-unknown-linux-musl cross: true - # Placeholder for future macOS support: - # - target: aarch64-apple-darwin - # runner: macos-14 - # cross: false runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -49,7 +53,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: ${{ matrix.python-version }} - name: Install maturin run: pip install "maturin>=1.5,<2.0" @@ -63,16 +67,16 @@ jobs: maturin build --release \ --target ${{ matrix.target }} \ ${{ matrix.cross && '--zig' || '' }} \ - -i python3.11 \ + -i python${{ matrix.python-version }} \ --out dist/ - name: Build sdist - if: matrix.target == 'x86_64-unknown-linux-gnu' + if: matrix.target == 'x86_64-unknown-linux-gnu' && matrix.python-version == '3.11' run: maturin sdist --out dist/ - uses: actions/upload-artifact@v4 with: - name: python-${{ matrix.target }} + name: python-${{ matrix.target }}-py${{ matrix.python-version }} path: dist/* release: From 977dced7b795d99c4749f68285737dbf3876c319 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:19:49 -0400 Subject: [PATCH 10/28] ci: update Python version matrix to 3.11-3.14 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 938c43e..5b865f4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] + python-version: ['3.11', '3.12', '3.13', '3.14'] target: - x86_64-unknown-linux-gnu - aarch64-unknown-linux-gnu From 6b0a1b45bb65c6b6e229578681f7d40e805cd173 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:32:41 -0400 Subject: [PATCH 11/28] ci: add Node.js build job (4 Linux targets); add ESM support and browser shim to npm package --- .github/workflows/release.yml | 59 ++++++++++++++++++++++++++++++++++- crates/node/Cargo.toml | 2 +- npm/browser.js | 9 ++++++ npm/package.json | 10 ++++++ npm/sdk.mjs | 26 +++++++++++++++ 5 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 npm/browser.js create mode 100644 npm/sdk.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b865f4..5b4a147 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,8 +79,65 @@ jobs: name: python-${{ matrix.target }}-py${{ matrix.python-version }} path: dist/* + build-node: + strategy: + fail-fast: false + matrix: + target: + - x86_64-unknown-linux-gnu + - aarch64-unknown-linux-gnu + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-musl + # Placeholder for future macOS support: + # - aarch64-apple-darwin + include: + - target: x86_64-unknown-linux-gnu + cross: false + - target: aarch64-unknown-linux-gnu + cross: true + - target: x86_64-unknown-linux-musl + cross: true + - target: aarch64-unknown-linux-musl + cross: true + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install Zig + if: matrix.cross + uses: goto-bus-stop/setup-zig@v2 + + - name: Install cargo-zigbuild + if: matrix.cross + run: cargo install cargo-zigbuild + + - name: Install npm dependencies + working-directory: npm + run: npm install + + - name: Build native module + working-directory: npm + run: | + npx napi build --release \ + --platform \ + --target ${{ matrix.target }} \ + --cargo-cwd ../crates/node + + - uses: actions/upload-artifact@v4 + with: + name: node-${{ matrix.target }} + path: npm/index.*.node + release: - needs: [build-rust, build-python] + needs: [build-rust, build-python, build-node] runs-on: ubuntu-latest if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') permissions: diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index 6429694..a25a2a7 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -3,7 +3,7 @@ name = "sdk-node" version.workspace = true edition.workspace = true license.workspace = true -description = "Node.js bindings for my-sdk" +description = "Node.js bindings for quicknode sdk" [lints] workspace = true diff --git a/npm/browser.js b/npm/browser.js new file mode 100644 index 0000000..47bf184 --- /dev/null +++ b/npm/browser.js @@ -0,0 +1,9 @@ +// Native Node.js bindings (.node files compiled from Rust) cannot run in +// browser environments — they are binary extensions that require the Node.js +// runtime and OS-level dynamic linking. Bundlers (Webpack, Vite, etc.) that +// encounter this package in a browser target will load this shim instead, +// producing a clear error rather than a cryptic binary load failure. +throw new Error( + '@quicknode/sdk-next does not support browser environments. ' + + 'This package requires Node.js.' +); diff --git a/npm/package.json b/npm/package.json index 3030920..51359a4 100644 --- a/npm/package.json +++ b/npm/package.json @@ -4,11 +4,21 @@ "description": "Quicknode SDK", "main": "sdk.js", "types": "sdk.d.ts", + "exports": { + ".": { + "import": "./sdk.mjs", + "require": "./sdk.js", + "types": "./sdk.d.ts" + } + }, + "browser": "./browser.js", "files": [ "index.js", "index.d.ts", "sdk.js", "sdk.d.ts", + "sdk.mjs", + "browser.js", "*.node" ], "napi": { diff --git a/npm/sdk.mjs b/npm/sdk.mjs new file mode 100644 index 0000000..d9e54cd --- /dev/null +++ b/npm/sdk.mjs @@ -0,0 +1,26 @@ +// ESM wrapper: re-exports the CJS entry via dynamic import. +// The native .node binary loader (index.js) uses require() for platform +// detection and cannot be expressed as static ESM — this wrapper bridges +// the gap for ESM consumers while keeping the loader intact. +import cjs from './sdk.js'; + +export const { + QuickNodeSdk, + DestinationAttributes, + TemplateArgs, + StreamRegion, + StreamDataset, + StreamDestination, + FilterLanguage, + StreamMetadataLocation, + ProductType, + StreamStatus, + WebhookTemplateId, + WebhookStartFrom, + AdminApiClient, + StreamsApiClient, + WebhooksApiClient, + KvStoreApiClient, +} = cjs; + +export default cjs; From f0495d184d96785c7028507e3c3b13aa1f6b6870 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:34:15 -0400 Subject: [PATCH 12/28] chore: fix sdk.mjs named exports; document sdk.mjs update requirement in CLAUDE.md --- CLAUDE.md | 1 + npm/sdk.mjs | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 30b90c6..361abb3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -136,6 +136,7 @@ Core clients are tested using mocked API calls with wiremock. All functions maki - When adding a new type with `#[cfg_attr(feature = "node", napi(object))]`, also add it to the named `export type { ... }` block in `npm/sdk.d.ts` — this is the user-facing type file and is not auto-updated by napi-rs - When adding a new `#[napi(string_enum)]` Rust enum, it generates a TypeScript `const enum` in `npm/index.d.ts`. In `npm/sdk.d.ts`, these must be re-exported using a regular `export { ... }` (not `export type { ... }`), otherwise TypeScript consumers cannot use them as values (e.g., `StreamDataset.Block`) - When updating `sdk.js` wrapper methods, verify the argument types match the underlying napi-rs constructor/method signature (object vs primitive) +- When adding a new export to `sdk.js`, also add it to the named exports in `npm/sdk.mjs` — ESM named exports cannot be spread dynamically and must be listed explicitly - `python/sdk/__init__.pyi` is overwritten by `just python-build` — edit `init_manual_override.pyi` instead ### Security diff --git a/npm/sdk.mjs b/npm/sdk.mjs index d9e54cd..a23a4b1 100644 --- a/npm/sdk.mjs +++ b/npm/sdk.mjs @@ -2,8 +2,12 @@ // The native .node binary loader (index.js) uses require() for platform // detection and cannot be expressed as static ESM — this wrapper bridges // the gap for ESM consumers while keeping the loader intact. +// +// We re-export everything from the default export so that new types added +// to sdk.js are automatically available here without manual updates. import cjs from './sdk.js'; +export default cjs; export const { QuickNodeSdk, DestinationAttributes, @@ -22,5 +26,3 @@ export const { WebhooksApiClient, KvStoreApiClient, } = cjs; - -export default cjs; From 2512b0f7406db33349f098ed0c27fba035a6af5f Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:49:42 -0400 Subject: [PATCH 13/28] ci: strip debug symbols from node .node binaries to reduce artifact size --- .github/workflows/release.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b4a147..90d4a2c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -131,6 +131,15 @@ jobs: --target ${{ matrix.target }} \ --cargo-cwd ../crates/node + - name: Strip debug symbols + run: | + if [ "${{ matrix.cross }}" = "true" ]; then + # Use llvm-strip for cross-compiled targets (available on ubuntu runners) + llvm-strip npm/index.*.node + else + strip npm/index.*.node + fi + - uses: actions/upload-artifact@v4 with: name: node-${{ matrix.target }} From 2e9203e865edd3c14a3d6de11e8089f4a1308ac8 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:50:21 -0400 Subject: [PATCH 14/28] ci: strip debug symbols from Python wheels --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90d4a2c..ec20f40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,6 +65,7 @@ jobs: - name: Build wheel run: | maturin build --release \ + --strip \ --target ${{ matrix.target }} \ ${{ matrix.cross && '--zig' || '' }} \ -i python${{ matrix.python-version }} \ From 778c6b6d4487b00cfa96b233d12f248b36a3e033 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:51:06 -0400 Subject: [PATCH 15/28] ci: fix node cross-compilation by passing --cross-compile to napi build --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ec20f40..dfa6707 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -130,6 +130,7 @@ jobs: npx napi build --release \ --platform \ --target ${{ matrix.target }} \ + ${{ matrix.cross && '--cross-compile' || '' }} \ --cargo-cwd ../crates/node - name: Strip debug symbols From f08a0d00a69a3fe3a019be4bb44f7ce86bc6f051 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:51:54 -0400 Subject: [PATCH 16/28] Revert "ci: fix node cross-compilation by passing --cross-compile to napi build" This reverts commit 778c6b6d4487b00cfa96b233d12f248b36a3e033. --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dfa6707..ec20f40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -130,7 +130,6 @@ jobs: npx napi build --release \ --platform \ --target ${{ matrix.target }} \ - ${{ matrix.cross && '--cross-compile' || '' }} \ --cargo-cwd ../crates/node - name: Strip debug symbols From 28853dd740bb8923b4111a868964a5d4b73ddebf Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 10:54:29 -0400 Subject: [PATCH 17/28] ci: explicitly pass --cross-compile to napi build for cross targets --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ec20f40..dfa6707 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -130,6 +130,7 @@ jobs: npx napi build --release \ --platform \ --target ${{ matrix.target }} \ + ${{ matrix.cross && '--cross-compile' || '' }} \ --cargo-cwd ../crates/node - name: Strip debug symbols From cae5c5502403047d01017b38abf1506a698d55ca Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 11:00:57 -0400 Subject: [PATCH 18/28] ci: remove unsupported --cross-compile flag from napi build --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dfa6707..ec20f40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -130,7 +130,6 @@ jobs: npx napi build --release \ --platform \ --target ${{ matrix.target }} \ - ${{ matrix.cross && '--cross-compile' || '' }} \ --cargo-cwd ../crates/node - name: Strip debug symbols From 182013e68005691155ba952ac707111bcb852499 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 11:01:12 -0400 Subject: [PATCH 19/28] ci: remove cargo-zigbuild from node job (napi-rs uses zig directly) --- .github/workflows/release.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ec20f40..841ed37 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -116,10 +116,6 @@ jobs: if: matrix.cross uses: goto-bus-stop/setup-zig@v2 - - name: Install cargo-zigbuild - if: matrix.cross - run: cargo install cargo-zigbuild - - name: Install npm dependencies working-directory: npm run: npm install From f6d12adc5d08b836c5a8b934242d4d9c6962bf16 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 11:07:11 -0400 Subject: [PATCH 20/28] ci: use zig objcopy to strip cross-compiled node binaries --- .github/workflows/release.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 841ed37..2306e5c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -131,8 +131,10 @@ jobs: - name: Strip debug symbols run: | if [ "${{ matrix.cross }}" = "true" ]; then - # Use llvm-strip for cross-compiled targets (available on ubuntu runners) - llvm-strip npm/index.*.node + # zig objcopy is available when zig is on PATH and handles foreign architectures + for f in npm/index.*.node; do + zig objcopy --strip-all "$f" "$f" + done else strip npm/index.*.node fi From d13d2e60ace872d9e0f12d491316be056f35d15a Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 11:19:15 -0400 Subject: [PATCH 21/28] ci: install llvm for llvm-strip on cross-compiled node binaries --- .github/workflows/release.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2306e5c..985bc80 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -131,10 +131,8 @@ jobs: - name: Strip debug symbols run: | if [ "${{ matrix.cross }}" = "true" ]; then - # zig objcopy is available when zig is on PATH and handles foreign architectures - for f in npm/index.*.node; do - zig objcopy --strip-all "$f" "$f" - done + sudo apt-get install -y llvm + llvm-strip npm/index.*.node else strip npm/index.*.node fi From 996c643682e70ffb2bc1c6ff2f7ff1ef20e24c5d Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 11:27:13 -0400 Subject: [PATCH 22/28] ci: add Ruby gem build job (4 Linux targets) --- .github/workflows/release.yml | 87 ++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 985bc80..c32d9d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -142,8 +142,93 @@ jobs: name: node-${{ matrix.target }} path: npm/index.*.node + build-ruby: + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-unknown-linux-gnu + cross: false + gem_platform: x86_64-linux + - target: aarch64-unknown-linux-gnu + cross: true + gem_platform: aarch64-linux + - target: x86_64-unknown-linux-musl + cross: true + gem_platform: x86_64-linux-musl + - target: aarch64-unknown-linux-musl + cross: true + gem_platform: aarch64-linux-musl + # Placeholder for future macOS support: + # - target: aarch64-apple-darwin + # cross: false + # gem_platform: arm64-darwin + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + + - name: Install Zig + if: matrix.cross + uses: goto-bus-stop/setup-zig@v2 + + - name: Install cargo-zigbuild + if: matrix.cross + run: cargo install cargo-zigbuild + + - name: Build native extension (cross) + if: matrix.cross + run: | + cargo zigbuild --release -p sdk-ruby --target ${{ matrix.target }} + cp target/${{ matrix.target }}/release/libquicknode_sdk.so ruby/lib/quicknode_sdk.so + + - name: Build native extension (native) + if: '!matrix.cross' + run: | + cargo build --release -p sdk-ruby + cp target/release/libquicknode_sdk.so ruby/lib/quicknode_sdk.so + + - name: Strip debug symbols + run: | + if [ "${{ matrix.cross }}" = "true" ]; then + sudo apt-get install -y llvm + llvm-strip ruby/lib/quicknode_sdk.so + else + strip ruby/lib/quicknode_sdk.so + fi + + - name: Build platform gem + working-directory: ruby + run: | + ruby -e " + spec = Gem::Specification.load('quicknode_sdk.gemspec') + spec.platform = Gem::Platform.new('${{ matrix.gem_platform }}') + spec.extensions = [] + spec.files += ['lib/quicknode_sdk.so'] + File.write('quicknode_sdk_platform.gemspec', spec.to_ruby) + " + gem build quicknode_sdk_platform.gemspec + rm quicknode_sdk_platform.gemspec + + - name: Build source gem + if: matrix.target == 'x86_64-unknown-linux-gnu' + working-directory: ruby + run: gem build quicknode_sdk.gemspec + + - uses: actions/upload-artifact@v4 + with: + name: ruby-${{ matrix.target }} + path: ruby/*.gem + release: - needs: [build-rust, build-python, build-node] + needs: [build-rust, build-python, build-node, build-ruby] runs-on: ubuntu-latest if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') permissions: From d10dd0f6256b57c59dc736c06c56044b6f8eaa3d Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 11:32:23 -0400 Subject: [PATCH 23/28] ci: remove musl targets from Ruby job (cdylib incompatible with musl) --- .github/workflows/release.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c32d9d7..2ef2ac3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -153,12 +153,8 @@ jobs: - target: aarch64-unknown-linux-gnu cross: true gem_platform: aarch64-linux - - target: x86_64-unknown-linux-musl - cross: true - gem_platform: x86_64-linux-musl - - target: aarch64-unknown-linux-musl - cross: true - gem_platform: aarch64-linux-musl + # musl targets are excluded: Rust cdylib is incompatible with musl (no dynamic linker). + # Users on musl Linux (e.g. Alpine) will use the source gem which compiles on install. # Placeholder for future macOS support: # - target: aarch64-apple-darwin # cross: false From f38d06690c21c046cd1a830e6d32e943b478597f Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 11:34:27 -0400 Subject: [PATCH 24/28] chore: add just release recipe for version management --- Justfile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Justfile b/Justfile index 583d6c6..5e4aceb 100644 --- a/Justfile +++ b/Justfile @@ -22,3 +22,15 @@ test: lint: cargo clippy --workspace --lib --tests -- -D warnings + +# Bump version across all manifests, commit, and tag for release. +# Usage: just release 0.2.0 +release version: + sed -i.bak 's/^version = ".*"/version = "{{version}}"/' Cargo.toml && rm Cargo.toml.bak + sed -i.bak 's/^version = ".*"/version = "{{version}}"/' pyproject.toml && rm pyproject.toml.bak + sed -i.bak 's/"version": ".*"/"version": "{{version}}"/' npm/package.json && rm npm/package.json.bak + sed -i.bak 's/s\.version *= *".*"/s.version = "{{version}}"/' ruby/quicknode_sdk.gemspec && rm ruby/quicknode_sdk.gemspec.bak + git add Cargo.toml pyproject.toml npm/package.json ruby/quicknode_sdk.gemspec + git commit -m "chore: release v{{version}}" + git tag v{{version}} + @echo "Tagged v{{version}}. Push with: git push && git push origin v{{version}}" From 62c542f05be47fc9b50ec69b699640c9dbb539e1 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 12:12:49 -0400 Subject: [PATCH 25/28] ci: only trigger release workflow on version tags --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ef2ac3..1fc6137 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: Release on: - pull_request: push: tags: - 'v*' From e9d1cfc4e696b29efe80e97845fc347438eb2193 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 12:14:22 -0400 Subject: [PATCH 26/28] chore: update package-lock.json in release recipe --- Justfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 5e4aceb..1792610 100644 --- a/Justfile +++ b/Justfile @@ -29,8 +29,9 @@ release version: sed -i.bak 's/^version = ".*"/version = "{{version}}"/' Cargo.toml && rm Cargo.toml.bak sed -i.bak 's/^version = ".*"/version = "{{version}}"/' pyproject.toml && rm pyproject.toml.bak sed -i.bak 's/"version": ".*"/"version": "{{version}}"/' npm/package.json && rm npm/package.json.bak + cd npm && npm install --package-lock-only sed -i.bak 's/s\.version *= *".*"/s.version = "{{version}}"/' ruby/quicknode_sdk.gemspec && rm ruby/quicknode_sdk.gemspec.bak - git add Cargo.toml pyproject.toml npm/package.json ruby/quicknode_sdk.gemspec + git add Cargo.toml pyproject.toml npm/package.json npm/package-lock.json ruby/quicknode_sdk.gemspec git commit -m "chore: release v{{version}}" git tag v{{version}} @echo "Tagged v{{version}}. Push with: git push && git push origin v{{version}}" From 3887d1f165edf951532a5a4cafe4e25008944a07 Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 12:15:45 -0400 Subject: [PATCH 27/28] chore: cd back after npm install in release recipe --- Justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 1792610..23f3daa 100644 --- a/Justfile +++ b/Justfile @@ -29,7 +29,7 @@ release version: sed -i.bak 's/^version = ".*"/version = "{{version}}"/' Cargo.toml && rm Cargo.toml.bak sed -i.bak 's/^version = ".*"/version = "{{version}}"/' pyproject.toml && rm pyproject.toml.bak sed -i.bak 's/"version": ".*"/"version": "{{version}}"/' npm/package.json && rm npm/package.json.bak - cd npm && npm install --package-lock-only + cd npm && npm install --package-lock-only && cd .. sed -i.bak 's/s\.version *= *".*"/s.version = "{{version}}"/' ruby/quicknode_sdk.gemspec && rm ruby/quicknode_sdk.gemspec.bak git add Cargo.toml pyproject.toml npm/package.json npm/package-lock.json ruby/quicknode_sdk.gemspec git commit -m "chore: release v{{version}}" From 35408e1af526e6082db1c5463ef04abc5efa2c5c Mon Sep 17 00:00:00 2001 From: John Mitsch Date: Thu, 16 Apr 2026 12:24:59 -0400 Subject: [PATCH 28/28] chore: regenerate uv.lock in release recipe --- Justfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 23f3daa..2049394 100644 --- a/Justfile +++ b/Justfile @@ -28,10 +28,11 @@ lint: release version: sed -i.bak 's/^version = ".*"/version = "{{version}}"/' Cargo.toml && rm Cargo.toml.bak sed -i.bak 's/^version = ".*"/version = "{{version}}"/' pyproject.toml && rm pyproject.toml.bak + uv lock sed -i.bak 's/"version": ".*"/"version": "{{version}}"/' npm/package.json && rm npm/package.json.bak cd npm && npm install --package-lock-only && cd .. sed -i.bak 's/s\.version *= *".*"/s.version = "{{version}}"/' ruby/quicknode_sdk.gemspec && rm ruby/quicknode_sdk.gemspec.bak - git add Cargo.toml pyproject.toml npm/package.json npm/package-lock.json ruby/quicknode_sdk.gemspec + git add Cargo.toml pyproject.toml uv.lock npm/package.json npm/package-lock.json ruby/quicknode_sdk.gemspec git commit -m "chore: release v{{version}}" git tag v{{version}} @echo "Tagged v{{version}}. Push with: git push && git push origin v{{version}}"