@@ -21,6 +21,11 @@ pub static JSON_RPC_VERSION: once_cell::sync::Lazy<Arc<str>> =
2121/// See <https://github.com/WalletConnect/walletconnect-docs/blob/main/docs/specs/servers/relay/relay-server-rpc.md>
2222pub const MAX_SUBSCRIPTION_BATCH_SIZE : usize = 500 ;
2323
24+ /// The maximum number of topics allowed for a batch fetch request.
25+ ///
26+ /// See <https://github.com/WalletConnect/walletconnect-docs/blob/main/docs/specs/servers/relay/relay-server-rpc.md>
27+ pub const MAX_FETCH_BATCH_SIZE : usize = 500 ;
28+
2429type BoxError = Box < dyn std:: error:: Error + Send + Sync > ;
2530
2631/// Errors covering payload validation problems.
@@ -35,14 +40,11 @@ pub enum ValidationError {
3540 #[ error( "Invalid JSON RPC version" ) ]
3641 JsonRpcVersion ,
3742
38- #[ error(
39- "The batch contains too many items. Maximum number of subscriptions is {}" ,
40- MAX_SUBSCRIPTION_BATCH_SIZE
41- ) ]
42- BatchSubscriptionLimit ,
43+ #[ error( "The batch contains too many items ({actual}). Maximum number of items is {limit}" ) ]
44+ BatchLimitExceeded { limit : usize , actual : usize } ,
4345
4446 #[ error( "The batch contains no items" ) ]
45- BatchSubscriptionListEmpty ,
47+ BatchEmpty ,
4648}
4749
4850/// Errors caught while processing the request. These are meant to be serialized
@@ -333,6 +335,42 @@ impl RequestPayload for Unsubscribe {
333335 }
334336}
335337
338+ /// Data structure representing fetch request params.
339+ #[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
340+ pub struct FetchMessages {
341+ /// The topic of the messages to fetch.
342+ pub topic : Topic ,
343+ }
344+
345+ impl RequestPayload for FetchMessages {
346+ type Error = GenericError ;
347+ type Response = FetchResponse ;
348+
349+ fn validate ( & self ) -> Result < ( ) , ValidationError > {
350+ self . topic
351+ . decode ( )
352+ . map_err ( ValidationError :: TopicDecoding ) ?;
353+
354+ Ok ( ( ) )
355+ }
356+
357+ fn into_params ( self ) -> Params {
358+ Params :: FetchMessages ( self )
359+ }
360+ }
361+
362+ /// Data structure representing fetch response.
363+ #[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
364+ #[ serde( rename_all = "camelCase" ) ]
365+ pub struct FetchResponse {
366+ /// Array of messages fetched from the mailbox.
367+ pub messages : Vec < SubscriptionData > ,
368+
369+ /// Flag that indicates whether the client should keep fetching the
370+ /// messages.
371+ pub has_more : bool ,
372+ }
373+
336374/// Multi-topic subscription request parameters.
337375#[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
338376pub struct BatchSubscribe {
@@ -345,12 +383,17 @@ impl RequestPayload for BatchSubscribe {
345383 type Response = Vec < SubscriptionId > ;
346384
347385 fn validate ( & self ) -> Result < ( ) , ValidationError > {
348- if self . topics . is_empty ( ) {
349- return Err ( ValidationError :: BatchSubscriptionListEmpty ) ;
386+ let batch_size = self . topics . len ( ) ;
387+
388+ if batch_size == 0 {
389+ return Err ( ValidationError :: BatchEmpty ) ;
350390 }
351391
352- if self . topics . len ( ) > MAX_SUBSCRIPTION_BATCH_SIZE {
353- return Err ( ValidationError :: BatchSubscriptionLimit ) ;
392+ if batch_size > MAX_SUBSCRIPTION_BATCH_SIZE {
393+ return Err ( ValidationError :: BatchLimitExceeded {
394+ limit : MAX_SUBSCRIPTION_BATCH_SIZE ,
395+ actual : batch_size,
396+ } ) ;
354397 }
355398
356399 for topic in & self . topics {
@@ -377,12 +420,17 @@ impl RequestPayload for BatchUnsubscribe {
377420 type Response = bool ;
378421
379422 fn validate ( & self ) -> Result < ( ) , ValidationError > {
380- if self . subscriptions . is_empty ( ) {
381- return Err ( ValidationError :: BatchSubscriptionListEmpty ) ;
423+ let batch_size = self . subscriptions . len ( ) ;
424+
425+ if batch_size == 0 {
426+ return Err ( ValidationError :: BatchEmpty ) ;
382427 }
383428
384- if self . subscriptions . len ( ) > MAX_SUBSCRIPTION_BATCH_SIZE {
385- return Err ( ValidationError :: BatchSubscriptionLimit ) ;
429+ if batch_size > MAX_SUBSCRIPTION_BATCH_SIZE {
430+ return Err ( ValidationError :: BatchLimitExceeded {
431+ limit : MAX_SUBSCRIPTION_BATCH_SIZE ,
432+ actual : batch_size,
433+ } ) ;
386434 }
387435
388436 for sub in & self . subscriptions {
@@ -397,6 +445,43 @@ impl RequestPayload for BatchUnsubscribe {
397445 }
398446}
399447
448+ /// Data structure representing batch fetch request params.
449+ #[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
450+ pub struct BatchFetchMessages {
451+ /// The topics of the messages to fetch.
452+ pub topics : Vec < Topic > ,
453+ }
454+
455+ impl RequestPayload for BatchFetchMessages {
456+ type Error = GenericError ;
457+ type Response = FetchResponse ;
458+
459+ fn validate ( & self ) -> Result < ( ) , ValidationError > {
460+ let batch_size = self . topics . len ( ) ;
461+
462+ if batch_size == 0 {
463+ return Err ( ValidationError :: BatchEmpty ) ;
464+ }
465+
466+ if batch_size > MAX_FETCH_BATCH_SIZE {
467+ return Err ( ValidationError :: BatchLimitExceeded {
468+ limit : MAX_FETCH_BATCH_SIZE ,
469+ actual : batch_size,
470+ } ) ;
471+ }
472+
473+ for topic in & self . topics {
474+ topic. decode ( ) . map_err ( ValidationError :: TopicDecoding ) ?;
475+ }
476+
477+ Ok ( ( ) )
478+ }
479+
480+ fn into_params ( self ) -> Params {
481+ Params :: BatchFetchMessages ( self )
482+ }
483+ }
484+
400485/// Data structure representing publish request params.
401486#[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
402487pub struct Publish {
@@ -550,6 +635,10 @@ pub enum Params {
550635 #[ serde( rename = "irn_unsubscribe" , alias = "iridium_unsubscribe" ) ]
551636 Unsubscribe ( Unsubscribe ) ,
552637
638+ /// Parameters to fetch.
639+ #[ serde( rename = "irn_fetchMessages" , alias = "iridium_fetchMessages" ) ]
640+ FetchMessages ( FetchMessages ) ,
641+
553642 /// Parameters to batch subscribe.
554643 #[ serde( rename = "irn_batchSubscribe" , alias = "iridium_batchSubscribe" ) ]
555644 BatchSubscribe ( BatchSubscribe ) ,
@@ -558,6 +647,13 @@ pub enum Params {
558647 #[ serde( rename = "irn_batchUnsubscribe" , alias = "iridium_batchUnsubscribe" ) ]
559648 BatchUnsubscribe ( BatchUnsubscribe ) ,
560649
650+ /// Parameters to batch fetch.
651+ #[ serde(
652+ rename = "irn_batchFetchMessages" ,
653+ alias = "iridium_batchFetchMessages"
654+ ) ]
655+ BatchFetchMessages ( BatchFetchMessages ) ,
656+
561657 /// Parameters to publish.
562658 #[ serde( rename = "irn_publish" , alias = "iridium_publish" ) ]
563659 Publish ( Publish ) ,
@@ -603,8 +699,10 @@ impl Request {
603699 match & self . params {
604700 Params :: Subscribe ( params) => params. validate ( ) ,
605701 Params :: Unsubscribe ( params) => params. validate ( ) ,
702+ Params :: FetchMessages ( params) => params. validate ( ) ,
606703 Params :: BatchSubscribe ( params) => params. validate ( ) ,
607704 Params :: BatchUnsubscribe ( params) => params. validate ( ) ,
705+ Params :: BatchFetchMessages ( params) => params. validate ( ) ,
608706 Params :: Publish ( params) => params. validate ( ) ,
609707 Params :: Subscription ( params) => params. validate ( ) ,
610708 }
0 commit comments