@@ -13,7 +13,8 @@ import {
13
13
KeyPair ,
14
14
LogLevel ,
15
15
MessageRpcQuery ,
16
- MessageRpcResponse
16
+ MessageRpcResponse ,
17
+ Ports
17
18
} from "../types.js" ;
18
19
import { existsAsync , mkdirAsync , openAsync } from "../utils/async_fs.js" ;
19
20
import { delay } from "../utils/delay.js" ;
@@ -49,6 +50,7 @@ export class ServiceNode {
49
50
private websocketPort ?: number ;
50
51
private readonly logPath : string ;
51
52
private rpcPort ?: number ;
53
+ private restPort ?: number ;
52
54
53
55
/**
54
56
* Convert a [[WakuMessage]] to a [[WakuRelayMessage]]. The latter is used
@@ -116,18 +118,26 @@ export class ServiceNode {
116
118
// we also randomize the first port that portfinder will try
117
119
const startPort = Math . floor ( Math . random ( ) * ( 65535 - 1025 ) + 1025 ) ;
118
120
119
- const ports : number [ ] = await new Promise ( ( resolve , reject ) => {
120
- portfinder . getPorts ( 4 , { port : startPort } , ( err , ports ) => {
121
+ const ports : Ports = await new Promise ( ( resolve , reject ) => {
122
+ portfinder . getPorts ( 5 , { port : startPort } , ( err , ports ) => {
121
123
if ( err ) reject ( err ) ;
122
- resolve ( ports ) ;
124
+ resolve ( {
125
+ rpcPort : ports [ 0 ] ,
126
+ tcpPort : ports [ 1 ] ,
127
+ websocketPort : ports [ 2 ] ,
128
+ restPort : ports [ 3 ] ,
129
+ discv5UdpPort : ports [ 4 ]
130
+ } ) ;
123
131
} ) ;
124
132
} ) ;
125
133
126
134
if ( isGoWaku && ! args . logLevel ) {
127
135
args . logLevel = LogLevel . Debug ;
128
136
}
129
137
130
- const [ rpcPort , tcpPort , websocketPort , discv5UdpPort ] = ports ;
138
+ const { rpcPort, tcpPort, websocketPort, restPort, discv5UdpPort } =
139
+ ports ;
140
+ this . restPort = restPort ;
131
141
this . rpcPort = rpcPort ;
132
142
this . websocketPort = websocketPort ;
133
143
@@ -138,13 +148,15 @@ export class ServiceNode {
138
148
Object . assign (
139
149
mergedArgs ,
140
150
{
151
+ rest : true ,
152
+ restPort,
141
153
rpcPort,
142
154
tcpPort,
143
155
websocketPort,
144
156
...( args ?. peerExchange && { discv5UdpPort } ) ,
145
157
...( isGoWaku && { minRelayPeersToPublish : 0 , legacyFilter } )
146
158
} ,
147
- { rpcAddress : "0.0.0.0" } ,
159
+ { rpcAddress : "0.0.0.0" , restAddress : "0.0.0.0" } ,
148
160
_args
149
161
) ;
150
162
@@ -210,21 +222,40 @@ export class ServiceNode {
210
222
async ensureSubscriptions (
211
223
pubsubTopics : string [ ] = [ DefaultPubsubTopic ]
212
224
) : Promise < boolean > {
213
- this . checkProcess ( ) ;
225
+ return this . restCall < boolean > (
226
+ "/relay/v1/subscriptions" ,
227
+ "POST" ,
228
+ pubsubTopics ,
229
+ async ( response ) => response . status === 200
230
+ ) ;
231
+ }
214
232
215
- return this . rpcCall < boolean > ( "post_waku_v2_relay_v1_subscriptions" , [
216
- pubsubTopics
217
- ] ) ;
233
+ async messages (
234
+ pubsubTopic : string = DefaultPubsubTopic
235
+ ) : Promise < MessageRpcResponse [ ] > {
236
+ pubsubTopic = encodeURIComponent ( pubsubTopic ) ;
237
+ return this . restCall < MessageRpcResponse [ ] > (
238
+ `/relay/v1/messages/${ pubsubTopic } ` ,
239
+ "GET" ,
240
+ null ,
241
+ async ( response ) => {
242
+ const data = await response . json ( ) ;
243
+ return data ?. length ? data : [ ] ;
244
+ }
245
+ ) ;
218
246
}
219
247
220
248
async ensureSubscriptionsAutosharding (
221
249
contentTopics : string [ ]
222
250
) : Promise < boolean > {
223
251
this . checkProcess ( ) ;
224
252
225
- return this . rpcCall < boolean > ( "post_waku_v2_relay_v1_auto_subscriptions" , [
226
- contentTopics
227
- ] ) ;
253
+ return this . restCall < boolean > (
254
+ "/relay/v1/subscriptions" ,
255
+ "POST" ,
256
+ contentTopics ,
257
+ async ( response ) => response . status === 200
258
+ ) ;
228
259
}
229
260
230
261
async sendMessage (
@@ -255,30 +286,21 @@ export class ServiceNode {
255
286
] ) ;
256
287
}
257
288
258
- async messages (
259
- pubsubTopic : string = DefaultPubsubTopic
260
- ) : Promise < MessageRpcResponse [ ] > {
261
- this . checkProcess ( ) ;
262
-
263
- const msgs = await this . rpcCall < MessageRpcResponse [ ] > (
264
- "get_waku_v2_relay_v1_messages" ,
265
- [ pubsubTopic ]
266
- ) ;
267
-
268
- return msgs . filter ( isDefined ) ;
269
- }
270
-
271
289
async messagesAutosharding (
272
290
contentTopic : string
273
291
) : Promise < MessageRpcResponse [ ] > {
274
292
this . checkProcess ( ) ;
275
293
276
- const msgs = await this . rpcCall < MessageRpcResponse [ ] > (
277
- "get_waku_v2_relay_v1_auto_messages" ,
278
- [ contentTopic ]
294
+ contentTopic = encodeURIComponent ( contentTopic ) ;
295
+ return this . restCall < MessageRpcResponse [ ] > (
296
+ `/relay/v1/auto/messages/${ contentTopic } ` ,
297
+ "GET" ,
298
+ null ,
299
+ async ( response ) => {
300
+ const data = await response . json ( ) ;
301
+ return data ?. length ? data . filter ( isDefined ) : [ ] ;
302
+ }
279
303
) ;
280
-
281
- return msgs . filter ( isDefined ) ;
282
304
}
283
305
284
306
async getAsymmetricKeyPair ( ) : Promise < KeyPair > {
@@ -411,6 +433,10 @@ export class ServiceNode {
411
433
return `http://127.0.0.1:${ this . rpcPort } /` ;
412
434
}
413
435
436
+ get httpUrl ( ) : string {
437
+ return `http://127.0.0.1:${ this . restPort } ` ;
438
+ }
439
+
414
440
async rpcCall < T > (
415
441
method : string ,
416
442
params : Array < string | number | unknown >
@@ -442,6 +468,31 @@ export class ServiceNode {
442
468
) ;
443
469
}
444
470
471
+ async restCall < T > (
472
+ endpoint : string ,
473
+ method : "GET" | "POST" ,
474
+ body : any = null ,
475
+ processResponse : ( response : Response ) => Promise < T >
476
+ ) : Promise < T > {
477
+ this . checkProcess ( ) ;
478
+
479
+ try {
480
+ log . info ( "Making a REST Call: " , endpoint , body ) ;
481
+ const options : RequestInit = {
482
+ method,
483
+ headers : new Headers ( { "Content-Type" : "application/json" } )
484
+ } ;
485
+ if ( body ) options . body = JSON . stringify ( body ) ;
486
+
487
+ const response = await fetch ( `${ this . httpUrl } ${ endpoint } ` , options ) ;
488
+ log . info ( `Received REST Response: ` , response . status ) ;
489
+ return await processResponse ( response ) ;
490
+ } catch ( error ) {
491
+ log . error ( `${ this . httpUrl } failed with error:` , error ) ;
492
+ throw error ;
493
+ }
494
+ }
495
+
445
496
private checkProcess ( ) : void {
446
497
if ( ! this . docker ?. container ) {
447
498
throw `${ this . type } container hasn't started` ;
@@ -454,6 +505,7 @@ export function defaultArgs(): Args {
454
505
listenAddress : "0.0.0.0" ,
455
506
rpc : true ,
456
507
relay : false ,
508
+ rest : true ,
457
509
rpcAdmin : true ,
458
510
websocketSupport : true ,
459
511
logLevel : LogLevel . Trace
0 commit comments