@libp2p/daemon-client 7.0.2 → 8.0.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/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@libp2p/daemon-client",
3
- "version": "7.0.2",
3
+ "version": "8.0.0",
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
  [
@@ -132,20 +136,20 @@
132
136
  },
133
137
  "dependencies": {
134
138
  "@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",
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'
6
- import { logger } from '@libp2p/logger'
4
+ import { CodeError, isPeerId } from '@libp2p/interface'
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
 
@@ -27,7 +23,9 @@ class Client implements DaemonClient {
27
23
 
28
24
  constructor (addr: Multiaddr) {
29
25
  this.multiaddr = addr
30
- this.tcp = tcp()()
26
+ this.tcp = tcp()({
27
+ logger: defaultLogger()
28
+ })
31
29
  this.dht = new DHT(this)
32
30
  this.pubsub = new Pubsub(this)
33
31
  }
@@ -51,15 +49,16 @@ class Client implements DaemonClient {
51
49
  * Sends the request to the daemon and returns a stream. This
52
50
  * should only be used when sending daemon requests.
53
51
  */
54
- async send (request: Request): Promise<StreamHandler> {
52
+ async send (request: Request): Promise<ProtobufStream<MultiaddrConnection>> {
55
53
  const maConn = await this.connectDaemon()
56
54
 
57
55
  const subtype = request.pubsub?.type ?? request.dht?.type ?? request.peerStore?.type ?? ''
58
56
  log('send', request.type, subtype)
59
57
 
60
- const streamHandler = new StreamHandler({ stream: maConn })
61
- streamHandler.write(Request.encode(request))
62
- return streamHandler
58
+ const pb = pbStream(maConn)
59
+ await pb.write(request, Request)
60
+
61
+ return pb
63
62
  }
64
63
 
65
64
  /**
@@ -88,18 +87,14 @@ class Client implements DaemonClient {
88
87
  }
89
88
  })
90
89
 
91
- const message = await sh.read()
92
- if (message == null) {
93
- throw new CodeError('unspecified', 'ERR_CONNECT_FAILED')
94
- }
90
+ const response = await sh.read(Response)
95
91
 
96
- const response = Response.decode(message)
97
92
  if (response.type !== Response.Type.OK) {
98
93
  const errResponse = response.error ?? { msg: 'unspecified' }
99
94
  throw new CodeError(errResponse.msg ?? 'unspecified', 'ERR_CONNECT_FAILED')
100
95
  }
101
96
 
102
- await sh.close()
97
+ await sh.unwrap().close()
103
98
  }
104
99
 
105
100
  /**
@@ -116,13 +111,7 @@ class Client implements DaemonClient {
116
111
  type: Request.Type.IDENTIFY
117
112
  })
118
113
 
119
- const message = await sh.read()
120
-
121
- if (message == null) {
122
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
123
- }
124
-
125
- const response = Response.decode(message)
114
+ const response = await sh.read(Response)
126
115
 
127
116
  if (response.type !== Response.Type.OK) {
128
117
  throw new CodeError(response.error?.msg ?? 'Identify failed', 'ERR_IDENTIFY_FAILED')
@@ -135,7 +124,7 @@ class Client implements DaemonClient {
135
124
  const peerId = peerIdFromBytes(response.identify?.id)
136
125
  const addrs = response.identify.addrs.map((a) => multiaddr(a))
137
126
 
138
- await sh.close()
127
+ await sh.unwrap().close()
139
128
 
140
129
  return ({ peerId, addrs })
141
130
  }
@@ -148,19 +137,13 @@ class Client implements DaemonClient {
148
137
  type: Request.Type.LIST_PEERS
149
138
  })
150
139
 
151
- const message = await sh.read()
152
-
153
- if (message == null) {
154
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
155
- }
156
-
157
- const response = Response.decode(message)
140
+ const response = await sh.read(Response)
158
141
 
159
142
  if (response.type !== Response.Type.OK) {
160
143
  throw new CodeError(response.error?.msg ?? 'List peers failed', 'ERR_LIST_PEERS_FAILED')
161
144
  }
162
145
 
163
- await sh.close()
146
+ await sh.unwrap().close()
164
147
 
165
148
  return response.peers.map((peer) => peerIdFromBytes(peer.id))
166
149
  }
@@ -168,7 +151,7 @@ class Client implements DaemonClient {
168
151
  /**
169
152
  * Initiate an outbound stream to a peer on one of a set of protocols.
170
153
  */
171
- async openStream (peerId: PeerId, protocol: string): Promise<Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>, Source<Uint8Array>, Promise<void>>> {
154
+ async openStream (peerId: PeerId, protocol: string): Promise<MultiaddrConnection> {
172
155
  if (!isPeerId(peerId)) {
173
156
  throw new CodeError('invalid peer id received', 'ERR_INVALID_PEER_ID')
174
157
  }
@@ -185,20 +168,14 @@ class Client implements DaemonClient {
185
168
  }
186
169
  })
187
170
 
188
- const message = await sh.read()
189
-
190
- if (message == null) {
191
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
192
- }
193
-
194
- const response = Response.decode(message)
171
+ const response = await sh.read(Response)
195
172
 
196
173
  if (response.type !== Response.Type.OK) {
197
- await sh.close()
174
+ await sh.unwrap().close()
198
175
  throw new CodeError(response.error?.msg ?? 'Open stream failed', 'ERR_OPEN_STREAM_FAILED')
199
176
  }
200
177
 
201
- return sh.rest()
178
+ return sh.unwrap()
202
179
  }
203
180
 
204
181
  /**
@@ -212,11 +189,11 @@ class Client implements DaemonClient {
212
189
  // open a tcp port, pipe any data from it to the handler function
213
190
  const listener = this.tcp.createListener({
214
191
  upgrader: passThroughUpgrader,
215
- handler: (connection) => {
192
+ // @ts-expect-error because we are using a passthrough upgrader, this is a MultiaddrConnection
193
+ handler: (connection: MultiaddrConnection) => {
216
194
  Promise.resolve()
217
195
  .then(async () => {
218
196
  const sh = new StreamHandler({
219
- // @ts-expect-error because we are using a passthrough upgrader, this is a MultiaddrConnection
220
197
  stream: connection
221
198
  })
222
199
  const message = await sh.read()
@@ -231,6 +208,7 @@ class Client implements DaemonClient {
231
208
  throw new CodeError('Incorrect protocol', 'ERR_OPEN_STREAM_FAILED')
232
209
  }
233
210
 
211
+ // @ts-expect-error because we are using a passthrough upgrader, this is a MultiaddrConnection
234
212
  await handler(sh.rest())
235
213
  })
236
214
  .finally(() => {
@@ -260,15 +238,9 @@ class Client implements DaemonClient {
260
238
  }
261
239
  })
262
240
 
263
- const message = await sh.read()
264
-
265
- if (message == null) {
266
- throw new CodeError('Empty response from remote', 'ERR_EMPTY_RESPONSE')
267
- }
268
-
269
- const response = Response.decode(message)
241
+ const response = await sh.read(Response)
270
242
 
271
- await sh.close()
243
+ await sh.unwrap().close()
272
244
 
273
245
  if (response.type !== Response.Type.OK) {
274
246
  throw new CodeError(response.error?.msg ?? 'Register stream handler failed', 'ERR_REGISTER_STREAM_HANDLER_FAILED')
@@ -282,7 +254,7 @@ export interface IdentifyResult {
282
254
  }
283
255
 
284
256
  export interface StreamHandlerFunction {
285
- (stream: Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>, Source<Uint8Array>, Promise<void>>): Promise<void>
257
+ (stream: Stream): Promise<void>
286
258
  }
287
259
 
288
260
  export interface DHTClient {
@@ -313,8 +285,8 @@ export interface DaemonClient {
313
285
  dht: DHTClient
314
286
  pubsub: PubSubClient
315
287
 
316
- send(request: Request): Promise<StreamHandler>
317
- 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>
318
290
  registerStreamHandler(protocol: string, handler: StreamHandlerFunction): Promise<void>
319
291
  }
320
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')