@@ -172,10 +172,14 @@ trait ChainstateRpc {
172172 delegation_address : String ,
173173 ) -> RpcResult < Option < Amount > > ;
174174
175- /// Get token information, given a token id, in address form.
175+ /// Get token information, given a token id in address form.
176176 #[ method( name = "token_info" ) ]
177177 async fn token_info ( & self , token_id : String ) -> RpcResult < Option < RPCTokenInfo > > ;
178178
179+ /// Get tokens information, given multiple token ids in address form.
180+ #[ method( name = "tokens_info" ) ]
181+ async fn tokens_info ( & self , token_ids : Vec < String > ) -> RpcResult < Vec < RPCTokenInfo > > ;
182+
179183 /// Get order information, given an order id, in address form.
180184 #[ method( name = "order_info" ) ]
181185 async fn order_info ( & self , order_id : String ) -> RpcResult < Option < RpcOrderInfo > > ;
@@ -243,19 +247,22 @@ impl ChainstateRpcServer for super::ChainstateHandle {
243247
244248 if let Some ( ( block, block_index) ) = both {
245249 let token_ids = collect_token_v1_ids_from_output_values_holder ( & block) ;
246- let mut token_decimals = BTreeMap :: new ( ) ;
247-
248- // TODO replace this loop with a single ChainstateInterface function call obtaining
249- // all infos at once (when the function is implemented).
250- for token_id in token_ids {
251- let token_info: RPCTokenInfo = rpc:: handle_result (
252- self . call ( move |this| get_existing_token_info_for_rpc ( this, token_id) ) . await ,
253- ) ?;
254- token_decimals. insert (
255- token_id,
256- TokenDecimals ( token_info. token_number_of_decimals ( ) ) ,
257- ) ;
258- }
250+ let token_decimals: BTreeMap < TokenId , TokenDecimals > = rpc:: handle_result (
251+ self . call ( move |this| -> Result < _ , ChainstateError > {
252+ let infos = this. get_tokens_info_for_rpc ( & token_ids) ?;
253+ let decimals = infos
254+ . iter ( )
255+ . map ( |info| {
256+ (
257+ info. token_id ( ) ,
258+ TokenDecimals ( info. token_number_of_decimals ( ) ) ,
259+ )
260+ } )
261+ . collect :: < BTreeMap < _ , _ > > ( ) ;
262+ Ok ( decimals)
263+ } )
264+ . await ,
265+ ) ?;
259266
260267 let rpc_block: RpcBlock = rpc:: handle_result ( RpcBlock :: new (
261268 & chain_config,
@@ -438,6 +445,27 @@ impl ChainstateRpcServer for super::ChainstateHandle {
438445 )
439446 }
440447
448+ async fn tokens_info ( & self , token_ids : Vec < String > ) -> RpcResult < Vec < RPCTokenInfo > > {
449+ rpc:: handle_result (
450+ self . call ( move |this| -> Result < _ , DynamizedError > {
451+ let chain_config = this. get_chain_config ( ) ;
452+
453+ let token_ids = token_ids
454+ . into_iter ( )
455+ . map ( |token_id| -> Result < _ , DynamizedError > {
456+ Ok (
457+ dynamize_err ( Address :: < TokenId > :: from_string ( chain_config, token_id) ) ?
458+ . into_object ( ) ,
459+ )
460+ } )
461+ . collect :: < Result < _ , _ > > ( ) ?;
462+
463+ dynamize_err ( this. get_tokens_info_for_rpc ( & token_ids) )
464+ } )
465+ . await ,
466+ )
467+ }
468+
441469 async fn order_info ( & self , order_id : String ) -> RpcResult < Option < RpcOrderInfo > > {
442470 rpc:: handle_result (
443471 self . call ( move |this| {
@@ -488,33 +516,15 @@ impl ChainstateRpcServer for super::ChainstateHandle {
488516 }
489517}
490518
491- fn dynamize_err < T , E : std:: error:: Error + Send + Sync > (
492- o : Result < T , E > ,
493- ) -> Result < T , Box < dyn std:: error:: Error + Send + Sync > >
519+ type DynamizedError = Box < dyn std:: error:: Error + Send + Sync > ;
520+
521+ fn dynamize_err < T , E : std:: error:: Error + Send + Sync > ( o : Result < T , E > ) -> Result < T , DynamizedError >
494522where
495- Box < dyn std :: error :: Error + Send + Sync > : From < E > ,
523+ DynamizedError : From < E > ,
496524{
497525 o. map_err ( Into :: into)
498526}
499527
500- fn get_existing_token_info_for_rpc (
501- chainstate : & ( impl ChainstateInterface + ?Sized ) ,
502- token_id : TokenId ,
503- ) -> Result < RPCTokenInfo , LocalRpcError > {
504- chainstate
505- . get_token_info_for_rpc ( token_id) ?
506- . ok_or ( LocalRpcError :: MissingTokenInfo ( token_id) )
507- }
508-
509- #[ derive( thiserror:: Error , Debug , PartialEq , Eq ) ]
510- enum LocalRpcError {
511- #[ error( "Token info missing for token {0:x}" ) ]
512- MissingTokenInfo ( TokenId ) ,
513-
514- #[ error( transparent) ]
515- ChainstateError ( #[ from] ChainstateError ) ,
516- }
517-
518528#[ cfg( test) ]
519529mod test {
520530 use super :: * ;
0 commit comments