@rpckit/http 0.9.99

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 ADDED
@@ -0,0 +1,82 @@
1
+ # @rpckit/http
2
+
3
+ HTTP transport for rpckit. Stateless JSON-RPC over HTTP POST with request batching.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @rpckit/core @rpckit/http
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { http } from '@rpckit/http'
15
+
16
+ const transport = http('https://example.com/rpc', {
17
+ headers: { 'Authorization': 'Bearer token' }
18
+ })
19
+
20
+ const result = await transport.request('my.method', 'param1')
21
+ await transport.close()
22
+ ```
23
+
24
+ ## Electrum Cash Variant
25
+
26
+ For Electrum Cash servers, use the `electrum-cash` subpath which pre-configures the `server.version` header:
27
+
28
+ ```typescript
29
+ import { http } from '@rpckit/http/electrum-cash'
30
+
31
+ const transport = http('https://electrum.example.com')
32
+ const tip = await transport.request('blockchain.headers.get_tip')
33
+ ```
34
+
35
+ The electrum-cash variant also accepts:
36
+
37
+ - `clientName` - Client name sent in server.version header (default: `'rpckit'`)
38
+ - `protocolVersion` - Protocol version (default: `'1.6'`)
39
+
40
+ ## Ethereum Variant
41
+
42
+ For Ethereum JSON-RPC nodes, use the `ethereum` subpath:
43
+
44
+ ```typescript
45
+ import { http } from '@rpckit/http/ethereum'
46
+
47
+ const transport = http('https://ethereum-rpc.publicnode.com')
48
+
49
+ const blockNumber = await transport.request('eth_blockNumber')
50
+ const balance = await transport.request('eth_getBalance', '0x...', 'latest')
51
+ ```
52
+
53
+ ## Options
54
+
55
+ - `timeout` - Request timeout in ms
56
+ - `headers` - Custom HTTP headers
57
+ - `retryCount` - Max retry attempts (default: 3)
58
+ - `retryDelay` - Base delay between retries in ms (default: 150, exponential backoff applied)
59
+ - `batch` - `true` (default), `false`, or `{ wait, batchSize }`
60
+ - `fetchFn` - Custom fetch implementation (e.g., `node-fetch`, `undici`)
61
+ - `fetchOptions` - Extra options passed to fetch (excluding `method`, `headers`, `body`, `signal`)
62
+ - `onRequest` - Callback before each request: `({ url, body }) => void`
63
+ - `onResponse` - Callback after each response: `({ status, body }) => void`
64
+ - `raw` - Return full RPC response objects instead of unwrapping results (default: `false`)
65
+
66
+ ## Raw Mode
67
+
68
+ When `raw: true`, responses include the full JSON-RPC envelope:
69
+
70
+ ```typescript
71
+ const transport = http('https://example.com', { raw: true })
72
+
73
+ const response = await transport.request('server.version')
74
+ // { jsonrpc: '2.0', result: ['Server', '1.4'], id: 1 }
75
+
76
+ // Errors are returned as results instead of thrown:
77
+ // { jsonrpc: '2.0', error: { code: -1, message: '...' }, id: 2 }
78
+ ```
79
+
80
+ ## Note
81
+
82
+ HTTP transport does not support subscriptions. Use WebSocket or TCP for subscription methods.
@@ -0,0 +1,10 @@
1
+ import type { AnySchema, HttpTransportConfig, Schema, Transport } from '@rpckit/core';
2
+ export interface ElectrumHttpConfig extends HttpTransportConfig {
3
+ /** Client name sent in server.version header (default: 'rpckit') */
4
+ clientName?: string;
5
+ /** Electrum protocol version (default: '1.6') */
6
+ protocolVersion?: string;
7
+ }
8
+ export declare function http<S extends Schema = AnySchema>(url: string, options?: Omit<ElectrumHttpConfig, 'url'>): Transport<S>;
9
+ export declare function http<S extends Schema = AnySchema>(config: ElectrumHttpConfig): Transport<S>;
10
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/electrum-cash/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,mBAAmB,EACnB,MAAM,EACN,SAAS,EACV,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC/C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,GACxC,SAAS,CAAC,CAAC,CAAC,CAAA;AACf,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC/C,MAAM,EAAE,kBAAkB,GACzB,SAAS,CAAC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { http as baseHttp } from '../http.js';
2
+ export function http(configOrUrl, options) {
3
+ const base = typeof configOrUrl === 'string'
4
+ ? { ...options, url: configOrUrl }
5
+ : configOrUrl;
6
+ const { clientName = 'rpckit', protocolVersion = '1.6', ...rest } = base;
7
+ return baseHttp({
8
+ ...rest,
9
+ headers: {
10
+ 'server.version': `["${clientName}", "${protocolVersion}"]`,
11
+ ...rest.headers,
12
+ },
13
+ });
14
+ }
15
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/electrum-cash/http.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAA;AAgB7C,MAAM,UAAU,IAAI,CAClB,WAAwC,EACxC,OAAyC;IAEzC,MAAM,IAAI,GACR,OAAO,WAAW,KAAK,QAAQ;QAC7B,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE;QAClC,CAAC,CAAC,WAAW,CAAA;IAEjB,MAAM,EAAE,UAAU,GAAG,QAAQ,EAAE,eAAe,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;IAExE,OAAO,QAAQ,CAAI;QACjB,GAAG,IAAI;QACP,OAAO,EAAE;YACP,gBAAgB,EAAE,KAAK,UAAU,OAAO,eAAe,IAAI;YAC3D,GAAG,IAAI,CAAC,OAAO;SAChB;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type { ElectrumHttpConfig } from './http.js';
2
+ export { http } from './http.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/electrum-cash/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { http } from './http.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/electrum-cash/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,16 @@
1
+ import type { AnySchema, HttpTransportConfig, Schema, Transport } from '@rpckit/core';
2
+ export interface EthereumHttpConfig extends HttpTransportConfig {
3
+ }
4
+ /**
5
+ * HTTP transport configured for Ethereum JSON-RPC.
6
+ *
7
+ * This is a thin wrapper over the base HTTP transport.
8
+ * Ethereum doesn't require special HTTP handling, but this variant
9
+ * is provided for consistency with the WebSocket variant.
10
+ *
11
+ * Note: HTTP transport does not support subscriptions.
12
+ * Use the WebSocket variant for `eth_subscribe`.
13
+ */
14
+ export declare function http<S extends Schema = AnySchema>(url: string, options?: Omit<EthereumHttpConfig, 'url'>): Transport<S>;
15
+ export declare function http<S extends Schema = AnySchema>(config: EthereumHttpConfig): Transport<S>;
16
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/ethereum/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,mBAAmB,EACnB,MAAM,EACN,SAAS,EACV,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;CAAG;AAElE;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC/C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,GACxC,SAAS,CAAC,CAAC,CAAC,CAAA;AACf,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC/C,MAAM,EAAE,kBAAkB,GACzB,SAAS,CAAC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { http as baseHttp } from '../http.js';
2
+ export function http(configOrUrl, options) {
3
+ const config = typeof configOrUrl === 'string'
4
+ ? { ...options, url: configOrUrl }
5
+ : configOrUrl;
6
+ return baseHttp(config);
7
+ }
8
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/ethereum/http.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAA;AAqB7C,MAAM,UAAU,IAAI,CAClB,WAAwC,EACxC,OAAyC;IAEzC,MAAM,MAAM,GACV,OAAO,WAAW,KAAK,QAAQ;QAC7B,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE;QAClC,CAAC,CAAC,WAAW,CAAA;IAEjB,OAAO,QAAQ,CAAI,MAAM,CAAC,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type { EthereumHttpConfig } from './http.js';
2
+ export { http } from './http.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ethereum/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { http } from './http.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ethereum/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { type AnySchema, type HttpTransportConfig, type Schema, type Transport } from '@rpckit/core';
2
+ export declare function http<S extends Schema = AnySchema>(url: string, options?: Omit<HttpTransportConfig, 'url'>): Transport<S>;
3
+ export declare function http<S extends Schema = AnySchema>(config: HttpTransportConfig): Transport<S>;
4
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,mBAAmB,EAGxB,KAAK,MAAM,EACX,KAAK,SAAS,EAEf,MAAM,cAAc,CAAA;AAErB,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC/C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,KAAK,CAAC,GACzC,SAAS,CAAC,CAAC,CAAC,CAAA;AACf,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAC/C,MAAM,EAAE,mBAAmB,GAC1B,SAAS,CAAC,CAAC,CAAC,CAAA"}
package/dist/http.js ADDED
@@ -0,0 +1,58 @@
1
+ import { BatchScheduler, withRetry, } from '@rpckit/core';
2
+ export function http(configOrUrl, options) {
3
+ const config = typeof configOrUrl === 'string'
4
+ ? { ...options, url: configOrUrl }
5
+ : configOrUrl;
6
+ let nextId = 1;
7
+ const batchScheduler = new BatchScheduler({
8
+ ...(typeof config.batch === 'object' ? config.batch : {}),
9
+ raw: config.raw,
10
+ }, sendBatch);
11
+ const fetchFn = config.fetchFn ?? fetch;
12
+ async function sendBatch(requests) {
13
+ const body = requests.length === 1 ? requests[0] : requests;
14
+ return withRetry(async () => {
15
+ config.onRequest?.({ url: config.url, body });
16
+ const res = await fetchFn(config.url, {
17
+ ...config.fetchOptions,
18
+ method: 'POST',
19
+ headers: { 'Content-Type': 'application/json', ...config.headers },
20
+ body: JSON.stringify(body),
21
+ signal: config.timeout
22
+ ? AbortSignal.timeout(config.timeout)
23
+ : undefined,
24
+ });
25
+ if (!res.ok) {
26
+ // Try to get error details from response body
27
+ let errorBody = '';
28
+ try {
29
+ errorBody = await res.text();
30
+ }
31
+ catch {
32
+ // Ignore if we can't read the body
33
+ }
34
+ throw new Error(`HTTP ${res.status}: ${res.statusText}${errorBody ? ` - ${errorBody}` : ''}`);
35
+ }
36
+ const json = await res.json();
37
+ const responses = Array.isArray(json) ? json : [json];
38
+ config.onResponse?.({ status: res.status, body: json });
39
+ return responses;
40
+ }, { retryCount: config.retryCount, retryDelay: config.retryDelay });
41
+ }
42
+ return {
43
+ url: config.url,
44
+ async connect() { },
45
+ async request(method, ...params) {
46
+ const id = nextId++;
47
+ const request = { jsonrpc: '2.0', method, params, id };
48
+ return batchScheduler.enqueue(request);
49
+ },
50
+ async subscribe() {
51
+ throw new Error('HTTP transport does not support subscriptions');
52
+ },
53
+ async close() {
54
+ await batchScheduler.flush();
55
+ },
56
+ };
57
+ }
58
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { http } from './http.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { http } from './http.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@rpckit/http",
3
+ "version": "0.9.99",
4
+ "description": "HTTP transport for rpckit with request batching",
5
+ "author": "mainnet_pat",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./electrum-cash": {
17
+ "types": "./dist/electrum-cash/index.d.ts",
18
+ "default": "./dist/electrum-cash/index.js"
19
+ },
20
+ "./ethereum": {
21
+ "types": "./dist/ethereum/index.d.ts",
22
+ "default": "./dist/ethereum/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "keywords": [
29
+ "json-rpc",
30
+ "rpc",
31
+ "http",
32
+ "electrum",
33
+ "electrum-cash",
34
+ "ethereum",
35
+ "typescript"
36
+ ],
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/mainnet-pat/rpckit.git",
40
+ "directory": "packages/http"
41
+ },
42
+ "homepage": "https://rpckit.dev",
43
+ "bugs": {
44
+ "url": "https://github.com/mainnet-pat/rpckit/issues"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc"
48
+ },
49
+ "dependencies": {
50
+ "@rpckit/core": "*"
51
+ },
52
+ "devDependencies": {
53
+ "typescript": "^5.7.0"
54
+ }
55
+ }