@quicknode/sdk 2.6.0 → 3.0.0-alpha.6
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.
- package/README.md +3500 -46
- package/browser.js +9 -0
- package/errors.js +121 -0
- package/index.d.ts +2298 -650
- package/index.darwin-arm64.node +0 -0
- package/index.js +328 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-arm64-musl.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.linux-x64-musl.node +0 -0
- package/package.json +47 -54
- package/sdk.d.ts +339 -0
- package/sdk.js +102 -0
- package/sdk.mjs +34 -0
- package/cjs/index.js +0 -542
- package/cjs/package.json +0 -3
- package/esm/client/client.js +0 -9
- package/esm/client/index.js +0 -2
- package/esm/core/addOns/nftTokenV2/actions.js +0 -107
- package/esm/core/addOns/nftTokenV2/types/qn_fetchNFTCollectionDetails.js +0 -10
- package/esm/core/addOns/nftTokenV2/types/qn_fetchNFTs.js +0 -13
- package/esm/core/addOns/nftTokenV2/types/qn_fetchNFTsByCollection.js +0 -13
- package/esm/core/addOns/nftTokenV2/types/qn_getTokenMetadataByContractAddress.js +0 -10
- package/esm/core/addOns/nftTokenV2/types/qn_getTokenMetadataBySymbol.js +0 -11
- package/esm/core/addOns/nftTokenV2/types/qn_getTransactionsByAddress.js +0 -18
- package/esm/core/addOns/nftTokenV2/types/qn_getTransfersByNFT.js +0 -12
- package/esm/core/addOns/nftTokenV2/types/qn_getWalletTokenBalance.js +0 -12
- package/esm/core/addOns/nftTokenV2/types/qn_getWalletTokenTransactions.js +0 -14
- package/esm/core/addOns/nftTokenV2/types/qn_verifyNFTsOwner.js +0 -11
- package/esm/core/addOns/shared/helpers.js +0 -10
- package/esm/core/chains.js +0 -118
- package/esm/core/core.js +0 -30
- package/esm/core/index.d.ts +0 -558
- package/esm/core/index.js +0 -2
- package/esm/index.js +0 -11
- package/esm/lib/constants.js +0 -4
- package/esm/lib/errors/QNChainNotSupported.js +0 -7
- package/esm/lib/errors/QNInputValidationError.js +0 -10
- package/esm/lib/errors/QNInvalidEnpointUrl.js +0 -7
- package/esm/lib/helpers/getClientHeaders.js +0 -11
- package/esm/lib/helpers/globalFetch.js +0 -13
- package/esm/lib/validation/ValidateInput.js +0 -16
- package/esm/lib/validation/validators.js +0 -15
- package/esm/package.json +0 -4
- package/esm/solana/index.d.ts +0 -76
- package/esm/solana/index.js +0 -2
- package/esm/solana/solana.js +0 -111
package/README.md
CHANGED
|
@@ -1,80 +1,3534 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Quicknode SDK
|
|
2
2
|
|
|
3
|
-
A SDK
|
|
3
|
+
A unified SDK for building on QuickNode.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Rust SDK with Python, Node.js, and Ruby bindings.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Table of Contents
|
|
8
8
|
|
|
9
|
-
[
|
|
10
|
-
[
|
|
11
|
-
[
|
|
12
|
-
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
9
|
+
- [Project Structure](#project-structure)
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Configuration](#configuration)
|
|
13
|
+
- [Option A — Pass config directly](#option-a--pass-config-directly)
|
|
14
|
+
- [Option B — Load from environment (`from_env()`)](#option-b--load-from-environment-from_env)
|
|
15
|
+
- [API Reference](#api-reference)
|
|
16
|
+
- [Language conventions](#language-conventions)
|
|
17
|
+
- [Admin Client](#admin-client)
|
|
18
|
+
- [Endpoints](#endpoints)
|
|
19
|
+
- [Endpoint Tags](#endpoint-tags)
|
|
20
|
+
- [Teams](#teams)
|
|
21
|
+
- [Usage](#usage)
|
|
22
|
+
- [Logs](#logs)
|
|
23
|
+
- [Endpoint Security](#endpoint-security)
|
|
24
|
+
- [Security Options](#security-options)
|
|
25
|
+
- [Tokens](#tokens)
|
|
26
|
+
- [Referrers](#referrers)
|
|
27
|
+
- [IPs](#ips)
|
|
28
|
+
- [Domain Masks](#domain-masks)
|
|
29
|
+
- [JWTs](#jwts)
|
|
30
|
+
- [Request Filters](#request-filters)
|
|
31
|
+
- [Multichain](#multichain)
|
|
32
|
+
- [IP Custom Headers](#ip-custom-headers)
|
|
33
|
+
- [Method Rate Limits](#method-rate-limits)
|
|
34
|
+
- [Endpoint Rate Limits](#endpoint-rate-limits)
|
|
35
|
+
- [Metrics](#metrics)
|
|
36
|
+
- [Chains](#chains)
|
|
37
|
+
- [Billing](#billing)
|
|
38
|
+
- [Bulk Operations](#bulk-operations)
|
|
39
|
+
- [Account Tags](#account-tags)
|
|
40
|
+
- [Streams Client](#streams-client)
|
|
41
|
+
- [Datasets, Regions, and Destinations](#datasets-regions-and-destinations)
|
|
42
|
+
- [Streams methods](#streams-methods)
|
|
43
|
+
- [Webhooks Client](#webhooks-client)
|
|
44
|
+
- [Templates and destination](#templates-and-destination)
|
|
45
|
+
- [Webhooks methods](#webhooks-methods)
|
|
46
|
+
- [KV Store Client](#kv-store-client)
|
|
47
|
+
- [Sets](#sets)
|
|
48
|
+
- [Lists](#lists)
|
|
49
|
+
- [Error Handling](#error-handling)
|
|
50
|
+
- [Development](#development)
|
|
51
|
+
- [License](#license)
|
|
16
52
|
|
|
17
|
-
|
|
53
|
+
## Project Structure
|
|
18
54
|
|
|
19
|
-
|
|
55
|
+
```
|
|
56
|
+
sdk/
|
|
57
|
+
├── crates/
|
|
58
|
+
│ ├── core/ # Pure Rust business logic
|
|
59
|
+
│ ├── python/ # PyO3 bindings
|
|
60
|
+
│ ├── node/ # napi-rs bindings
|
|
61
|
+
│ └── ruby/ # magnus bindings
|
|
62
|
+
├── python/sdk/ # Python package with type hints
|
|
63
|
+
├── npm/ # Node.js package with TypeScript types
|
|
64
|
+
├── ruby/ # Ruby package
|
|
65
|
+
└── pyproject.toml # maturin build config
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
**Python:** `uv add quicknode-sdk`
|
|
71
|
+
|
|
72
|
+
**Node.js:** `npm install quicknode-sdk`
|
|
73
|
+
|
|
74
|
+
**Ruby:** `gem install quicknode-sdk` _(not yet published — see Development below)_
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
Construct the SDK once, then reach into the four sub-clients (`admin`, `streams`, `webhooks`, `kvstore`). Subsequent API Reference snippets assume you have a `qn` handle from one of these blocks.
|
|
79
|
+
|
|
80
|
+
```rust
|
|
81
|
+
// Rust
|
|
82
|
+
use quicknode_sdk::{QuickNodeSdk, SdkFullConfig};
|
|
83
|
+
|
|
84
|
+
#[tokio::main]
|
|
85
|
+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
86
|
+
let qn = QuickNodeSdk::from_env()?;
|
|
87
|
+
let resp = qn.admin.get_endpoints(&Default::default()).await?;
|
|
88
|
+
println!("{} endpoints", resp.data.len());
|
|
89
|
+
Ok(())
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Python
|
|
95
|
+
import asyncio
|
|
96
|
+
from sdk import QuickNodeSdk
|
|
97
|
+
|
|
98
|
+
async def main():
|
|
99
|
+
qn = QuickNodeSdk.from_env()
|
|
100
|
+
resp = await qn.admin.get_endpoints()
|
|
101
|
+
print(f"{len(resp.data)} endpoints")
|
|
102
|
+
|
|
103
|
+
asyncio.run(main())
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Node.js
|
|
108
|
+
import { QuickNodeSdk } from "quicknode-sdk";
|
|
109
|
+
|
|
110
|
+
const qn = QuickNodeSdk.fromEnv();
|
|
111
|
+
const resp = await qn.admin.getEndpoints();
|
|
112
|
+
console.log(`${resp.data.length} endpoints`);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
# Ruby
|
|
117
|
+
require "json"
|
|
118
|
+
require "quicknode_sdk"
|
|
119
|
+
|
|
120
|
+
qn = QuickNodeSdk::SDK.from_env
|
|
121
|
+
resp = JSON.parse(qn.admin.get_endpoints({}))
|
|
122
|
+
puts "#{resp["data"].length} endpoints"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Configuration
|
|
126
|
+
|
|
127
|
+
There are two ways to configure the SDK.
|
|
128
|
+
|
|
129
|
+
### Option A — Pass config directly
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# Python
|
|
133
|
+
from sdk import QuickNodeSdk, SdkFullConfig, HttpConfig
|
|
134
|
+
qn = QuickNodeSdk(SdkFullConfig(api_key="your-key", http=HttpConfig(timeout_secs=30)))
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Node.js
|
|
139
|
+
import { QuickNodeSdk } from "quicknode-sdk";
|
|
140
|
+
const qn = new QuickNodeSdk({ apiKey: "your-key", http: { timeoutSecs: 30 } });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```rust
|
|
144
|
+
// Rust
|
|
145
|
+
let qn = QuickNodeSdk::new(&SdkFullConfig::builder().api_key("your-key").build())?;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Option B — Load from environment (`from_env()`)
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
# Python
|
|
152
|
+
qn = QuickNodeSdk.from_env()
|
|
153
|
+
```
|
|
154
|
+
```typescript
|
|
155
|
+
// Node.js
|
|
156
|
+
const qn = QuickNodeSdk.fromEnv();
|
|
157
|
+
```
|
|
158
|
+
```ruby
|
|
159
|
+
# Ruby
|
|
160
|
+
qn = QuickNodeSdk::SDK.from_env
|
|
161
|
+
```
|
|
162
|
+
```rust
|
|
163
|
+
// Rust
|
|
164
|
+
let qn = QuickNodeSdk::from_env()?;
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Environment variables (prefix `QN_SDK__`, separator `__`):
|
|
168
|
+
|
|
169
|
+
| Variable | Required | Default | Description |
|
|
170
|
+
|----------|----------|---------|-------------|
|
|
171
|
+
| `QN_SDK__API_KEY` | yes | — | Your QuickNode API key |
|
|
172
|
+
| `QN_SDK__HTTP__TIMEOUT_SECS` | no | 30 | HTTP request timeout in seconds |
|
|
173
|
+
| `QN_SDK__HTTP__POOL_MAX_IDLE_PER_HOST` | no | — | Max idle HTTP connections per host |
|
|
174
|
+
| `QN_SDK__ADMIN__BASE_URL` | no | `https://api.quicknode.com/v0/` | Override admin API base URL (HTTPS, must end with `/`) |
|
|
175
|
+
| `QN_SDK__STREAMS__BASE_URL` | no | `https://api.quicknode.com/streams/rest/v1/` | Override streams base URL |
|
|
176
|
+
| `QN_SDK__WEBHOOKS__BASE_URL` | no | `https://api.quicknode.com/webhooks/rest/v1/` | Override webhooks base URL |
|
|
177
|
+
| `QN_SDK__KVSTORE__BASE_URL` | no | `https://api.quicknode.com/kv/rest/v1/` | Override KV store base URL |
|
|
178
|
+
|
|
179
|
+
## API Reference
|
|
180
|
+
|
|
181
|
+
Each method below shows the call pattern in Rust, Python, Node.js, and Ruby in that order. Snippets assume `qn` was already constructed via the Quick Start. Optional parameters are skipped unless showing one is needed to illustrate usage.
|
|
182
|
+
|
|
183
|
+
### Language conventions
|
|
184
|
+
|
|
185
|
+
- **Rust**: methods are `async` and return `Result<T, SdkError>`. Request structs use the [`bon`](https://docs.rs/bon) builder pattern via `::builder()`.
|
|
186
|
+
- **Python**: methods are `async` — call with `await`. Parameters are kwargs; responses are native `pyclass` objects with attribute access.
|
|
187
|
+
- **Node.js**: methods are `async` and take a single options object with camelCase keys.
|
|
188
|
+
- **Ruby**: methods are **blocking** (not async). Parameters are a single Hash with symbol keys. Responses that carry data are returned as **JSON strings** — wrap calls with `JSON.parse`. Unknown keys raise `ArgumentError`.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### Admin Client
|
|
193
|
+
|
|
194
|
+
Accessed as `qn.admin`. Manages endpoints, tags, teams, billing, usage, metrics, security, and rate limits. Backed by `https://api.quicknode.com/v0/`.
|
|
195
|
+
|
|
196
|
+
#### Endpoints
|
|
197
|
+
|
|
198
|
+
##### `get_endpoints` / `getEndpoints`
|
|
199
|
+
|
|
200
|
+
Returns a paginated list of endpoints on the account with optional search, filters (networks, statuses, labels, tags, dedicated, flat-rate), sorting, and pagination.
|
|
201
|
+
|
|
202
|
+
**Parameters** (all optional): `limit` (i32), `offset` (i32), `search` (string), `sort_by` (string), `sort_direction` (`"asc"` | `"desc"`), `networks` (string[]), `statuses` (string[]), `labels` (string[]), `dedicated` (bool), `is_flat_rate` (bool), `tag_ids` (i32[]), `tag_labels` (string[]).
|
|
203
|
+
|
|
204
|
+
**Returns**: `GetEndpointsResponse` — `{ data: Endpoint[], pagination?: Pagination }`.
|
|
205
|
+
|
|
206
|
+
```rust
|
|
207
|
+
// Rust
|
|
208
|
+
let params = GetEndpointsRequest::builder()
|
|
209
|
+
.limit(20)
|
|
210
|
+
.sort_by("created_at".to_string())
|
|
211
|
+
.sort_direction("desc".to_string())
|
|
212
|
+
.build();
|
|
213
|
+
let resp = qn.admin.get_endpoints(¶ms).await?;
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
# Python
|
|
218
|
+
resp = await qn.admin.get_endpoints(limit=20, sort_by="created_at", sort_direction="desc")
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// Node.js
|
|
223
|
+
const resp = await qn.admin.getEndpoints({
|
|
224
|
+
limit: 20,
|
|
225
|
+
sortBy: "created_at",
|
|
226
|
+
sortDirection: "desc",
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
# Ruby
|
|
232
|
+
resp = JSON.parse(qn.admin.get_endpoints(limit: 20, sort_by: "created_at", sort_direction: "desc"))
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
##### `create_endpoint` / `createEndpoint`
|
|
236
|
+
|
|
237
|
+
Creates a new endpoint for the given blockchain and network.
|
|
238
|
+
|
|
239
|
+
**Parameters**: `chain` (string, optional), `network` (string, optional).
|
|
240
|
+
|
|
241
|
+
**Returns**: `CreateEndpointResponse` with `data: SingleEndpoint`.
|
|
242
|
+
|
|
243
|
+
```rust
|
|
244
|
+
// Rust
|
|
245
|
+
let params = CreateEndpointRequest::builder()
|
|
246
|
+
.chain("ethereum".to_string())
|
|
247
|
+
.network("mainnet".to_string())
|
|
248
|
+
.build();
|
|
249
|
+
let resp = qn.admin.create_endpoint(¶ms).await?;
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
# Python
|
|
254
|
+
resp = await qn.admin.create_endpoint(chain="ethereum", network="mainnet")
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Node.js
|
|
259
|
+
const resp = await qn.admin.createEndpoint({ chain: "ethereum", network: "mainnet" });
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
```ruby
|
|
263
|
+
# Ruby
|
|
264
|
+
resp = JSON.parse(qn.admin.create_endpoint(chain: "ethereum", network: "mainnet"))
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
##### `show_endpoint` / `showEndpoint`
|
|
268
|
+
|
|
269
|
+
Fetches a single endpoint by id, including its full security configuration and rate limits.
|
|
270
|
+
|
|
271
|
+
**Parameters**: `id` (string, required).
|
|
272
|
+
|
|
273
|
+
**Returns**: `ShowEndpointResponse` with `data: SingleEndpoint`.
|
|
274
|
+
|
|
275
|
+
```rust
|
|
276
|
+
// Rust
|
|
277
|
+
let resp = qn.admin.show_endpoint("ep-123").await?;
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
# Python
|
|
282
|
+
resp = await qn.admin.show_endpoint("ep-123")
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
// Node.js
|
|
287
|
+
const resp = await qn.admin.showEndpoint("ep-123");
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
```ruby
|
|
291
|
+
# Ruby
|
|
292
|
+
resp = JSON.parse(qn.admin.show_endpoint(id: "ep-123"))
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
##### `update_endpoint` / `updateEndpoint`
|
|
296
|
+
|
|
297
|
+
Updates editable fields on an endpoint. Currently supports `label`.
|
|
298
|
+
|
|
299
|
+
**Parameters**: `id` (string, required); body: `label` (string, optional).
|
|
300
|
+
|
|
301
|
+
**Returns**: nothing.
|
|
302
|
+
|
|
303
|
+
```rust
|
|
304
|
+
// Rust
|
|
305
|
+
let params = UpdateEndpointRequest::builder().label("my label".to_string()).build();
|
|
306
|
+
qn.admin.update_endpoint("ep-123", ¶ms).await?;
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
# Python
|
|
311
|
+
await qn.admin.update_endpoint("ep-123", label="my label")
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
// Node.js
|
|
316
|
+
await qn.admin.updateEndpoint("ep-123", { label: "my label" });
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
```ruby
|
|
320
|
+
# Ruby
|
|
321
|
+
qn.admin.update_endpoint(id: "ep-123", label: "my label")
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
##### `archive_endpoint` / `archiveEndpoint`
|
|
325
|
+
|
|
326
|
+
Archives an endpoint. The HTTP verb is `DELETE` but the effect is archival, not permanent deletion.
|
|
327
|
+
|
|
328
|
+
**Parameters**: `id` (string, required).
|
|
329
|
+
|
|
330
|
+
**Returns**: nothing.
|
|
331
|
+
|
|
332
|
+
```rust
|
|
333
|
+
// Rust
|
|
334
|
+
qn.admin.archive_endpoint("ep-123").await?;
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
# Python
|
|
339
|
+
await qn.admin.archive_endpoint("ep-123")
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
// Node.js
|
|
344
|
+
await qn.admin.archiveEndpoint("ep-123");
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
```ruby
|
|
348
|
+
# Ruby
|
|
349
|
+
qn.admin.archive_endpoint(id: "ep-123")
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
##### `update_endpoint_status` / `updateEndpointStatus`
|
|
353
|
+
|
|
354
|
+
Pauses or unpauses an endpoint.
|
|
355
|
+
|
|
356
|
+
**Parameters**: `id` (string, required); body: `status` (string, required — `"active"` or `"paused"`).
|
|
357
|
+
|
|
358
|
+
**Returns**: `UpdateEndpointStatusResponse`.
|
|
359
|
+
|
|
360
|
+
```rust
|
|
361
|
+
// Rust
|
|
362
|
+
let params = UpdateEndpointStatusRequest::builder().status("paused".to_string()).build();
|
|
363
|
+
qn.admin.update_endpoint_status("ep-123", ¶ms).await?;
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
```python
|
|
367
|
+
# Python
|
|
368
|
+
await qn.admin.update_endpoint_status("ep-123", status="paused")
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
// Node.js
|
|
373
|
+
await qn.admin.updateEndpointStatus("ep-123", { status: "paused" });
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
```ruby
|
|
377
|
+
# Ruby
|
|
378
|
+
JSON.parse(qn.admin.update_endpoint_status(id: "ep-123", status: "paused"))
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### Endpoint Tags
|
|
382
|
+
|
|
383
|
+
Per-endpoint tag add/remove. For account-wide tag management see [Account Tags](#account-tags).
|
|
384
|
+
|
|
385
|
+
##### `create_tag` / `createTag`
|
|
386
|
+
|
|
387
|
+
Tags an endpoint with the given label. Creates the tag on the account if it does not exist.
|
|
388
|
+
|
|
389
|
+
**Parameters**: `id` (string, required); body: `label` (string, optional).
|
|
390
|
+
|
|
391
|
+
**Returns**: nothing.
|
|
392
|
+
|
|
393
|
+
```rust
|
|
394
|
+
// Rust
|
|
395
|
+
let params = CreateTagRequest::builder().label("prod".to_string()).build();
|
|
396
|
+
qn.admin.create_tag("ep-123", ¶ms).await?;
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
```python
|
|
400
|
+
# Python
|
|
401
|
+
await qn.admin.create_tag("ep-123", label="prod")
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
// Node.js
|
|
406
|
+
await qn.admin.createTag("ep-123", { label: "prod" });
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
```ruby
|
|
410
|
+
# Ruby
|
|
411
|
+
qn.admin.create_tag(id: "ep-123", label: "prod")
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
##### `delete_tag` / `deleteTag`
|
|
415
|
+
|
|
416
|
+
Removes a tag from a specific endpoint.
|
|
417
|
+
|
|
418
|
+
**Parameters**: `id` (endpoint id, string, required), `tag_id` (string, required).
|
|
419
|
+
|
|
420
|
+
**Returns**: nothing.
|
|
421
|
+
|
|
422
|
+
```rust
|
|
423
|
+
// Rust
|
|
424
|
+
qn.admin.delete_tag("ep-123", "42").await?;
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
```python
|
|
428
|
+
# Python
|
|
429
|
+
await qn.admin.delete_tag("ep-123", "42")
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
// Node.js
|
|
434
|
+
await qn.admin.deleteTag("ep-123", "42");
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
```ruby
|
|
438
|
+
# Ruby
|
|
439
|
+
qn.admin.delete_tag(id: "ep-123", tag_id: "42")
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### Teams
|
|
443
|
+
|
|
444
|
+
##### `list_teams` / `listTeams`
|
|
445
|
+
|
|
446
|
+
Lists all teams on the account.
|
|
447
|
+
|
|
448
|
+
**Parameters**: none.
|
|
449
|
+
|
|
450
|
+
**Returns**: `ListTeamsResponse` with `data: TeamSummary[]`.
|
|
451
|
+
|
|
452
|
+
```rust
|
|
453
|
+
// Rust
|
|
454
|
+
let resp = qn.admin.list_teams().await?;
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
```python
|
|
458
|
+
# Python
|
|
459
|
+
resp = await qn.admin.list_teams()
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
// Node.js
|
|
464
|
+
const resp = await qn.admin.listTeams();
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
```ruby
|
|
468
|
+
# Ruby
|
|
469
|
+
resp = JSON.parse(qn.admin.list_teams)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
##### `create_team` / `createTeam`
|
|
473
|
+
|
|
474
|
+
Creates a new team.
|
|
475
|
+
|
|
476
|
+
**Parameters**: `name` (string, required).
|
|
477
|
+
|
|
478
|
+
**Returns**: `CreateTeamResponse` with `data: CreateTeamData`.
|
|
479
|
+
|
|
480
|
+
```rust
|
|
481
|
+
// Rust
|
|
482
|
+
let params = CreateTeamRequest::builder().name("Payments".to_string()).build();
|
|
483
|
+
let resp = qn.admin.create_team(¶ms).await?;
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
```python
|
|
487
|
+
# Python
|
|
488
|
+
resp = await qn.admin.create_team(name="Payments")
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
// Node.js
|
|
493
|
+
const resp = await qn.admin.createTeam({ name: "Payments" });
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
```ruby
|
|
497
|
+
# Ruby
|
|
498
|
+
resp = JSON.parse(qn.admin.create_team(name: "Payments"))
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
##### `get_team` / `getTeam`
|
|
502
|
+
|
|
503
|
+
Fetches team detail including pending invites.
|
|
504
|
+
|
|
505
|
+
**Parameters**: `id` (i64, required).
|
|
506
|
+
|
|
507
|
+
**Returns**: `GetTeamResponse` with `data: TeamDetail`.
|
|
508
|
+
|
|
509
|
+
```rust
|
|
510
|
+
// Rust
|
|
511
|
+
let resp = qn.admin.get_team(42).await?;
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
```python
|
|
515
|
+
# Python
|
|
516
|
+
resp = await qn.admin.get_team(42)
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
// Node.js
|
|
521
|
+
const resp = await qn.admin.getTeam(42);
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
```ruby
|
|
525
|
+
# Ruby
|
|
526
|
+
resp = JSON.parse(qn.admin.get_team(id: 42))
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
##### `delete_team` / `deleteTeam`
|
|
530
|
+
|
|
531
|
+
Deletes a team.
|
|
532
|
+
|
|
533
|
+
**Parameters**: `id` (i64, required).
|
|
534
|
+
|
|
535
|
+
**Returns**: `DeleteTeamResponse`.
|
|
536
|
+
|
|
537
|
+
```rust
|
|
538
|
+
// Rust
|
|
539
|
+
qn.admin.delete_team(42).await?;
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
```python
|
|
543
|
+
# Python
|
|
544
|
+
await qn.admin.delete_team(42)
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
// Node.js
|
|
549
|
+
await qn.admin.deleteTeam(42);
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
```ruby
|
|
553
|
+
# Ruby
|
|
554
|
+
qn.admin.delete_team(id: 42)
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
##### `list_team_endpoints` / `listTeamEndpoints`
|
|
558
|
+
|
|
559
|
+
Lists endpoints accessible to a team.
|
|
560
|
+
|
|
561
|
+
**Parameters**: `id` (i64, required).
|
|
562
|
+
|
|
563
|
+
**Returns**: `ListTeamEndpointsResponse` with `data: TeamEndpoint[]`.
|
|
564
|
+
|
|
565
|
+
```rust
|
|
566
|
+
// Rust
|
|
567
|
+
let resp = qn.admin.list_team_endpoints(42).await?;
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
```python
|
|
571
|
+
# Python
|
|
572
|
+
resp = await qn.admin.list_team_endpoints(42)
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
```typescript
|
|
576
|
+
// Node.js
|
|
577
|
+
const resp = await qn.admin.listTeamEndpoints(42);
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
```ruby
|
|
581
|
+
# Ruby
|
|
582
|
+
resp = JSON.parse(qn.admin.list_team_endpoints(id: 42))
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
##### `update_team_endpoints` / `updateTeamEndpoints`
|
|
586
|
+
|
|
587
|
+
Replaces the set of endpoints associated with a team. Pass an empty array to remove all.
|
|
588
|
+
|
|
589
|
+
**Parameters**: `id` (i64, required); body: `endpoint_ids` (string[], required).
|
|
590
|
+
|
|
591
|
+
**Returns**: `UpdateTeamEndpointsResponse`.
|
|
592
|
+
|
|
593
|
+
```rust
|
|
594
|
+
// Rust
|
|
595
|
+
let params = UpdateTeamEndpointsRequest::builder()
|
|
596
|
+
.endpoint_ids(vec!["ep-123".to_string(), "ep-456".to_string()])
|
|
597
|
+
.build();
|
|
598
|
+
qn.admin.update_team_endpoints(42, ¶ms).await?;
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
```python
|
|
602
|
+
# Python
|
|
603
|
+
await qn.admin.update_team_endpoints(42, endpoint_ids=["ep-123", "ep-456"])
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
// Node.js
|
|
608
|
+
await qn.admin.updateTeamEndpoints(42, { endpointIds: ["ep-123", "ep-456"] });
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
```ruby
|
|
612
|
+
# Ruby
|
|
613
|
+
qn.admin.update_team_endpoints(id: 42, endpoint_ids: ["ep-123", "ep-456"])
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
##### `invite_team_member` / `inviteTeamMember`
|
|
617
|
+
|
|
618
|
+
Invites a user to a team. Existing users only need `email`; new users require `full_name` and `role`.
|
|
619
|
+
|
|
620
|
+
**Parameters**: `id` (i64, required); body: `email` (string, required), `full_name` (string, optional), `role` (string, optional — `admin` | `viewer` | `billing`).
|
|
621
|
+
|
|
622
|
+
**Returns**: `InviteTeamMemberResponse`.
|
|
623
|
+
|
|
624
|
+
```rust
|
|
625
|
+
// Rust
|
|
626
|
+
let params = InviteTeamMemberRequest::builder()
|
|
627
|
+
.email("alice@example.com".to_string())
|
|
628
|
+
.role("viewer".to_string())
|
|
629
|
+
.build();
|
|
630
|
+
qn.admin.invite_team_member(42, ¶ms).await?;
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
```python
|
|
634
|
+
# Python
|
|
635
|
+
await qn.admin.invite_team_member(42, email="alice@example.com", role="viewer")
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
// Node.js
|
|
640
|
+
await qn.admin.inviteTeamMember(42, { email: "alice@example.com", role: "viewer" });
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
```ruby
|
|
644
|
+
# Ruby
|
|
645
|
+
qn.admin.invite_team_member(id: 42, email: "alice@example.com", role: "viewer")
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
##### `remove_team_member` / `removeTeamMember`
|
|
649
|
+
|
|
650
|
+
Removes a user from a team.
|
|
651
|
+
|
|
652
|
+
**Parameters**: `id` (team id, i64, required), `user_id` (i64, required).
|
|
653
|
+
|
|
654
|
+
**Returns**: `RemoveTeamMemberResponse`.
|
|
655
|
+
|
|
656
|
+
```rust
|
|
657
|
+
// Rust
|
|
658
|
+
qn.admin.remove_team_member(42, 7).await?;
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
```python
|
|
662
|
+
# Python
|
|
663
|
+
await qn.admin.remove_team_member(42, 7)
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
```typescript
|
|
667
|
+
// Node.js
|
|
668
|
+
await qn.admin.removeTeamMember(42, 7);
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
```ruby
|
|
672
|
+
# Ruby
|
|
673
|
+
qn.admin.remove_team_member(id: 42, user_id: 7)
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
##### `resend_team_invite` / `resendTeamInvite`
|
|
677
|
+
|
|
678
|
+
Re-sends a pending team invitation.
|
|
679
|
+
|
|
680
|
+
**Parameters**: `id` (team id, i64, required), `user_id` (i64, required).
|
|
681
|
+
|
|
682
|
+
**Returns**: `ResendTeamInviteResponse`.
|
|
683
|
+
|
|
684
|
+
```rust
|
|
685
|
+
// Rust
|
|
686
|
+
qn.admin.resend_team_invite(42, 7).await?;
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
```python
|
|
690
|
+
# Python
|
|
691
|
+
await qn.admin.resend_team_invite(42, 7)
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
```typescript
|
|
695
|
+
// Node.js
|
|
696
|
+
await qn.admin.resendTeamInvite(42, 7);
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
```ruby
|
|
700
|
+
# Ruby
|
|
701
|
+
qn.admin.resend_team_invite(id: 42, user_id: 7)
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
#### Usage
|
|
705
|
+
|
|
706
|
+
All usage methods accept optional `start_time` and `end_time` Unix timestamps. Omit both for account-to-date totals.
|
|
707
|
+
|
|
708
|
+
##### `get_usage` / `getUsage`
|
|
709
|
+
|
|
710
|
+
Aggregate account usage for a time window.
|
|
711
|
+
|
|
712
|
+
**Returns**: `GetUsageResponse` with `data: UsageData` (`credits_used`, `credits_remaining`, `limit`, `overages`, `start_time`, `end_time`).
|
|
713
|
+
|
|
714
|
+
```rust
|
|
715
|
+
// Rust
|
|
716
|
+
let resp = qn.admin.get_usage(&GetUsageRequest::default()).await?;
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
```python
|
|
720
|
+
# Python
|
|
721
|
+
resp = await qn.admin.get_usage()
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
```typescript
|
|
725
|
+
// Node.js
|
|
726
|
+
const resp = await qn.admin.getUsage();
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
```ruby
|
|
730
|
+
# Ruby
|
|
731
|
+
resp = JSON.parse(qn.admin.get_usage({}))
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
##### `get_usage_by_endpoint` / `getUsageByEndpoint`
|
|
735
|
+
|
|
736
|
+
Per-endpoint usage breakdown.
|
|
737
|
+
|
|
738
|
+
**Returns**: `GetUsageByEndpointResponse` with `data.endpoints: EndpointUsage[]`.
|
|
739
|
+
|
|
740
|
+
```rust
|
|
741
|
+
// Rust
|
|
742
|
+
let resp = qn.admin.get_usage_by_endpoint(&GetUsageRequest::default()).await?;
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
```python
|
|
746
|
+
# Python
|
|
747
|
+
resp = await qn.admin.get_usage_by_endpoint()
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
// Node.js
|
|
752
|
+
const resp = await qn.admin.getUsageByEndpoint();
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
```ruby
|
|
756
|
+
# Ruby
|
|
757
|
+
resp = JSON.parse(qn.admin.get_usage_by_endpoint({}))
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
##### `get_usage_by_method` / `getUsageByMethod`
|
|
761
|
+
|
|
762
|
+
Per-RPC-method usage breakdown.
|
|
763
|
+
|
|
764
|
+
**Returns**: `GetUsageByMethodResponse` with `data.methods: MethodUsage[]`.
|
|
765
|
+
|
|
766
|
+
```rust
|
|
767
|
+
// Rust
|
|
768
|
+
let resp = qn.admin.get_usage_by_method(&GetUsageRequest::default()).await?;
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
```python
|
|
772
|
+
# Python
|
|
773
|
+
resp = await qn.admin.get_usage_by_method()
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
```typescript
|
|
777
|
+
// Node.js
|
|
778
|
+
const resp = await qn.admin.getUsageByMethod();
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
```ruby
|
|
782
|
+
# Ruby
|
|
783
|
+
resp = JSON.parse(qn.admin.get_usage_by_method({}))
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
##### `get_usage_by_chain` / `getUsageByChain`
|
|
787
|
+
|
|
788
|
+
Per-chain usage breakdown.
|
|
789
|
+
|
|
790
|
+
**Returns**: `GetUsageByChainResponse` with `data.chains: ChainUsage[]`.
|
|
791
|
+
|
|
792
|
+
```rust
|
|
793
|
+
// Rust
|
|
794
|
+
let resp = qn.admin.get_usage_by_chain(&GetUsageRequest::default()).await?;
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
```python
|
|
798
|
+
# Python
|
|
799
|
+
resp = await qn.admin.get_usage_by_chain()
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
```typescript
|
|
803
|
+
// Node.js
|
|
804
|
+
const resp = await qn.admin.getUsageByChain();
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
```ruby
|
|
808
|
+
# Ruby
|
|
809
|
+
resp = JSON.parse(qn.admin.get_usage_by_chain({}))
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
##### `get_usage_by_tag` / `getUsageByTag`
|
|
813
|
+
|
|
814
|
+
Per-tag usage breakdown.
|
|
815
|
+
|
|
816
|
+
**Returns**: `GetUsageByTagResponse` with `data.tags: TagUsage[]`.
|
|
817
|
+
|
|
818
|
+
```rust
|
|
819
|
+
// Rust
|
|
820
|
+
let resp = qn.admin.get_usage_by_tag(&GetUsageRequest::default()).await?;
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
```python
|
|
824
|
+
# Python
|
|
825
|
+
resp = await qn.admin.get_usage_by_tag()
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
```typescript
|
|
829
|
+
// Node.js
|
|
830
|
+
const resp = await qn.admin.getUsageByTag();
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
```ruby
|
|
834
|
+
# Ruby
|
|
835
|
+
resp = JSON.parse(qn.admin.get_usage_by_tag({}))
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
#### Logs
|
|
839
|
+
|
|
840
|
+
##### `get_endpoint_logs` / `getEndpointLogs`
|
|
841
|
+
|
|
842
|
+
Fetches a page of request logs for an endpoint. Set `include_details=true` for full request/response payloads (truncated at 2 KB each).
|
|
843
|
+
|
|
844
|
+
**Parameters**: `id` (endpoint id, required); body: `from` (string timestamp, required), `to` (string timestamp, required), `include_details` (bool, optional), `limit` (i32, optional), `next_at` (string cursor, optional).
|
|
845
|
+
|
|
846
|
+
**Returns**: `GetEndpointLogsResponse` — `{ data: EndpointLog[], next_at?: string }`.
|
|
847
|
+
|
|
848
|
+
```rust
|
|
849
|
+
// Rust
|
|
850
|
+
let params = GetEndpointLogsRequest::builder()
|
|
851
|
+
.from("2026-04-01T00:00:00Z".to_string())
|
|
852
|
+
.to("2026-04-02T00:00:00Z".to_string())
|
|
853
|
+
.limit(100)
|
|
854
|
+
.build();
|
|
855
|
+
let resp = qn.admin.get_endpoint_logs("ep-123", ¶ms).await?;
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
```python
|
|
859
|
+
# Python
|
|
860
|
+
resp = await qn.admin.get_endpoint_logs(
|
|
861
|
+
"ep-123",
|
|
862
|
+
from_time="2026-04-01T00:00:00Z",
|
|
863
|
+
to_time="2026-04-02T00:00:00Z",
|
|
864
|
+
limit=100,
|
|
865
|
+
)
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
```typescript
|
|
869
|
+
// Node.js
|
|
870
|
+
const resp = await qn.admin.getEndpointLogs("ep-123", {
|
|
871
|
+
from: "2026-04-01T00:00:00Z",
|
|
872
|
+
to: "2026-04-02T00:00:00Z",
|
|
873
|
+
limit: 100,
|
|
874
|
+
});
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
```ruby
|
|
878
|
+
# Ruby
|
|
879
|
+
resp = JSON.parse(qn.admin.get_endpoint_logs(
|
|
880
|
+
id: "ep-123",
|
|
881
|
+
from_time: "2026-04-01T00:00:00Z",
|
|
882
|
+
to_time: "2026-04-02T00:00:00Z",
|
|
883
|
+
limit: 100
|
|
884
|
+
))
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
##### `get_log_details` / `getLogDetails`
|
|
888
|
+
|
|
889
|
+
Returns the full request/response payloads for a single log entry.
|
|
890
|
+
|
|
891
|
+
**Parameters**: `id` (endpoint id, required), `request_id` (log request uuid, required).
|
|
892
|
+
|
|
893
|
+
**Returns**: `GetLogDetailsResponse` with `data: LogDetails`.
|
|
894
|
+
|
|
895
|
+
```rust
|
|
896
|
+
// Rust
|
|
897
|
+
let resp = qn.admin.get_log_details("ep-123", "req-abc").await?;
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
```python
|
|
901
|
+
# Python
|
|
902
|
+
resp = await qn.admin.get_log_details("ep-123", "req-abc")
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
```typescript
|
|
906
|
+
// Node.js
|
|
907
|
+
const resp = await qn.admin.getLogDetails("ep-123", "req-abc");
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
```ruby
|
|
911
|
+
# Ruby
|
|
912
|
+
resp = JSON.parse(qn.admin.get_log_details(id: "ep-123", request_id: "req-abc"))
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
#### Endpoint Security
|
|
916
|
+
|
|
917
|
+
##### `get_endpoint_security` / `getEndpointSecurity`
|
|
918
|
+
|
|
919
|
+
Returns the full security configuration for an endpoint: tokens, JWTs, referrers, domain masks, IPs, request filters, and their per-feature toggles.
|
|
920
|
+
|
|
921
|
+
**Parameters**: `id` (string, required).
|
|
922
|
+
|
|
923
|
+
**Returns**: `GetEndpointSecurityResponse` with `data: EndpointSecurity`.
|
|
924
|
+
|
|
925
|
+
```rust
|
|
926
|
+
// Rust
|
|
927
|
+
let resp = qn.admin.get_endpoint_security("ep-123").await?;
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
```python
|
|
931
|
+
# Python
|
|
932
|
+
resp = await qn.admin.get_endpoint_security("ep-123")
|
|
933
|
+
```
|
|
934
|
+
|
|
935
|
+
```typescript
|
|
936
|
+
// Node.js
|
|
937
|
+
const resp = await qn.admin.getEndpointSecurity("ep-123");
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
```ruby
|
|
941
|
+
# Ruby
|
|
942
|
+
resp = JSON.parse(qn.admin.get_endpoint_security(id: "ep-123"))
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
#### Security Options
|
|
946
|
+
|
|
947
|
+
##### `get_security_options` / `getSecurityOptions`
|
|
948
|
+
|
|
949
|
+
Returns the list of security features and their enabled state for an endpoint.
|
|
950
|
+
|
|
951
|
+
**Parameters**: `id` (string, required).
|
|
952
|
+
|
|
953
|
+
**Returns**: `GetSecurityOptionsResponse` with `data: SecurityOption[]`.
|
|
954
|
+
|
|
955
|
+
```rust
|
|
956
|
+
// Rust
|
|
957
|
+
let resp = qn.admin.get_security_options("ep-123").await?;
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
```python
|
|
961
|
+
# Python
|
|
962
|
+
resp = await qn.admin.get_security_options("ep-123")
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
```typescript
|
|
966
|
+
// Node.js
|
|
967
|
+
const resp = await qn.admin.getSecurityOptions("ep-123");
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
```ruby
|
|
971
|
+
# Ruby
|
|
972
|
+
resp = JSON.parse(qn.admin.get_security_options(id: "ep-123"))
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
##### `update_security_options` / `updateSecurityOptions`
|
|
976
|
+
|
|
977
|
+
Enables or disables individual security features. Each field accepts `"enabled"` or `"disabled"`.
|
|
978
|
+
|
|
979
|
+
**Parameters**: `id` (string, required); `options`: `SecurityOptionsUpdate` (`tokens`, `referrers`, `jwts`, `ips`, `domain_masks`, `hsts`, `cors`, `request_filters`, `ip_custom_header`).
|
|
980
|
+
|
|
981
|
+
**Returns**: `UpdateSecurityOptionsResponse` with updated `SecurityOption[]`.
|
|
982
|
+
|
|
983
|
+
```rust
|
|
984
|
+
// Rust
|
|
985
|
+
let options = SecurityOptionsUpdate::builder()
|
|
986
|
+
.tokens("enabled".to_string())
|
|
987
|
+
.jwts("disabled".to_string())
|
|
988
|
+
.build();
|
|
989
|
+
let params = UpdateSecurityOptionsRequest { options };
|
|
990
|
+
qn.admin.update_security_options("ep-123", ¶ms).await?;
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
```python
|
|
994
|
+
# Python
|
|
995
|
+
await qn.admin.update_security_options(
|
|
996
|
+
"ep-123",
|
|
997
|
+
tokens="enabled",
|
|
998
|
+
jwts="disabled",
|
|
999
|
+
)
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
```typescript
|
|
1003
|
+
// Node.js
|
|
1004
|
+
await qn.admin.updateSecurityOptions("ep-123", {
|
|
1005
|
+
options: { tokens: "enabled", jwts: "disabled" },
|
|
1006
|
+
});
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
```ruby
|
|
1010
|
+
# Ruby
|
|
1011
|
+
qn.admin.update_security_options(id: "ep-123", tokens: "enabled", jwts: "disabled")
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
#### Tokens
|
|
1015
|
+
|
|
1016
|
+
##### `create_token` / `createToken`
|
|
1017
|
+
|
|
1018
|
+
Generates a new auth token on an endpoint.
|
|
1019
|
+
|
|
1020
|
+
**Parameters**: `id` (endpoint id, required).
|
|
1021
|
+
|
|
1022
|
+
**Returns**: nothing.
|
|
1023
|
+
|
|
1024
|
+
```rust
|
|
1025
|
+
// Rust
|
|
1026
|
+
qn.admin.create_token("ep-123").await?;
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
```python
|
|
1030
|
+
# Python
|
|
1031
|
+
await qn.admin.create_token("ep-123")
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
```typescript
|
|
1035
|
+
// Node.js
|
|
1036
|
+
await qn.admin.createToken("ep-123");
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
```ruby
|
|
1040
|
+
# Ruby
|
|
1041
|
+
qn.admin.create_token(id: "ep-123")
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
##### `delete_token` / `deleteToken`
|
|
1045
|
+
|
|
1046
|
+
Revokes a token on an endpoint.
|
|
1047
|
+
|
|
1048
|
+
**Parameters**: `id` (endpoint id, required), `token_id` (string, required).
|
|
1049
|
+
|
|
1050
|
+
**Returns**: nothing.
|
|
1051
|
+
|
|
1052
|
+
```rust
|
|
1053
|
+
// Rust
|
|
1054
|
+
qn.admin.delete_token("ep-123", "tok-1").await?;
|
|
1055
|
+
```
|
|
1056
|
+
|
|
1057
|
+
```python
|
|
1058
|
+
# Python
|
|
1059
|
+
await qn.admin.delete_token("ep-123", "tok-1")
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
```typescript
|
|
1063
|
+
// Node.js
|
|
1064
|
+
await qn.admin.deleteToken("ep-123", "tok-1");
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
```ruby
|
|
1068
|
+
# Ruby
|
|
1069
|
+
qn.admin.delete_token(id: "ep-123", token_id: "tok-1")
|
|
1070
|
+
```
|
|
1071
|
+
|
|
1072
|
+
#### Referrers
|
|
1073
|
+
|
|
1074
|
+
##### `create_referrer` / `createReferrer`
|
|
1075
|
+
|
|
1076
|
+
Whitelists a referrer URL or domain on an endpoint.
|
|
1077
|
+
|
|
1078
|
+
**Parameters**: `id` (endpoint id, required); body: `referrer` (string, optional).
|
|
1079
|
+
|
|
1080
|
+
**Returns**: nothing.
|
|
1081
|
+
|
|
1082
|
+
```rust
|
|
1083
|
+
// Rust
|
|
1084
|
+
let params = CreateReferrerRequest::builder().referrer("example.com".to_string()).build();
|
|
1085
|
+
qn.admin.create_referrer("ep-123", ¶ms).await?;
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
```python
|
|
1089
|
+
# Python
|
|
1090
|
+
await qn.admin.create_referrer("ep-123", referrer="example.com")
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
```typescript
|
|
1094
|
+
// Node.js
|
|
1095
|
+
await qn.admin.createReferrer("ep-123", { referrer: "example.com" });
|
|
1096
|
+
```
|
|
1097
|
+
|
|
1098
|
+
```ruby
|
|
1099
|
+
# Ruby
|
|
1100
|
+
qn.admin.create_referrer(id: "ep-123", referrer: "example.com")
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
##### `delete_referrer` / `deleteReferrer`
|
|
1104
|
+
|
|
1105
|
+
Removes a referrer from the whitelist.
|
|
1106
|
+
|
|
1107
|
+
**Parameters**: `id` (endpoint id, required), `referrer_id` (string, required).
|
|
1108
|
+
|
|
1109
|
+
**Returns**: nothing.
|
|
1110
|
+
|
|
1111
|
+
```rust
|
|
1112
|
+
// Rust
|
|
1113
|
+
qn.admin.delete_referrer("ep-123", "ref-1").await?;
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
```python
|
|
1117
|
+
# Python
|
|
1118
|
+
await qn.admin.delete_referrer("ep-123", "ref-1")
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
```typescript
|
|
1122
|
+
// Node.js
|
|
1123
|
+
await qn.admin.deleteReferrer("ep-123", "ref-1");
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
```ruby
|
|
1127
|
+
# Ruby
|
|
1128
|
+
qn.admin.delete_referrer(id: "ep-123", referrer_id: "ref-1")
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
#### IPs
|
|
1132
|
+
|
|
1133
|
+
##### `create_ip` / `createIp`
|
|
1134
|
+
|
|
1135
|
+
Whitelists an IP address on an endpoint.
|
|
1136
|
+
|
|
1137
|
+
**Parameters**: `id` (endpoint id, required); body: `ip` (string, optional).
|
|
1138
|
+
|
|
1139
|
+
**Returns**: nothing.
|
|
1140
|
+
|
|
1141
|
+
```rust
|
|
1142
|
+
// Rust
|
|
1143
|
+
let params = CreateIpRequest::builder().ip("198.51.100.7".to_string()).build();
|
|
1144
|
+
qn.admin.create_ip("ep-123", ¶ms).await?;
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
```python
|
|
1148
|
+
# Python
|
|
1149
|
+
await qn.admin.create_ip("ep-123", ip="198.51.100.7")
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
```typescript
|
|
1153
|
+
// Node.js
|
|
1154
|
+
await qn.admin.createIp("ep-123", { ip: "198.51.100.7" });
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1157
|
+
```ruby
|
|
1158
|
+
# Ruby
|
|
1159
|
+
qn.admin.create_ip(id: "ep-123", ip: "198.51.100.7")
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
##### `delete_ip` / `deleteIp`
|
|
1163
|
+
|
|
1164
|
+
Removes an IP from the whitelist.
|
|
1165
|
+
|
|
1166
|
+
**Parameters**: `id` (endpoint id, required), `ip_id` (string, required).
|
|
1167
|
+
|
|
1168
|
+
**Returns**: `DeleteBoolResponse`.
|
|
1169
|
+
|
|
1170
|
+
```rust
|
|
1171
|
+
// Rust
|
|
1172
|
+
qn.admin.delete_ip("ep-123", "ip-1").await?;
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
```python
|
|
1176
|
+
# Python
|
|
1177
|
+
await qn.admin.delete_ip("ep-123", "ip-1")
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
```typescript
|
|
1181
|
+
// Node.js
|
|
1182
|
+
await qn.admin.deleteIp("ep-123", "ip-1");
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
```ruby
|
|
1186
|
+
# Ruby
|
|
1187
|
+
resp = JSON.parse(qn.admin.delete_ip(id: "ep-123", ip_id: "ip-1"))
|
|
1188
|
+
```
|
|
1189
|
+
|
|
1190
|
+
#### Domain Masks
|
|
1191
|
+
|
|
1192
|
+
##### `create_domain_mask` / `createDomainMask`
|
|
1193
|
+
|
|
1194
|
+
Adds a custom domain mask to an endpoint.
|
|
1195
|
+
|
|
1196
|
+
**Parameters**: `id` (endpoint id, required); body: `domain_mask` (string, optional).
|
|
1197
|
+
|
|
1198
|
+
**Returns**: nothing.
|
|
1199
|
+
|
|
1200
|
+
```rust
|
|
1201
|
+
// Rust
|
|
1202
|
+
let params = CreateDomainMaskRequest::builder()
|
|
1203
|
+
.domain_mask("rpc.example.com".to_string())
|
|
1204
|
+
.build();
|
|
1205
|
+
qn.admin.create_domain_mask("ep-123", ¶ms).await?;
|
|
1206
|
+
```
|
|
1207
|
+
|
|
1208
|
+
```python
|
|
1209
|
+
# Python
|
|
1210
|
+
await qn.admin.create_domain_mask("ep-123", domain_mask="rpc.example.com")
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
```typescript
|
|
1214
|
+
// Node.js
|
|
1215
|
+
await qn.admin.createDomainMask("ep-123", { domainMask: "rpc.example.com" });
|
|
1216
|
+
```
|
|
1217
|
+
|
|
1218
|
+
```ruby
|
|
1219
|
+
# Ruby
|
|
1220
|
+
qn.admin.create_domain_mask(id: "ep-123", domain_mask: "rpc.example.com")
|
|
1221
|
+
```
|
|
1222
|
+
|
|
1223
|
+
##### `delete_domain_mask` / `deleteDomainMask`
|
|
1224
|
+
|
|
1225
|
+
Removes a domain mask.
|
|
1226
|
+
|
|
1227
|
+
**Parameters**: `id` (endpoint id, required), `domain_mask_id` (string, required).
|
|
1228
|
+
|
|
1229
|
+
**Returns**: nothing.
|
|
1230
|
+
|
|
1231
|
+
```rust
|
|
1232
|
+
// Rust
|
|
1233
|
+
qn.admin.delete_domain_mask("ep-123", "dm-1").await?;
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
```python
|
|
1237
|
+
# Python
|
|
1238
|
+
await qn.admin.delete_domain_mask("ep-123", "dm-1")
|
|
1239
|
+
```
|
|
1240
|
+
|
|
1241
|
+
```typescript
|
|
1242
|
+
// Node.js
|
|
1243
|
+
await qn.admin.deleteDomainMask("ep-123", "dm-1");
|
|
1244
|
+
```
|
|
1245
|
+
|
|
1246
|
+
```ruby
|
|
1247
|
+
# Ruby
|
|
1248
|
+
qn.admin.delete_domain_mask(id: "ep-123", domain_mask_id: "dm-1")
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
#### JWTs
|
|
1252
|
+
|
|
1253
|
+
##### `create_jwt` / `createJwt`
|
|
1254
|
+
|
|
1255
|
+
Configures JWT validation on an endpoint.
|
|
1256
|
+
|
|
1257
|
+
**Parameters**: `id` (endpoint id, required); body: `public_key` (string, optional), `kid` (string, optional), `name` (string, optional).
|
|
1258
|
+
|
|
1259
|
+
**Returns**: nothing.
|
|
1260
|
+
|
|
1261
|
+
```rust
|
|
1262
|
+
// Rust
|
|
1263
|
+
let params = CreateJwtRequest::builder()
|
|
1264
|
+
.public_key("-----BEGIN PUBLIC KEY-----\n...".to_string())
|
|
1265
|
+
.kid("key-1".to_string())
|
|
1266
|
+
.name("primary".to_string())
|
|
1267
|
+
.build();
|
|
1268
|
+
qn.admin.create_jwt("ep-123", ¶ms).await?;
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1271
|
+
```python
|
|
1272
|
+
# Python
|
|
1273
|
+
await qn.admin.create_jwt(
|
|
1274
|
+
"ep-123",
|
|
1275
|
+
public_key="-----BEGIN PUBLIC KEY-----\n...",
|
|
1276
|
+
kid="key-1",
|
|
1277
|
+
name="primary",
|
|
1278
|
+
)
|
|
1279
|
+
```
|
|
1280
|
+
|
|
1281
|
+
```typescript
|
|
1282
|
+
// Node.js
|
|
1283
|
+
await qn.admin.createJwt("ep-123", {
|
|
1284
|
+
publicKey: "-----BEGIN PUBLIC KEY-----\n...",
|
|
1285
|
+
kid: "key-1",
|
|
1286
|
+
name: "primary",
|
|
1287
|
+
});
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
```ruby
|
|
1291
|
+
# Ruby
|
|
1292
|
+
qn.admin.create_jwt(
|
|
1293
|
+
id: "ep-123",
|
|
1294
|
+
public_key: "-----BEGIN PUBLIC KEY-----\n...",
|
|
1295
|
+
kid: "key-1",
|
|
1296
|
+
name: "primary"
|
|
1297
|
+
)
|
|
1298
|
+
```
|
|
1299
|
+
|
|
1300
|
+
##### `delete_jwt` / `deleteJwt`
|
|
1301
|
+
|
|
1302
|
+
Removes a JWT configuration.
|
|
1303
|
+
|
|
1304
|
+
**Parameters**: `id` (endpoint id, required), `jwt_id` (string, required).
|
|
1305
|
+
|
|
1306
|
+
**Returns**: nothing.
|
|
1307
|
+
|
|
1308
|
+
```rust
|
|
1309
|
+
// Rust
|
|
1310
|
+
qn.admin.delete_jwt("ep-123", "jwt-1").await?;
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
```python
|
|
1314
|
+
# Python
|
|
1315
|
+
await qn.admin.delete_jwt("ep-123", "jwt-1")
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
```typescript
|
|
1319
|
+
// Node.js
|
|
1320
|
+
await qn.admin.deleteJwt("ep-123", "jwt-1");
|
|
1321
|
+
```
|
|
1322
|
+
|
|
1323
|
+
```ruby
|
|
1324
|
+
# Ruby
|
|
1325
|
+
qn.admin.delete_jwt(id: "ep-123", jwt_id: "jwt-1")
|
|
1326
|
+
```
|
|
1327
|
+
|
|
1328
|
+
#### Request Filters
|
|
1329
|
+
|
|
1330
|
+
Whitelist specific RPC methods on an endpoint. Requests for methods not on the list are blocked when the feature is enabled.
|
|
1331
|
+
|
|
1332
|
+
##### `create_request_filter` / `createRequestFilter`
|
|
1333
|
+
|
|
1334
|
+
**Parameters**: `id` (endpoint id, required); body: `method` (string[], optional). Ruby's Hash key is `methods` (plural).
|
|
1335
|
+
|
|
1336
|
+
**Returns**: `CreateRequestFilterResponse` with `data.id`.
|
|
1337
|
+
|
|
1338
|
+
```rust
|
|
1339
|
+
// Rust
|
|
1340
|
+
let params = CreateRequestFilterRequest::builder()
|
|
1341
|
+
.method(vec!["eth_blockNumber".to_string(), "eth_getBalance".to_string()])
|
|
1342
|
+
.build();
|
|
1343
|
+
let resp = qn.admin.create_request_filter("ep-123", ¶ms).await?;
|
|
1344
|
+
```
|
|
1345
|
+
|
|
1346
|
+
```python
|
|
1347
|
+
# Python
|
|
1348
|
+
resp = await qn.admin.create_request_filter(
|
|
1349
|
+
"ep-123",
|
|
1350
|
+
method=["eth_blockNumber", "eth_getBalance"],
|
|
1351
|
+
)
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
```typescript
|
|
1355
|
+
// Node.js
|
|
1356
|
+
const resp = await qn.admin.createRequestFilter("ep-123", {
|
|
1357
|
+
method: ["eth_blockNumber", "eth_getBalance"],
|
|
1358
|
+
});
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
```ruby
|
|
1362
|
+
# Ruby
|
|
1363
|
+
resp = JSON.parse(qn.admin.create_request_filter(
|
|
1364
|
+
id: "ep-123",
|
|
1365
|
+
methods: ["eth_blockNumber", "eth_getBalance"]
|
|
1366
|
+
))
|
|
1367
|
+
```
|
|
1368
|
+
|
|
1369
|
+
##### `update_request_filter` / `updateRequestFilter`
|
|
1370
|
+
|
|
1371
|
+
**Parameters**: `id` (endpoint id, required), `request_filter_id` (string, required); body: `method` (string[], optional). Ruby's Hash keys are `request_filter_id` and `methods` (plural).
|
|
1372
|
+
|
|
1373
|
+
**Returns**: nothing.
|
|
1374
|
+
|
|
1375
|
+
```rust
|
|
1376
|
+
// Rust
|
|
1377
|
+
let params = UpdateRequestFilterRequest::builder()
|
|
1378
|
+
.method(vec!["eth_call".to_string()])
|
|
1379
|
+
.build();
|
|
1380
|
+
qn.admin.update_request_filter("ep-123", "f-1", ¶ms).await?;
|
|
1381
|
+
```
|
|
1382
|
+
|
|
1383
|
+
```python
|
|
1384
|
+
# Python
|
|
1385
|
+
await qn.admin.update_request_filter("ep-123", "f-1", method=["eth_call"])
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
```typescript
|
|
1389
|
+
// Node.js
|
|
1390
|
+
await qn.admin.updateRequestFilter("ep-123", "f-1", { method: ["eth_call"] });
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
```ruby
|
|
1394
|
+
# Ruby
|
|
1395
|
+
qn.admin.update_request_filter(id: "ep-123", request_filter_id: "f-1", methods: ["eth_call"])
|
|
1396
|
+
```
|
|
1397
|
+
|
|
1398
|
+
##### `delete_request_filter` / `deleteRequestFilter`
|
|
1399
|
+
|
|
1400
|
+
**Parameters**: `id` (endpoint id, required), `request_filter_id` (string, required).
|
|
1401
|
+
|
|
1402
|
+
**Returns**: nothing.
|
|
1403
|
+
|
|
1404
|
+
```rust
|
|
1405
|
+
// Rust
|
|
1406
|
+
qn.admin.delete_request_filter("ep-123", "f-1").await?;
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
```python
|
|
1410
|
+
# Python
|
|
1411
|
+
await qn.admin.delete_request_filter("ep-123", "f-1")
|
|
1412
|
+
```
|
|
1413
|
+
|
|
1414
|
+
```typescript
|
|
1415
|
+
// Node.js
|
|
1416
|
+
await qn.admin.deleteRequestFilter("ep-123", "f-1");
|
|
1417
|
+
```
|
|
1418
|
+
|
|
1419
|
+
```ruby
|
|
1420
|
+
# Ruby
|
|
1421
|
+
qn.admin.delete_request_filter(id: "ep-123", request_filter_id: "f-1")
|
|
1422
|
+
```
|
|
1423
|
+
|
|
1424
|
+
#### Multichain
|
|
1425
|
+
|
|
1426
|
+
##### `enable_multichain` / `enableMultichain`
|
|
1427
|
+
|
|
1428
|
+
Enables multichain on an endpoint.
|
|
1429
|
+
|
|
1430
|
+
**Parameters**: `id` (endpoint id, required).
|
|
1431
|
+
|
|
1432
|
+
**Returns**: nothing.
|
|
1433
|
+
|
|
1434
|
+
```rust
|
|
1435
|
+
// Rust
|
|
1436
|
+
qn.admin.enable_multichain("ep-123").await?;
|
|
1437
|
+
```
|
|
1438
|
+
|
|
1439
|
+
```python
|
|
1440
|
+
# Python
|
|
1441
|
+
await qn.admin.enable_multichain("ep-123")
|
|
1442
|
+
```
|
|
1443
|
+
|
|
1444
|
+
```typescript
|
|
1445
|
+
// Node.js
|
|
1446
|
+
await qn.admin.enableMultichain("ep-123");
|
|
1447
|
+
```
|
|
1448
|
+
|
|
1449
|
+
```ruby
|
|
1450
|
+
# Ruby
|
|
1451
|
+
qn.admin.enable_multichain(id: "ep-123")
|
|
1452
|
+
```
|
|
1453
|
+
|
|
1454
|
+
##### `disable_multichain` / `disableMultichain`
|
|
1455
|
+
|
|
1456
|
+
Disables multichain on an endpoint.
|
|
1457
|
+
|
|
1458
|
+
**Parameters**: `id` (endpoint id, required).
|
|
1459
|
+
|
|
1460
|
+
**Returns**: nothing.
|
|
1461
|
+
|
|
1462
|
+
```rust
|
|
1463
|
+
// Rust
|
|
1464
|
+
qn.admin.disable_multichain("ep-123").await?;
|
|
1465
|
+
```
|
|
1466
|
+
|
|
1467
|
+
```python
|
|
1468
|
+
# Python
|
|
1469
|
+
await qn.admin.disable_multichain("ep-123")
|
|
1470
|
+
```
|
|
1471
|
+
|
|
1472
|
+
```typescript
|
|
1473
|
+
// Node.js
|
|
1474
|
+
await qn.admin.disableMultichain("ep-123");
|
|
1475
|
+
```
|
|
1476
|
+
|
|
1477
|
+
```ruby
|
|
1478
|
+
# Ruby
|
|
1479
|
+
qn.admin.disable_multichain(id: "ep-123")
|
|
1480
|
+
```
|
|
1481
|
+
|
|
1482
|
+
#### IP Custom Headers
|
|
1483
|
+
|
|
1484
|
+
##### `create_or_update_ip_custom_header` / `createOrUpdateIpCustomHeader`
|
|
1485
|
+
|
|
1486
|
+
Sets the custom header used to identify the client IP (e.g. when traffic is proxied).
|
|
1487
|
+
|
|
1488
|
+
**Parameters**: `id` (endpoint id, required); body: `header_name` (string, required).
|
|
1489
|
+
|
|
1490
|
+
**Returns**: `CreateOrUpdateIpCustomHeaderResponse` with `data.header_name`.
|
|
1491
|
+
|
|
1492
|
+
```rust
|
|
1493
|
+
// Rust
|
|
1494
|
+
let params = CreateOrUpdateIpCustomHeaderRequest::builder()
|
|
1495
|
+
.header_name("X-Forwarded-For".to_string())
|
|
1496
|
+
.build();
|
|
1497
|
+
qn.admin.create_or_update_ip_custom_header("ep-123", ¶ms).await?;
|
|
1498
|
+
```
|
|
1499
|
+
|
|
1500
|
+
```python
|
|
1501
|
+
# Python
|
|
1502
|
+
await qn.admin.create_or_update_ip_custom_header("ep-123", header_name="X-Forwarded-For")
|
|
1503
|
+
```
|
|
1504
|
+
|
|
1505
|
+
```typescript
|
|
1506
|
+
// Node.js
|
|
1507
|
+
await qn.admin.createOrUpdateIpCustomHeader("ep-123", { headerName: "X-Forwarded-For" });
|
|
1508
|
+
```
|
|
1509
|
+
|
|
1510
|
+
```ruby
|
|
1511
|
+
# Ruby
|
|
1512
|
+
JSON.parse(qn.admin.create_or_update_ip_custom_header(
|
|
1513
|
+
id: "ep-123",
|
|
1514
|
+
header_name: "X-Forwarded-For"
|
|
1515
|
+
))
|
|
1516
|
+
```
|
|
1517
|
+
|
|
1518
|
+
##### `delete_ip_custom_header` / `deleteIpCustomHeader`
|
|
1519
|
+
|
|
1520
|
+
Removes the custom IP header configuration.
|
|
1521
|
+
|
|
1522
|
+
**Parameters**: `id` (endpoint id, required).
|
|
1523
|
+
|
|
1524
|
+
**Returns**: `DeleteBoolResponse`.
|
|
1525
|
+
|
|
1526
|
+
```rust
|
|
1527
|
+
// Rust
|
|
1528
|
+
qn.admin.delete_ip_custom_header("ep-123").await?;
|
|
1529
|
+
```
|
|
1530
|
+
|
|
1531
|
+
```python
|
|
1532
|
+
# Python
|
|
1533
|
+
await qn.admin.delete_ip_custom_header("ep-123")
|
|
1534
|
+
```
|
|
1535
|
+
|
|
1536
|
+
```typescript
|
|
1537
|
+
// Node.js
|
|
1538
|
+
await qn.admin.deleteIpCustomHeader("ep-123");
|
|
1539
|
+
```
|
|
1540
|
+
|
|
1541
|
+
```ruby
|
|
1542
|
+
# Ruby
|
|
1543
|
+
JSON.parse(qn.admin.delete_ip_custom_header(id: "ep-123"))
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
#### Method Rate Limits
|
|
1547
|
+
|
|
1548
|
+
##### `get_method_rate_limits` / `getMethodRateLimits`
|
|
1549
|
+
|
|
1550
|
+
Lists method-level rate limiters configured on an endpoint.
|
|
1551
|
+
|
|
1552
|
+
**Parameters**: `id` (endpoint id, required).
|
|
1553
|
+
|
|
1554
|
+
**Returns**: `GetMethodRateLimitsResponse` with `data.rate_limiters: MethodRateLimiter[]`.
|
|
1555
|
+
|
|
1556
|
+
```rust
|
|
1557
|
+
// Rust
|
|
1558
|
+
let resp = qn.admin.get_method_rate_limits("ep-123").await?;
|
|
1559
|
+
```
|
|
1560
|
+
|
|
1561
|
+
```python
|
|
1562
|
+
# Python
|
|
1563
|
+
resp = await qn.admin.get_method_rate_limits("ep-123")
|
|
1564
|
+
```
|
|
1565
|
+
|
|
1566
|
+
```typescript
|
|
1567
|
+
// Node.js
|
|
1568
|
+
const resp = await qn.admin.getMethodRateLimits("ep-123");
|
|
1569
|
+
```
|
|
1570
|
+
|
|
1571
|
+
```ruby
|
|
1572
|
+
# Ruby
|
|
1573
|
+
resp = JSON.parse(qn.admin.get_method_rate_limits(id: "ep-123"))
|
|
1574
|
+
```
|
|
1575
|
+
|
|
1576
|
+
##### `create_method_rate_limit` / `createMethodRateLimit`
|
|
1577
|
+
|
|
1578
|
+
Creates a new method-level rate limiter.
|
|
1579
|
+
|
|
1580
|
+
**Parameters**: `id` (endpoint id, required); body: `interval` (string, e.g. `"second"`), `methods` (string[]), `rate` (i32).
|
|
1581
|
+
|
|
1582
|
+
**Returns**: `CreateMethodRateLimitResponse` with `data: MethodRateLimiter`.
|
|
1583
|
+
|
|
1584
|
+
```rust
|
|
1585
|
+
// Rust
|
|
1586
|
+
let params = CreateMethodRateLimitRequest::builder()
|
|
1587
|
+
.interval("second".to_string())
|
|
1588
|
+
.methods(vec!["eth_call".to_string()])
|
|
1589
|
+
.rate(10)
|
|
1590
|
+
.build();
|
|
1591
|
+
let resp = qn.admin.create_method_rate_limit("ep-123", ¶ms).await?;
|
|
1592
|
+
```
|
|
1593
|
+
|
|
1594
|
+
```python
|
|
1595
|
+
# Python
|
|
1596
|
+
resp = await qn.admin.create_method_rate_limit(
|
|
1597
|
+
"ep-123",
|
|
1598
|
+
interval="second",
|
|
1599
|
+
methods=["eth_call"],
|
|
1600
|
+
rate=10,
|
|
1601
|
+
)
|
|
1602
|
+
```
|
|
1603
|
+
|
|
1604
|
+
```typescript
|
|
1605
|
+
// Node.js
|
|
1606
|
+
const resp = await qn.admin.createMethodRateLimit("ep-123", {
|
|
1607
|
+
interval: "second",
|
|
1608
|
+
methods: ["eth_call"],
|
|
1609
|
+
rate: 10,
|
|
1610
|
+
});
|
|
1611
|
+
```
|
|
1612
|
+
|
|
1613
|
+
```ruby
|
|
1614
|
+
# Ruby
|
|
1615
|
+
resp = JSON.parse(qn.admin.create_method_rate_limit(
|
|
1616
|
+
id: "ep-123",
|
|
1617
|
+
interval: "second",
|
|
1618
|
+
methods: ["eth_call"],
|
|
1619
|
+
rate: 10
|
|
1620
|
+
))
|
|
1621
|
+
```
|
|
1622
|
+
|
|
1623
|
+
##### `update_method_rate_limit` / `updateMethodRateLimit`
|
|
1624
|
+
|
|
1625
|
+
Updates an existing rate limiter. Only provided fields change.
|
|
1626
|
+
|
|
1627
|
+
**Parameters**: `id` (endpoint id, required), `method_rate_limit_id` (string, required); body: `methods` (string[], optional), `status` (`"enabled"` | `"disabled"`, optional), `rate` (i32, optional).
|
|
1628
|
+
|
|
1629
|
+
**Returns**: `UpdateMethodRateLimitResponse`.
|
|
1630
|
+
|
|
1631
|
+
```rust
|
|
1632
|
+
// Rust
|
|
1633
|
+
let params = UpdateMethodRateLimitRequest::builder().rate(50).build();
|
|
1634
|
+
qn.admin.update_method_rate_limit("ep-123", "rl-1", ¶ms).await?;
|
|
1635
|
+
```
|
|
1636
|
+
|
|
1637
|
+
```python
|
|
1638
|
+
# Python
|
|
1639
|
+
await qn.admin.update_method_rate_limit("ep-123", "rl-1", rate=50)
|
|
1640
|
+
```
|
|
1641
|
+
|
|
1642
|
+
```typescript
|
|
1643
|
+
// Node.js
|
|
1644
|
+
await qn.admin.updateMethodRateLimit("ep-123", "rl-1", { rate: 50 });
|
|
1645
|
+
```
|
|
1646
|
+
|
|
1647
|
+
```ruby
|
|
1648
|
+
# Ruby
|
|
1649
|
+
JSON.parse(qn.admin.update_method_rate_limit(id: "ep-123", method_rate_limit_id: "rl-1", rate: 50))
|
|
1650
|
+
```
|
|
1651
|
+
|
|
1652
|
+
##### `delete_method_rate_limit` / `deleteMethodRateLimit`
|
|
1653
|
+
|
|
1654
|
+
Deletes a rate limiter.
|
|
1655
|
+
|
|
1656
|
+
**Parameters**: `id` (endpoint id, required), `method_rate_limit_id` (string, required).
|
|
1657
|
+
|
|
1658
|
+
**Returns**: nothing.
|
|
1659
|
+
|
|
1660
|
+
```rust
|
|
1661
|
+
// Rust
|
|
1662
|
+
qn.admin.delete_method_rate_limit("ep-123", "rl-1").await?;
|
|
1663
|
+
```
|
|
1664
|
+
|
|
1665
|
+
```python
|
|
1666
|
+
# Python
|
|
1667
|
+
await qn.admin.delete_method_rate_limit("ep-123", "rl-1")
|
|
1668
|
+
```
|
|
1669
|
+
|
|
1670
|
+
```typescript
|
|
1671
|
+
// Node.js
|
|
1672
|
+
await qn.admin.deleteMethodRateLimit("ep-123", "rl-1");
|
|
1673
|
+
```
|
|
1674
|
+
|
|
1675
|
+
```ruby
|
|
1676
|
+
# Ruby
|
|
1677
|
+
qn.admin.delete_method_rate_limit(id: "ep-123", method_rate_limit_id: "rl-1")
|
|
1678
|
+
```
|
|
1679
|
+
|
|
1680
|
+
#### Endpoint Rate Limits
|
|
1681
|
+
|
|
1682
|
+
##### `update_rate_limits` / `updateRateLimits`
|
|
1683
|
+
|
|
1684
|
+
Updates the endpoint-level RPS / RPM / RPD caps.
|
|
1685
|
+
|
|
1686
|
+
**Parameters**: `id` (endpoint id, required); `rate_limits`: `RateLimitSettings` (`rps`, `rpm`, `rpd`, all optional).
|
|
1687
|
+
|
|
1688
|
+
**Returns**: nothing.
|
|
1689
|
+
|
|
1690
|
+
```rust
|
|
1691
|
+
// Rust
|
|
1692
|
+
let rate_limits = RateLimitSettings::builder().rps(100).rpm(5000).build();
|
|
1693
|
+
let params = UpdateRateLimitsRequest { rate_limits };
|
|
1694
|
+
qn.admin.update_rate_limits("ep-123", ¶ms).await?;
|
|
1695
|
+
```
|
|
1696
|
+
|
|
1697
|
+
```python
|
|
1698
|
+
# Python
|
|
1699
|
+
await qn.admin.update_rate_limits("ep-123", rps=100, rpm=5000)
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
```typescript
|
|
1703
|
+
// Node.js
|
|
1704
|
+
await qn.admin.updateRateLimits("ep-123", { rateLimits: { rps: 100, rpm: 5000 } });
|
|
1705
|
+
```
|
|
1706
|
+
|
|
1707
|
+
```ruby
|
|
1708
|
+
# Ruby
|
|
1709
|
+
qn.admin.update_rate_limits(id: "ep-123", rps: 100, rpm: 5000)
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
#### Metrics
|
|
1713
|
+
|
|
1714
|
+
##### `get_endpoint_metrics` / `getEndpointMetrics`
|
|
1715
|
+
|
|
1716
|
+
Returns metric series for an endpoint over a time period.
|
|
1717
|
+
|
|
1718
|
+
**Parameters**: `id` (endpoint id, required); body: `period` (`"hour"` | `"day"` | `"week"` | `"month"`), `metric` (e.g. `"method_calls_over_time"`, `"response_status_breakdown"`).
|
|
1719
|
+
|
|
1720
|
+
**Returns**: `GetEndpointMetricsResponse` with `data: EndpointMetric[]`.
|
|
1721
|
+
|
|
1722
|
+
```rust
|
|
1723
|
+
// Rust
|
|
1724
|
+
let params = GetEndpointMetricsRequest {
|
|
1725
|
+
period: "day".to_string(),
|
|
1726
|
+
metric: "method_calls_over_time".to_string(),
|
|
1727
|
+
};
|
|
1728
|
+
let resp = qn.admin.get_endpoint_metrics("ep-123", ¶ms).await?;
|
|
1729
|
+
```
|
|
1730
|
+
|
|
1731
|
+
```python
|
|
1732
|
+
# Python
|
|
1733
|
+
resp = await qn.admin.get_endpoint_metrics(
|
|
1734
|
+
"ep-123",
|
|
1735
|
+
period="day",
|
|
1736
|
+
metric="method_calls_over_time",
|
|
1737
|
+
)
|
|
1738
|
+
```
|
|
1739
|
+
|
|
1740
|
+
```typescript
|
|
1741
|
+
// Node.js
|
|
1742
|
+
const resp = await qn.admin.getEndpointMetrics("ep-123", {
|
|
1743
|
+
period: "day",
|
|
1744
|
+
metric: "method_calls_over_time",
|
|
1745
|
+
});
|
|
1746
|
+
```
|
|
1747
|
+
|
|
1748
|
+
```ruby
|
|
1749
|
+
# Ruby
|
|
1750
|
+
resp = JSON.parse(qn.admin.get_endpoint_metrics(
|
|
1751
|
+
id: "ep-123",
|
|
1752
|
+
period: "day",
|
|
1753
|
+
metric: "method_calls_over_time"
|
|
1754
|
+
))
|
|
1755
|
+
```
|
|
1756
|
+
|
|
1757
|
+
##### `get_account_metrics` / `getAccountMetrics`
|
|
1758
|
+
|
|
1759
|
+
Returns account-level metric series. Supports an optional `percentile` (e.g. `"p50"`, `"p95"`, `"p99"`) for latency metrics.
|
|
1760
|
+
|
|
1761
|
+
**Parameters**: `period` (required), `metric` (required), `percentile` (string, optional).
|
|
1762
|
+
|
|
1763
|
+
**Returns**: `GetAccountMetricsResponse` with `data: EndpointMetric[]`.
|
|
1764
|
+
|
|
1765
|
+
```rust
|
|
1766
|
+
// Rust
|
|
1767
|
+
let params = GetAccountMetricsRequest {
|
|
1768
|
+
period: "day".to_string(),
|
|
1769
|
+
metric: "credits_over_time".to_string(),
|
|
1770
|
+
percentile: None,
|
|
1771
|
+
};
|
|
1772
|
+
let resp = qn.admin.get_account_metrics(¶ms).await?;
|
|
1773
|
+
```
|
|
1774
|
+
|
|
1775
|
+
```python
|
|
1776
|
+
# Python
|
|
1777
|
+
resp = await qn.admin.get_account_metrics(period="day", metric="credits_over_time")
|
|
1778
|
+
```
|
|
1779
|
+
|
|
1780
|
+
```typescript
|
|
1781
|
+
// Node.js
|
|
1782
|
+
const resp = await qn.admin.getAccountMetrics({
|
|
1783
|
+
period: "day",
|
|
1784
|
+
metric: "credits_over_time",
|
|
1785
|
+
});
|
|
1786
|
+
```
|
|
1787
|
+
|
|
1788
|
+
```ruby
|
|
1789
|
+
# Ruby
|
|
1790
|
+
resp = JSON.parse(qn.admin.get_account_metrics(period: "day", metric: "credits_over_time"))
|
|
1791
|
+
```
|
|
1792
|
+
|
|
1793
|
+
#### Chains
|
|
1794
|
+
|
|
1795
|
+
##### `list_chains` / `listChains`
|
|
1796
|
+
|
|
1797
|
+
Lists the blockchains supported by QuickNode along with their networks.
|
|
1798
|
+
|
|
1799
|
+
**Parameters**: none.
|
|
1800
|
+
|
|
1801
|
+
**Returns**: `ListChainsResponse` with `data: Chain[]`.
|
|
1802
|
+
|
|
1803
|
+
```rust
|
|
1804
|
+
// Rust
|
|
1805
|
+
let resp = qn.admin.list_chains().await?;
|
|
1806
|
+
```
|
|
1807
|
+
|
|
1808
|
+
```python
|
|
1809
|
+
# Python
|
|
1810
|
+
resp = await qn.admin.list_chains()
|
|
1811
|
+
```
|
|
1812
|
+
|
|
1813
|
+
```typescript
|
|
1814
|
+
// Node.js
|
|
1815
|
+
const resp = await qn.admin.listChains();
|
|
1816
|
+
```
|
|
1817
|
+
|
|
1818
|
+
```ruby
|
|
1819
|
+
# Ruby
|
|
1820
|
+
resp = JSON.parse(qn.admin.list_chains)
|
|
1821
|
+
```
|
|
1822
|
+
|
|
1823
|
+
#### Billing
|
|
1824
|
+
|
|
1825
|
+
##### `list_invoices` / `listInvoices`
|
|
1826
|
+
|
|
1827
|
+
Lists invoices on the account.
|
|
1828
|
+
|
|
1829
|
+
**Parameters**: none.
|
|
1830
|
+
|
|
1831
|
+
**Returns**: `ListInvoicesResponse` with `data.invoices: Invoice[]`.
|
|
1832
|
+
|
|
1833
|
+
```rust
|
|
1834
|
+
// Rust
|
|
1835
|
+
let resp = qn.admin.list_invoices().await?;
|
|
1836
|
+
```
|
|
1837
|
+
|
|
1838
|
+
```python
|
|
1839
|
+
# Python
|
|
1840
|
+
resp = await qn.admin.list_invoices()
|
|
1841
|
+
```
|
|
1842
|
+
|
|
1843
|
+
```typescript
|
|
1844
|
+
// Node.js
|
|
1845
|
+
const resp = await qn.admin.listInvoices();
|
|
1846
|
+
```
|
|
1847
|
+
|
|
1848
|
+
```ruby
|
|
1849
|
+
# Ruby
|
|
1850
|
+
resp = JSON.parse(qn.admin.list_invoices)
|
|
1851
|
+
```
|
|
1852
|
+
|
|
1853
|
+
##### `list_payments` / `listPayments`
|
|
1854
|
+
|
|
1855
|
+
Lists payments on the account.
|
|
1856
|
+
|
|
1857
|
+
**Parameters**: none.
|
|
1858
|
+
|
|
1859
|
+
**Returns**: `ListPaymentsResponse` with `data.payments: Payment[]`.
|
|
1860
|
+
|
|
1861
|
+
```rust
|
|
1862
|
+
// Rust
|
|
1863
|
+
let resp = qn.admin.list_payments().await?;
|
|
1864
|
+
```
|
|
1865
|
+
|
|
1866
|
+
```python
|
|
1867
|
+
# Python
|
|
1868
|
+
resp = await qn.admin.list_payments()
|
|
1869
|
+
```
|
|
1870
|
+
|
|
1871
|
+
```typescript
|
|
1872
|
+
// Node.js
|
|
1873
|
+
const resp = await qn.admin.listPayments();
|
|
1874
|
+
```
|
|
1875
|
+
|
|
1876
|
+
```ruby
|
|
1877
|
+
# Ruby
|
|
1878
|
+
resp = JSON.parse(qn.admin.list_payments)
|
|
1879
|
+
```
|
|
1880
|
+
|
|
1881
|
+
#### Bulk Operations
|
|
1882
|
+
|
|
1883
|
+
##### `bulk_update_endpoint_status` / `bulkUpdateEndpointStatus`
|
|
1884
|
+
|
|
1885
|
+
Activates or pauses many endpoints at once.
|
|
1886
|
+
|
|
1887
|
+
**Parameters**: `ids` (string[], required), `status` (`"active"` | `"paused"`, required).
|
|
1888
|
+
|
|
1889
|
+
**Returns**: `BulkUpdateEndpointStatusResponse` with per-endpoint `results`.
|
|
1890
|
+
|
|
1891
|
+
```rust
|
|
1892
|
+
// Rust
|
|
1893
|
+
let params = BulkUpdateEndpointStatusRequest::builder()
|
|
1894
|
+
.ids(vec!["ep-1".to_string(), "ep-2".to_string()])
|
|
1895
|
+
.status("paused".to_string())
|
|
1896
|
+
.build();
|
|
1897
|
+
let resp = qn.admin.bulk_update_endpoint_status(¶ms).await?;
|
|
1898
|
+
```
|
|
1899
|
+
|
|
1900
|
+
```python
|
|
1901
|
+
# Python
|
|
1902
|
+
resp = await qn.admin.bulk_update_endpoint_status(ids=["ep-1", "ep-2"], status="paused")
|
|
1903
|
+
```
|
|
1904
|
+
|
|
1905
|
+
```typescript
|
|
1906
|
+
// Node.js
|
|
1907
|
+
const resp = await qn.admin.bulkUpdateEndpointStatus({
|
|
1908
|
+
ids: ["ep-1", "ep-2"],
|
|
1909
|
+
status: "paused",
|
|
1910
|
+
});
|
|
1911
|
+
```
|
|
1912
|
+
|
|
1913
|
+
```ruby
|
|
1914
|
+
# Ruby
|
|
1915
|
+
resp = JSON.parse(qn.admin.bulk_update_endpoint_status(ids: ["ep-1", "ep-2"], status: "paused"))
|
|
1916
|
+
```
|
|
1917
|
+
|
|
1918
|
+
##### `bulk_add_tag` / `bulkAddTag`
|
|
1919
|
+
|
|
1920
|
+
Applies a tag (created if missing) to many endpoints at once.
|
|
1921
|
+
|
|
1922
|
+
**Parameters**: `ids` (string[], required), `label` (string, required).
|
|
1923
|
+
|
|
1924
|
+
**Returns**: `BulkAddTagResponse`.
|
|
1925
|
+
|
|
1926
|
+
```rust
|
|
1927
|
+
// Rust
|
|
1928
|
+
let params = BulkAddTagRequest::builder()
|
|
1929
|
+
.ids(vec!["ep-1".to_string(), "ep-2".to_string()])
|
|
1930
|
+
.label("prod".to_string())
|
|
1931
|
+
.build();
|
|
1932
|
+
let resp = qn.admin.bulk_add_tag(¶ms).await?;
|
|
1933
|
+
```
|
|
1934
|
+
|
|
1935
|
+
```python
|
|
1936
|
+
# Python
|
|
1937
|
+
resp = await qn.admin.bulk_add_tag(ids=["ep-1", "ep-2"], label="prod")
|
|
1938
|
+
```
|
|
1939
|
+
|
|
1940
|
+
```typescript
|
|
1941
|
+
// Node.js
|
|
1942
|
+
const resp = await qn.admin.bulkAddTag({ ids: ["ep-1", "ep-2"], label: "prod" });
|
|
1943
|
+
```
|
|
1944
|
+
|
|
1945
|
+
```ruby
|
|
1946
|
+
# Ruby
|
|
1947
|
+
resp = JSON.parse(qn.admin.bulk_add_tag(ids: ["ep-1", "ep-2"], label: "prod"))
|
|
1948
|
+
```
|
|
1949
|
+
|
|
1950
|
+
##### `bulk_remove_tag` / `bulkRemoveTag`
|
|
1951
|
+
|
|
1952
|
+
Removes a tag from many endpoints at once.
|
|
1953
|
+
|
|
1954
|
+
**Parameters**: `ids` (string[], required), `tag_id` (i32, required).
|
|
1955
|
+
|
|
1956
|
+
**Returns**: `BulkRemoveTagResponse`.
|
|
1957
|
+
|
|
1958
|
+
```rust
|
|
1959
|
+
// Rust
|
|
1960
|
+
let params = BulkRemoveTagRequest::builder()
|
|
1961
|
+
.ids(vec!["ep-1".to_string(), "ep-2".to_string()])
|
|
1962
|
+
.tag_id(42)
|
|
1963
|
+
.build();
|
|
1964
|
+
let resp = qn.admin.bulk_remove_tag(¶ms).await?;
|
|
1965
|
+
```
|
|
1966
|
+
|
|
1967
|
+
```python
|
|
1968
|
+
# Python
|
|
1969
|
+
resp = await qn.admin.bulk_remove_tag(ids=["ep-1", "ep-2"], tag_id=42)
|
|
1970
|
+
```
|
|
1971
|
+
|
|
1972
|
+
```typescript
|
|
1973
|
+
// Node.js
|
|
1974
|
+
const resp = await qn.admin.bulkRemoveTag({ ids: ["ep-1", "ep-2"], tagId: 42 });
|
|
1975
|
+
```
|
|
1976
|
+
|
|
1977
|
+
```ruby
|
|
1978
|
+
# Ruby
|
|
1979
|
+
resp = JSON.parse(qn.admin.bulk_remove_tag(ids: ["ep-1", "ep-2"], tag_id: 42))
|
|
1980
|
+
```
|
|
1981
|
+
|
|
1982
|
+
#### Account Tags
|
|
1983
|
+
|
|
1984
|
+
##### `list_tags` / `listTags`
|
|
1985
|
+
|
|
1986
|
+
Lists every tag on the account along with usage counts.
|
|
1987
|
+
|
|
1988
|
+
**Parameters**: none.
|
|
1989
|
+
|
|
1990
|
+
**Returns**: `ListTagsResponse` with `data.tags: AccountTag[]`.
|
|
1991
|
+
|
|
1992
|
+
```rust
|
|
1993
|
+
// Rust
|
|
1994
|
+
let resp = qn.admin.list_tags().await?;
|
|
1995
|
+
```
|
|
1996
|
+
|
|
1997
|
+
```python
|
|
1998
|
+
# Python
|
|
1999
|
+
resp = await qn.admin.list_tags()
|
|
2000
|
+
```
|
|
2001
|
+
|
|
2002
|
+
```typescript
|
|
2003
|
+
// Node.js
|
|
2004
|
+
const resp = await qn.admin.listTags();
|
|
2005
|
+
```
|
|
2006
|
+
|
|
2007
|
+
```ruby
|
|
2008
|
+
# Ruby
|
|
2009
|
+
resp = JSON.parse(qn.admin.list_tags)
|
|
2010
|
+
```
|
|
2011
|
+
|
|
2012
|
+
##### `rename_tag` / `renameTag`
|
|
2013
|
+
|
|
2014
|
+
Renames an account-level tag.
|
|
2015
|
+
|
|
2016
|
+
**Parameters**: `tag_id` (i32, required); body: `label` (string, required).
|
|
2017
|
+
|
|
2018
|
+
**Returns**: `RenameTagResponse` with updated `AccountTag`.
|
|
2019
|
+
|
|
2020
|
+
```rust
|
|
2021
|
+
// Rust
|
|
2022
|
+
let params = RenameTagRequest::builder().label("staging".to_string()).build();
|
|
2023
|
+
let resp = qn.admin.rename_tag(42, ¶ms).await?;
|
|
2024
|
+
```
|
|
2025
|
+
|
|
2026
|
+
```python
|
|
2027
|
+
# Python
|
|
2028
|
+
resp = await qn.admin.rename_tag(42, label="staging")
|
|
2029
|
+
```
|
|
2030
|
+
|
|
2031
|
+
```typescript
|
|
2032
|
+
// Node.js
|
|
2033
|
+
const resp = await qn.admin.renameTag(42, { label: "staging" });
|
|
2034
|
+
```
|
|
2035
|
+
|
|
2036
|
+
```ruby
|
|
2037
|
+
# Ruby
|
|
2038
|
+
resp = JSON.parse(qn.admin.rename_tag(tag_id: 42, label: "staging"))
|
|
2039
|
+
```
|
|
2040
|
+
|
|
2041
|
+
##### `delete_account_tag` / `deleteAccountTag`
|
|
2042
|
+
|
|
2043
|
+
Deletes a tag from the account. The tag must first be removed from any endpoints using it.
|
|
2044
|
+
|
|
2045
|
+
**Parameters**: `id` (i32, required).
|
|
2046
|
+
|
|
2047
|
+
**Returns**: `DeleteAccountTagResponse`.
|
|
2048
|
+
|
|
2049
|
+
```rust
|
|
2050
|
+
// Rust
|
|
2051
|
+
qn.admin.delete_account_tag(42).await?;
|
|
2052
|
+
```
|
|
2053
|
+
|
|
2054
|
+
```python
|
|
2055
|
+
# Python
|
|
2056
|
+
await qn.admin.delete_account_tag(42)
|
|
2057
|
+
```
|
|
2058
|
+
|
|
2059
|
+
```typescript
|
|
2060
|
+
// Node.js
|
|
2061
|
+
await qn.admin.deleteAccountTag(42);
|
|
2062
|
+
```
|
|
2063
|
+
|
|
2064
|
+
```ruby
|
|
2065
|
+
# Ruby
|
|
2066
|
+
JSON.parse(qn.admin.delete_account_tag(id: 42))
|
|
2067
|
+
```
|
|
2068
|
+
|
|
2069
|
+
---
|
|
2070
|
+
|
|
2071
|
+
### Streams Client
|
|
2072
|
+
|
|
2073
|
+
Accessed as `qn.streams`. Creates and manages blockchain data streams that deliver filtered on-chain events to configured destinations. Backed by `https://api.quicknode.com/streams/rest/v1/`.
|
|
2074
|
+
|
|
2075
|
+
#### Datasets, Regions, and Destinations
|
|
2076
|
+
|
|
2077
|
+
Enums used across stream methods:
|
|
2078
|
+
|
|
2079
|
+
- **`StreamRegion`**: `UsaEast`, `EuropeCentral`, `AsiaEast` (wire values: `usa_east`, `europe_central`, `asia_east`).
|
|
2080
|
+
- **`StreamDataset`**: `Block`, `BlockWithReceipts`, `Transactions`, `Logs`, `Receipts`, `TraceBlocks`, `DebugTraces`, `BlockWithReceiptsDebugTrace`, `BlockWithReceiptsTraceBlock`, `BlobSidecars`, `ProgramsWithLogs`, `Ledger`, `Events`, `Orders`, `Trades`, `BookUpdates`, `Twap`, `WriterActions`.
|
|
2081
|
+
- **`StreamStatus`**: `Active`, `Paused`, `Terminated`, `Completed`, `Blocked`.
|
|
2082
|
+
- **`FilterLanguage`**: `Javascript`, `Go`, `Wasm`.
|
|
2083
|
+
- **`StreamMetadataLocation`**: `Body`, `Header`, `None`.
|
|
2084
|
+
|
|
2085
|
+
Destinations are expressed via `DestinationAttributes`. Each variant wraps an attribute struct:
|
|
2086
|
+
|
|
2087
|
+
| Variant | Struct | Key fields |
|
|
2088
|
+
|---|---|---|
|
|
2089
|
+
| `Webhook` | `WebhookAttributes` | `url`, `max_retry`, `retry_interval_sec`, `post_timeout_sec`, `compression`, `security_token?` |
|
|
2090
|
+
| `S3` | `S3Attributes` | `endpoint`, `access_key`, `secret_key`, `bucket`, `object_prefix`, `compression`, `file_type`, `max_retry`, `retry_interval_sec`, `use_ssl?` |
|
|
2091
|
+
| `Azure` | `AzureAttributes` | `storage_account`, `sas_token`, `container`, `compression`, `file_type`, `max_retry`, `retry_interval_sec`, `blob_prefix?` |
|
|
2092
|
+
| `Postgres` | `PostgresAttributes` | `host`, `port`, `username`, `password`, `database`, `schema`, `table`, `max_retry`, `retry_interval_sec`, `use_ssl?` |
|
|
2093
|
+
| `Mysql` | `MysqlAttributes` | `host`, `port`, `username`, `password`, `database`, `table`, `max_retry`, `retry_interval_sec`, `use_ssl?` |
|
|
2094
|
+
| `Mongo` | `MongoAttributes` | `connection_string`, `database`, `collection`, `max_retry`, `retry_interval_sec` |
|
|
2095
|
+
| `Clickhouse` | `ClickhouseAttributes` | `host`, `port`, `username`, `password`, `database`, `table`, `max_retry`, `retry_interval_sec`, `use_ssl?` |
|
|
2096
|
+
| `Snowflake` | `SnowflakeAttributes` | `account`, `warehouse`, `database`, `schema`, `table`, `username`, `private_key`, `max_retry`, `retry_interval_sec` |
|
|
2097
|
+
| `Kafka` | `KafkaAttributes` | `bootstrap_servers`, `topic`, `compression`, `max_retry`, `retry_interval_sec` |
|
|
2098
|
+
| `Redis` | `RedisAttributes` | `host`, `port`, `username`, `password`, `key`, `max_retry`, `retry_interval_sec`, `use_ssl?` |
|
|
2099
|
+
|
|
2100
|
+
Wrapper naming per language:
|
|
2101
|
+
|
|
2102
|
+
- **Rust**: `DestinationAttributes::Webhook(WebhookAttributes { .. })` etc.
|
|
2103
|
+
- **Python**: `StreamWebhookDestination(WebhookAttributes(...))`, `StreamS3Destination(S3Attributes(...))`, etc.
|
|
2104
|
+
- **Node.js**: a discriminated object `{ destination: "webhook", attributes: { ... } }` using string discriminators.
|
|
2105
|
+
- **Ruby**: factory methods on `QuickNodeSdk::DestinationAttributes`, e.g. `QuickNodeSdk::DestinationAttributes.webhook(url: ..., ...)`.
|
|
2106
|
+
|
|
2107
|
+
#### Streams methods
|
|
2108
|
+
|
|
2109
|
+
##### `create_stream` / `createStream`
|
|
2110
|
+
|
|
2111
|
+
Creates a new stream that delivers filtered data to the configured destination. Start from a specific block for backfills or from the tip for real-time streaming. Supports filters, reorg handling, distance-from-tip, elastic batching, notification emails, and extra destinations.
|
|
2112
|
+
|
|
2113
|
+
**Parameters**: `CreateStreamParams` — required: `name`, `region`, `network`, `dataset`, `start_range` (i64), `end_range` (i64, `-1` = follow tip), `destination_attributes`, `plan`, `threshold_fetch_buffer`. Common optional fields: `dataset_batch_size`, `include_stream_metadata`, `fix_block_reorgs`, `keep_distance_from_tip`, `elastic_batch_enabled`, `filter_function`, `filter_language`, `status`, `notification_email`, `extra_destinations`.
|
|
2114
|
+
|
|
2115
|
+
**Returns**: `Stream`.
|
|
2116
|
+
|
|
2117
|
+
```rust
|
|
2118
|
+
// Rust
|
|
2119
|
+
let params = CreateStreamParams::builder()
|
|
2120
|
+
.name("My Stream".to_string())
|
|
2121
|
+
.region(StreamRegion::UsaEast)
|
|
2122
|
+
.network("ethereum-mainnet".to_string())
|
|
2123
|
+
.dataset(StreamDataset::Block)
|
|
2124
|
+
.start_range(24691804)
|
|
2125
|
+
.end_range(24691904)
|
|
2126
|
+
.destination_attributes(DestinationAttributes::Webhook(WebhookAttributes {
|
|
2127
|
+
url: "https://webhook.site/...".to_string(),
|
|
2128
|
+
max_retry: 3,
|
|
2129
|
+
retry_interval_sec: 1,
|
|
2130
|
+
post_timeout_sec: 10,
|
|
2131
|
+
compression: "none".to_string(),
|
|
2132
|
+
security_token: None,
|
|
2133
|
+
}))
|
|
2134
|
+
.plan("growth_plan".to_string())
|
|
2135
|
+
.threshold_fetch_buffer(1000)
|
|
2136
|
+
.status(StreamStatus::Active)
|
|
2137
|
+
.build();
|
|
2138
|
+
let stream = qn.streams.create_stream(¶ms).await?;
|
|
2139
|
+
```
|
|
2140
|
+
|
|
2141
|
+
```python
|
|
2142
|
+
# Python
|
|
2143
|
+
from sdk import WebhookAttributes, StreamWebhookDestination
|
|
2144
|
+
|
|
2145
|
+
stream = await qn.streams.create_stream(
|
|
2146
|
+
name="My Stream",
|
|
2147
|
+
network="ethereum-mainnet",
|
|
2148
|
+
dataset="block",
|
|
2149
|
+
region="usa_east",
|
|
2150
|
+
start_range=24691804,
|
|
2151
|
+
end_range=24691904,
|
|
2152
|
+
destination_attributes=StreamWebhookDestination(
|
|
2153
|
+
WebhookAttributes(
|
|
2154
|
+
url="https://webhook.site/...",
|
|
2155
|
+
max_retry=3,
|
|
2156
|
+
retry_interval_sec=1,
|
|
2157
|
+
post_timeout_sec=10,
|
|
2158
|
+
compression="none",
|
|
2159
|
+
)
|
|
2160
|
+
),
|
|
2161
|
+
plan="growth_plan",
|
|
2162
|
+
threshold_fetch_buffer=1000,
|
|
2163
|
+
status="active",
|
|
2164
|
+
)
|
|
2165
|
+
```
|
|
2166
|
+
|
|
2167
|
+
```typescript
|
|
2168
|
+
// Node.js
|
|
2169
|
+
import { StreamDataset, StreamRegion, StreamStatus } from "quicknode-sdk";
|
|
2170
|
+
|
|
2171
|
+
const stream = await qn.streams.createStream({
|
|
2172
|
+
name: "My Stream",
|
|
2173
|
+
network: "ethereum-mainnet",
|
|
2174
|
+
dataset: StreamDataset.Block,
|
|
2175
|
+
region: StreamRegion.UsaEast,
|
|
2176
|
+
startRange: 24691804,
|
|
2177
|
+
endRange: 24691904,
|
|
2178
|
+
destinationAttributes: {
|
|
2179
|
+
destination: "webhook",
|
|
2180
|
+
attributes: {
|
|
2181
|
+
url: "https://webhook.site/...",
|
|
2182
|
+
maxRetry: 3,
|
|
2183
|
+
retryIntervalSec: 1,
|
|
2184
|
+
postTimeoutSec: 10,
|
|
2185
|
+
compression: "none",
|
|
2186
|
+
},
|
|
2187
|
+
},
|
|
2188
|
+
plan: "growth_plan",
|
|
2189
|
+
thresholdFetchBuffer: 1000,
|
|
2190
|
+
status: StreamStatus.Active,
|
|
2191
|
+
});
|
|
2192
|
+
```
|
|
2193
|
+
|
|
2194
|
+
```ruby
|
|
2195
|
+
# Ruby
|
|
2196
|
+
dest = QuickNodeSdk::DestinationAttributes.webhook(
|
|
2197
|
+
url: "https://webhook.site/...",
|
|
2198
|
+
max_retry: 3,
|
|
2199
|
+
retry_interval_sec: 1,
|
|
2200
|
+
post_timeout_sec: 10,
|
|
2201
|
+
compression: "none"
|
|
2202
|
+
)
|
|
2203
|
+
stream = JSON.parse(qn.streams.create_stream(
|
|
2204
|
+
name: "My Stream",
|
|
2205
|
+
network: "ethereum-mainnet",
|
|
2206
|
+
dataset: "block",
|
|
2207
|
+
region: "usa_east",
|
|
2208
|
+
start_range: 24691804,
|
|
2209
|
+
end_range: 24691904,
|
|
2210
|
+
destination_attributes: dest,
|
|
2211
|
+
plan: "growth_plan",
|
|
2212
|
+
threshold_fetch_buffer: 1000,
|
|
2213
|
+
status: "active"
|
|
2214
|
+
))
|
|
2215
|
+
```
|
|
2216
|
+
|
|
2217
|
+
##### `list_streams` / `listStreams`
|
|
2218
|
+
|
|
2219
|
+
Paginated list of streams on the account.
|
|
2220
|
+
|
|
2221
|
+
**Parameters** (all optional): `offset` (i64), `limit` (i64), `order_by` (string), `order_direction` (`"asc"` | `"desc"`), `stream_type` (string).
|
|
2222
|
+
|
|
2223
|
+
**Returns**: `ListStreamsResponse` with `data: Stream[]` and `page_info`.
|
|
2224
|
+
|
|
2225
|
+
```rust
|
|
2226
|
+
// Rust
|
|
2227
|
+
let resp = qn.streams.list_streams(&ListStreamsParams::default()).await?;
|
|
2228
|
+
```
|
|
2229
|
+
|
|
2230
|
+
```python
|
|
2231
|
+
# Python
|
|
2232
|
+
resp = await qn.streams.list_streams()
|
|
2233
|
+
```
|
|
2234
|
+
|
|
2235
|
+
```typescript
|
|
2236
|
+
// Node.js
|
|
2237
|
+
const resp = await qn.streams.listStreams();
|
|
2238
|
+
```
|
|
2239
|
+
|
|
2240
|
+
```ruby
|
|
2241
|
+
# Ruby
|
|
2242
|
+
resp = JSON.parse(qn.streams.list_streams({}))
|
|
2243
|
+
```
|
|
2244
|
+
|
|
2245
|
+
##### `get_stream` / `getStream`
|
|
2246
|
+
|
|
2247
|
+
Fetches one stream by id.
|
|
2248
|
+
|
|
2249
|
+
**Parameters**: `id` (string, required).
|
|
2250
|
+
|
|
2251
|
+
**Returns**: `Stream`.
|
|
2252
|
+
|
|
2253
|
+
```rust
|
|
2254
|
+
// Rust
|
|
2255
|
+
let stream = qn.streams.get_stream("stream-id").await?;
|
|
2256
|
+
```
|
|
2257
|
+
|
|
2258
|
+
```python
|
|
2259
|
+
# Python
|
|
2260
|
+
stream = await qn.streams.get_stream("stream-id")
|
|
2261
|
+
```
|
|
2262
|
+
|
|
2263
|
+
```typescript
|
|
2264
|
+
// Node.js
|
|
2265
|
+
const stream = await qn.streams.getStream("stream-id");
|
|
2266
|
+
```
|
|
2267
|
+
|
|
2268
|
+
```ruby
|
|
2269
|
+
# Ruby
|
|
2270
|
+
stream = JSON.parse(qn.streams.get_stream(id: "stream-id"))
|
|
2271
|
+
```
|
|
2272
|
+
|
|
2273
|
+
##### `update_stream` / `updateStream`
|
|
2274
|
+
|
|
2275
|
+
Partially updates a stream. Omitted fields are left unchanged.
|
|
2276
|
+
|
|
2277
|
+
**Parameters**: `id` (string, required); body: any field from `CreateStreamParams` (all optional).
|
|
2278
|
+
|
|
2279
|
+
**Returns**: updated `Stream`.
|
|
2280
|
+
|
|
2281
|
+
```rust
|
|
2282
|
+
// Rust
|
|
2283
|
+
let params = UpdateStreamParams {
|
|
2284
|
+
name: Some("Renamed".to_string()),
|
|
2285
|
+
..Default::default()
|
|
2286
|
+
};
|
|
2287
|
+
let stream = qn.streams.update_stream("stream-id", ¶ms).await?;
|
|
2288
|
+
```
|
|
2289
|
+
|
|
2290
|
+
```python
|
|
2291
|
+
# Python
|
|
2292
|
+
stream = await qn.streams.update_stream("stream-id", name="Renamed")
|
|
2293
|
+
```
|
|
2294
|
+
|
|
2295
|
+
```typescript
|
|
2296
|
+
// Node.js
|
|
2297
|
+
const stream = await qn.streams.updateStream("stream-id", { name: "Renamed" });
|
|
2298
|
+
```
|
|
2299
|
+
|
|
2300
|
+
```ruby
|
|
2301
|
+
# Ruby
|
|
2302
|
+
stream = JSON.parse(qn.streams.update_stream(id: "stream-id", name: "Renamed"))
|
|
2303
|
+
```
|
|
2304
|
+
|
|
2305
|
+
##### `delete_stream` / `deleteStream`
|
|
2306
|
+
|
|
2307
|
+
Deletes one stream by id.
|
|
2308
|
+
|
|
2309
|
+
**Parameters**: `id` (string, required).
|
|
2310
|
+
|
|
2311
|
+
**Returns**: nothing.
|
|
2312
|
+
|
|
2313
|
+
```rust
|
|
2314
|
+
// Rust
|
|
2315
|
+
qn.streams.delete_stream("stream-id").await?;
|
|
2316
|
+
```
|
|
2317
|
+
|
|
2318
|
+
```python
|
|
2319
|
+
# Python
|
|
2320
|
+
await qn.streams.delete_stream("stream-id")
|
|
2321
|
+
```
|
|
2322
|
+
|
|
2323
|
+
```typescript
|
|
2324
|
+
// Node.js
|
|
2325
|
+
await qn.streams.deleteStream("stream-id");
|
|
2326
|
+
```
|
|
2327
|
+
|
|
2328
|
+
```ruby
|
|
2329
|
+
# Ruby
|
|
2330
|
+
qn.streams.delete_stream(id: "stream-id")
|
|
2331
|
+
```
|
|
2332
|
+
|
|
2333
|
+
##### `delete_all_streams` / `deleteAllStreams`
|
|
2334
|
+
|
|
2335
|
+
Deletes every stream on the account. Destructive and takes no arguments.
|
|
2336
|
+
|
|
2337
|
+
**Parameters**: none.
|
|
2338
|
+
|
|
2339
|
+
**Returns**: nothing.
|
|
2340
|
+
|
|
2341
|
+
```rust
|
|
2342
|
+
// Rust
|
|
2343
|
+
qn.streams.delete_all_streams().await?;
|
|
2344
|
+
```
|
|
2345
|
+
|
|
2346
|
+
```python
|
|
2347
|
+
# Python
|
|
2348
|
+
await qn.streams.delete_all_streams()
|
|
2349
|
+
```
|
|
2350
|
+
|
|
2351
|
+
```typescript
|
|
2352
|
+
// Node.js
|
|
2353
|
+
await qn.streams.deleteAllStreams();
|
|
2354
|
+
```
|
|
2355
|
+
|
|
2356
|
+
```ruby
|
|
2357
|
+
# Ruby
|
|
2358
|
+
qn.streams.delete_all_streams
|
|
2359
|
+
```
|
|
2360
|
+
|
|
2361
|
+
##### `activate_stream` / `activateStream`
|
|
2362
|
+
|
|
2363
|
+
Resumes delivery on a stream from its current position.
|
|
2364
|
+
|
|
2365
|
+
**Parameters**: `id` (string, required).
|
|
2366
|
+
|
|
2367
|
+
**Returns**: nothing.
|
|
2368
|
+
|
|
2369
|
+
```rust
|
|
2370
|
+
// Rust
|
|
2371
|
+
qn.streams.activate_stream("stream-id").await?;
|
|
2372
|
+
```
|
|
2373
|
+
|
|
2374
|
+
```python
|
|
2375
|
+
# Python
|
|
2376
|
+
await qn.streams.activate_stream("stream-id")
|
|
2377
|
+
```
|
|
2378
|
+
|
|
2379
|
+
```typescript
|
|
2380
|
+
// Node.js
|
|
2381
|
+
await qn.streams.activateStream("stream-id");
|
|
2382
|
+
```
|
|
2383
|
+
|
|
2384
|
+
```ruby
|
|
2385
|
+
# Ruby
|
|
2386
|
+
qn.streams.activate_stream(id: "stream-id")
|
|
2387
|
+
```
|
|
2388
|
+
|
|
2389
|
+
##### `pause_stream` / `pauseStream`
|
|
2390
|
+
|
|
2391
|
+
Halts delivery on a stream.
|
|
2392
|
+
|
|
2393
|
+
**Parameters**: `id` (string, required).
|
|
2394
|
+
|
|
2395
|
+
**Returns**: nothing.
|
|
2396
|
+
|
|
2397
|
+
```rust
|
|
2398
|
+
// Rust
|
|
2399
|
+
qn.streams.pause_stream("stream-id").await?;
|
|
2400
|
+
```
|
|
2401
|
+
|
|
2402
|
+
```python
|
|
2403
|
+
# Python
|
|
2404
|
+
await qn.streams.pause_stream("stream-id")
|
|
2405
|
+
```
|
|
2406
|
+
|
|
2407
|
+
```typescript
|
|
2408
|
+
// Node.js
|
|
2409
|
+
await qn.streams.pauseStream("stream-id");
|
|
2410
|
+
```
|
|
2411
|
+
|
|
2412
|
+
```ruby
|
|
2413
|
+
# Ruby
|
|
2414
|
+
qn.streams.pause_stream(id: "stream-id")
|
|
2415
|
+
```
|
|
2416
|
+
|
|
2417
|
+
##### `test_filter` / `testFilter`
|
|
2418
|
+
|
|
2419
|
+
Runs a filter function against a block so it can be validated before being attached to a live stream.
|
|
2420
|
+
|
|
2421
|
+
**Parameters**: `network` (string, required), `dataset` (`StreamDataset`, required), `block` (string, required), `filter_function` (string, optional), `filter_language` (`FilterLanguage`, optional), `address_book_config` (optional).
|
|
2422
|
+
|
|
2423
|
+
**Returns**: `TestFilterResponse` with `result` and `logs`.
|
|
2424
|
+
|
|
2425
|
+
```rust
|
|
2426
|
+
// Rust
|
|
2427
|
+
let params = TestFilterParams {
|
|
2428
|
+
network: "ethereum-mainnet".to_string(),
|
|
2429
|
+
dataset: StreamDataset::Block,
|
|
2430
|
+
block: "17811625".to_string(),
|
|
2431
|
+
filter_function: None,
|
|
2432
|
+
filter_language: None,
|
|
2433
|
+
address_book_config: None,
|
|
2434
|
+
};
|
|
2435
|
+
let resp = qn.streams.test_filter(¶ms).await?;
|
|
2436
|
+
```
|
|
2437
|
+
|
|
2438
|
+
```python
|
|
2439
|
+
# Python
|
|
2440
|
+
resp = await qn.streams.test_filter(
|
|
2441
|
+
network="ethereum-mainnet",
|
|
2442
|
+
dataset="block",
|
|
2443
|
+
block="17811625",
|
|
2444
|
+
)
|
|
2445
|
+
```
|
|
2446
|
+
|
|
2447
|
+
```typescript
|
|
2448
|
+
// Node.js
|
|
2449
|
+
import { StreamDataset } from "quicknode-sdk";
|
|
2450
|
+
|
|
2451
|
+
const resp = await qn.streams.testFilter({
|
|
2452
|
+
network: "ethereum-mainnet",
|
|
2453
|
+
dataset: StreamDataset.Block,
|
|
2454
|
+
block: "17811625",
|
|
2455
|
+
});
|
|
2456
|
+
```
|
|
2457
|
+
|
|
2458
|
+
```ruby
|
|
2459
|
+
# Ruby
|
|
2460
|
+
resp = JSON.parse(qn.streams.test_filter(
|
|
2461
|
+
network: "ethereum-mainnet",
|
|
2462
|
+
dataset: "block",
|
|
2463
|
+
block: "17811625"
|
|
2464
|
+
))
|
|
2465
|
+
```
|
|
2466
|
+
|
|
2467
|
+
##### `get_enabled_count` / `getEnabledCount`
|
|
2468
|
+
|
|
2469
|
+
Counts currently enabled (active) streams, optionally filtered by type.
|
|
2470
|
+
|
|
2471
|
+
**Parameters**: `stream_type` (string, optional).
|
|
2472
|
+
|
|
2473
|
+
**Returns**: `EnabledCountResponse` with `total`.
|
|
2474
|
+
|
|
2475
|
+
```rust
|
|
2476
|
+
// Rust
|
|
2477
|
+
let resp = qn.streams.get_enabled_count(None).await?;
|
|
2478
|
+
```
|
|
2479
|
+
|
|
2480
|
+
```python
|
|
2481
|
+
# Python
|
|
2482
|
+
resp = await qn.streams.get_enabled_count()
|
|
2483
|
+
```
|
|
2484
|
+
|
|
2485
|
+
```typescript
|
|
2486
|
+
// Node.js
|
|
2487
|
+
const resp = await qn.streams.getEnabledCount();
|
|
2488
|
+
```
|
|
2489
|
+
|
|
2490
|
+
```ruby
|
|
2491
|
+
# Ruby
|
|
2492
|
+
resp = JSON.parse(qn.streams.get_enabled_count({}))
|
|
2493
|
+
```
|
|
2494
|
+
|
|
2495
|
+
---
|
|
2496
|
+
|
|
2497
|
+
### Webhooks Client
|
|
2498
|
+
|
|
2499
|
+
Accessed as `qn.webhooks`. Creates webhooks from filter templates and manages their lifecycle. Backed by `https://api.quicknode.com/webhooks/rest/v1/`.
|
|
2500
|
+
|
|
2501
|
+
#### Templates and destination
|
|
2502
|
+
|
|
2503
|
+
`WebhookTemplateId` identifies the filter template:
|
|
2504
|
+
|
|
2505
|
+
| Variant | Wire value |
|
|
2506
|
+
|---|---|
|
|
2507
|
+
| `EvmWalletFilter` | `evmWalletFilter` |
|
|
2508
|
+
| `EvmContractEvents` | `evmContractEvents` |
|
|
2509
|
+
| `EvmAbiFilter` | `evmAbiFilter` |
|
|
2510
|
+
| `SolanaWalletFilter` | `solanaWalletFilter` |
|
|
2511
|
+
| `BitcoinWalletFilter` | `bitcoinWalletFilter` |
|
|
2512
|
+
| `XrplWalletFilter` | `xrplWalletFilter` |
|
|
2513
|
+
| `HyperliquidWalletEventsFilter` | `hyperliquidWalletEventsFilter` |
|
|
2514
|
+
| `StellarWalletTransactionsSourceAccountFilter` | `stellarWalletTransactionsSourceAccountFilter` |
|
|
2515
|
+
|
|
2516
|
+
`TemplateArgs` carries the arguments; construct one per template via the factory methods:
|
|
2517
|
+
|
|
2518
|
+
| Factory | Argument struct | Fields |
|
|
2519
|
+
|---|---|---|
|
|
2520
|
+
| `evm_wallet_filter` | `EvmWalletFilterTemplate` | `wallets: string[]` |
|
|
2521
|
+
| `evm_contract_events` | `EvmContractEventsTemplate` | `contracts: string[]`, `event_hashes?: string[]` |
|
|
2522
|
+
| `evm_abi_filter` | `EvmAbiFilterTemplate` | `abi: string` (JSON), `contracts: string[]` |
|
|
2523
|
+
| `solana_wallet_filter` | `SolanaWalletFilterTemplate` | `accounts: string[]` |
|
|
2524
|
+
| `bitcoin_wallet_filter` | `BitcoinWalletFilterTemplate` | `wallets: string[]` |
|
|
2525
|
+
| `xrpl_wallet_filter` | `XrplWalletFilterTemplate` | `wallets: string[]` |
|
|
2526
|
+
| `hyperliquid_wallet_events_filter` | `HyperliquidWalletEventsFilterTemplate` | `wallets: string[]` |
|
|
2527
|
+
| `stellar_wallet_transactions_filter` | `StellarWalletTransactionsFilterTemplate` | `source_accounts: string[]` |
|
|
2528
|
+
|
|
2529
|
+
`WebhookDestinationAttributes`: `url` (required), `security_token` (optional — auto-generated if omitted), `compression` (optional — `"none"` | `"gzip"`).
|
|
2530
|
+
|
|
2531
|
+
`WebhookStartFrom`: `Last` (resume from last delivered block) or `Latest` (start from newest).
|
|
2532
|
+
|
|
2533
|
+
In Ruby, `template_args` is passed as a JSON string under the key `template_args_json`; destination is passed as a JSON string under `destination_attributes_json`.
|
|
2534
|
+
|
|
2535
|
+
#### Webhooks methods
|
|
2536
|
+
|
|
2537
|
+
##### `list_webhooks` / `listWebhooks`
|
|
2538
|
+
|
|
2539
|
+
Paginated list of webhooks.
|
|
2540
|
+
|
|
2541
|
+
**Parameters** (all optional): `limit` (i64), `offset` (i64).
|
|
2542
|
+
|
|
2543
|
+
**Returns**: `ListWebhooksResponse` with `data: Webhook[]` and `pageInfo`.
|
|
2544
|
+
|
|
2545
|
+
```rust
|
|
2546
|
+
// Rust
|
|
2547
|
+
let resp = qn.webhooks.list_webhooks(&GetWebhooksParams::default()).await?;
|
|
2548
|
+
```
|
|
2549
|
+
|
|
2550
|
+
```python
|
|
2551
|
+
# Python
|
|
2552
|
+
resp = await qn.webhooks.list_webhooks()
|
|
2553
|
+
```
|
|
2554
|
+
|
|
2555
|
+
```typescript
|
|
2556
|
+
// Node.js
|
|
2557
|
+
const resp = await qn.webhooks.listWebhooks();
|
|
2558
|
+
```
|
|
2559
|
+
|
|
2560
|
+
```ruby
|
|
2561
|
+
# Ruby
|
|
2562
|
+
resp = JSON.parse(qn.webhooks.list_webhooks({}))
|
|
2563
|
+
```
|
|
2564
|
+
|
|
2565
|
+
##### `get_webhook` / `getWebhook`
|
|
2566
|
+
|
|
2567
|
+
Fetches a webhook by id.
|
|
2568
|
+
|
|
2569
|
+
**Parameters**: `id` (string, required).
|
|
2570
|
+
|
|
2571
|
+
**Returns**: `Webhook`.
|
|
2572
|
+
|
|
2573
|
+
```rust
|
|
2574
|
+
// Rust
|
|
2575
|
+
let webhook = qn.webhooks.get_webhook("wh-1").await?;
|
|
2576
|
+
```
|
|
2577
|
+
|
|
2578
|
+
```python
|
|
2579
|
+
# Python
|
|
2580
|
+
webhook = await qn.webhooks.get_webhook("wh-1")
|
|
2581
|
+
```
|
|
2582
|
+
|
|
2583
|
+
```typescript
|
|
2584
|
+
// Node.js
|
|
2585
|
+
const webhook = await qn.webhooks.getWebhook("wh-1");
|
|
2586
|
+
```
|
|
2587
|
+
|
|
2588
|
+
```ruby
|
|
2589
|
+
# Ruby
|
|
2590
|
+
webhook = JSON.parse(qn.webhooks.get_webhook(id: "wh-1"))
|
|
2591
|
+
```
|
|
2592
|
+
|
|
2593
|
+
##### `create_webhook_from_template` / `createWebhookFromTemplate`
|
|
2594
|
+
|
|
2595
|
+
Creates a webhook from a predefined filter template.
|
|
2596
|
+
|
|
2597
|
+
**Parameters**: `name` (required), `network` (required), `destination_attributes` (`WebhookDestinationAttributes`, required), `template_args` (`TemplateArgs`, required), `notification_email` (optional).
|
|
2598
|
+
|
|
2599
|
+
**Returns**: `Webhook`.
|
|
2600
|
+
|
|
2601
|
+
```rust
|
|
2602
|
+
// Rust
|
|
2603
|
+
let template_args = TemplateArgs::evm_wallet_filter(&EvmWalletFilterTemplate {
|
|
2604
|
+
wallets: vec!["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48".to_string()],
|
|
2605
|
+
})?;
|
|
2606
|
+
let params = CreateWebhookFromTemplateParams {
|
|
2607
|
+
name: "Wallet Webhook".to_string(),
|
|
2608
|
+
network: "ethereum-mainnet".to_string(),
|
|
2609
|
+
notification_email: None,
|
|
2610
|
+
destination_attributes: WebhookDestinationAttributes {
|
|
2611
|
+
url: "https://webhook.site/...".to_string(),
|
|
2612
|
+
security_token: None,
|
|
2613
|
+
compression: None,
|
|
2614
|
+
},
|
|
2615
|
+
template_args,
|
|
2616
|
+
};
|
|
2617
|
+
let webhook = qn.webhooks.create_webhook_from_template(¶ms).await?;
|
|
2618
|
+
```
|
|
2619
|
+
|
|
2620
|
+
```python
|
|
2621
|
+
# Python
|
|
2622
|
+
from sdk import EvmWalletFilterTemplate, TemplateArgs, WebhookDestinationAttributes
|
|
2623
|
+
|
|
2624
|
+
webhook = await qn.webhooks.create_webhook_from_template(
|
|
2625
|
+
name="Wallet Webhook",
|
|
2626
|
+
network="ethereum-mainnet",
|
|
2627
|
+
destination_attributes=WebhookDestinationAttributes(url="https://webhook.site/..."),
|
|
2628
|
+
template_args=TemplateArgs.evm_wallet_filter(
|
|
2629
|
+
EvmWalletFilterTemplate(wallets=["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"])
|
|
2630
|
+
),
|
|
2631
|
+
)
|
|
2632
|
+
```
|
|
2633
|
+
|
|
2634
|
+
```typescript
|
|
2635
|
+
// Node.js
|
|
2636
|
+
import { TemplateArgs } from "quicknode-sdk";
|
|
2637
|
+
|
|
2638
|
+
const webhook = await qn.webhooks.createWebhookFromTemplate({
|
|
2639
|
+
name: "Wallet Webhook",
|
|
2640
|
+
network: "ethereum-mainnet",
|
|
2641
|
+
destinationAttributes: { url: "https://webhook.site/..." },
|
|
2642
|
+
templateArgs: TemplateArgs.evmWalletFilter({
|
|
2643
|
+
wallets: ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"],
|
|
2644
|
+
}),
|
|
2645
|
+
});
|
|
2646
|
+
```
|
|
2647
|
+
|
|
2648
|
+
```ruby
|
|
2649
|
+
# Ruby
|
|
2650
|
+
destination_attributes = JSON.generate({
|
|
2651
|
+
url: "https://webhook.site/...",
|
|
2652
|
+
compression: "none"
|
|
2653
|
+
})
|
|
2654
|
+
template_args = JSON.generate({
|
|
2655
|
+
template_id: "evmWalletFilter",
|
|
2656
|
+
value: JSON.generate({ wallets: ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"] })
|
|
2657
|
+
})
|
|
2658
|
+
webhook = JSON.parse(qn.webhooks.create_webhook_from_template(
|
|
2659
|
+
name: "Wallet Webhook",
|
|
2660
|
+
network: "ethereum-mainnet",
|
|
2661
|
+
destination_attributes_json: destination_attributes,
|
|
2662
|
+
template_args_json: template_args
|
|
2663
|
+
))
|
|
2664
|
+
```
|
|
2665
|
+
|
|
2666
|
+
##### `update_webhook` / `updateWebhook`
|
|
2667
|
+
|
|
2668
|
+
Partially updates a webhook's name, notification email, and/or destination. If `destination_attributes` is supplied without `security_token`, a new token is generated automatically.
|
|
2669
|
+
|
|
2670
|
+
**Parameters**: `id` (required); body — all optional: `name`, `notification_email`, `destination_attributes`. In Ruby, `destination_attributes` is passed as a JSON string under the key `destination_attributes_json`.
|
|
2671
|
+
|
|
2672
|
+
**Returns**: updated `Webhook`.
|
|
2673
|
+
|
|
2674
|
+
```rust
|
|
2675
|
+
// Rust
|
|
2676
|
+
let params = UpdateWebhookParams {
|
|
2677
|
+
name: Some("Renamed Webhook".to_string()),
|
|
2678
|
+
..Default::default()
|
|
2679
|
+
};
|
|
2680
|
+
let webhook = qn.webhooks.update_webhook("wh-1", ¶ms).await?;
|
|
2681
|
+
```
|
|
2682
|
+
|
|
2683
|
+
```python
|
|
2684
|
+
# Python
|
|
2685
|
+
webhook = await qn.webhooks.update_webhook("wh-1", name="Renamed Webhook")
|
|
2686
|
+
```
|
|
2687
|
+
|
|
2688
|
+
```typescript
|
|
2689
|
+
// Node.js
|
|
2690
|
+
const webhook = await qn.webhooks.updateWebhook("wh-1", { name: "Renamed Webhook" });
|
|
2691
|
+
```
|
|
2692
|
+
|
|
2693
|
+
```ruby
|
|
2694
|
+
# Ruby
|
|
2695
|
+
webhook = JSON.parse(qn.webhooks.update_webhook(id: "wh-1", name: "Renamed Webhook"))
|
|
2696
|
+
```
|
|
2697
|
+
|
|
2698
|
+
##### `update_webhook_template` / `updateWebhookTemplate`
|
|
2699
|
+
|
|
2700
|
+
Updates the template args (and optionally name, email, destination) on an existing template-backed webhook.
|
|
2701
|
+
|
|
2702
|
+
**Parameters**: `webhook_id` (required), `template_args` (required); optional: `name`, `notification_email`, `destination_attributes`.
|
|
2703
|
+
|
|
2704
|
+
**Returns**: updated `Webhook`.
|
|
2705
|
+
|
|
2706
|
+
```rust
|
|
2707
|
+
// Rust
|
|
2708
|
+
let template_args = TemplateArgs::evm_wallet_filter(&EvmWalletFilterTemplate {
|
|
2709
|
+
wallets: vec!["0xnewwallet".to_string()],
|
|
2710
|
+
})?;
|
|
2711
|
+
let params = UpdateWebhookTemplateParams {
|
|
2712
|
+
name: None,
|
|
2713
|
+
notification_email: None,
|
|
2714
|
+
destination_attributes: None,
|
|
2715
|
+
template_args,
|
|
2716
|
+
};
|
|
2717
|
+
let webhook = qn.webhooks.update_webhook_template("wh-1", ¶ms).await?;
|
|
2718
|
+
```
|
|
2719
|
+
|
|
2720
|
+
```python
|
|
2721
|
+
# Python
|
|
2722
|
+
webhook = await qn.webhooks.update_webhook_template(
|
|
2723
|
+
"wh-1",
|
|
2724
|
+
template_args=TemplateArgs.evm_wallet_filter(
|
|
2725
|
+
EvmWalletFilterTemplate(wallets=["0xnewwallet"])
|
|
2726
|
+
),
|
|
2727
|
+
)
|
|
2728
|
+
```
|
|
2729
|
+
|
|
2730
|
+
```typescript
|
|
2731
|
+
// Node.js
|
|
2732
|
+
const webhook = await qn.webhooks.updateWebhookTemplate("wh-1", {
|
|
2733
|
+
templateArgs: TemplateArgs.evmWalletFilter({ wallets: ["0xnewwallet"] }),
|
|
2734
|
+
});
|
|
2735
|
+
```
|
|
2736
|
+
|
|
2737
|
+
```ruby
|
|
2738
|
+
# Ruby
|
|
2739
|
+
template_args = JSON.generate({
|
|
2740
|
+
template_id: "evmWalletFilter",
|
|
2741
|
+
value: JSON.generate({ wallets: ["0xnewwallet"] })
|
|
2742
|
+
})
|
|
2743
|
+
webhook = JSON.parse(qn.webhooks.update_webhook_template(
|
|
2744
|
+
webhook_id: "wh-1",
|
|
2745
|
+
template_args_json: template_args
|
|
2746
|
+
))
|
|
2747
|
+
```
|
|
2748
|
+
|
|
2749
|
+
##### `delete_webhook` / `deleteWebhook`
|
|
2750
|
+
|
|
2751
|
+
Deletes a webhook.
|
|
2752
|
+
|
|
2753
|
+
**Parameters**: `id` (required).
|
|
2754
|
+
|
|
2755
|
+
**Returns**: nothing.
|
|
2756
|
+
|
|
2757
|
+
```rust
|
|
2758
|
+
// Rust
|
|
2759
|
+
qn.webhooks.delete_webhook("wh-1").await?;
|
|
2760
|
+
```
|
|
20
2761
|
|
|
21
|
-
|
|
2762
|
+
```python
|
|
2763
|
+
# Python
|
|
2764
|
+
await qn.webhooks.delete_webhook("wh-1")
|
|
2765
|
+
```
|
|
2766
|
+
|
|
2767
|
+
```typescript
|
|
2768
|
+
// Node.js
|
|
2769
|
+
await qn.webhooks.deleteWebhook("wh-1");
|
|
2770
|
+
```
|
|
2771
|
+
|
|
2772
|
+
```ruby
|
|
2773
|
+
# Ruby
|
|
2774
|
+
qn.webhooks.delete_webhook(id: "wh-1")
|
|
2775
|
+
```
|
|
2776
|
+
|
|
2777
|
+
##### `delete_all_webhooks` / `deleteAllWebhooks`
|
|
2778
|
+
|
|
2779
|
+
Deletes every webhook on the account. Destructive and takes no arguments.
|
|
2780
|
+
|
|
2781
|
+
**Parameters**: none.
|
|
2782
|
+
|
|
2783
|
+
**Returns**: nothing.
|
|
2784
|
+
|
|
2785
|
+
```rust
|
|
2786
|
+
// Rust
|
|
2787
|
+
qn.webhooks.delete_all_webhooks().await?;
|
|
2788
|
+
```
|
|
2789
|
+
|
|
2790
|
+
```python
|
|
2791
|
+
# Python
|
|
2792
|
+
await qn.webhooks.delete_all_webhooks()
|
|
2793
|
+
```
|
|
2794
|
+
|
|
2795
|
+
```typescript
|
|
2796
|
+
// Node.js
|
|
2797
|
+
await qn.webhooks.deleteAllWebhooks();
|
|
2798
|
+
```
|
|
2799
|
+
|
|
2800
|
+
```ruby
|
|
2801
|
+
# Ruby
|
|
2802
|
+
qn.webhooks.delete_all_webhooks
|
|
2803
|
+
```
|
|
2804
|
+
|
|
2805
|
+
##### `pause_webhook` / `pauseWebhook`
|
|
2806
|
+
|
|
2807
|
+
Pauses a webhook so it stops delivering events.
|
|
2808
|
+
|
|
2809
|
+
**Parameters**: `id` (required).
|
|
2810
|
+
|
|
2811
|
+
**Returns**: nothing.
|
|
2812
|
+
|
|
2813
|
+
```rust
|
|
2814
|
+
// Rust
|
|
2815
|
+
qn.webhooks.pause_webhook("wh-1").await?;
|
|
2816
|
+
```
|
|
2817
|
+
|
|
2818
|
+
```python
|
|
2819
|
+
# Python
|
|
2820
|
+
await qn.webhooks.pause_webhook("wh-1")
|
|
2821
|
+
```
|
|
2822
|
+
|
|
2823
|
+
```typescript
|
|
2824
|
+
// Node.js
|
|
2825
|
+
await qn.webhooks.pauseWebhook("wh-1");
|
|
2826
|
+
```
|
|
2827
|
+
|
|
2828
|
+
```ruby
|
|
2829
|
+
# Ruby
|
|
2830
|
+
qn.webhooks.pause_webhook(id: "wh-1")
|
|
2831
|
+
```
|
|
2832
|
+
|
|
2833
|
+
##### `activate_webhook` / `activateWebhook`
|
|
2834
|
+
|
|
2835
|
+
Activates a paused or new webhook so it resumes delivering events. `start_from` determines where processing resumes.
|
|
2836
|
+
|
|
2837
|
+
**Parameters**: `id` (required), `start_from` (`WebhookStartFrom`, required — `Last` or `Latest`).
|
|
2838
|
+
|
|
2839
|
+
**Returns**: nothing.
|
|
2840
|
+
|
|
2841
|
+
```rust
|
|
2842
|
+
// Rust
|
|
2843
|
+
let params = ActivateWebhookParams { start_from: WebhookStartFrom::Latest };
|
|
2844
|
+
qn.webhooks.activate_webhook("wh-1", ¶ms).await?;
|
|
2845
|
+
```
|
|
2846
|
+
|
|
2847
|
+
```python
|
|
2848
|
+
# Python
|
|
2849
|
+
await qn.webhooks.activate_webhook("wh-1", start_from="latest")
|
|
2850
|
+
```
|
|
2851
|
+
|
|
2852
|
+
```typescript
|
|
2853
|
+
// Node.js
|
|
2854
|
+
import { WebhookStartFrom } from "quicknode-sdk";
|
|
2855
|
+
|
|
2856
|
+
await qn.webhooks.activateWebhook("wh-1", { startFrom: WebhookStartFrom.Latest });
|
|
2857
|
+
```
|
|
2858
|
+
|
|
2859
|
+
```ruby
|
|
2860
|
+
# Ruby
|
|
2861
|
+
qn.webhooks.activate_webhook(id: "wh-1", start_from: "latest")
|
|
2862
|
+
```
|
|
2863
|
+
|
|
2864
|
+
##### `get_enabled_count` / `getEnabledCount`
|
|
2865
|
+
|
|
2866
|
+
Counts currently enabled webhooks.
|
|
2867
|
+
|
|
2868
|
+
**Parameters**: none.
|
|
2869
|
+
|
|
2870
|
+
**Returns**: `WebhookEnabledCountResponse` with `total`.
|
|
2871
|
+
|
|
2872
|
+
```rust
|
|
2873
|
+
// Rust
|
|
2874
|
+
let resp = qn.webhooks.get_enabled_count().await?;
|
|
2875
|
+
```
|
|
2876
|
+
|
|
2877
|
+
```python
|
|
2878
|
+
# Python
|
|
2879
|
+
resp = await qn.webhooks.get_enabled_count()
|
|
2880
|
+
```
|
|
2881
|
+
|
|
2882
|
+
```typescript
|
|
2883
|
+
// Node.js
|
|
2884
|
+
const resp = await qn.webhooks.getEnabledCount();
|
|
2885
|
+
```
|
|
2886
|
+
|
|
2887
|
+
```ruby
|
|
2888
|
+
# Ruby
|
|
2889
|
+
resp = JSON.parse(qn.webhooks.get_enabled_count)
|
|
2890
|
+
```
|
|
2891
|
+
|
|
2892
|
+
---
|
|
2893
|
+
|
|
2894
|
+
### KV Store Client
|
|
2895
|
+
|
|
2896
|
+
Accessed as `qn.kvstore`. Provides two primitives — **sets** (single string values under a key) and **lists** (ordered collections of strings under a key). Backed by `https://api.quicknode.com/kv/rest/v1/`.
|
|
2897
|
+
|
|
2898
|
+
#### Sets
|
|
2899
|
+
|
|
2900
|
+
##### `create_set` / `createSet`
|
|
2901
|
+
|
|
2902
|
+
Stores a single string value under a key.
|
|
2903
|
+
|
|
2904
|
+
**Parameters**: `key` (string, required), `value` (string, required).
|
|
2905
|
+
|
|
2906
|
+
**Returns**: nothing.
|
|
2907
|
+
|
|
2908
|
+
```rust
|
|
2909
|
+
// Rust
|
|
2910
|
+
qn.kvstore.create_set(&CreateSetParams {
|
|
2911
|
+
key: "my-key".to_string(),
|
|
2912
|
+
value: "hello".to_string(),
|
|
2913
|
+
}).await?;
|
|
2914
|
+
```
|
|
2915
|
+
|
|
2916
|
+
```python
|
|
2917
|
+
# Python
|
|
2918
|
+
await qn.kvstore.create_set(key="my-key", value="hello")
|
|
2919
|
+
```
|
|
2920
|
+
|
|
2921
|
+
```typescript
|
|
2922
|
+
// Node.js
|
|
2923
|
+
await qn.kvstore.createSet({ key: "my-key", value: "hello" });
|
|
2924
|
+
```
|
|
2925
|
+
|
|
2926
|
+
```ruby
|
|
2927
|
+
# Ruby
|
|
2928
|
+
qn.kvstore.create_set(key: "my-key", value: "hello")
|
|
2929
|
+
```
|
|
2930
|
+
|
|
2931
|
+
##### `get_sets` / `getSets`
|
|
2932
|
+
|
|
2933
|
+
Paginated page of key/value entries.
|
|
2934
|
+
|
|
2935
|
+
**Parameters** (all optional): `limit` (i64), `cursor` (string).
|
|
2936
|
+
|
|
2937
|
+
**Returns**: `GetSetsResponse` — `{ data: KvSetEntry[], cursor: string }`.
|
|
2938
|
+
|
|
2939
|
+
```rust
|
|
2940
|
+
// Rust
|
|
2941
|
+
let resp = qn.kvstore.get_sets(&Default::default()).await?;
|
|
2942
|
+
```
|
|
2943
|
+
|
|
2944
|
+
```python
|
|
2945
|
+
# Python
|
|
2946
|
+
resp = await qn.kvstore.get_sets()
|
|
2947
|
+
```
|
|
2948
|
+
|
|
2949
|
+
```typescript
|
|
2950
|
+
// Node.js
|
|
2951
|
+
const resp = await qn.kvstore.getSets();
|
|
2952
|
+
```
|
|
2953
|
+
|
|
2954
|
+
```ruby
|
|
2955
|
+
# Ruby
|
|
2956
|
+
resp = JSON.parse(qn.kvstore.get_sets({}))
|
|
2957
|
+
```
|
|
2958
|
+
|
|
2959
|
+
##### `get_set` / `getSet`
|
|
2960
|
+
|
|
2961
|
+
Returns the value stored under a key.
|
|
2962
|
+
|
|
2963
|
+
**Parameters**: `key` (string, required).
|
|
2964
|
+
|
|
2965
|
+
**Returns**: `GetSetResponse` with `value`.
|
|
2966
|
+
|
|
2967
|
+
```rust
|
|
2968
|
+
// Rust
|
|
2969
|
+
let resp = qn.kvstore.get_set("my-key").await?;
|
|
2970
|
+
```
|
|
2971
|
+
|
|
2972
|
+
```python
|
|
2973
|
+
# Python
|
|
2974
|
+
resp = await qn.kvstore.get_set("my-key")
|
|
2975
|
+
```
|
|
2976
|
+
|
|
2977
|
+
```typescript
|
|
2978
|
+
// Node.js
|
|
2979
|
+
const resp = await qn.kvstore.getSet("my-key");
|
|
2980
|
+
```
|
|
2981
|
+
|
|
2982
|
+
```ruby
|
|
2983
|
+
# Ruby
|
|
2984
|
+
resp = JSON.parse(qn.kvstore.get_set(key: "my-key"))
|
|
2985
|
+
```
|
|
2986
|
+
|
|
2987
|
+
##### `bulk_sets` / `bulkSets`
|
|
2988
|
+
|
|
2989
|
+
Adds and/or deletes multiple sets in a single request.
|
|
2990
|
+
|
|
2991
|
+
**Parameters** (at least one required): `add_sets` (map<string,string>, optional), `delete_sets` (string[], optional).
|
|
2992
|
+
|
|
2993
|
+
**Returns**: nothing.
|
|
2994
|
+
|
|
2995
|
+
```rust
|
|
2996
|
+
// Rust
|
|
2997
|
+
use std::collections::HashMap;
|
|
2998
|
+
|
|
2999
|
+
let mut add_sets = HashMap::new();
|
|
3000
|
+
add_sets.insert("k1".to_string(), "v1".to_string());
|
|
3001
|
+
qn.kvstore.bulk_sets(&BulkSetsParams {
|
|
3002
|
+
add_sets: Some(add_sets),
|
|
3003
|
+
delete_sets: Some(vec!["old-key".to_string()]),
|
|
3004
|
+
}).await?;
|
|
3005
|
+
```
|
|
3006
|
+
|
|
3007
|
+
```python
|
|
3008
|
+
# Python
|
|
3009
|
+
await qn.kvstore.bulk_sets(
|
|
3010
|
+
add_sets={"k1": "v1"},
|
|
3011
|
+
delete_sets=["old-key"],
|
|
3012
|
+
)
|
|
3013
|
+
```
|
|
3014
|
+
|
|
3015
|
+
```typescript
|
|
3016
|
+
// Node.js
|
|
3017
|
+
await qn.kvstore.bulkSets({
|
|
3018
|
+
addSets: { k1: "v1" },
|
|
3019
|
+
deleteSets: ["old-key"],
|
|
3020
|
+
});
|
|
3021
|
+
```
|
|
3022
|
+
|
|
3023
|
+
```ruby
|
|
3024
|
+
# Ruby
|
|
3025
|
+
qn.kvstore.bulk_sets(add_sets: { "k1" => "v1" }, delete_sets: ["old-key"])
|
|
3026
|
+
```
|
|
3027
|
+
|
|
3028
|
+
##### `delete_set` / `deleteSet`
|
|
3029
|
+
|
|
3030
|
+
Deletes a single set.
|
|
3031
|
+
|
|
3032
|
+
**Parameters**: `key` (string, required).
|
|
3033
|
+
|
|
3034
|
+
**Returns**: nothing.
|
|
3035
|
+
|
|
3036
|
+
```rust
|
|
3037
|
+
// Rust
|
|
3038
|
+
qn.kvstore.delete_set("my-key").await?;
|
|
3039
|
+
```
|
|
3040
|
+
|
|
3041
|
+
```python
|
|
3042
|
+
# Python
|
|
3043
|
+
await qn.kvstore.delete_set("my-key")
|
|
3044
|
+
```
|
|
3045
|
+
|
|
3046
|
+
```typescript
|
|
3047
|
+
// Node.js
|
|
3048
|
+
await qn.kvstore.deleteSet("my-key");
|
|
3049
|
+
```
|
|
3050
|
+
|
|
3051
|
+
```ruby
|
|
3052
|
+
# Ruby
|
|
3053
|
+
qn.kvstore.delete_set(key: "my-key")
|
|
3054
|
+
```
|
|
3055
|
+
|
|
3056
|
+
#### Lists
|
|
3057
|
+
|
|
3058
|
+
##### `create_list` / `createList`
|
|
3059
|
+
|
|
3060
|
+
Creates a list under a key, seeded with the initial items.
|
|
3061
|
+
|
|
3062
|
+
**Parameters**: `key` (string, required), `items` (string[], required).
|
|
3063
|
+
|
|
3064
|
+
**Returns**: nothing.
|
|
3065
|
+
|
|
3066
|
+
```rust
|
|
3067
|
+
// Rust
|
|
3068
|
+
qn.kvstore.create_list(&CreateListParams {
|
|
3069
|
+
key: "my-list".to_string(),
|
|
3070
|
+
items: vec!["0xabc".to_string(), "0xdef".to_string()],
|
|
3071
|
+
}).await?;
|
|
3072
|
+
```
|
|
3073
|
+
|
|
3074
|
+
```python
|
|
3075
|
+
# Python
|
|
3076
|
+
await qn.kvstore.create_list(key="my-list", items=["0xabc", "0xdef"])
|
|
3077
|
+
```
|
|
22
3078
|
|
|
23
|
-
|
|
24
|
-
|
|
3079
|
+
```typescript
|
|
3080
|
+
// Node.js
|
|
3081
|
+
await qn.kvstore.createList({ key: "my-list", items: ["0xabc", "0xdef"] });
|
|
3082
|
+
```
|
|
3083
|
+
|
|
3084
|
+
```ruby
|
|
3085
|
+
# Ruby
|
|
3086
|
+
qn.kvstore.create_list(key: "my-list", items: ["0xabc", "0xdef"])
|
|
3087
|
+
```
|
|
3088
|
+
|
|
3089
|
+
##### `get_lists` / `getLists`
|
|
3090
|
+
|
|
3091
|
+
Paginated page of list keys.
|
|
3092
|
+
|
|
3093
|
+
**Parameters** (all optional): `limit` (i64), `cursor` (string).
|
|
3094
|
+
|
|
3095
|
+
**Returns**: `GetListsResponse` — `{ data: { keys: string[] }, cursor: string }`.
|
|
3096
|
+
|
|
3097
|
+
```rust
|
|
3098
|
+
// Rust
|
|
3099
|
+
let resp = qn.kvstore.get_lists(&Default::default()).await?;
|
|
3100
|
+
```
|
|
3101
|
+
|
|
3102
|
+
```python
|
|
3103
|
+
# Python
|
|
3104
|
+
resp = await qn.kvstore.get_lists()
|
|
3105
|
+
```
|
|
3106
|
+
|
|
3107
|
+
```typescript
|
|
3108
|
+
// Node.js
|
|
3109
|
+
const resp = await qn.kvstore.getLists();
|
|
3110
|
+
```
|
|
3111
|
+
|
|
3112
|
+
```ruby
|
|
3113
|
+
# Ruby
|
|
3114
|
+
resp = JSON.parse(qn.kvstore.get_lists({}))
|
|
3115
|
+
```
|
|
3116
|
+
|
|
3117
|
+
##### `get_list` / `getList`
|
|
3118
|
+
|
|
3119
|
+
Paginated page of items for a specific list.
|
|
3120
|
+
|
|
3121
|
+
**Parameters**: `key` (string, required); optional `limit` (i64), `cursor` (string).
|
|
3122
|
+
|
|
3123
|
+
**Returns**: `GetListResponse` — `{ data: { items: string[] }, cursor: string }`.
|
|
3124
|
+
|
|
3125
|
+
```rust
|
|
3126
|
+
// Rust
|
|
3127
|
+
let resp = qn.kvstore.get_list("my-list", &Default::default()).await?;
|
|
3128
|
+
```
|
|
3129
|
+
|
|
3130
|
+
```python
|
|
3131
|
+
# Python
|
|
3132
|
+
resp = await qn.kvstore.get_list("my-list")
|
|
3133
|
+
```
|
|
3134
|
+
|
|
3135
|
+
```typescript
|
|
3136
|
+
// Node.js
|
|
3137
|
+
const resp = await qn.kvstore.getList("my-list");
|
|
3138
|
+
```
|
|
3139
|
+
|
|
3140
|
+
```ruby
|
|
3141
|
+
# Ruby
|
|
3142
|
+
resp = JSON.parse(qn.kvstore.get_list(key: "my-list"))
|
|
3143
|
+
```
|
|
3144
|
+
|
|
3145
|
+
##### `update_list` / `updateList`
|
|
3146
|
+
|
|
3147
|
+
Adds and/or removes items in a single operation.
|
|
3148
|
+
|
|
3149
|
+
**Parameters**: `key` (string, required); optional: `add_items` (string[]), `remove_items` (string[]).
|
|
3150
|
+
|
|
3151
|
+
**Returns**: nothing.
|
|
3152
|
+
|
|
3153
|
+
```rust
|
|
3154
|
+
// Rust
|
|
3155
|
+
qn.kvstore.update_list(
|
|
3156
|
+
"my-list",
|
|
3157
|
+
&UpdateListParams {
|
|
3158
|
+
add_items: Some(vec!["0x456".to_string()]),
|
|
3159
|
+
remove_items: Some(vec!["0xabc".to_string()]),
|
|
3160
|
+
},
|
|
3161
|
+
).await?;
|
|
3162
|
+
```
|
|
3163
|
+
|
|
3164
|
+
```python
|
|
3165
|
+
# Python
|
|
3166
|
+
await qn.kvstore.update_list(
|
|
3167
|
+
"my-list",
|
|
3168
|
+
add_items=["0x456"],
|
|
3169
|
+
remove_items=["0xabc"],
|
|
3170
|
+
)
|
|
3171
|
+
```
|
|
3172
|
+
|
|
3173
|
+
```typescript
|
|
3174
|
+
// Node.js
|
|
3175
|
+
await qn.kvstore.updateList("my-list", {
|
|
3176
|
+
addItems: ["0x456"],
|
|
3177
|
+
removeItems: ["0xabc"],
|
|
3178
|
+
});
|
|
3179
|
+
```
|
|
3180
|
+
|
|
3181
|
+
```ruby
|
|
3182
|
+
# Ruby
|
|
3183
|
+
qn.kvstore.update_list(key: "my-list", add_items: ["0x456"], remove_items: ["0xabc"])
|
|
3184
|
+
```
|
|
3185
|
+
|
|
3186
|
+
##### `add_list_item` / `addListItem`
|
|
3187
|
+
|
|
3188
|
+
Appends a single item to a list.
|
|
3189
|
+
|
|
3190
|
+
**Parameters**: `key` (string, required), `item` (string, required).
|
|
3191
|
+
|
|
3192
|
+
**Returns**: nothing.
|
|
3193
|
+
|
|
3194
|
+
```rust
|
|
3195
|
+
// Rust
|
|
3196
|
+
qn.kvstore.add_list_item(
|
|
3197
|
+
"my-list",
|
|
3198
|
+
&AddListItemParams { item: "0x123".to_string() },
|
|
3199
|
+
).await?;
|
|
3200
|
+
```
|
|
3201
|
+
|
|
3202
|
+
```python
|
|
3203
|
+
# Python
|
|
3204
|
+
await qn.kvstore.add_list_item("my-list", "0x123")
|
|
3205
|
+
```
|
|
3206
|
+
|
|
3207
|
+
```typescript
|
|
3208
|
+
// Node.js
|
|
3209
|
+
await qn.kvstore.addListItem("my-list", { item: "0x123" });
|
|
3210
|
+
```
|
|
3211
|
+
|
|
3212
|
+
```ruby
|
|
3213
|
+
# Ruby
|
|
3214
|
+
qn.kvstore.add_list_item(key: "my-list", item: "0x123")
|
|
3215
|
+
```
|
|
3216
|
+
|
|
3217
|
+
##### `list_contains_item` / `listContainsItem`
|
|
3218
|
+
|
|
3219
|
+
Checks whether a list contains a specific item.
|
|
3220
|
+
|
|
3221
|
+
**Parameters**: `key` (string, required), `item` (string, required).
|
|
3222
|
+
|
|
3223
|
+
**Returns**: `ListContainsItemResponse` with `exists: bool`.
|
|
3224
|
+
|
|
3225
|
+
```rust
|
|
3226
|
+
// Rust
|
|
3227
|
+
let resp = qn.kvstore.list_contains_item("my-list", "0x123").await?;
|
|
3228
|
+
```
|
|
3229
|
+
|
|
3230
|
+
```python
|
|
3231
|
+
# Python
|
|
3232
|
+
resp = await qn.kvstore.list_contains_item("my-list", "0x123")
|
|
3233
|
+
```
|
|
3234
|
+
|
|
3235
|
+
```typescript
|
|
3236
|
+
// Node.js
|
|
3237
|
+
const resp = await qn.kvstore.listContainsItem("my-list", "0x123");
|
|
3238
|
+
```
|
|
3239
|
+
|
|
3240
|
+
```ruby
|
|
3241
|
+
# Ruby
|
|
3242
|
+
resp = JSON.parse(qn.kvstore.list_contains_item(key: "my-list", item: "0x123"))
|
|
3243
|
+
```
|
|
3244
|
+
|
|
3245
|
+
##### `delete_list_item` / `deleteListItem`
|
|
25
3246
|
|
|
26
|
-
|
|
3247
|
+
Removes a single item from a list.
|
|
27
3248
|
|
|
28
|
-
|
|
3249
|
+
**Parameters**: `key` (string, required), `item` (string, required).
|
|
29
3250
|
|
|
30
|
-
|
|
31
|
-
import Core from '@quicknode/sdk/core';
|
|
3251
|
+
**Returns**: nothing.
|
|
32
3252
|
|
|
33
|
-
|
|
3253
|
+
```rust
|
|
3254
|
+
// Rust
|
|
3255
|
+
qn.kvstore.delete_list_item("my-list", "0x123").await?;
|
|
3256
|
+
```
|
|
3257
|
+
|
|
3258
|
+
```python
|
|
3259
|
+
# Python
|
|
3260
|
+
await qn.kvstore.delete_list_item("my-list", "0x123")
|
|
3261
|
+
```
|
|
3262
|
+
|
|
3263
|
+
```typescript
|
|
3264
|
+
// Node.js
|
|
3265
|
+
await qn.kvstore.deleteListItem("my-list", "0x123");
|
|
3266
|
+
```
|
|
3267
|
+
|
|
3268
|
+
```ruby
|
|
3269
|
+
# Ruby
|
|
3270
|
+
qn.kvstore.delete_list_item(key: "my-list", item: "0x123")
|
|
3271
|
+
```
|
|
3272
|
+
|
|
3273
|
+
##### `delete_list` / `deleteList`
|
|
3274
|
+
|
|
3275
|
+
Deletes a list and all of its items.
|
|
3276
|
+
|
|
3277
|
+
**Parameters**: `key` (string, required).
|
|
3278
|
+
|
|
3279
|
+
**Returns**: nothing.
|
|
3280
|
+
|
|
3281
|
+
```rust
|
|
3282
|
+
// Rust
|
|
3283
|
+
qn.kvstore.delete_list("my-list").await?;
|
|
3284
|
+
```
|
|
3285
|
+
|
|
3286
|
+
```python
|
|
3287
|
+
# Python
|
|
3288
|
+
await qn.kvstore.delete_list("my-list")
|
|
3289
|
+
```
|
|
3290
|
+
|
|
3291
|
+
```typescript
|
|
3292
|
+
// Node.js
|
|
3293
|
+
await qn.kvstore.deleteList("my-list");
|
|
3294
|
+
```
|
|
3295
|
+
|
|
3296
|
+
```ruby
|
|
3297
|
+
# Ruby
|
|
3298
|
+
qn.kvstore.delete_list(key: "my-list")
|
|
3299
|
+
```
|
|
3300
|
+
|
|
3301
|
+
## Error Handling
|
|
3302
|
+
|
|
3303
|
+
Every binding exposes a typed exception hierarchy derived from the core `SdkError`
|
|
3304
|
+
enum (`crates/core/src/errors.rs`). Catch the base class (`QuickNodeError` /
|
|
3305
|
+
`QuickNodeSdk::Error` / `SdkError`) for any SDK-originated failure, or a specific
|
|
3306
|
+
subclass to branch on transport vs. API semantics.
|
|
3307
|
+
|
|
3308
|
+
| Logical class | When it fires | Extra fields |
|
|
3309
|
+
|----------------------|-------------------------------------------------------------|----------------------|
|
|
3310
|
+
| `QuickNodeError` | base class; catches everything below | — |
|
|
3311
|
+
| `ConfigError` | invalid config or URL surfaced at construction time | — |
|
|
3312
|
+
| `HttpError` | transport failure that isn't a timeout/connect | — |
|
|
3313
|
+
| `TimeoutError` | request timed out (subclass of `HttpError`) | — |
|
|
3314
|
+
| `ConnectionError` | connection refused / DNS / TLS (subclass of `HttpError`) | — |
|
|
3315
|
+
| `ApiError` | non-2xx HTTP response | `status`, `body` |
|
|
3316
|
+
| `DecodeError` | 2xx response but JSON parse failed | `body` |
|
|
3317
|
+
|
|
3318
|
+
Per-language names:
|
|
3319
|
+
|
|
3320
|
+
- **Rust** — pattern-match on `SdkError { Http, Api, Decode, UrlParse, Config }`; use `err.http_kind()` to classify `Http` into `Timeout`, `Connect`, or `Other`.
|
|
3321
|
+
- **Python** — `QuickNodeError`, `ConfigError`, `HttpError`, `TimeoutError`, `ConnectionError`, `ApiError`, `DecodeError` (importable from `sdk`).
|
|
3322
|
+
- **Node.js** — same class names, importable from `@quicknode/sdk`, all extend `Error`.
|
|
3323
|
+
- **Ruby** — `QuickNodeSdk::Error`, `QuickNodeSdk::ConfigError`, `QuickNodeSdk::HttpError`, `QuickNodeSdk::TimeoutError`, `QuickNodeSdk::ConnectionError`, `QuickNodeSdk::ApiError`, `QuickNodeSdk::DecodeError`; all extend `StandardError`. Hash-key validation still raises `ArgumentError`.
|
|
3324
|
+
|
|
3325
|
+
```rust
|
|
3326
|
+
// Rust
|
|
3327
|
+
match qn.admin.show_endpoint("missing").await {
|
|
3328
|
+
Ok(resp) => println!("{:?}", resp.data),
|
|
3329
|
+
Err(SdkError::Api { status, body }) if status.as_u16() == 404 => {
|
|
3330
|
+
eprintln!("not found: {body}")
|
|
3331
|
+
}
|
|
3332
|
+
Err(e) if matches!(e.http_kind(), Some(HttpKind::Timeout)) => eprintln!("timed out"),
|
|
3333
|
+
Err(e) => eprintln!("other: {e}"),
|
|
3334
|
+
}
|
|
3335
|
+
```
|
|
3336
|
+
|
|
3337
|
+
```python
|
|
3338
|
+
# Python
|
|
3339
|
+
from sdk import ApiError, TimeoutError
|
|
3340
|
+
try:
|
|
3341
|
+
await qn.admin.show_endpoint("missing")
|
|
3342
|
+
except ApiError as e:
|
|
3343
|
+
if e.status == 404:
|
|
3344
|
+
print(f"not found: {e.body}")
|
|
3345
|
+
else:
|
|
3346
|
+
raise
|
|
3347
|
+
except TimeoutError:
|
|
3348
|
+
print("timed out")
|
|
3349
|
+
```
|
|
3350
|
+
|
|
3351
|
+
```typescript
|
|
3352
|
+
// Node.js
|
|
3353
|
+
import { ApiError, TimeoutError } from "@quicknode/sdk";
|
|
3354
|
+
try {
|
|
3355
|
+
await qn.admin.showEndpoint("missing");
|
|
3356
|
+
} catch (e) {
|
|
3357
|
+
if (e instanceof ApiError && e.status === 404) console.error("not found:", e.body);
|
|
3358
|
+
else if (e instanceof TimeoutError) console.error("timed out");
|
|
3359
|
+
else throw e;
|
|
3360
|
+
}
|
|
3361
|
+
```
|
|
3362
|
+
|
|
3363
|
+
```ruby
|
|
3364
|
+
# Ruby
|
|
3365
|
+
begin
|
|
3366
|
+
qn.admin.show_endpoint(id: "missing")
|
|
3367
|
+
rescue QuickNodeSdk::ApiError => e
|
|
3368
|
+
warn "api #{e.status}: #{e.body}" if e.status == 404
|
|
3369
|
+
rescue QuickNodeSdk::TimeoutError
|
|
3370
|
+
warn "timed out"
|
|
3371
|
+
end
|
|
3372
|
+
```
|
|
34
3373
|
|
|
35
|
-
|
|
3374
|
+
## Development
|
|
3375
|
+
|
|
3376
|
+
### Prerequisites
|
|
3377
|
+
|
|
3378
|
+
- Rust (stable)
|
|
3379
|
+
- Python 3.8+ with [uv](https://docs.astral.sh/uv/)
|
|
3380
|
+
- Node.js 18+
|
|
3381
|
+
- Ruby 3.0+
|
|
3382
|
+
- [just](https://github.com/casey/just)
|
|
3383
|
+
|
|
3384
|
+
### Build Commands
|
|
3385
|
+
|
|
3386
|
+
Use the commands in the `Justfile` for the setup and build commands.
|
|
3387
|
+
|
|
3388
|
+
```bash
|
|
3389
|
+
# Core library
|
|
3390
|
+
cargo check
|
|
3391
|
+
cargo test -p quicknode-sdk
|
|
3392
|
+
|
|
3393
|
+
# Python (from project root)
|
|
3394
|
+
just python-setup-env
|
|
3395
|
+
just python-build
|
|
3396
|
+
|
|
3397
|
+
# Node.js (from npm/)
|
|
3398
|
+
just node-build
|
|
3399
|
+
|
|
3400
|
+
# Ruby
|
|
3401
|
+
just ruby-build
|
|
3402
|
+
|
|
3403
|
+
# Rust
|
|
3404
|
+
cargo build -p quicknode-sdk
|
|
3405
|
+
```
|
|
3406
|
+
|
|
3407
|
+
### Testing
|
|
3408
|
+
|
|
3409
|
+
```bash
|
|
3410
|
+
just test
|
|
3411
|
+
```
|
|
3412
|
+
|
|
3413
|
+
Runs the Rust unit tests for `quicknode-sdk` using [wiremock](https://github.com/LukeMathWalker/wiremock-rs) to mock HTTP responses — no API key required.
|
|
3414
|
+
|
|
3415
|
+
### Examples
|
|
3416
|
+
|
|
3417
|
+
```bash
|
|
3418
|
+
# Rust
|
|
3419
|
+
QN_SDK__API_KEY=replaceme cargo run --example admin -p quicknode-sdk --features rust
|
|
3420
|
+
|
|
3421
|
+
# Python
|
|
3422
|
+
QN_SDK__API_KEY=replaceme uv run python/examples/admin.py
|
|
3423
|
+
QN_SDK__API_KEY=replaceme uv run python/examples/streams.py
|
|
3424
|
+
|
|
3425
|
+
# Node.js
|
|
3426
|
+
cd npm && QN_SDK__API_KEY=replaceme npx tsx examples/admin.ts
|
|
3427
|
+
cd npm && QN_SDK__API_KEY=replaceme npx tsx examples/streams.ts
|
|
3428
|
+
|
|
3429
|
+
# Ruby (build first, then run)
|
|
3430
|
+
just ruby-build
|
|
3431
|
+
QN_SDK__API_KEY=replaceme ruby ruby/examples/admin.rb
|
|
3432
|
+
QN_SDK__API_KEY=replaceme ruby ruby/examples/admin_e2e.rb
|
|
3433
|
+
QN_SDK__API_KEY=replaceme ruby ruby/examples/streams.rb
|
|
3434
|
+
```
|
|
3435
|
+
|
|
3436
|
+
### Releasing
|
|
3437
|
+
|
|
3438
|
+
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`.
|
|
3439
|
+
|
|
3440
|
+
#### Rust crate only (crates.io)
|
|
3441
|
+
|
|
3442
|
+
```bash
|
|
3443
|
+
# 1. Bump the version in crates/core/Cargo.toml (e.g. 0.1.0 → 0.1.0-alpha.5)
|
|
3444
|
+
# Pre-release identifiers use SemVer 2.0 syntax: MAJOR.MINOR.PATCH-<id>.<N>
|
|
3445
|
+
# Examples: 0.1.0-alpha.4, 0.2.0-beta.1, 0.2.0-rc.1
|
|
3446
|
+
|
|
3447
|
+
# 2. Commit and push
|
|
3448
|
+
git commit -am "chore: release quicknode-sdk 0.1.0-alpha.5"
|
|
3449
|
+
git push
|
|
3450
|
+
|
|
3451
|
+
# 3. Validate the tarball (no upload)
|
|
3452
|
+
cargo publish -p quicknode-sdk --dry-run
|
|
3453
|
+
|
|
3454
|
+
# 4. Publish (requires `cargo login` with a crates.io token)
|
|
3455
|
+
cargo publish -p quicknode-sdk
|
|
36
3456
|
```
|
|
37
3457
|
|
|
38
|
-
|
|
3458
|
+
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).
|
|
3459
|
+
|
|
3460
|
+
#### All bindings together (Python / Node / Ruby)
|
|
3461
|
+
|
|
3462
|
+
macOS (Apple Silicon) artifacts are built locally rather than on GitHub Actions to avoid the ~10× runner cost. Linux artifacts are built by CI when a GitHub release is published.
|
|
3463
|
+
|
|
3464
|
+
1. **Bump versions and commit:**
|
|
3465
|
+
```bash
|
|
3466
|
+
just release 0.2.0
|
|
3467
|
+
git push
|
|
3468
|
+
```
|
|
3469
|
+
|
|
3470
|
+
2. **Create the GitHub release** via the GitHub UI:
|
|
3471
|
+
- **Releases → Draft a new release**.
|
|
3472
|
+
- **Choose a tag** → type `v0.2.0` → **Create new tag on publish**.
|
|
3473
|
+
- Target branch: `main`.
|
|
3474
|
+
- Fill in title and notes (or click **Generate release notes**).
|
|
3475
|
+
- Click **Publish release**.
|
|
3476
|
+
|
|
3477
|
+
This creates + pushes the tag and triggers `.github/workflows/release.yml`, which builds Linux artifacts and attaches them to the release.
|
|
39
3478
|
|
|
40
|
-
|
|
3479
|
+
3. **Build macOS arm64 artifacts locally and append them to the release:**
|
|
3480
|
+
```bash
|
|
3481
|
+
just macos-build-and-publish 0.2.0
|
|
3482
|
+
```
|
|
41
3483
|
|
|
42
|
-
|
|
3484
|
+
Step 3 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.
|
|
43
3485
|
|
|
44
|
-
|
|
3486
|
+
`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.
|
|
45
3487
|
|
|
46
|
-
|
|
3488
|
+
#### npm publish (`@quicknode/sdk`)
|
|
47
3489
|
|
|
48
|
-
|
|
3490
|
+
The Node package is published to npm as `@quicknode/sdk`. During the 3.x pre-release period, publishes use the `next` dist-tag so `npm install @quicknode/sdk` continues to resolve to the legacy 2.x release while `npm install @quicknode/sdk@next` pulls the rewrite.
|
|
49
3491
|
|
|
50
|
-
|
|
3492
|
+
The npm publish uses [napi-rs's multi-package layout](https://napi.rs/docs/deep-dive/release): one main package plus per-platform sub-packages (`@quicknode/sdk-linux-x64-gnu`, `@quicknode/sdk-darwin-arm64`, etc.) declared as `optionalDependencies`. Publishing is triggered manually via a GitHub Actions workflow so the macOS binary (built locally) can be uploaded to the GitHub release before publish.
|
|
51
3493
|
|
|
52
|
-
|
|
3494
|
+
Anyone with permission to run the `Publish npm` workflow in this repo can cut a release.
|
|
53
3495
|
|
|
54
|
-
|
|
3496
|
+
**Note on versions:** the git tag tracks the overall project version (e.g. `v0.1.0-alpha.5`) and is set in `crates/core/Cargo.toml` / the root `Cargo.toml`. The npm package version is set independently in `npm/package.json` (e.g. `3.0.0-alpha.5`) to stay compatible with the pre-existing `@quicknode/sdk` 2.x series on npm. The two versions do not need to match.
|
|
55
3497
|
|
|
56
|
-
|
|
3498
|
+
**Per-release flow:**
|
|
57
3499
|
|
|
58
|
-
|
|
3500
|
+
1. **Bump the npm version** in `npm/package.json` (e.g. `3.0.0-alpha.4` → `3.0.0-alpha.5`), commit, and push to `main`. (Bump the overall project version in `just release <version>` as part of the normal release flow above — this sets the git tag.)
|
|
59
3501
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
3502
|
+
2. **Create the GitHub release** via the GitHub UI:
|
|
3503
|
+
- Go to **Releases → Draft a new release**.
|
|
3504
|
+
- Click **Choose a tag**, type the new tag (e.g. `v0.1.0-alpha.5`), and select **Create new tag on publish**.
|
|
3505
|
+
- Target branch: `main`.
|
|
3506
|
+
- Fill in the title and release notes (or click **Generate release notes**).
|
|
3507
|
+
- Click **Publish release**.
|
|
65
3508
|
|
|
66
|
-
|
|
3509
|
+
Publishing the release creates + pushes the tag, which triggers `.github/workflows/release.yml`. CI builds the Linux `.node` artifacts and attaches them to the release you just created.
|
|
67
3510
|
|
|
68
|
-
|
|
3511
|
+
3. **Wait for `release.yml` to finish.** Confirm the four Linux `index.*.node` artifacts are attached to the release.
|
|
69
3512
|
|
|
70
|
-
|
|
3513
|
+
4. **Build and upload the macOS arm64 binary** locally (Apple Silicon Mac required):
|
|
3514
|
+
```bash
|
|
3515
|
+
just node-build
|
|
3516
|
+
gh release upload v0.1.0-alpha.5 npm/index.darwin-arm64.node
|
|
3517
|
+
```
|
|
71
3518
|
|
|
72
|
-
|
|
3519
|
+
5. **Trigger the publish workflow.** From the GitHub UI: **Actions → Publish npm → Run workflow**, then enter the git tag (`v0.1.0-alpha.5`) and npm dist-tag (`next`). Or via CLI:
|
|
3520
|
+
```bash
|
|
3521
|
+
gh workflow run publish-npm.yml -f tag=v0.1.0-alpha.5 -f npm_tag=next
|
|
3522
|
+
```
|
|
73
3523
|
|
|
74
|
-
|
|
3524
|
+
6. **Verify.**
|
|
3525
|
+
```bash
|
|
3526
|
+
npm view @quicknode/sdk dist-tags
|
|
3527
|
+
# Expected: next: 3.0.0-alpha.5, latest: 2.6.0 (unchanged)
|
|
3528
|
+
```
|
|
75
3529
|
|
|
76
|
-
|
|
3530
|
+
Users can install the pre-release with `npm install @quicknode/sdk@next`.
|
|
77
3531
|
|
|
78
|
-
|
|
3532
|
+
## License
|
|
79
3533
|
|
|
80
|
-
|
|
3534
|
+
MIT
|