@libp2p/daemon-client 7.0.3 → 8.0.1

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/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@libp2p/daemon-client",
3
- "version": "7.0.3",
3
+ "version": "8.0.1",
4
4
  "description": "libp2p-daemon client implementation",
5
5
  "license": "Apache-2.0 OR MIT",
6
- "homepage": "https://github.com/libp2p/js-libp2p-daemon/tree/master/packages/libp2p-daemon-client#readme",
6
+ "homepage": "https://github.com/libp2p/js-libp2p-daemon/tree/main/packages/libp2p-daemon-client#readme",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/libp2p/js-libp2p-daemon.git"
@@ -11,6 +11,10 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/libp2p/js-libp2p-daemon/issues"
13
13
  },
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "provenance": true
17
+ },
14
18
  "keywords": [
15
19
  "libp2p"
16
20
  ],
@@ -37,7 +41,7 @@
37
41
  },
38
42
  "release": {
39
43
  "branches": [
40
- "master"
44
+ "main"
41
45
  ],
42
46
  "plugins": [
43
47
  [
@@ -131,21 +135,21 @@
131
135
  "release": "aegir release"
132
136
  },
133
137
  "dependencies": {
134
- "@chainsafe/libp2p-gossipsub": "^10.0.0",
135
- "@libp2p/daemon-protocol": "^5.0.0",
136
- "@libp2p/interface": "^0.1.0",
137
- "@libp2p/kad-dht": "^10.0.0",
138
- "@libp2p/logger": "^3.0.0",
139
- "@libp2p/peer-id": "^3.0.0",
140
- "@libp2p/tcp": "^8.0.0",
138
+ "@chainsafe/libp2p-gossipsub": "^11.0.0",
139
+ "@libp2p/daemon-protocol": "^6.0.0",
140
+ "@libp2p/interface": "^1.0.0",
141
+ "@libp2p/kad-dht": "^11.0.0",
142
+ "@libp2p/logger": "^4.0.0",
143
+ "@libp2p/peer-id": "^4.0.0",
144
+ "@libp2p/tcp": "^9.0.0",
141
145
  "@multiformats/multiaddr": "^12.1.3",
142
- "it-stream-types": "^2.0.1",
146
+ "it-protobuf-stream": "^1.1.1",
143
147
  "multiformats": "^12.0.1",
144
148
  "uint8arraylist": "^2.4.3"
145
149
  },
146
150
  "devDependencies": {
147
- "@libp2p/daemon-server": "^6.0.0",
148
- "@libp2p/interface-compliance-tests": "^4.0.0",
151
+ "@libp2p/daemon-server": "^7.0.0",
152
+ "@libp2p/interface-compliance-tests": "^5.0.0",
149
153
  "aegir": "^41.1.6",
150
154
  "it-all": "^3.0.1",
151
155
  "it-pipe": "^3.0.1",
package/src/dht.ts CHANGED
@@ -4,13 +4,15 @@ import {
4
4
  DHTRequest,
5
5
  DHTResponse
6
6
  } from '@libp2p/daemon-protocol'
7
- import { CodeError } from '@libp2p/interface/errors'
8
- import { isPeerId, type PeerId } from '@libp2p/interface/peer-id'
7
+ import { CodeError } from '@libp2p/interface'
8
+ import { isPeerId, type PeerId, type PeerInfo } from '@libp2p/interface'
9
+ import { logger } from '@libp2p/logger'
9
10
  import { peerIdFromBytes } from '@libp2p/peer-id'
10
11
  import { multiaddr } from '@multiformats/multiaddr'
11
12
  import { CID } from 'multiformats/cid'
12
13
  import type { DaemonClient } from './index.js'
13
- import type { PeerInfo } from '@libp2p/interface/peer-info'
14
+
15
+ const log = logger('libp2p:daemon-client:dht')
14
16
 
15
17
  export class DHT {
16
18
  private readonly client: DaemonClient
@@ -40,15 +42,11 @@ export class DHT {
40
42
  }
41
43
  })
42
44
 
43
- const message = await sh.read()
44
-
45
- if (message == null) {
46
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
47
- }
45
+ const response = await sh.read(Response)
48
46
 
49
- const response = Response.decode(message)
47
+ log('read', response)
50
48
 
51
- await sh.close()
49
+ await sh.unwrap().close()
52
50
 
53
51
  if (response.type !== Response.Type.OK) {
54
52
  throw new CodeError(response.error?.msg ?? 'DHT put failed', 'ERR_DHT_PUT_FAILED')
@@ -71,15 +69,9 @@ export class DHT {
71
69
  }
72
70
  })
73
71
 
74
- const message = await sh.read()
72
+ const response = await sh.read(Response)
75
73
 
76
- if (message == null) {
77
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
78
- }
79
-
80
- const response = Response.decode(message)
81
-
82
- await sh.close()
74
+ await sh.unwrap().close()
83
75
 
84
76
  if (response.type !== Response.Type.OK) {
85
77
  throw new CodeError(response.error?.msg ?? 'DHT get failed', 'ERR_DHT_GET_FAILED')
@@ -108,15 +100,9 @@ export class DHT {
108
100
  }
109
101
  })
