quicknode-sdk 0.4.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/Cargo.lock +30 -19
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/Cargo.toml +4 -1
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/PKG-INFO +41 -2
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/Cargo.toml +1 -1
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/README.md +43 -1
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/examples/admin_e2e.rs +1 -0
- quicknode_sdk-0.5.0/crates/core/examples/sql.rs +70 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/mod.rs +2 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/config.rs +25 -1
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/kvstore/mod.rs +1 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/lib.rs +20 -2
- quicknode_sdk-0.5.0/crates/core/src/sql/mod.rs +466 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/streams/mod.rs +1 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/webhooks/mod.rs +1 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/python/Cargo.toml +1 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/python/src/lib.rs +68 -1
- quicknode_sdk-0.5.0/crates/python/src/sql.rs +59 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/pyproject.toml +1 -1
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/python/README.md +40 -1
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/python/quicknode_sdk/__init__.py +16 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/python/quicknode_sdk/__init__.pyi +16 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/python/quicknode_sdk/_core/__init__.pyi +246 -1
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/python/quicknode_sdk/init_manual_override.pyi +16 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/LICENSE +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/LICENSE +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/examples/admin.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/examples/kvstore_e2e.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/examples/streams.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/examples/streams_e2e.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/examples/webhooks_e2e.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/billing.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/bulk.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/chains.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/endpoint_metrics.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/endpoint_rate_limits.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/endpoint_security.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/endpoint_urls.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/endpoints.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/logs.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/tags.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/teams.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/admin/usage.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/errors.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/streams/stream.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/core/src/webhooks/webhook.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/python/src/errors.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/python/src/streams_destination.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/crates/python/src/webhooks_template.rs +0 -0
- {quicknode_sdk-0.4.0 → quicknode_sdk-0.5.0}/python/quicknode_sdk/py.typed +0 -0
|
@@ -1085,9 +1085,9 @@ dependencies = [
|
|
|
1085
1085
|
|
|
1086
1086
|
[[package]]
|
|
1087
1087
|
name = "js-sys"
|
|
1088
|
-
version = "0.3.
|
|
1088
|
+
version = "0.3.103"
|
|
1089
1089
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1090
|
-
checksum = "
|
|
1090
|
+
checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
|
|
1091
1091
|
dependencies = [
|
|
1092
1092
|
"cfg-if",
|
|
1093
1093
|
"futures-util",
|
|
@@ -1694,9 +1694,19 @@ dependencies = [
|
|
|
1694
1694
|
"syn",
|
|
1695
1695
|
]
|
|
1696
1696
|
|
|
1697
|
+
[[package]]
|
|
1698
|
+
name = "pythonize"
|
|
1699
|
+
version = "0.27.0"
|
|
1700
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1701
|
+
checksum = "a3a8f29db331e28c332c63496cfcbb822aca3d7320bc08b655d7fd0c29c50ede"
|
|
1702
|
+
dependencies = [
|
|
1703
|
+
"pyo3",
|
|
1704
|
+
"serde",
|
|
1705
|
+
]
|
|
1706
|
+
|
|
1697
1707
|
[[package]]
|
|
1698
1708
|
name = "quicknode-sdk"
|
|
1699
|
-
version = "0.
|
|
1709
|
+
version = "0.5.0"
|
|
1700
1710
|
dependencies = [
|
|
1701
1711
|
"bon",
|
|
1702
1712
|
"config",
|
|
@@ -2173,7 +2183,7 @@ dependencies = [
|
|
|
2173
2183
|
|
|
2174
2184
|
[[package]]
|
|
2175
2185
|
name = "sdk-node"
|
|
2176
|
-
version = "0.
|
|
2186
|
+
version = "0.5.0"
|
|
2177
2187
|
dependencies = [
|
|
2178
2188
|
"napi",
|
|
2179
2189
|
"napi-build",
|
|
@@ -2185,18 +2195,19 @@ dependencies = [
|
|
|
2185
2195
|
|
|
2186
2196
|
[[package]]
|
|
2187
2197
|
name = "sdk-python"
|
|
2188
|
-
version = "0.
|
|
2198
|
+
version = "0.5.0"
|
|
2189
2199
|
dependencies = [
|
|
2190
2200
|
"pyo3",
|
|
2191
2201
|
"pyo3-async-runtimes",
|
|
2192
2202
|
"pyo3-stub-gen",
|
|
2203
|
+
"pythonize",
|
|
2193
2204
|
"quicknode-sdk",
|
|
2194
2205
|
"serde_json",
|
|
2195
2206
|
]
|
|
2196
2207
|
|
|
2197
2208
|
[[package]]
|
|
2198
2209
|
name = "sdk-python-stubs"
|
|
2199
|
-
version = "0.
|
|
2210
|
+
version = "0.5.0"
|
|
2200
2211
|
dependencies = [
|
|
2201
2212
|
"pyo3-stub-gen",
|
|
2202
2213
|
"sdk-python",
|
|
@@ -2204,7 +2215,7 @@ dependencies = [
|
|
|
2204
2215
|
|
|
2205
2216
|
[[package]]
|
|
2206
2217
|
name = "sdk-ruby"
|
|
2207
|
-
version = "0.
|
|
2218
|
+
version = "0.5.0"
|
|
2208
2219
|
dependencies = [
|
|
2209
2220
|
"magnus",
|
|
2210
2221
|
"quicknode-sdk",
|
|
@@ -2919,9 +2930,9 @@ dependencies = [
|
|
|
2919
2930
|
|
|
2920
2931
|
[[package]]
|
|
2921
2932
|
name = "wasm-bindgen"
|
|
2922
|
-
version = "0.2.
|
|
2933
|
+
version = "0.2.126"
|
|
2923
2934
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2924
|
-
checksum = "
|
|
2935
|
+
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
|
|
2925
2936
|
dependencies = [
|
|
2926
2937
|
"cfg-if",
|
|
2927
2938
|
"once_cell",
|
|
@@ -2932,9 +2943,9 @@ dependencies = [
|
|
|
2932
2943
|
|
|
2933
2944
|
[[package]]
|
|
2934
2945
|
name = "wasm-bindgen-futures"
|
|
2935
|
-
version = "0.4.
|
|
2946
|
+
version = "0.4.76"
|
|
2936
2947
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2937
|
-
checksum = "
|
|
2948
|
+
checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"
|
|
2938
2949
|
dependencies = [
|
|
2939
2950
|
"js-sys",
|
|
2940
2951
|
"wasm-bindgen",
|
|
@@ -2942,9 +2953,9 @@ dependencies = [
|
|
|
2942
2953
|
|
|
2943
2954
|
[[package]]
|
|
2944
2955
|
name = "wasm-bindgen-macro"
|
|
2945
|
-
version = "0.2.
|
|
2956
|
+
version = "0.2.126"
|
|
2946
2957
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2947
|
-
checksum = "
|
|
2958
|
+
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
|
|
2948
2959
|
dependencies = [
|
|
2949
2960
|
"quote",
|
|
2950
2961
|
"wasm-bindgen-macro-support",
|
|
@@ -2952,9 +2963,9 @@ dependencies = [
|
|
|
2952
2963
|
|
|
2953
2964
|
[[package]]
|
|
2954
2965
|
name = "wasm-bindgen-macro-support"
|
|
2955
|
-
version = "0.2.
|
|
2966
|
+
version = "0.2.126"
|
|
2956
2967
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2957
|
-
checksum = "
|
|
2968
|
+
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
|
|
2958
2969
|
dependencies = [
|
|
2959
2970
|
"bumpalo",
|
|
2960
2971
|
"proc-macro2",
|
|
@@ -2965,18 +2976,18 @@ dependencies = [
|
|
|
2965
2976
|
|
|
2966
2977
|
[[package]]
|
|
2967
2978
|
name = "wasm-bindgen-shared"
|
|
2968
|
-
version = "0.2.
|
|
2979
|
+
version = "0.2.126"
|
|
2969
2980
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2970
|
-
checksum = "
|
|
2981
|
+
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
|
|
2971
2982
|
dependencies = [
|
|
2972
2983
|
"unicode-ident",
|
|
2973
2984
|
]
|
|
2974
2985
|
|
|
2975
2986
|
[[package]]
|
|
2976
2987
|
name = "web-sys"
|
|
2977
|
-
version = "0.3.
|
|
2988
|
+
version = "0.3.103"
|
|
2978
2989
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2979
|
-
checksum = "
|
|
2990
|
+
checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"
|
|
2980
2991
|
dependencies = [
|
|
2981
2992
|
"js-sys",
|
|
2982
2993
|
"wasm-bindgen",
|
|
@@ -3,7 +3,7 @@ resolver = "2"
|
|
|
3
3
|
members = ["crates/core", "crates/python"]
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.
|
|
6
|
+
version = "0.5.0"
|
|
7
7
|
edition = "2021"
|
|
8
8
|
license = "MIT"
|
|
9
9
|
|
|
@@ -20,6 +20,9 @@ needless_pass_by_value = "warn"
|
|
|
20
20
|
[workspace.dependencies]
|
|
21
21
|
pyo3 = { version = "0.27", features = ["experimental-async"] }
|
|
22
22
|
pyo3-async-runtimes = { version = "0.27", features = ["tokio-runtime"] }
|
|
23
|
+
# Tracks pyo3 versions in lockstep; converts dynamic SQL result rows
|
|
24
|
+
# (serde_json::Value) to native Python objects.
|
|
25
|
+
pythonize = { version = "0.27" }
|
|
23
26
|
napi = { version = "3", features = ["async", "tokio_rt", "compat-mode"] }
|
|
24
27
|
napi-derive = { version = "3", features = ["compat-mode"] }
|
|
25
28
|
pyo3-stub-gen = { version = "0.19.0" }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quicknode-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Classifier: Intended Audience :: Developers
|
|
5
5
|
Classifier: License :: OSI Approved :: MIT License
|
|
6
6
|
Classifier: Operating System :: POSIX :: Linux
|
|
@@ -70,6 +70,7 @@ This is one of four language bindings published from the same Rust core. See the
|
|
|
70
70
|
- [KV Store Client](#kv-store-client)
|
|
71
71
|
- [Sets](#sets)
|
|
72
72
|
- [Lists](#lists)
|
|
73
|
+
- [SQL Client](#sql-client)
|
|
73
74
|
- [Error Handling](#error-handling)
|
|
74
75
|
- [License](#license)
|
|
75
76
|
|
|
@@ -79,7 +80,7 @@ This is one of four language bindings published from the same Rust core. See the
|
|
|
79
80
|
|
|
80
81
|
## Quick Start
|
|
81
82
|
|
|
82
|
-
Construct the SDK once, then reach into the
|
|
83
|
+
Construct the SDK once, then reach into the five sub-clients (`admin`, `streams`, `webhooks`, `kvstore`, `sql`). Subsequent API Reference snippets assume you have a `qn` handle from one of these blocks.
|
|
83
84
|
|
|
84
85
|
```python
|
|
85
86
|
# Python
|
|
@@ -124,6 +125,7 @@ Environment variables (prefix `QN_SDK__`, separator `__`):
|
|
|
124
125
|
| `QN_SDK__STREAMS__BASE_URL` | no | `https://api.quicknode.com/streams/rest/v1/` | Override streams base URL |
|
|
125
126
|
| `QN_SDK__WEBHOOKS__BASE_URL` | no | `https://api.quicknode.com/webhooks/rest/v1/` | Override webhooks base URL |
|
|
126
127
|
| `QN_SDK__KVSTORE__BASE_URL` | no | `https://api.quicknode.com/kv/rest/v1/` | Override KV store base URL |
|
|
128
|
+
| `QN_SDK__SQL__BASE_URL` | no | `https://api.quicknode.com/sql/rest/v1/` | Override SQL Explorer base URL |
|
|
127
129
|
| `QN_SDK__HTTP__HEADERS__<NAME>` | no | — | Custom HTTP header sent on every request. Overrides SDK-managed headers (see below). |
|
|
128
130
|
|
|
129
131
|
### Custom headers and `User-Agent`
|
|
@@ -1630,6 +1632,43 @@ Deletes a list and all of its items.
|
|
|
1630
1632
|
await qn.kvstore.delete_list("my-list")
|
|
1631
1633
|
```
|
|
1632
1634
|
|
|
1635
|
+
---
|
|
1636
|
+
|
|
1637
|
+
### SQL Client
|
|
1638
|
+
|
|
1639
|
+
Accessed as `qn.sql`. Runs SQL queries against indexed blockchain data and fetches the database schema. Backed by `https://api.quicknode.com/sql/rest/v1/`.
|
|
1640
|
+
|
|
1641
|
+
##### `query`
|
|
1642
|
+
|
|
1643
|
+
Executes a SQL query against a cluster and returns the result set. Paginate by writing `LIMIT`/`OFFSET` into the SQL.
|
|
1644
|
+
|
|
1645
|
+
**Parameters**: `query` (str, required), `cluster_id` (str, required).
|
|
1646
|
+
|
|
1647
|
+
**Returns**: `QueryResponse` — `meta` (list of `ColumnMeta`, each with `name` and `column_type`), `data` (`list[dict]`, rows keyed by column name), `rows`, `rows_before_limit_at_least`, `statistics` (`QueryStatistics` with `elapsed`, `rows_read`, `bytes_read`), and `credits`.
|
|
1648
|
+
|
|
1649
|
+
```python
|
|
1650
|
+
# Python
|
|
1651
|
+
resp = await qn.sql.query(
|
|
1652
|
+
query="SELECT action_type, user FROM hyperliquid_system_actions ORDER BY block_time DESC LIMIT 100",
|
|
1653
|
+
cluster_id="hyperliquid-core-mainnet",
|
|
1654
|
+
)
|
|
1655
|
+
print(resp.rows, resp.data[0])
|
|
1656
|
+
```
|
|
1657
|
+
|
|
1658
|
+
##### `get_schema`
|
|
1659
|
+
|
|
1660
|
+
Fetches the database schema for a cluster: table names, columns, types, sort keys, and partition strategies.
|
|
1661
|
+
|
|
1662
|
+
**Parameters**: `cluster_id` (str, required).
|
|
1663
|
+
|
|
1664
|
+
**Returns**: `ChainSchema` — `chain`, `cluster_id`, and `tables` (list of `TableSchema`, each with `name`, `engine`, `total_rows`, `partition_key`, `sorting_key`, and `columns` of `ColumnSchema` with `name` and `column_type`).
|
|
1665
|
+
|
|
1666
|
+
```python
|
|
1667
|
+
# Python
|
|
1668
|
+
schema = await qn.sql.get_schema("hyperliquid-core-mainnet")
|
|
1669
|
+
print(len(schema.tables))
|
|
1670
|
+
```
|
|
1671
|
+
|
|
1633
1672
|
## Error Handling
|
|
1634
1673
|
|
|
1635
1674
|
Every binding exposes a typed exception hierarchy derived from the core `SdkError`
|
|
@@ -46,6 +46,7 @@ This is one of four language bindings published from the same Rust core. See the
|
|
|
46
46
|
- [KV Store Client](#kv-store-client)
|
|
47
47
|
- [Sets](#sets)
|
|
48
48
|
- [Lists](#lists)
|
|
49
|
+
- [SQL Client](#sql-client)
|
|
49
50
|
- [Error Handling](#error-handling)
|
|
50
51
|
- [License](#license)
|
|
51
52
|
|
|
@@ -55,7 +56,7 @@ This is one of four language bindings published from the same Rust core. See the
|
|
|
55
56
|
|
|
56
57
|
## Quick Start
|
|
57
58
|
|
|
58
|
-
Construct the SDK once, then reach into the
|
|
59
|
+
Construct the SDK once, then reach into the five sub-clients (`admin`, `streams`, `webhooks`, `kvstore`, `sql`). Subsequent API Reference snippets assume you have a `qn` handle from one of these blocks.
|
|
59
60
|
|
|
60
61
|
```rust
|
|
61
62
|
// Rust
|
|
@@ -99,6 +100,7 @@ Environment variables (prefix `QN_SDK__`, separator `__`):
|
|
|
99
100
|
| `QN_SDK__STREAMS__BASE_URL` | no | `https://api.quicknode.com/streams/rest/v1/` | Override streams base URL |
|
|
100
101
|
| `QN_SDK__WEBHOOKS__BASE_URL` | no | `https://api.quicknode.com/webhooks/rest/v1/` | Override webhooks base URL |
|
|
101
102
|
| `QN_SDK__KVSTORE__BASE_URL` | no | `https://api.quicknode.com/kv/rest/v1/` | Override KV store base URL |
|
|
103
|
+
| `QN_SDK__SQL__BASE_URL` | no | `https://api.quicknode.com/sql/rest/v1/` | Override SQL Explorer base URL |
|
|
102
104
|
| `QN_SDK__HTTP__HEADERS__<NAME>` | no | — | Custom HTTP header sent on every request. Overrides SDK-managed headers (see below). |
|
|
103
105
|
|
|
104
106
|
### Custom headers and `User-Agent`
|
|
@@ -1689,6 +1691,46 @@ Deletes a list and all of its items.
|
|
|
1689
1691
|
qn.kvstore.delete_list("my-list").await?;
|
|
1690
1692
|
```
|
|
1691
1693
|
|
|
1694
|
+
---
|
|
1695
|
+
|
|
1696
|
+
### SQL Client
|
|
1697
|
+
|
|
1698
|
+
Accessed as `qn.sql`. Runs SQL queries against indexed blockchain data and fetches the database schema. Backed by `https://api.quicknode.com/sql/rest/v1/`.
|
|
1699
|
+
|
|
1700
|
+
##### `query`
|
|
1701
|
+
|
|
1702
|
+
Executes a SQL query against a cluster and returns the result set. Paginate by writing `LIMIT`/`OFFSET` into the SQL.
|
|
1703
|
+
|
|
1704
|
+
**Parameters**: `QueryParams` with `query` (String, required) and `cluster_id` (String, required).
|
|
1705
|
+
|
|
1706
|
+
**Returns**: `QueryResponse` — `meta` (`Vec<ColumnMeta>`, each with `name` and `column_type`), `data` (`Vec<serde_json::Value>`, rows as JSON objects keyed by column name), `rows`, `rows_before_limit_at_least`, `statistics` (`QueryStatistics` with `elapsed`, `rows_read`, `bytes_read`), and `credits`.
|
|
1707
|
+
|
|
1708
|
+
```rust
|
|
1709
|
+
// Rust
|
|
1710
|
+
let resp = qn
|
|
1711
|
+
.sql
|
|
1712
|
+
.query(&QueryParams {
|
|
1713
|
+
query: "SELECT action_type, user FROM hyperliquid_system_actions ORDER BY block_time DESC LIMIT 100".to_string(),
|
|
1714
|
+
cluster_id: "hyperliquid-core-mainnet".to_string(),
|
|
1715
|
+
})
|
|
1716
|
+
.await?;
|
|
1717
|
+
println!("{} rows, {:?}", resp.rows, resp.data.first());
|
|
1718
|
+
```
|
|
1719
|
+
|
|
1720
|
+
##### `get_schema`
|
|
1721
|
+
|
|
1722
|
+
Fetches the database schema for a cluster: table names, columns, types, sort keys, and partition strategies.
|
|
1723
|
+
|
|
1724
|
+
**Parameters**: `cluster_id` (`&str`, required).
|
|
1725
|
+
|
|
1726
|
+
**Returns**: `ChainSchema` — `chain`, `cluster_id`, and `tables` (`Vec<TableSchema>`, each with `name`, `engine`, `total_rows`, `partition_key`, `sorting_key`, and `columns` of `ColumnSchema { name, column_type }`).
|
|
1727
|
+
|
|
1728
|
+
```rust
|
|
1729
|
+
// Rust
|
|
1730
|
+
let schema = qn.sql.get_schema("hyperliquid-core-mainnet").await?;
|
|
1731
|
+
println!("{} tables", schema.tables.len());
|
|
1732
|
+
```
|
|
1733
|
+
|
|
1692
1734
|
## Error Handling
|
|
1693
1735
|
|
|
1694
1736
|
Every binding exposes a typed exception hierarchy derived from the core `SdkError`
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
use quicknode_sdk::{errors::SdkError, sql::QueryParams, QuicknodeSdk, SdkFullConfig};
|
|
2
|
+
|
|
3
|
+
const CLUSTER_ID: &str = "hyperliquid-core-mainnet";
|
|
4
|
+
|
|
5
|
+
#[tokio::main]
|
|
6
|
+
#[allow(clippy::unwrap_used, clippy::expect_used)]
|
|
7
|
+
async fn main() {
|
|
8
|
+
let config = SdkFullConfig::from_env().expect("Config from env failed");
|
|
9
|
+
let qn = QuicknodeSdk::new(&config).expect("sdk failed to initialize");
|
|
10
|
+
|
|
11
|
+
// ── Query ─────────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
let params = QueryParams {
|
|
14
|
+
query: "SELECT toDateTime(block_time) AS time, action_type, user \
|
|
15
|
+
FROM hyperliquid_system_actions \
|
|
16
|
+
ORDER BY block_time DESC LIMIT 3"
|
|
17
|
+
.to_string(),
|
|
18
|
+
cluster_id: CLUSTER_ID.to_string(),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
match qn.sql.query(¶ms).await {
|
|
22
|
+
Ok(resp) => {
|
|
23
|
+
println!(
|
|
24
|
+
"query: {} rows ({} before limit), {} credits, {:.4}s",
|
|
25
|
+
resp.rows, resp.rows_before_limit_at_least, resp.credits, resp.statistics.elapsed
|
|
26
|
+
);
|
|
27
|
+
println!(
|
|
28
|
+
"columns: {:?}",
|
|
29
|
+
resp.meta.iter().map(|c| &c.name).collect::<Vec<_>>()
|
|
30
|
+
);
|
|
31
|
+
// Read a value out of a dynamic row to confirm the conversion works.
|
|
32
|
+
if let Some(row) = resp.data.first() {
|
|
33
|
+
println!("first row action_type: {}", row["action_type"]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
Err(e) => eprintln!("query error: {e}"),
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ── Schema ──────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
match qn.sql.get_schema(CLUSTER_ID).await {
|
|
42
|
+
Ok(schema) => {
|
|
43
|
+
println!("schema: {} ({} tables)", schema.chain, schema.tables.len());
|
|
44
|
+
if let Some(table) = schema.tables.first() {
|
|
45
|
+
println!(
|
|
46
|
+
"first table: {} ({} columns, {} rows)",
|
|
47
|
+
table.name,
|
|
48
|
+
table.columns.len(),
|
|
49
|
+
table.total_rows
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
Err(e) => eprintln!("get_schema error: {e}"),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Error handling ────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
// An empty query is rejected with a 403 and a JSON body carrying the error
|
|
59
|
+
// message.
|
|
60
|
+
let bad = QueryParams {
|
|
61
|
+
query: String::new(),
|
|
62
|
+
cluster_id: CLUSTER_ID.to_string(),
|
|
63
|
+
};
|
|
64
|
+
match qn.sql.query(&bad).await {
|
|
65
|
+
Err(SdkError::Api { status, body }) => {
|
|
66
|
+
println!("api error {status}: {}", &body[..body.len().min(120)]);
|
|
67
|
+
}
|
|
68
|
+
other => eprintln!("expected Api error, got {other:?}"),
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -1903,6 +1903,7 @@ mod tests {
|
|
|
1903
1903
|
streams: None,
|
|
1904
1904
|
webhooks: None,
|
|
1905
1905
|
kvstore: None,
|
|
1906
|
+
sql: None,
|
|
1906
1907
|
})
|
|
1907
1908
|
.unwrap()
|
|
1908
1909
|
}
|
|
@@ -3673,6 +3674,7 @@ mod tests {
|
|
|
3673
3674
|
streams: None,
|
|
3674
3675
|
webhooks: None,
|
|
3675
3676
|
kvstore: None,
|
|
3677
|
+
sql: None,
|
|
3676
3678
|
});
|
|
3677
3679
|
assert!(matches!(result, Err(crate::errors::SdkError::Config(_))));
|
|
3678
3680
|
}
|
|
@@ -140,6 +140,26 @@ impl KvStoreConfig {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
#[cfg_attr(feature = "python", gen_stub_pyclass)]
|
|
144
|
+
#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
|
|
145
|
+
#[cfg_attr(feature = "node", napi(object))]
|
|
146
|
+
#[cfg_attr(feature = "rust", derive(Builder))]
|
|
147
|
+
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
|
|
148
|
+
pub struct SqlConfig {
|
|
149
|
+
pub base_url: Option<String>,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#[cfg(feature = "python")]
|
|
153
|
+
#[gen_stub_pymethods]
|
|
154
|
+
#[pymethods]
|
|
155
|
+
impl SqlConfig {
|
|
156
|
+
#[new]
|
|
157
|
+
#[pyo3(signature = (base_url=None))]
|
|
158
|
+
pub fn new(base_url: Option<String>) -> Self {
|
|
159
|
+
SqlConfig { base_url }
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
143
163
|
#[cfg_attr(feature = "python", gen_stub_pyclass)]
|
|
144
164
|
#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
|
|
145
165
|
#[cfg_attr(feature = "node", napi(object))]
|
|
@@ -152,6 +172,7 @@ pub struct SdkFullConfig {
|
|
|
152
172
|
pub streams: Option<StreamsConfig>,
|
|
153
173
|
pub webhooks: Option<WebhooksConfig>,
|
|
154
174
|
pub kvstore: Option<KvStoreConfig>,
|
|
175
|
+
pub sql: Option<SqlConfig>,
|
|
155
176
|
}
|
|
156
177
|
|
|
157
178
|
impl SdkFullConfig {
|
|
@@ -163,6 +184,7 @@ impl SdkFullConfig {
|
|
|
163
184
|
streams: None,
|
|
164
185
|
webhooks: None,
|
|
165
186
|
kvstore: None,
|
|
187
|
+
sql: None,
|
|
166
188
|
}
|
|
167
189
|
}
|
|
168
190
|
|
|
@@ -189,7 +211,7 @@ impl SdkFullConfig {
|
|
|
189
211
|
#[pymethods]
|
|
190
212
|
impl SdkFullConfig {
|
|
191
213
|
#[new]
|
|
192
|
-
#[pyo3(signature = (api_key, http=None, admin=None, streams=None, webhooks=None, kvstore=None))]
|
|
214
|
+
#[pyo3(signature = (api_key, http=None, admin=None, streams=None, webhooks=None, kvstore=None, sql=None))]
|
|
193
215
|
pub fn new(
|
|
194
216
|
api_key: String,
|
|
195
217
|
http: Option<HttpConfig>,
|
|
@@ -197,6 +219,7 @@ impl SdkFullConfig {
|
|
|
197
219
|
streams: Option<StreamsConfig>,
|
|
198
220
|
webhooks: Option<WebhooksConfig>,
|
|
199
221
|
kvstore: Option<KvStoreConfig>,
|
|
222
|
+
sql: Option<SqlConfig>,
|
|
200
223
|
) -> Self {
|
|
201
224
|
SdkFullConfig {
|
|
202
225
|
api_key,
|
|
@@ -205,6 +228,7 @@ impl SdkFullConfig {
|
|
|
205
228
|
streams,
|
|
206
229
|
webhooks,
|
|
207
230
|
kvstore,
|
|
231
|
+
sql,
|
|
208
232
|
}
|
|
209
233
|
}
|
|
210
234
|
}
|
|
@@ -2,11 +2,12 @@ pub mod admin;
|
|
|
2
2
|
pub mod config;
|
|
3
3
|
pub mod errors;
|
|
4
4
|
pub mod kvstore;
|
|
5
|
+
pub mod sql;
|
|
5
6
|
pub mod streams;
|
|
6
7
|
pub mod webhooks;
|
|
7
8
|
|
|
8
9
|
pub use config::{
|
|
9
|
-
AdminConfig, ClientInfo, HttpConfig, KvStoreConfig, SdkFullConfig, StreamsConfig,
|
|
10
|
+
AdminConfig, ClientInfo, HttpConfig, KvStoreConfig, SdkFullConfig, SqlConfig, StreamsConfig,
|
|
10
11
|
WebhooksConfig,
|
|
11
12
|
};
|
|
12
13
|
pub use kvstore::{
|
|
@@ -15,6 +16,10 @@ pub use kvstore::{
|
|
|
15
16
|
GetSetsParams, GetSetsResponse, KvSetEntry, KvStoreApiClient, ListContainsItemResponse,
|
|
16
17
|
UpdateListParams,
|
|
17
18
|
};
|
|
19
|
+
pub use sql::{
|
|
20
|
+
ChainSchema, ColumnMeta, ColumnSchema, QueryParams, QueryResponse, QueryStatistics,
|
|
21
|
+
SqlApiClient, TableSchema,
|
|
22
|
+
};
|
|
18
23
|
|
|
19
24
|
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
|
20
25
|
use reqwest::Client as ReqwestClient;
|
|
@@ -64,6 +69,7 @@ impl std::fmt::Debug for SdkConfig {
|
|
|
64
69
|
.field("streams_base_url", &self.0.streams.base_url)
|
|
65
70
|
.field("webhooks_base_url", &self.0.webhooks.base_url)
|
|
66
71
|
.field("kvstore_base_url", &self.0.kvstore.base_url)
|
|
72
|
+
.field("sql_base_url", &self.0.sql.base_url)
|
|
67
73
|
.finish()
|
|
68
74
|
}
|
|
69
75
|
}
|
|
@@ -74,6 +80,7 @@ struct SdkConfigInner {
|
|
|
74
80
|
streams: streams::ResolvedStreamsConfig,
|
|
75
81
|
webhooks: webhooks::ResolvedWebhooksConfig,
|
|
76
82
|
kvstore: kvstore::ResolvedKvStoreConfig,
|
|
83
|
+
sql: sql::ResolvedSqlConfig,
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
impl SdkConfig {
|
|
@@ -159,6 +166,7 @@ impl SdkConfig {
|
|
|
159
166
|
streams: streams::ResolvedStreamsConfig::from_config(config.streams.as_ref())?,
|
|
160
167
|
webhooks: webhooks::ResolvedWebhooksConfig::from_config(config.webhooks.as_ref())?,
|
|
161
168
|
kvstore: kvstore::ResolvedKvStoreConfig::from_config(config.kvstore.as_ref())?,
|
|
169
|
+
sql: sql::ResolvedSqlConfig::from_config(config.sql.as_ref())?,
|
|
162
170
|
})))
|
|
163
171
|
}
|
|
164
172
|
|
|
@@ -181,6 +189,10 @@ impl SdkConfig {
|
|
|
181
189
|
pub(crate) fn kvstore(&self) -> &kvstore::ResolvedKvStoreConfig {
|
|
182
190
|
&self.0.kvstore
|
|
183
191
|
}
|
|
192
|
+
|
|
193
|
+
pub(crate) fn sql(&self) -> &sql::ResolvedSqlConfig {
|
|
194
|
+
&self.0.sql
|
|
195
|
+
}
|
|
184
196
|
}
|
|
185
197
|
|
|
186
198
|
/// Top-level entry point for the Quicknode SDK. Holds sub-clients for each
|
|
@@ -196,6 +208,9 @@ pub struct QuicknodeSdk {
|
|
|
196
208
|
/// Key-Value Store client: manages sets (single values) and lists
|
|
197
209
|
/// (ordered collections) under string keys.
|
|
198
210
|
pub kvstore: kvstore::KvStoreApiClient,
|
|
211
|
+
/// SQL Explorer client: executes SQL queries against indexed blockchain
|
|
212
|
+
/// data and fetches the database schema.
|
|
213
|
+
pub sql: sql::SqlApiClient,
|
|
199
214
|
}
|
|
200
215
|
|
|
201
216
|
impl QuicknodeSdk {
|
|
@@ -216,7 +231,8 @@ impl QuicknodeSdk {
|
|
|
216
231
|
admin: admin::AdminApiClient::new(sdk_config.clone()),
|
|
217
232
|
streams: streams::StreamsApiClient::new(sdk_config.clone()),
|
|
218
233
|
webhooks: webhooks::WebhooksApiClient::new(sdk_config.clone()),
|
|
219
|
-
kvstore: kvstore::KvStoreApiClient::new(sdk_config),
|
|
234
|
+
kvstore: kvstore::KvStoreApiClient::new(sdk_config.clone()),
|
|
235
|
+
sql: sql::SqlApiClient::new(sdk_config),
|
|
220
236
|
})
|
|
221
237
|
}
|
|
222
238
|
|
|
@@ -247,6 +263,7 @@ mod headers_tests {
|
|
|
247
263
|
streams: None,
|
|
248
264
|
webhooks: None,
|
|
249
265
|
kvstore: None,
|
|
266
|
+
sql: None,
|
|
250
267
|
}
|
|
251
268
|
}
|
|
252
269
|
|
|
@@ -335,6 +352,7 @@ mod headers_tests {
|
|
|
335
352
|
streams: None,
|
|
336
353
|
webhooks: None,
|
|
337
354
|
kvstore: None,
|
|
355
|
+
sql: None,
|
|
338
356
|
};
|
|
339
357
|
|
|
340
358
|
let sdk = QuicknodeSdk::new(&cfg).unwrap();
|