@direct.dev/sdk 1.0.0 → 1.0.2
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 +52 -26
- package/lib/index.cjs +3 -3
- package/lib/index.d.ts +140 -3
- package/lib/index.mjs +3 -3
- package/package.json +13 -14
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
</p>
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
|
-
A drop-in `fetch` wrapper for [Direct.dev](https://direct.dev/) RPC endpoints. Your existing code keeps working — Direct.dev quietly takes over JSON-RPC
|
|
16
|
+
A drop-in `fetch` wrapper for [Direct.dev](https://direct.dev/) RPC endpoints. Your existing code keeps working — Direct.dev quietly takes over JSON-RPC requests to its own URLs and serves them faster, with caching, sync, and failover built in.
|
|
17
17
|
|
|
18
18
|
## Highlights
|
|
19
19
|
|
|
@@ -21,13 +21,13 @@ A drop-in `fetch` wrapper for [Direct.dev](https://direct.dev/) RPC endpoints. Y
|
|
|
21
21
|
Popular requests are answered from a local cache; the rest are routed through the Direct.dev edge.
|
|
22
22
|
|
|
23
23
|
**Less bandwidth**<br />
|
|
24
|
-
Direct Sync streams only what changed since your last
|
|
24
|
+
Direct Sync streams only what changed since your last request, instead of resending the full payload every time.
|
|
25
25
|
|
|
26
26
|
**Compact wire format**<br />
|
|
27
27
|
Direct Wire is a binary protocol tuned for Web3 traffic — smaller frames and faster decode than JSON-RPC.
|
|
28
28
|
|
|
29
29
|
**Built-in failover**<br />
|
|
30
|
-
|
|
30
|
+
Requests reroute through a healthy path automatically when an upstream is unavailable. No retry logic to write.
|
|
31
31
|
|
|
32
32
|
**Drop-in**<br />
|
|
33
33
|
Plugs into native `fetch`, so viem, ethers, and your own code work unchanged. Only Direct.dev URLs are intercepted.
|
|
@@ -40,14 +40,14 @@ npm install @direct.dev/sdk
|
|
|
40
40
|
|
|
41
41
|
## Quick start
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
Run `install()` once at app startup and you're done:
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
46
|
import { install } from "@direct.dev/sdk";
|
|
47
47
|
|
|
48
48
|
install();
|
|
49
49
|
|
|
50
|
-
const res = await fetch("https://rpc.direct.dev/v1/<
|
|
50
|
+
const res = await fetch("https://rpc.direct.dev/v1/<project>.<token>/ethereum", {
|
|
51
51
|
method: "POST",
|
|
52
52
|
headers: { "Content-Type": "application/json" },
|
|
53
53
|
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }),
|
|
@@ -57,7 +57,7 @@ const { result } = await res.json();
|
|
|
57
57
|
// "0x134a1c0"
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
That's it. Every
|
|
60
|
+
That's it. Every request to a Direct.dev RPC URL now goes through the SDK.
|
|
61
61
|
|
|
62
62
|
### With options
|
|
63
63
|
|
|
@@ -78,7 +78,7 @@ const directFetch = createFetch({
|
|
|
78
78
|
logging: { client: "info" },
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
const res = await directFetch("https://rpc.direct.dev/v1/<
|
|
81
|
+
const res = await directFetch("https://rpc.direct.dev/v1/<project>.<token>/ethereum", {
|
|
82
82
|
method: "POST",
|
|
83
83
|
headers: { "Content-Type": "application/json" },
|
|
84
84
|
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }),
|
|
@@ -102,7 +102,7 @@ install();
|
|
|
102
102
|
|
|
103
103
|
const client = createPublicClient({
|
|
104
104
|
chain: mainnet,
|
|
105
|
-
transport: http("https://rpc.direct.dev/v1/<
|
|
105
|
+
transport: http("https://rpc.direct.dev/v1/<project>.<token>/ethereum"),
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
await client.getBlockNumber();
|
|
@@ -119,7 +119,7 @@ const directFetch = createFetch({ logging: { client: "info" } });
|
|
|
119
119
|
|
|
120
120
|
const client = createPublicClient({
|
|
121
121
|
chain: mainnet,
|
|
122
|
-
transport: http("https://rpc.direct.dev/v1/<
|
|
122
|
+
transport: http("https://rpc.direct.dev/v1/<project>.<token>/ethereum", {
|
|
123
123
|
fetch: directFetch,
|
|
124
124
|
}),
|
|
125
125
|
});
|
|
@@ -136,7 +136,7 @@ In the browser, prefer an HTML preload link. It lets the browser start fetching
|
|
|
136
136
|
rel="preload"
|
|
137
137
|
as="fetch"
|
|
138
138
|
crossorigin="anonymous"
|
|
139
|
-
href="https://rpc.direct.dev/v1/<
|
|
139
|
+
href="https://rpc.direct.dev/v1/<project>.<token>/ethereum"
|
|
140
140
|
/>
|
|
141
141
|
```
|
|
142
142
|
|
|
@@ -145,8 +145,8 @@ On the server, or in environments without preload links, pass `preload` to `inst
|
|
|
145
145
|
```ts
|
|
146
146
|
install({
|
|
147
147
|
preload: [
|
|
148
|
-
"https://rpc.direct.dev/v1/<
|
|
149
|
-
"https://rpc.direct.dev/v1/<
|
|
148
|
+
"https://rpc.direct.dev/v1/<project>.<token>/ethereum",
|
|
149
|
+
"https://rpc.direct.dev/v1/<project>.<token>/sonic",
|
|
150
150
|
],
|
|
151
151
|
});
|
|
152
152
|
```
|
|
@@ -157,14 +157,14 @@ install({
|
|
|
157
157
|
| --- | --- | --- | --- |
|
|
158
158
|
| `logging.client` | `"silent" \| "error" \| "warn" \| "info" \| "debug"` | `"warn"` | Operational / lifecycle log verbosity. |
|
|
159
159
|
| `logging.requests` | `"off" \| "summary" \| "debug"` | `"off"` | Per-request tracing. |
|
|
160
|
-
| `logging.onEvent` | `(event) => void` | — | Structured event sink. Replaces console output when set. |
|
|
160
|
+
| `logging.onEvent` | `(event: LogEvent) => void` | — | Structured event sink. Replaces console output when set. |
|
|
161
161
|
| `fetch` | `typeof fetch` | `globalThis.fetch` | Underlying fetch to wrap. |
|
|
162
162
|
| `createWebSocket` | `(url) => WebSocket` | `globalThis.WebSocket` | WebSocket factory for Direct Wire sync. |
|
|
163
163
|
| `preload` | `string[]` | auto from `<link rel="preload">` | Endpoint URLs to warm at startup. In the browser, the SDK already picks up `<link rel="preload">` tags automatically — use this option for SSR / non-browser runtimes, or to add endpoints not declared in the HTML. |
|
|
164
164
|
|
|
165
165
|
### `fetch`
|
|
166
166
|
|
|
167
|
-
Wrap a specific implementation instead of `globalThis.fetch`. Useful in tests,
|
|
167
|
+
Wrap a specific implementation instead of `globalThis.fetch`. Useful in tests, custom runtimes, or when you need a `createFetch()` instance that bypasses an existing `install()`:
|
|
168
168
|
|
|
169
169
|
```ts
|
|
170
170
|
const directFetch = createFetch({
|
|
@@ -199,7 +199,7 @@ The `logging` option covers three independent concerns:
|
|
|
199
199
|
| `silent` | Nothing. |
|
|
200
200
|
| `error` | Errors only. `[direct:ERROR] Batch contains duplicate request IDs { ids: [1, 1] }` |
|
|
201
201
|
| `warn` | Errors + warnings. `[direct:WARN] Request failed { input: ..., err: ... }` |
|
|
202
|
-
| `info` |
|
|
202
|
+
| `info` | Sparse operational summaries, including live sync connection state. |
|
|
203
203
|
| `debug` | Full lifecycle: preload, sync, client phases. |
|
|
204
204
|
|
|
205
205
|
Example debug output:
|
|
@@ -215,6 +215,27 @@ Example debug output:
|
|
|
215
215
|
client_instance_id: "client_ethereum_f47ac10b_1",
|
|
216
216
|
network_id: "ethereum"
|
|
217
217
|
}
|
|
218
|
+
[direct:INFO] sync.connection {
|
|
219
|
+
client_instance_id: "client_ethereum_f47ac10b_1",
|
|
220
|
+
network_id: "ethereum",
|
|
221
|
+
connected: true,
|
|
222
|
+
transport: "wire_socket",
|
|
223
|
+
reason: "started"
|
|
224
|
+
}
|
|
225
|
+
[direct:INFO] sync.ready {
|
|
226
|
+
client_instance_id: "client_ethereum_f47ac10b_1",
|
|
227
|
+
network_id: "ethereum",
|
|
228
|
+
ready: true,
|
|
229
|
+
transport: "wire_socket",
|
|
230
|
+
reason: "block_state_available",
|
|
231
|
+
current_block_height: "0x134a1c0"
|
|
232
|
+
}
|
|
233
|
+
[direct:INFO] block.advanced {
|
|
234
|
+
client_instance_id: "client_ethereum_f47ac10b_1",
|
|
235
|
+
network_id: "ethereum",
|
|
236
|
+
source: "wire_socket",
|
|
237
|
+
current_block_height: "0x134a1c1"
|
|
238
|
+
}
|
|
218
239
|
```
|
|
219
240
|
|
|
220
241
|
### `logging.requests`
|
|
@@ -257,13 +278,17 @@ Debug example (a single request):
|
|
|
257
278
|
Get events as structured objects — useful for dashboards, telemetry, or piping into your own observability stack:
|
|
258
279
|
|
|
259
280
|
```ts
|
|
281
|
+
import { install, type LogEvent } from "@direct.dev/sdk";
|
|
282
|
+
|
|
283
|
+
const onDirectEvent = (event: LogEvent) => {
|
|
284
|
+
dashboard.push(event);
|
|
285
|
+
};
|
|
286
|
+
|
|
260
287
|
install({
|
|
261
288
|
logging: {
|
|
262
289
|
client: "debug",
|
|
263
290
|
requests: "debug",
|
|
264
|
-
onEvent
|
|
265
|
-
dashboard.push(event);
|
|
266
|
-
},
|
|
291
|
+
onEvent: onDirectEvent,
|
|
267
292
|
},
|
|
268
293
|
});
|
|
269
294
|
```
|
|
@@ -271,7 +296,7 @@ install({
|
|
|
271
296
|
Event shape:
|
|
272
297
|
|
|
273
298
|
```ts
|
|
274
|
-
type
|
|
299
|
+
type LogEvent = {
|
|
275
300
|
level: "debug" | "info" | "warn" | "error";
|
|
276
301
|
name: string;
|
|
277
302
|
value: Record<string, unknown>;
|
|
@@ -285,6 +310,9 @@ type DirectLogEvent = {
|
|
|
285
310
|
- `preload.phase`
|
|
286
311
|
- `preload.clock_sync`
|
|
287
312
|
- `sync.rebuild`
|
|
313
|
+
- `sync.connection`
|
|
314
|
+
- `sync.ready`
|
|
315
|
+
- `block.advanced`
|
|
288
316
|
- `client.phase`
|
|
289
317
|
|
|
290
318
|
**Debug-only diagnostics** — only emitted when the relevant log level is active:
|
|
@@ -293,14 +321,14 @@ type DirectLogEvent = {
|
|
|
293
321
|
- `request_handled`
|
|
294
322
|
- `block.state_probe`
|
|
295
323
|
|
|
296
|
-
|
|
324
|
+
The SDK exports `LogEvent`, `LoggingOptions`, and `CreateFetchOptions` for typed integrations.
|
|
297
325
|
|
|
298
326
|
## Inspecting the live client
|
|
299
327
|
|
|
300
328
|
The SDK intercepts a special JSON-RPC method, `direct_client_status`, and answers it locally without touching the network. Useful for debugging your integration:
|
|
301
329
|
|
|
302
330
|
```ts
|
|
303
|
-
const res = await fetch("https://rpc.direct.dev/v1/<
|
|
331
|
+
const res = await fetch("https://rpc.direct.dev/v1/<project>.<token>/ethereum", {
|
|
304
332
|
method: "POST",
|
|
305
333
|
headers: { "Content-Type": "application/json" },
|
|
306
334
|
body: JSON.stringify({
|
|
@@ -326,11 +354,9 @@ const { result } = await res.json();
|
|
|
326
354
|
|
|
327
355
|
The SDK only takes over POST requests whose body is JSON-RPC and whose URL matches a Direct.dev RPC endpoint:
|
|
328
356
|
|
|
329
|
-
- `https://rpc.direct.dev/v1/<
|
|
330
|
-
- `https://staging.rpc.direct.dev/v1/<
|
|
331
|
-
- `https://prod.rpc.direct.dev/v1/<
|
|
332
|
-
|
|
333
|
-
Everything else — REST APIs, image loads, third-party APIs — passes straight through to native `fetch`.
|
|
357
|
+
- `https://rpc.direct.dev/v1/<project>.<token>/<network>`
|
|
358
|
+
- `https://staging.rpc.direct.dev/v1/<project>.<token>/<network>`
|
|
359
|
+
- `https://prod.rpc.direct.dev/v1/<project>.<token>/<network>`
|
|
334
360
|
|
|
335
361
|
## License
|
|
336
362
|
|