110
102
 
111
- const message = await sh.read()
112
-
113
- if (message == null) {
114
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
115
- }
116
-
117
- const response = Response.decode(message)
103
+ const response = await sh.read(Response)
118
104
 
119
- await sh.close()
105
+ await sh.unwrap().close()
120
106
 
121
107
  if (response.type !== Response.Type.OK) {
122
108
  throw new CodeError(response.error?.msg ?? 'DHT find peer failed', 'ERR_DHT_FIND_PEER_FAILED')
@@ -128,8 +114,7 @@ export class DHT {
128
114
 
129
115
  return {
130
116
  id: peerIdFromBytes(response.dht.peer.id),
131
- multiaddrs: response.dht.peer.addrs.map((a) => multiaddr(a)),
132
- protocols: []
117
+ multiaddrs: response.dht.peer.addrs.map((a) => multiaddr(a))
133
118
  }
134
119
  }
135
120
 
@@ -149,15 +134,9 @@ export class DHT {
149
134
  }
150
135
  })
151
136
 
152
- const message = await sh.read()
153
-
154
- if (message == null) {
155
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
156
- }
137
+ const response = await sh.read(Response)
157
138
 
158
- const response = Response.decode(message)
159
-
160
- await sh.close()
139
+ await sh.unwrap().close()
161
140
 
162
141
  if (response.type !== Response.Type.OK) {
163
142
  throw new CodeError(response.error?.msg ?? 'DHT provide failed', 'ERR_DHT_PROVIDE_FAILED')
@@ -181,45 +160,32 @@ export class DHT {
181
160
  }
182
161
  })
183
162
 
184
- let message = await sh.read()
185
-
186
- if (message == null) {
187
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
188
- }
189
-
190
163
  // stream begin message
191
- const response = Response.decode(message)
164
+ const response = await sh.read(Response)
192
165
 
193
166
  if (response.type !== Response.Type.OK) {
194
- await sh.close()
167
+ await sh.unwrap().close()
195
168
  throw new CodeError(response.error?.msg ?? 'DHT find providers failed', 'ERR_DHT_FIND_PROVIDERS_FAILED')
196
169
  }
197
170
 
