viem 2.4.1 → 2.5.0
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/CHANGELOG.md +6 -0
- package/_cjs/clients/transports/http.js +8 -5
- package/_cjs/clients/transports/http.js.map +1 -1
- package/_cjs/clients/transports/ipc.js +77 -0
- package/_cjs/clients/transports/ipc.js.map +1 -0
- package/_cjs/clients/transports/webSocket.js +11 -7
- package/_cjs/clients/transports/webSocket.js.map +1 -1
- package/_cjs/errors/version.js +1 -1
- package/_cjs/node/index.js +8 -0
- package/_cjs/node/index.js.map +1 -0
- package/_cjs/utils/index.js +13 -6
- package/_cjs/utils/index.js.map +1 -1
- package/_cjs/utils/rpc/compat.js +35 -0
- package/_cjs/utils/rpc/compat.js.map +1 -0
- package/_cjs/utils/rpc/http.js +74 -0
- package/_cjs/utils/rpc/http.js.map +1 -0
- package/_cjs/utils/rpc/id.js +17 -0
- package/_cjs/utils/rpc/id.js.map +1 -0
- package/_cjs/utils/rpc/ipc.js +75 -0
- package/_cjs/utils/rpc/ipc.js.map +1 -0
- package/_cjs/utils/rpc/socket.js +85 -0
- package/_cjs/utils/rpc/socket.js.map +1 -0
- package/_cjs/utils/rpc/webSocket.js +50 -0
- package/_cjs/utils/rpc/webSocket.js.map +1 -0
- package/_esm/clients/transports/http.js +8 -5
- package/_esm/clients/transports/http.js.map +1 -1
- package/_esm/clients/transports/ipc.js +77 -0
- package/_esm/clients/transports/ipc.js.map +1 -0
- package/_esm/clients/transports/webSocket.js +10 -6
- package/_esm/clients/transports/webSocket.js.map +1 -1
- package/_esm/errors/version.js +1 -1
- package/_esm/node/index.js +3 -0
- package/_esm/node/index.js.map +1 -0
- package/_esm/utils/index.js +4 -1
- package/_esm/utils/index.js.map +1 -1
- package/_esm/utils/rpc/compat.js +86 -0
- package/_esm/utils/rpc/compat.js.map +1 -0
- package/_esm/utils/rpc/http.js +70 -0
- package/_esm/utils/rpc/http.js.map +1 -0
- package/_esm/utils/rpc/id.js +13 -0
- package/_esm/utils/rpc/id.js.map +1 -0
- package/_esm/utils/rpc/ipc.js +71 -0
- package/_esm/utils/rpc/ipc.js.map +1 -0
- package/_esm/utils/rpc/socket.js +90 -0
- package/_esm/utils/rpc/socket.js.map +1 -0
- package/_esm/utils/rpc/webSocket.js +48 -0
- package/_esm/utils/rpc/webSocket.js.map +1 -0
- package/_types/clients/transports/http.d.ts +2 -2
- package/_types/clients/transports/http.d.ts.map +1 -1
- package/_types/clients/transports/ipc.d.ts +46 -0
- package/_types/clients/transports/ipc.d.ts.map +1 -0
- package/_types/clients/transports/webSocket.d.ts +6 -1
- package/_types/clients/transports/webSocket.d.ts.map +1 -1
- package/_types/errors/version.d.ts +1 -1
- package/_types/node/index.d.ts +3 -0
- package/_types/node/index.d.ts.map +1 -0
- package/_types/types/rpc.d.ts +35 -0
- package/_types/types/rpc.d.ts.map +1 -1
- package/_types/utils/buildRequest.d.ts +2 -2
- package/_types/utils/buildRequest.d.ts.map +1 -1
- package/_types/utils/index.d.ts +4 -1
- package/_types/utils/index.d.ts.map +1 -1
- package/_types/utils/rpc/compat.d.ts +78 -0
- package/_types/utils/rpc/compat.d.ts.map +1 -0
- package/_types/utils/rpc/http.d.ts +20 -0
- package/_types/utils/rpc/http.d.ts.map +1 -0
- package/_types/utils/rpc/id.d.ts +11 -0
- package/_types/utils/rpc/id.d.ts.map +1 -0
- package/_types/utils/rpc/ipc.d.ts +8 -0
- package/_types/utils/rpc/ipc.d.ts.map +1 -0
- package/_types/utils/rpc/socket.d.ts +45 -0
- package/_types/utils/rpc/socket.d.ts.map +1 -0
- package/_types/utils/rpc/webSocket.d.ts +3 -0
- package/_types/utils/rpc/webSocket.d.ts.map +1 -0
- package/clients/transports/http.ts +15 -6
- package/clients/transports/ipc.ts +144 -0
- package/clients/transports/webSocket.ts +16 -6
- package/errors/version.ts +1 -1
- package/node/index.ts +11 -0
- package/node/package.json +6 -0
- package/package.json +9 -1
- package/types/rpc.ts +44 -0
- package/utils/buildRequest.ts +2 -2
- package/utils/index.ts +19 -8
- package/utils/rpc/compat.ts +117 -0
- package/utils/rpc/http.ts +132 -0
- package/utils/rpc/id.ts +13 -0
- package/utils/rpc/ipc.ts +89 -0
- package/utils/rpc/socket.ts +162 -0
- package/utils/rpc/webSocket.ts +63 -0
- package/_cjs/utils/rpc.js +0 -154
- package/_cjs/utils/rpc.js.map +0 -1
- package/_esm/utils/rpc.js +0 -160
- package/_esm/utils/rpc.js.map +0 -1
- package/_types/utils/rpc.d.ts +0 -80
- package/_types/utils/rpc.d.ts.map +0 -1
- package/utils/rpc.ts +0 -318
@@ -4,8 +4,12 @@ import {
|
|
4
4
|
type UrlRequiredErrorType,
|
5
5
|
} from '../../errors/transport.js'
|
6
6
|
import type { ErrorType } from '../../errors/utils.js'
|
7
|
+
import type { RpcRequest } from '../../types/rpc.js'
|
7
8
|
import { createBatchScheduler } from '../../utils/promise/createBatchScheduler.js'
|
8
|
-
import {
|
9
|
+
import {
|
10
|
+
type HttpRpcClientOptions,
|
11
|
+
getHttpRpcClient,
|
12
|
+
} from '../../utils/rpc/http.js'
|
9
13
|
|
10
14
|
import {
|
11
15
|
type CreateTransportErrorType,
|
@@ -31,7 +35,7 @@ export type HttpTransportConfig = {
|
|
31
35
|
* Request configuration to pass to `fetch`.
|
32
36
|
* @link https://developer.mozilla.org/en-US/docs/Web/API/fetch
|
33
37
|
*/
|
34
|
-
fetchOptions?:
|
38
|
+
fetchOptions?: HttpRpcClientOptions['fetchOptions']
|
35
39
|
/** The key of the HTTP transport. */
|
36
40
|
key?: TransportConfig['key']
|
37
41
|
/** The name of the HTTP transport. */
|
@@ -79,6 +83,9 @@ export function http(
|
|
79
83
|
const timeout = timeout_ ?? config.timeout ?? 10_000
|
80
84
|
const url_ = url || chain?.rpcUrls.default.http[0]
|
81
85
|
if (!url_) throw new UrlRequiredError()
|
86
|
+
|
87
|
+
const rpcClient = getHttpRpcClient(url_, { fetchOptions, timeout })
|
88
|
+
|
82
89
|
return createTransport(
|
83
90
|
{
|
84
91
|
key,
|
@@ -93,10 +100,8 @@ export function http(
|
|
93
100
|
return requests.length > batchSize
|
94
101
|
},
|
95
102
|
fn: (body: RpcRequest[]) =>
|
96
|
-
|
103
|
+
rpcClient.request({
|
97
104
|
body,
|
98
|
-
fetchOptions,
|
99
|
-
timeout,
|
100
105
|
}),
|
101
106
|
sort: (a, b) => a.id - b.id,
|
102
107
|
})
|
@@ -104,7 +109,11 @@ export function http(
|
|
104
109
|
const fn = async (body: RpcRequest) =>
|
105
110
|
batch
|
106
111
|
? schedule(body)
|
107
|
-
: [
|
112
|
+
: [
|
113
|
+
await rpcClient.request({
|
114
|
+
body,
|
115
|
+
}),
|
116
|
+
]
|
108
117
|
|
109
118
|
const [{ error, result }] = await fn(body)
|
110
119
|
if (error)
|
@@ -0,0 +1,144 @@
|
|
1
|
+
import { RpcRequestError } from '../../errors/request.js'
|
2
|
+
import { type UrlRequiredErrorType } from '../../errors/transport.js'
|
3
|
+
import type { ErrorType } from '../../errors/utils.js'
|
4
|
+
import type { Hash } from '../../types/misc.js'
|
5
|
+
import type { RpcResponse } from '../../types/rpc.js'
|
6
|
+
import { type IpcRpcClient, getIpcRpcClient } from '../../utils/rpc/ipc.js'
|
7
|
+
import {
|
8
|
+
type CreateTransportErrorType,
|
9
|
+
type Transport,
|
10
|
+
type TransportConfig,
|
11
|
+
createTransport,
|
12
|
+
} from './createTransport.js'
|
13
|
+
|
14
|
+
type IpcTransportSubscribeParameters = {
|
15
|
+
onData: (data: RpcResponse) => void
|
16
|
+
onError?: (error: any) => void
|
17
|
+
}
|
18
|
+
|
19
|
+
type IpcTransportSubscribeReturnType = {
|
20
|
+
subscriptionId: Hash
|
21
|
+
unsubscribe: () => Promise<RpcResponse<boolean>>
|
22
|
+
}
|
23
|
+
|
24
|
+
type IpcTransportSubscribe = {
|
25
|
+
subscribe(
|
26
|
+
args: IpcTransportSubscribeParameters & {
|
27
|
+
/**
|
28
|
+
* @description Add information about compiled contracts
|
29
|
+
* @link https://hardhat.org/hardhat-network/docs/reference#hardhat_addcompilationresult
|
30
|
+
*/
|
31
|
+
params: ['newHeads']
|
32
|
+
},
|
33
|
+
): Promise<IpcTransportSubscribeReturnType>
|
34
|
+
}
|
35
|
+
|
36
|
+
export type IpcTransportConfig = {
|
37
|
+
/** The key of the Ipc transport. */
|
38
|
+
key?: TransportConfig['key']
|
39
|
+
/** The name of the Ipc transport. */
|
40
|
+
name?: TransportConfig['name']
|
41
|
+
/** The max number of times to retry. */
|
42
|
+
retryCount?: TransportConfig['retryCount']
|
43
|
+
/** The base delay (in ms) between retries. */
|
44
|
+
retryDelay?: TransportConfig['retryDelay']
|
45
|
+
/** The timeout (in ms) for async Ipc requests. Default: 10_000 */
|
46
|
+
timeout?: TransportConfig['timeout']
|
47
|
+
}
|
48
|
+
|
49
|
+
export type IpcTransport = Transport<
|
50
|
+
'ipc',
|
51
|
+
{
|
52
|
+
getRpcClient(): Promise<IpcRpcClient>
|
53
|
+
subscribe: IpcTransportSubscribe['subscribe']
|
54
|
+
}
|
55
|
+
>
|
56
|
+
|
57
|
+
export type IpcTransportErrorType =
|
58
|
+
| CreateTransportErrorType
|
59
|
+
| UrlRequiredErrorType
|
60
|
+
| ErrorType
|
61
|
+
|
62
|
+
/**
|
63
|
+
* @description Creates an IPC transport that connects to a JSON-RPC API.
|
64
|
+
*/
|
65
|
+
export function ipc(
|
66
|
+
path: string,
|
67
|
+
config: IpcTransportConfig = {},
|
68
|
+
): IpcTransport {
|
69
|
+
const { key = 'ipc', name = 'IPC JSON-RPC', retryDelay } = config
|
70
|
+
return ({ retryCount: retryCount_, timeout: timeout_ }) => {
|
71
|
+
const retryCount = config.retryCount ?? retryCount_
|
72
|
+
const timeout = timeout_ ?? config.timeout ?? 10_000
|
73
|
+
return createTransport(
|
74
|
+
{
|
75
|
+
key,
|
76
|
+
name,
|
77
|
+
async request({ method, params }) {
|
78
|
+
const body = { method, params }
|
79
|
+
const rpcClient = await getIpcRpcClient(path)
|
80
|
+
const { error, result } = await rpcClient.requestAsync({
|
81
|
+
body,
|
82
|
+
timeout,
|
83
|
+
})
|
84
|
+
if (error)
|
85
|
+
throw new RpcRequestError({
|
86
|
+
body,
|
87
|
+
error,
|
88
|
+
url: path,
|
89
|
+
})
|
90
|
+
return result
|
91
|
+
},
|
92
|
+
retryCount,
|
93
|
+
retryDelay,
|
94
|
+
timeout,
|
95
|
+
type: 'ipc',
|
96
|
+
},
|
97
|
+
{
|
98
|
+
getRpcClient() {
|
99
|
+
return getIpcRpcClient(path)
|
100
|
+
},
|
101
|
+
async subscribe({ params, onData, onError }: any) {
|
102
|
+
const rpcClient = await getIpcRpcClient(path)
|
103
|
+
const { result: subscriptionId } = await new Promise<any>(
|
104
|
+
(resolve, reject) =>
|
105
|
+
rpcClient.request({
|
106
|
+
body: {
|
107
|
+
method: 'eth_subscribe',
|
108
|
+
params,
|
109
|
+
},
|
110
|
+
onResponse(response) {
|
111
|
+
if (response.error) {
|
112
|
+
reject(response.error)
|
113
|
+
onError?.(response.error)
|
114
|
+
return
|
115
|
+
}
|
116
|
+
|
117
|
+
if (typeof response.id === 'number') {
|
118
|
+
resolve(response)
|
119
|
+
return
|
120
|
+
}
|
121
|
+
if (response.method !== 'eth_subscription') return
|
122
|
+
onData(response.params)
|
123
|
+
},
|
124
|
+
}),
|
125
|
+
)
|
126
|
+
return {
|
127
|
+
subscriptionId,
|
128
|
+
async unsubscribe() {
|
129
|
+
return new Promise<any>((resolve) =>
|
130
|
+
rpcClient.request({
|
131
|
+
body: {
|
132
|
+
method: 'eth_unsubscribe',
|
133
|
+
params: [subscriptionId],
|
134
|
+
},
|
135
|
+
onResponse: resolve,
|
136
|
+
}),
|
137
|
+
)
|
138
|
+
},
|
139
|
+
}
|
140
|
+
},
|
141
|
+
},
|
142
|
+
)
|
143
|
+
}
|
144
|
+
}
|
@@ -5,7 +5,10 @@ import {
|
|
5
5
|
} from '../../errors/transport.js'
|
6
6
|
import type { ErrorType } from '../../errors/utils.js'
|
7
7
|
import type { Hash } from '../../types/misc.js'
|
8
|
-
import {
|
8
|
+
import type { RpcResponse } from '../../types/rpc.js'
|
9
|
+
import { getSocket } from '../../utils/rpc/compat.js'
|
10
|
+
import type { SocketRpcClient } from '../../utils/rpc/socket.js'
|
11
|
+
import { getWebSocketRpcClient } from '../../utils/rpc/webSocket.js'
|
9
12
|
import {
|
10
13
|
type CreateTransportErrorType,
|
11
14
|
type Transport,
|
@@ -51,7 +54,11 @@ export type WebSocketTransportConfig = {
|
|
51
54
|
export type WebSocketTransport = Transport<
|
52
55
|
'webSocket',
|
53
56
|
{
|
57
|
+
/**
|
58
|
+
* @deprecated use `getRpcClient` instead.
|
59
|
+
*/
|
54
60
|
getSocket(): Promise<WebSocket>
|
61
|
+
getRpcClient(): Promise<SocketRpcClient<WebSocket>>
|
55
62
|
subscribe: WebSocketTransportSubscribe['subscribe']
|
56
63
|
}
|
57
64
|
>
|
@@ -81,8 +88,8 @@ export function webSocket(
|
|
81
88
|
name,
|
82
89
|
async request({ method, params }) {
|
83
90
|
const body = { method, params }
|
84
|
-
const
|
85
|
-
const { error, result } = await
|
91
|
+
const rpcClient = await getWebSocketRpcClient(url_)
|
92
|
+
const { error, result } = await rpcClient.requestAsync({
|
86
93
|
body,
|
87
94
|
timeout,
|
88
95
|
})
|
@@ -103,11 +110,14 @@ export function webSocket(
|
|
103
110
|
getSocket() {
|
104
111
|
return getSocket(url_)
|
105
112
|
},
|
113
|
+
getRpcClient() {
|
114
|
+
return getWebSocketRpcClient(url_)
|
115
|
+
},
|
106
116
|
async subscribe({ params, onData, onError }: any) {
|
107
|
-
const
|
117
|
+
const rpcClient = await getWebSocketRpcClient(url_)
|
108
118
|
const { result: subscriptionId } = await new Promise<any>(
|
109
119
|
(resolve, reject) =>
|
110
|
-
|
120
|
+
rpcClient.request({
|
111
121
|
body: {
|
112
122
|
method: 'eth_subscribe',
|
113
123
|
params,
|
@@ -132,7 +142,7 @@ export function webSocket(
|
|
132
142
|
subscriptionId,
|
133
143
|
async unsubscribe() {
|
134
144
|
return new Promise<any>((resolve) =>
|
135
|
-
|
145
|
+
rpcClient.request({
|
136
146
|
body: {
|
137
147
|
method: 'eth_unsubscribe',
|
138
148
|
params: [subscriptionId],
|
package/errors/version.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const version = '2.
|
1
|
+
export const version = '2.5.0'
|
package/node/index.ts
ADDED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "viem",
|
3
3
|
"description": "TypeScript Interface for Ethereum",
|
4
|
-
"version": "2.
|
4
|
+
"version": "2.5.0",
|
5
5
|
"main": "./_cjs/index.js",
|
6
6
|
"module": "./_esm/index.js",
|
7
7
|
"types": "./_types/index.d.ts",
|
@@ -52,6 +52,11 @@
|
|
52
52
|
"import": "./_esm/ens/index.js",
|
53
53
|
"default": "./_cjs/ens/index.js"
|
54
54
|
},
|
55
|
+
"./node": {
|
56
|
+
"types": "./_types/node/index.d.ts",
|
57
|
+
"import": "./_esm/node/index.js",
|
58
|
+
"default": "./_cjs/node/index.js"
|
59
|
+
},
|
55
60
|
"./op-stack": {
|
56
61
|
"types": "./_types/chains/opStack/index.d.ts",
|
57
62
|
"import": "./_esm/chains/opStack/index.js",
|
@@ -94,6 +99,9 @@
|
|
94
99
|
"ens": [
|
95
100
|
"./_types/ens/index.d.ts"
|
96
101
|
],
|
102
|
+
"node": [
|
103
|
+
"./_types/node/index.d.ts"
|
104
|
+
],
|
97
105
|
"op-stack": [
|
98
106
|
"./_types/chains/opStack/index.d.ts"
|
99
107
|
],
|
package/types/rpc.ts
CHANGED
@@ -57,3 +57,47 @@ export type RpcTransaction<TPending extends boolean = boolean> = UnionOmit<
|
|
57
57
|
>,
|
58
58
|
'typeHex'
|
59
59
|
>
|
60
|
+
|
61
|
+
type SuccessResult<T> = {
|
62
|
+
method?: never
|
63
|
+
result: T
|
64
|
+
error?: never
|
65
|
+
}
|
66
|
+
type ErrorResult<T> = {
|
67
|
+
method?: never
|
68
|
+
result?: never
|
69
|
+
error: T
|
70
|
+
}
|
71
|
+
type Subscription<TResult, TError> = {
|
72
|
+
method: 'eth_subscription'
|
73
|
+
error?: never
|
74
|
+
result?: never
|
75
|
+
params: {
|
76
|
+
subscription: string
|
77
|
+
} & (
|
78
|
+
| {
|
79
|
+
result: TResult
|
80
|
+
error?: never
|
81
|
+
}
|
82
|
+
| {
|
83
|
+
result?: never
|
84
|
+
error: TError
|
85
|
+
}
|
86
|
+
)
|
87
|
+
}
|
88
|
+
|
89
|
+
export type RpcRequest = {
|
90
|
+
jsonrpc?: '2.0'
|
91
|
+
method: string
|
92
|
+
params?: any
|
93
|
+
id?: number
|
94
|
+
}
|
95
|
+
|
96
|
+
export type RpcResponse<TResult = any, TError = any> = {
|
97
|
+
jsonrpc: `${number}`
|
98
|
+
id: number
|
99
|
+
} & (
|
100
|
+
| SuccessResult<TResult>
|
101
|
+
| ErrorResult<TError>
|
102
|
+
| Subscription<TResult, TError>
|
103
|
+
)
|
package/utils/buildRequest.ts
CHANGED
@@ -57,7 +57,7 @@ import type {
|
|
57
57
|
} from '../types/eip1193.js'
|
58
58
|
import type { CreateBatchSchedulerErrorType } from './promise/createBatchScheduler.js'
|
59
59
|
import { type WithRetryErrorType, withRetry } from './promise/withRetry.js'
|
60
|
-
import type {
|
60
|
+
import type { GetSocketRpcClientErrorType } from './rpc/socket.js'
|
61
61
|
|
62
62
|
export type RequestErrorType =
|
63
63
|
| ChainDisconnectedErrorType
|
@@ -67,7 +67,7 @@ export type RequestErrorType =
|
|
67
67
|
| InvalidInputRpcErrorType
|
68
68
|
| InvalidParamsRpcErrorType
|
69
69
|
| InvalidRequestRpcErrorType
|
70
|
-
|
|
70
|
+
| GetSocketRpcClientErrorType
|
71
71
|
| JsonRpcVersionUnsupportedErrorType
|
72
72
|
| LimitExceededRpcErrorType
|
73
73
|
| MethodNotFoundRpcErrorType
|
package/utils/index.ts
CHANGED
@@ -32,13 +32,6 @@ export {
|
|
32
32
|
export { arrayRegex, bytesRegex, integerRegex } from './regex.js'
|
33
33
|
|
34
34
|
export {
|
35
|
-
type GetSocketErrorType,
|
36
|
-
type HttpErrorType,
|
37
|
-
type HttpOptions,
|
38
|
-
type HttpReturnType,
|
39
|
-
type RpcRequest,
|
40
|
-
type RpcResponse,
|
41
|
-
type Socket,
|
42
35
|
type WebSocketAsyncErrorType,
|
43
36
|
type WebSocketAsyncOptions,
|
44
37
|
type WebSocketAsyncReturnType,
|
@@ -47,7 +40,25 @@ export {
|
|
47
40
|
type WebSocketReturnType,
|
48
41
|
getSocket,
|
49
42
|
rpc,
|
50
|
-
} from './rpc.js'
|
43
|
+
} from './rpc/compat.js'
|
44
|
+
export {
|
45
|
+
type HttpRpcClient,
|
46
|
+
type HttpRpcClientOptions,
|
47
|
+
type HttpRequestErrorType,
|
48
|
+
type HttpRequestParameters,
|
49
|
+
type HttpRequestReturnType,
|
50
|
+
getHttpRpcClient,
|
51
|
+
} from './rpc/http.js'
|
52
|
+
export {
|
53
|
+
type GetSocketRpcClientErrorType,
|
54
|
+
type GetSocketRpcClientParameters,
|
55
|
+
type GetSocketParameters,
|
56
|
+
type Socket,
|
57
|
+
type SocketRpcClient,
|
58
|
+
getSocketRpcClient,
|
59
|
+
socketClientCache,
|
60
|
+
} from './rpc/socket.js'
|
61
|
+
export { getWebSocketRpcClient } from './rpc/webSocket.js'
|
51
62
|
export { type StringifyErrorType, stringify } from './stringify.js'
|
52
63
|
export {
|
53
64
|
type DomainSeparatorErrorType,
|
@@ -0,0 +1,117 @@
|
|
1
|
+
// TODO(v3): This file is here for backwards compatibility, and to prevent breaking changes.
|
2
|
+
// These APIs will be removed in v3.
|
3
|
+
|
4
|
+
/* c8 ignore start */
|
5
|
+
import {
|
6
|
+
type TimeoutErrorType,
|
7
|
+
WebSocketRequestError,
|
8
|
+
} from '../../errors/request.js'
|
9
|
+
import type { ErrorType } from '../../errors/utils.js'
|
10
|
+
import type { RpcResponse } from '../../types/rpc.js'
|
11
|
+
import { type WithTimeoutErrorType } from '../promise/withTimeout.js'
|
12
|
+
import { type HttpRequestParameters, getHttpRpcClient } from './http.js'
|
13
|
+
import { type SocketRpcClient } from './socket.js'
|
14
|
+
import { getWebSocketRpcClient } from './webSocket.js'
|
15
|
+
|
16
|
+
export type WebSocketOptions = Parameters<
|
17
|
+
SocketRpcClient<WebSocket>['request']
|
18
|
+
>[0]
|
19
|
+
export type WebSocketReturnType = SocketRpcClient<WebSocket>
|
20
|
+
export type WebSocketErrorType = WebSocketRequestError | ErrorType
|
21
|
+
|
22
|
+
function webSocket(
|
23
|
+
socketClient: SocketRpcClient<WebSocket>,
|
24
|
+
{ body, onError, onResponse }: WebSocketOptions,
|
25
|
+
): WebSocketReturnType {
|
26
|
+
socketClient.request({
|
27
|
+
body,
|
28
|
+
onError,
|
29
|
+
onResponse,
|
30
|
+
})
|
31
|
+
return socketClient
|
32
|
+
}
|
33
|
+
|
34
|
+
export type WebSocketAsyncOptions = Parameters<
|
35
|
+
SocketRpcClient<WebSocket>['requestAsync']
|
36
|
+
>[0]
|
37
|
+
export type WebSocketAsyncReturnType = RpcResponse
|
38
|
+
export type WebSocketAsyncErrorType =
|
39
|
+
| WebSocketErrorType
|
40
|
+
| TimeoutErrorType
|
41
|
+
| WithTimeoutErrorType
|
42
|
+
| ErrorType
|
43
|
+
|
44
|
+
async function webSocketAsync(
|
45
|
+
socketClient: SocketRpcClient<WebSocket>,
|
46
|
+
{ body, timeout = 10_000 }: WebSocketAsyncOptions,
|
47
|
+
): Promise<WebSocketAsyncReturnType> {
|
48
|
+
return socketClient.requestAsync({
|
49
|
+
body,
|
50
|
+
timeout,
|
51
|
+
})
|
52
|
+
}
|
53
|
+
|
54
|
+
/**
|
55
|
+
* @deprecated use `getSocketClient` instead.
|
56
|
+
*
|
57
|
+
* ```diff
|
58
|
+
* -import { getSocket } from 'viem/utils'
|
59
|
+
* +import { getSocketClient } from 'viem/utils'
|
60
|
+
*
|
61
|
+
* -const socket = await getSocket(url)
|
62
|
+
* +const socketClient = await getSocketClient(url)
|
63
|
+
* +const socket = socketClient.socket
|
64
|
+
* ```
|
65
|
+
*/
|
66
|
+
export async function getSocket(url: string) {
|
67
|
+
const client = await getWebSocketRpcClient(url)
|
68
|
+
return Object.assign(client.socket, {
|
69
|
+
requests: client.requests,
|
70
|
+
subscriptions: client.subscriptions,
|
71
|
+
})
|
72
|
+
}
|
73
|
+
|
74
|
+
export const rpc = {
|
75
|
+
/**
|
76
|
+
* @deprecated use `getHttpRpcClient` instead.
|
77
|
+
*
|
78
|
+
* ```diff
|
79
|
+
* -import { rpc } from 'viem/utils'
|
80
|
+
* +import { getHttpRpcClient } from 'viem/utils'
|
81
|
+
*
|
82
|
+
* -rpc.http(url, params)
|
83
|
+
* +const httpClient = getHttpRpcClient(url)
|
84
|
+
* +httpClient.request(params)
|
85
|
+
* ```
|
86
|
+
*/
|
87
|
+
http(url: string, params: HttpRequestParameters) {
|
88
|
+
return getHttpRpcClient(url).request(params)
|
89
|
+
},
|
90
|
+
/**
|
91
|
+
* @deprecated use `getWebSocketRpcClient` instead.
|
92
|
+
*
|
93
|
+
* ```diff
|
94
|
+
* -import { rpc } from 'viem/utils'
|
95
|
+
* +import { getWebSocketRpcClient } from 'viem/utils'
|
96
|
+
*
|
97
|
+
* -rpc.webSocket(url, params)
|
98
|
+
* +const webSocketClient = getWebSocketRpcClient(url)
|
99
|
+
* +webSocketClient.request(params)
|
100
|
+
* ```
|
101
|
+
*/
|
102
|
+
webSocket,
|
103
|
+
/**
|
104
|
+
* @deprecated use `getWebSocketRpcClient` instead.
|
105
|
+
*
|
106
|
+
* ```diff
|
107
|
+
* -import { rpc } from 'viem/utils'
|
108
|
+
* +import { getWebSocketRpcClient } from 'viem/utils'
|
109
|
+
*
|
110
|
+
* -const response = await rpc.webSocketAsync(url, params)
|
111
|
+
* +const webSocketClient = getWebSocketRpcClient(url)
|
112
|
+
* +const response = await webSocketClient.requestAsync(params)
|
113
|
+
* ```
|
114
|
+
*/
|
115
|
+
webSocketAsync,
|
116
|
+
}
|
117
|
+
/* c8 ignore end */
|
@@ -0,0 +1,132 @@
|
|
1
|
+
import {
|
2
|
+
HttpRequestError,
|
3
|
+
type HttpRequestErrorType as HttpRequestErrorType_,
|
4
|
+
TimeoutError,
|
5
|
+
type TimeoutErrorType,
|
6
|
+
} from '../../errors/request.js'
|
7
|
+
import type { ErrorType } from '../../errors/utils.js'
|
8
|
+
import type { RpcRequest, RpcResponse } from '../../types/rpc.js'
|
9
|
+
import {
|
10
|
+
type WithTimeoutErrorType,
|
11
|
+
withTimeout,
|
12
|
+
} from '../promise/withTimeout.js'
|
13
|
+
import { stringify } from '../stringify.js'
|
14
|
+
import { idCache } from './id.js'
|
15
|
+
|
16
|
+
export type HttpRpcClientOptions = {
|
17
|
+
// Request configuration to pass to `fetch`.
|
18
|
+
fetchOptions?: Omit<RequestInit, 'body'>
|
19
|
+
// The timeout (in ms) for the request.
|
20
|
+
timeout?: number
|
21
|
+
}
|
22
|
+
|
23
|
+
export type HttpRequestParameters<
|
24
|
+
TBody extends RpcRequest | RpcRequest[] = RpcRequest,
|
25
|
+
> = {
|
26
|
+
// The RPC request body.
|
27
|
+
body: TBody
|
28
|
+
// Request configuration to pass to `fetch`.
|
29
|
+
fetchOptions?: HttpRpcClientOptions['fetchOptions']
|
30
|
+
// The timeout (in ms) for the request.
|
31
|
+
timeout?: HttpRpcClientOptions['timeout']
|
32
|
+
}
|
33
|
+
|
34
|
+
export type HttpRequestReturnType<
|
35
|
+
TBody extends RpcRequest | RpcRequest[] = RpcRequest,
|
36
|
+
> = TBody extends RpcRequest[] ? RpcResponse[] : RpcResponse
|
37
|
+
|
38
|
+
export type HttpRequestErrorType =
|
39
|
+
| HttpRequestErrorType_
|
40
|
+
| TimeoutErrorType
|
41
|
+
| WithTimeoutErrorType
|
42
|
+
| ErrorType
|
43
|
+
|
44
|
+
export type HttpRpcClient = {
|
45
|
+
request<TBody extends RpcRequest | RpcRequest[]>(
|
46
|
+
params: HttpRequestParameters<TBody>,
|
47
|
+
): Promise<HttpRequestReturnType<TBody>>
|
48
|
+
}
|
49
|
+
|
50
|
+
export function getHttpRpcClient(
|
51
|
+
url: string,
|
52
|
+
options: HttpRpcClientOptions = {},
|
53
|
+
): HttpRpcClient {
|
54
|
+
return {
|
55
|
+
async request(params) {
|
56
|
+
const {
|
57
|
+
body,
|
58
|
+
fetchOptions = {},
|
59
|
+
timeout = options.timeout ?? 10_000,
|
60
|
+
} = params
|
61
|
+
const {
|
62
|
+
headers,
|
63
|
+
method,
|
64
|
+
signal: signal_,
|
65
|
+
} = { ...options.fetchOptions, ...fetchOptions }
|
66
|
+
|
67
|
+
try {
|
68
|
+
const response = await withTimeout(
|
69
|
+
async ({ signal }) => {
|
70
|
+
const response = await fetch(url, {
|
71
|
+
...fetchOptions,
|
72
|
+
body: Array.isArray(body)
|
73
|
+
? stringify(
|
74
|
+
body.map((body) => ({
|
75
|
+
jsonrpc: '2.0',
|
76
|
+
id: body.id ?? idCache.take(),
|
77
|
+
...body,
|
78
|
+
})),
|
79
|
+
)
|
80
|
+
: stringify({
|
81
|
+
jsonrpc: '2.0',
|
82
|
+
id: body.id ?? idCache.take(),
|
83
|
+
...body,
|
84
|
+
}),
|
85
|
+
headers: {
|
86
|
+
...headers,
|
87
|
+
'Content-Type': 'application/json',
|
88
|
+
},
|
89
|
+
method: method || 'POST',
|
90
|
+
signal: signal_ || (timeout > 0 ? signal : undefined),
|
91
|
+
})
|
92
|
+
return response
|
93
|
+
},
|
94
|
+
{
|
95
|
+
errorInstance: new TimeoutError({ body, url }),
|
96
|
+
timeout,
|
97
|
+
signal: true,
|
98
|
+
},
|
99
|
+
)
|
100
|
+
|
101
|
+
let data: any
|
102
|
+
if (
|
103
|
+
response.headers.get('Content-Type')?.startsWith('application/json')
|
104
|
+
) {
|
105
|
+
data = await response.json()
|
106
|
+
} else {
|
107
|
+
data = await response.text()
|
108
|
+
}
|
109
|
+
|
110
|
+
if (!response.ok) {
|
111
|
+
throw new HttpRequestError({
|
112
|
+
body,
|
113
|
+
details: stringify(data.error) || response.statusText,
|
114
|
+
headers: response.headers,
|
115
|
+
status: response.status,
|
116
|
+
url,
|
117
|
+
})
|
118
|
+
}
|
119
|
+
|
120
|
+
return data
|
121
|
+
} catch (err) {
|
122
|
+
if (err instanceof HttpRequestError) throw err
|
123
|
+
if (err instanceof TimeoutError) throw err
|
124
|
+
throw new HttpRequestError({
|
125
|
+
body,
|
126
|
+
details: (err as Error).message,
|
127
|
+
url,
|
128
|
+
})
|
129
|
+
}
|
130
|
+
},
|
131
|
+
}
|
132
|
+
}
|