@@ -643,6 +643,43 @@ impl<R: Runtime> PairedBitBox<R> {
643643 }
644644 }
645645
646+ /// Retrieves multiple xpubs at once. Only standard keypaths are allowed.
647+ /// On firmware <v9.24.0, this falls back to calling `btc_xpub()` for each keypath.
648+ pub async fn btc_xpubs (
649+ & self ,
650+ coin : pb:: BtcCoin ,
651+ keypaths : & [ Keypath ] ,
652+ xpub_type : pb:: btc_xpubs_request:: XPubType ,
653+ ) -> Result < Vec < String > , Error > {
654+ if self . validate_version ( ">=9.24.0" ) . is_err ( ) {
655+ // Fallback to fetching them one-by-one on older firmware.
656+ let mut xpubs = Vec :: < String > :: with_capacity ( keypaths. len ( ) ) ;
657+ for keypath in keypaths {
658+ let converted_xpub_type = match xpub_type {
659+ pb:: btc_xpubs_request:: XPubType :: Unknown => return Err ( Error :: Unknown ) ,
660+ pb:: btc_xpubs_request:: XPubType :: Tpub => pb:: btc_pub_request:: XPubType :: Tpub ,
661+ pb:: btc_xpubs_request:: XPubType :: Xpub => pb:: btc_pub_request:: XPubType :: Xpub ,
662+ } ;
663+ let xpub = self
664+ . btc_xpub ( coin, keypath, converted_xpub_type, false )
665+ . await ?;
666+ xpubs. push ( xpub) ;
667+ }
668+ return Ok ( xpubs) ;
669+ }
670+ match self
671+ . query_proto_btc ( pb:: btc_request:: Request :: Xpubs ( pb:: BtcXpubsRequest {
672+ coin : coin as _ ,
673+ xpub_type : xpub_type as _ ,
674+ keypaths : keypaths. iter ( ) . map ( |kp| kp. into ( ) ) . collect ( ) ,
675+ } ) )
676+ . await ?
677+ {
678+ pb:: btc_response:: Response :: Pubs ( pb:: PubsResponse { pubs } ) => Ok ( pubs) ,
679+ _ => Err ( Error :: UnexpectedResponse ) ,
680+ }
681+ }
682+
646683 /// Retrieves a Bitcoin address at the provided keypath.
647684 ///
648685 /// For the simple script configs (single-sig), the keypath must follow the
0 commit comments