198
171
  while (true) {
199
- message = await sh.read()
200
-
201
- if (message == null) {
202
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
203
- }
204
-
205
- const response = DHTResponse.decode(message)
172
+ const dhtResponse = await sh.read(DHTResponse)
206
173
 
207
174
  // Stream end
208
- if (response.type === DHTResponse.Type.END) {
209
- await sh.close()
175
+ if (dhtResponse.type === DHTResponse.Type.END) {
176
+ await sh.unwrap().close()
210
177
  return
211
178
  }
212
179
 
213
180
  // Stream values
214
- if (response.type === DHTResponse.Type.VALUE && response.peer != null && response.peer?.addrs != null) {
181
+ if (dhtResponse.type === DHTResponse.Type.VALUE && dhtResponse.peer != null && dhtResponse.peer?.addrs != null) {
215
182
  yield {
216
- id: peerIdFromBytes(response.peer.id),
217
- multiaddrs: response.peer.addrs.map((a) => multiaddr(a)),
218
- protocols: []
183
+ id: peerIdFromBytes(dhtResponse.peer.id),
184
+ multiaddrs: dhtResponse.peer.addrs.map((a) => multiaddr(a))
219
185
  }
220
186
  } else {
221
187
  // Unexpected message received
222
- await sh.close()
188
+ await sh.unwrap().close()
223
189
  throw new CodeError('unexpected message received', 'ERR_UNEXPECTED_MESSAGE_RECEIVED')
224
190
  }
225
191
  }
@@ -242,46 +208,33 @@ export class DHT {
242
208
  })
243
209
 
244
210
  // stream begin message
245
- let message = await sh.read()
246
-
247
- if (message == null) {
248
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
249
- }
250
-
251
- const response = Response.decode(message)
211
+ const response = await sh.read(Response)
252
212
 
253
213
  if (response.type !== Response.Type.OK) {
254
- await sh.close()
214
+ await sh.unwrap().close()
255
215
  throw new CodeError(response.error?.msg ?? 'DHT find providers failed', 'ERR_DHT_FIND_PROVIDERS_FAILED')
256
216
  }
257
217
 
258
218
  while (true) {
259
- message = await sh.read()
260
-
261
- if (message == null) {
262
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
263
- }
264
-
265
- const response = DHTResponse.decode(message)
219
+ const dhtResponse = await sh.read(DHTResponse)
266
220
 
267
221
  // Stream end
268
- if (response.type === DHTResponse.Type.END) {
269
- await sh.close()
222
+ if (dhtResponse.type === DHTResponse.Type.END) {
223
+ await sh.unwrap().close()
270
224
  return
271
225
  }
272
226
 
273
227
  // Stream values
274
- if (response.type === DHTResponse.Type.VALUE && response.value != null) {
275
- const peerId = peerIdFromBytes(response.value)
228
+ if (dhtResponse.type === DHTResponse.Type.VALUE && dhtResponse.value != null) {
229
+ const peerId = peerIdFromBytes(dhtResponse.value)
276
230
 
277
231
  yield {
278
232
  id: peerId,
279
- multiaddrs: [],
280
- protocols: []
233
+ multiaddrs: []
281
234
  }
282
235
  } else {
283
236
  // Unexpected message received
284
- await sh.close()
237
+ await sh.unwrap().close()
285
238
  throw new CodeError('unexpected message received', 'ERR_UNEXPECTED_MESSAGE_RECEIVED')
286
239
  }
287
240
  }
@@ -303,15 +256,9 @@ export class DHT {
303
256
  }
304
257
  })
305
258
 
306
- const message = await sh.read()
307
-
308
- if (message == null) {
309
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
310
- }
311
-
312
- const response = Response.decode(message)
259
+ const response = await sh.read(Response)
313
260
 
314
- await sh.close()
261
+ await sh.unwrap().close()
315
262
 
316
263
  if (response.type !== Response.Type.OK) {
317
264
  throw new CodeError(response.error?.msg ?? 'DHT get public key failed', 'ERR_DHT_GET_PUBLIC_KEY_FAILED')
package/src/index.ts CHANGED
@@ -1,21 +1,17 @@
1
1
  import { type PSMessage, Request, Response, StreamInfo } from '@libp2p/daemon-protocol'
2
2
  import { StreamHandler } from '@libp2p/daemon-protocol/stream-handler'
3
3
  import { passThroughUpgrader } from '@libp2p/daemon-protocol/upgrader'
4
- import { CodeError } from '@libp2p/interface/errors'
5
- import { isPeerId, type PeerId } from '@libp2p/interface/peer-id'
4
+ import { CodeError, isPeerId } from '@libp2p/interface'
6
5
  import { defaultLogger, logger } from '@libp2p/logger'
7
6
  import { peerIdFromBytes } from '@libp2p/peer-id'
8
7
  import { tcp } from '@libp2p/tcp'
9
8
  import { multiaddr, isMultiaddr } from '@multiformats/multiaddr'
9
+ import { pbStream, type ProtobufStream } from 'it-protobuf-stream'
10
10
  import { DHT } from './dht.js'
11
11
  import { Pubsub } from './pubsub.js'
12
- import type { MultiaddrConnection } from '@libp2p/interface/connection'
13
- import type { PeerInfo } from '@libp2p/interface/peer-info'
14
- import type { Transport } from '@libp2p/interface/transport'
12
+ import type { Stream, PeerId, MultiaddrConnection, PeerInfo, Transport } from '@libp2p/interface'
15
13
  import type { Multiaddr } from '@multiformats/multiaddr'
16
- import type { Duplex, Source } from 'it-stream-types'
17
14
  import type { CID } from 'multiformats/cid'
18
- import type { Uint8ArrayList } from 'uint8arraylist'
19
15
 
20
16
  const log = logger('libp2p:daemon-client')
21
17
 
@@ -28,7 +24,6 @@ class Client implements DaemonClient {
28
24
  constructor (addr: Multiaddr) {
29
25
  this.multiaddr = addr
30
26
  this.tcp = tcp()({
31
- // @ts-expect-error this field will be present post v1
32
27
  logger: defaultLogger()
33
28
  })
34
29
  this.dht = new DHT(this)
@@ -54,15 +49,16 @@ class Client implements DaemonClient {
54
49
  * Sends the request to the daemon and returns a stream. This
55
50
  * should only be used when sending daemon requests.
56
51
  */
57
- async send (request: Request): Promise<StreamHandler> {
52
+ async send (request: Request): Promise<ProtobufStream<MultiaddrConnection>> {
58
53
  const maConn = await this.connectDaemon()
59
54
 
60
55
  const subtype = request.pubsub?.type ?? request.dht?.type ?? request.peerStore?.type ?? ''
61
56
  log('send', request.type, subtype)
62
57
 
63
- const streamHandler = new StreamHandler({ stream: maConn })
64
- streamHandler.write(Request.encode(request))
65
- return streamHandler
58
+ const pb = pbStream(maConn)
59
+ await pb.write(request, Request)
60
+
61
+ return pb
66
62
  }
67
63
 
68
64
  /**
@@ -91,18 +87,14 @@ class Client implements DaemonClient {
91
87
  }
92
88
  })
93
89
 
94
- const message = await sh.read()
95
- if (message == null) {
96
- throw new CodeError('unspecified', 'ERR_CONNECT_FAILED')
97
- }
90
+ const response = await sh.read(Response)
98
91
 
99
- const response = Response.decode(message)
100
92
  if (response.type !== Response.Type.OK) {
101
93
  const errResponse = response.error ?? { msg: 'unspecified' }
102
94
  throw new CodeError(errResponse.msg ?? 'unspecified', 'ERR_CONNECT_FAILED')
103
95
  }
104
96
 
105
- await sh.close()
97
+ await sh.unwrap().close()
106
98
  }
107
99
 
108
100
  /**
@@ -119,13 +111,7 @@ class Client implements DaemonClient {
119
111
  type: Request.Type.IDENTIFY
120
112
  })
121
113
 
122
- const message = await sh.read()
123
-
124
- if (message == null) {
125
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
126
- }
127
-
128
- const response = Response.decode(message)
114
+ const response = await sh.read(Response)
129
115
 
130
116
  if (response.type !== Response.Type.OK) {
131
117
  throw new CodeError(response.error?.msg ?? 'Identify failed', 'ERR_IDENTIFY_FAILED')
@@ -138,7 +124,7 @@ class Client implements DaemonClient {
138
124
  const peerId = peerIdFromBytes(response.identify?.id)
139
125
  const addrs = response.identify.addrs.map((a) => multiaddr(a))
140
126
 
141
- await sh.close()
127
+ await sh.unwrap().close()
142
128
 
143
129
  return ({ peerId, addrs })
144
130
  }
@@ -151,19 +137,13 @@ class Client implements DaemonClient {
151
137
  type: Request.Type.LIST_PEERS
152
138
  })
153
139
 
154
- const message = await sh.read()
155
-
156
- if (message == null) {
157
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
158
- }
159
-
160
- const response = Response.decode(message)
140
+ const response = await sh.read(Response)
161
141
 
162
142
  if (response.type !== Response.Type.OK) {
163
143
  throw new CodeError(response.error?.msg ?? 'List peers failed', 'ERR_LIST_PEERS_FAILED')
164
144
  }
165
145
 
166
- await sh.close()
146
+ await sh.unwrap().close()
167
147
 
168
148
  return response.peers.map((peer) => peerIdFromBytes(peer.id))
169
149
  }
@@ -171,7 +151,7 @@ class Client implements DaemonClient {
171
151
  /**
172
152
  * Initiate an outbound stream to a peer on one of a set of protocols.
173
153
  */
174
- async openStream (peerId: PeerId, protocol: string): Promise<Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>, Source<Uint8Array>, Promise<void>>> {
154
+ async openStream (peerId: PeerId, protocol: string): Promise<MultiaddrConnection> {
175
155
  if (!isPeerId(peerId)) {
176
156
  throw new CodeError('invalid peer id received', 'ERR_INVALID_PEER_ID')
177
157
  }
@@ -188,20 +168,14 @@ class Client implements DaemonClient {
188
168
  }
189
169
  })
190
170
 
191
- const message = await sh.read()
192
-
193
- if (message == null) {
194
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
195
- }
196
-
197
- const response = Response.decode(message)
171
+ const response = await sh.read(Response)
198
172
 
199
173
  if (response.type !== Response.Type.OK) {
200
- await sh.close()
174
+ await sh.unwrap().close()
201
175
  throw new CodeError(response.error?.msg ?? 'Open stream failed', 'ERR_OPEN_STREAM_FAILED')
202
176
  }
203
177
 
204
- return sh.rest()
178
+ return sh.unwrap()
205
179
  }
206
180
 
207
181
  /**
@@ -215,11 +189,11 @@ class Client implements DaemonClient {
215
189
  // open a tcp port, pipe any data from it to the handler function
216
190
  const listener = this.tcp.createListener({
217
191
  upgrader: passThroughUpgrader,
218
- handler: (connection) => {
192
+ // @ts-expect-error because we are using a passthrough upgrader, this is a MultiaddrConnection
193
+ handler: (connection: MultiaddrConnection) => {
219
194
  Promise.resolve()
220
195
  .then(async () => {
221
196
  const sh = new StreamHandler({
222
- // @ts-expect-error because we are using a passthrough upgrader, this is a MultiaddrConnection
223
197
  stream: connection
224
198
  })
225
199
  const message = await sh.read()
@@ -234,6 +208,7 @@ class Client implements DaemonClient {
234
208
  throw new CodeError('Incorrect protocol', 'ERR_OPEN_STREAM_FAILED')
235
209
  }
236
210
 
211
+ // @ts-expect-error because we are using a passthrough upgrader, this is a MultiaddrConnection
237
212
  await handler(sh.rest())
238
213
  })
239
214
  .finally(() => {
@@ -263,15 +238,9 @@ class Client implements DaemonClient {
263
238
  }
264
239
  })
265
240
 
266
- const message = await sh.read()
267
-
268
- if (message == null) {
269
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
270
- }
271
-
272
- const response = Response.decode(message)
241
+ const response = await sh.read(Response)
273
242
 
274
- await sh.close()
243
+ await sh.unwrap().close()
275
244
 
276
245
  if (response.type !== Response.Type.OK) {
277
246
  throw new CodeError(response.error?.msg ?? 'Register stream handler failed', 'ERR_REGISTER_STREAM_HANDLER_FAILED')
@@ -285,7 +254,7 @@ export interface IdentifyResult {
285
254
  }
286
255
 
287
256
  export interface StreamHandlerFunction {
288
- (stream: Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>, Source<Uint8Array>, Promise<void>>): Promise<void>
257
+ (stream: Stream): Promise<void>
289
258
  }
290
259
 
291
260
  export interface DHTClient {
@@ -316,8 +285,8 @@ export interface DaemonClient {
316
285
  dht: DHTClient
317
286
  pubsub: PubSubClient
318
287
 
319
- send(request: Request): Promise<StreamHandler>
320
- openStream(peerId: PeerId, protocol: string): Promise<Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>, Source<Uint8Array>, Promise<void>>>
288
+ send(request: Request): Promise<ProtobufStream<MultiaddrConnection>>
289
+ openStream(peerId: PeerId, protocol: string): Promise<MultiaddrConnection>
321
290
  registerStreamHandler(protocol: string, handler: StreamHandlerFunction): Promise<void>
322
291
  }
323
292
 
package/src/pubsub.ts CHANGED
@@ -4,10 +4,10 @@ import {
4
4
  PSRequest,
5
5
  PSMessage
6
6
  } from '@libp2p/daemon-protocol'
7
- import { CodeError } from '@libp2p/interface/errors'
7
+ import { CodeError } from '@libp2p/interface'
8
8
  import { peerIdFromBytes } from '@libp2p/peer-id'
9
9
  import type { DaemonClient, Subscription } from './index.js'
10
- import type { PeerId } from '@libp2p/interface/peer-id'
10
+ import type { PeerId } from '@libp2p/interface'
11
11
 
12
12
  export class Pubsub {
13
13
  private readonly client: DaemonClient
@@ -29,15 +29,9 @@ export class Pubsub {
29
29
  }
30
30
  })
31
31
 
32
- const message = await sh.read()
32
+ const response = await sh.read(Response)
33
33
 
34
- if (message == null) {
35
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
36
- }
37
-
38
- const response = Response.decode(message)
39
-
40
- await sh.close()
34
+ await sh.unwrap().close()
41
35
 
42
36
  if (response.type !== Response.Type.OK) {
43
37
  throw new CodeError(response.error?.msg ?? 'Pubsub get topics failed', 'ERR_PUBSUB_GET_TOPICS_FAILED')
@@ -71,15 +65,9 @@ export class Pubsub {
71
65
  }
72
66
  })
73
67
 
74
- const message = await sh.read()
68
+ const response = await sh.read(Response)
75
69
 
76
- if (message == null) {
77
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
78
- }
79
-
80
- const response = Response.decode(message)
81
-
82
- await sh.close()
70
+ await sh.unwrap().close()
83
71
 
84
72
  if (response.type !== Response.Type.OK) {
85
73
  throw new CodeError(response.error?.msg ?? 'Pubsub publish failed', 'ERR_PUBSUB_PUBLISH_FAILED')
@@ -102,13 +90,7 @@ export class Pubsub {
102
90
  }
103
91
  })
104
92
 
105
- let message = await sh.read()
106
-
107
- if (message == null) {
108
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
109
- }
110
-
111
- const response = Response.decode(message)
93
+ const response = await sh.read(Response)
112
94
 
113
95
  if (response.type !== Response.Type.OK) {
114
96
  throw new CodeError(response.error?.msg ?? 'Pubsub publish failed', 'ERR_PUBSUB_PUBLISH_FAILED')
@@ -119,18 +101,12 @@ export class Pubsub {
119
101
  const subscription: Subscription = {
120
102
  async * messages () {
121
103
  while (subscribed) { // eslint-disable-line no-unmodified-loop-condition
122
- message = await sh.read()
123
-
124
- if (message == null) {
125
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
126
- }
127
-
128
- yield PSMessage.decode(message)
104
+ yield await sh.read(PSMessage)
129
105
  }
130
106
  },
131
107
  async cancel () {
132
108
  subscribed = false
133
- await sh.close()
109
+ await sh.unwrap().close()
134
110
  }
135
111
  }
136
112
 
@@ -150,15 +126,9 @@ export class Pubsub {
150
126
  }
151
127
  })
152
128
 
153
- const message = await sh.read()
154
-
155
- if (message == null) {
156
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
157
- }
158
-
159
- const response = Response.decode(message)
129
+ const response = await sh.read(Response)
160
130
 
161
- await sh.close()
131
+ await sh.unwrap().close()
162
132
 
163
133
  if (response.type !== Response.Type.OK) {
164
134
  throw new CodeError(response.error?.msg ?? 'Pubsub get subscribers failed', 'ERR_PUBSUB_GET_SUBSCRIBERS_FAILED')