8787/// Execute an offline wallet sub-command
8888///
8989/// Offline wallet sub-commands are described in [`OfflineWalletSubCommand`].
90- pub async fn handle_offline_wallet_subcommand (
90+ pub fn handle_offline_wallet_subcommand (
9191 wallet : & mut Wallet ,
9292 wallet_opts : & WalletOpts ,
9393 cli_opts : & CliOpts ,
@@ -581,56 +581,6 @@ pub async fn handle_offline_wallet_subcommand(
581581 & json ! ( { "psbt" : BASE64_STANDARD . encode( final_psbt. serialize( ) ) } ) ,
582582 ) ?)
583583 }
584- #[ cfg( feature = "hwi" ) ]
585- Hwi { subcommand } => match subcommand {
586- HwiSubCommand :: Devices => {
587- let device = crate :: utils:: connect_to_hardware_wallet (
588- wallet. network ( ) ,
589- wallet_opts,
590- Some ( wallet) ,
591- )
592- . await ?;
593- let device = if let Some ( device) = device {
594- json ! ( {
595- "type" : device. device_kind( ) . to_string( ) ,
596- "fingerprint" : device. get_master_fingerprint( ) . await ?. to_string( ) ,
597- "model" : device. device_kind( ) . to_string( ) ,
598- } )
599- } else {
600- json ! ( null)
601- } ;
602- Ok ( json ! ( { "devices" : device } ) )
603- }
604- HwiSubCommand :: Register => {
605- let policy = wallet_opts. ext_descriptor . clone ( ) . ok_or_else ( || {
606- Error :: Generic (
607- "External descriptor required for wallet registration" . to_string ( ) ,
608- )
609- } ) ?;
610- let wallet_name = wallet_opts. wallet . clone ( ) . ok_or_else ( || {
611- Error :: Generic ( "Wallet name is required for wallet registration" . to_string ( ) )
612- } ) ?;
613-
614- let device = crate :: utils:: connect_to_hardware_wallet (
615- wallet. network ( ) ,
616- wallet_opts,
617- Some ( wallet) ,
618- )
619- . await ?;
620- let hmac = if let Some ( device) = device {
621- let hmac = device. register_wallet ( & wallet_name, & policy) . await ?;
622- hmac. map ( |h| h. to_lower_hex_string ( ) )
623- } else {
624- None
625- } ;
626- //TODO: return status of wallet registration
627- Ok ( json ! ( { "hmac" : hmac } ) )
628- }
629- HwiSubCommand :: Address => {
630- let address = wallet. next_unused_address ( KeychainKind :: External ) ;
631- Ok ( json ! ( { "address" : address. address } ) )
632- }
633- } ,
634584 }
635585}
636586
@@ -1093,6 +1043,138 @@ pub(crate) fn handle_compile_subcommand(
10931043 }
10941044}
10951045
1046+ /// Handle hardware wallet operations
1047+ #[ cfg( feature = "hwi" ) ]
1048+ pub async fn handle_hwi_subcommand (
1049+ network : Network ,
1050+ wallet_opts : & WalletOpts ,
1051+ subcommand : HwiSubCommand ,
1052+ ) -> Result < serde_json:: Value , Error > {
1053+ match subcommand {
1054+ HwiSubCommand :: Devices => {
1055+ let devices = crate :: utils:: connect_to_hardware_wallet (
1056+ wallet. network ( ) ,
1057+ wallet_opts,
1058+ Some ( wallet) ,
1059+ )
1060+ . await ?;
1061+ let device = if let Some ( device) = device {
1062+ json ! ( {
1063+ "type" : device. device_kind( ) . to_string( ) ,
1064+ "fingerprint" : device. get_master_fingerprint( ) . await ?. to_string( ) ,
1065+ "model" : device. device_kind( ) . to_string( ) ,
1066+ } )
1067+ } else {
1068+ json ! ( null)
1069+ } ;
1070+ Ok ( json ! ( { "devices" : device } ) )
1071+ }
1072+ HwiSubCommand :: Register => {
1073+ let policy = wallet_opts. ext_descriptor . clone ( ) . ok_or_else ( || {
1074+ Error :: Generic ( "External descriptor required for wallet registration" . to_string ( ) )
1075+ } ) ?;
1076+ let wallet_name = wallet_opts. wallet . clone ( ) . ok_or_else ( || {
1077+ Error :: Generic ( "Wallet name is required for wallet registration" . to_string ( ) )
1078+ } ) ?;
1079+
1080+ let home_dir = prepare_home_dir ( None ) ?;
1081+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1082+ #[ cfg( feature = "sqlite" ) ]
1083+ let wallet = {
1084+ let mut persister = match & wallet_opts. database_type {
1085+ DatabaseType :: Sqlite => {
1086+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1087+ let connection = Connection :: open ( db_file) ?;
1088+ log:: debug!( "Sqlite database opened successfully" ) ;
1089+ connection
1090+ }
1091+ } ;
1092+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1093+ wallet. persist ( & mut persister) ?;
1094+ wallet
1095+ } ;
1096+ #[ cfg( not( feature = "sqlite" ) ) ]
1097+ let wallet = new_wallet ( network, wallet_opts) ?;
1098+
1099+ let device = crate :: utils:: connect_to_hardware_wallet (
1100+ wallet. network ( ) ,
1101+ wallet_opts,
1102+ Some ( wallet) ,
1103+ )
1104+ . await ?;
1105+ let hmac = if let Some ( device) = device {
1106+ let hmac = device. register_wallet ( & wallet_name, & policy) . await ?;
1107+ hmac. map ( |h| h. to_lower_hex_string ( ) )
1108+ } else {
1109+ None
1110+ } ;
1111+ Ok ( json ! ( { "hmac" : hmac } ) )
1112+ }
1113+ HwiSubCommand :: Address => {
1114+ let home_dir = prepare_home_dir ( None ) ?;
1115+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1116+ #[ cfg( feature = "sqlite" ) ]
1117+ let wallet = {
1118+ let mut persister = match & wallet_opts. database_type {
1119+ DatabaseType :: Sqlite => {
1120+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1121+ let connection = Connection :: open ( db_file) ?;
1122+ log:: debug!( "Sqlite database opened successfully" ) ;
1123+ connection
1124+ }
1125+ } ;
1126+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1127+ wallet. persist ( & mut persister) ?;
1128+ wallet
1129+ } ;
1130+ #[ cfg( not( feature = "sqlite" ) ) ]
1131+ let wallet = new_wallet ( network, wallet_opts) ?;
1132+
1133+ let address = wallet. next_unused_address ( KeychainKind :: External ) ;
1134+ Ok ( json ! ( { "address" : address. address } ) )
1135+ }
1136+ HwiSubCommand :: Sign { psbt } => {
1137+ let home_dir = prepare_home_dir ( None ) ?;
1138+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1139+ #[ cfg( feature = "sqlite" ) ]
1140+ let wallet = {
1141+ let mut persister = match & wallet_opts. database_type {
1142+ DatabaseType :: Sqlite => {
1143+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1144+ let connection = Connection :: open ( db_file) ?;
1145+ log:: debug!( "Sqlite database opened successfully" ) ;
1146+ connection
1147+ }
1148+ } ;
1149+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1150+ wallet. persist ( & mut persister) ?;
1151+ wallet
1152+ } ;
1153+ #[ cfg( not( feature = "sqlite" ) ) ]
1154+ let wallet = new_wallet ( network, wallet_opts) ?;
1155+
1156+ let mut psbt = Psbt :: from_str ( & psbt)
1157+ . map_err ( |e| Error :: Generic ( format ! ( "Failed to parse PSBT: {e}" ) ) ) ?;
1158+ let device = crate :: utils:: connect_to_hardware_wallet (
1159+ wallet. network ( ) ,
1160+ wallet_opts,
1161+ Some ( wallet) ,
1162+ )
1163+ . await ?;
1164+ let signed_psbt = if let Some ( device) = device {
1165+ device
1166+ . sign_tx ( & mut psbt)
1167+ . await
1168+ . map_err ( |e| Error :: Generic ( format ! ( "Failed to sign PSBT: {e}" ) ) ) ?;
1169+ Some ( psbt. to_string ( ) )
1170+ } else {
1171+ None
1172+ } ;
1173+ Ok ( json ! ( { "psbt" : signed_psbt } ) )
1174+ }
1175+ }
1176+ }
1177+
10961178/// The global top level handler.
10971179pub ( crate ) async fn handle_command ( cli_opts : CliOpts ) -> Result < String , Error > {
10981180 let network = cli_opts. network ;
@@ -1196,8 +1278,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
11961278
11971279 let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
11981280 let result =
1199- handle_offline_wallet_subcommand ( & mut wallet, wallet_opts, & cli_opts, offline_subcommand. clone ( ) )
1200- . await ?;
1281+ handle_offline_wallet_subcommand ( & mut wallet, wallet_opts, & cli_opts, offline_subcommand. clone ( ) ) ;
12011282 wallet. persist ( & mut persister) ?;
12021283 result
12031284 } ;
@@ -1211,7 +1292,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
12111292 offline_subcommand. clone ( ) ,
12121293 ) ?
12131294 } ;
1214- Ok ( result)
1295+ Ok ( result? )
12151296 }
12161297 CliSubCommand :: Key {
12171298 subcommand : key_subcommand,
@@ -1340,7 +1421,6 @@ async fn respond(
13401421 subcommand : WalletSubCommand :: OfflineWalletSubCommand ( offline_subcommand) ,
13411422 } => {
13421423 let value = handle_offline_wallet_subcommand ( wallet, wallet_opts, cli_opts, offline_subcommand)
1343- . await
13441424 . map_err ( |e| e. to_string ( ) ) ?;
13451425 Some ( value)
13461426 }
0 commit comments