@@ -92,7 +92,7 @@ const NUMS_UNSPENDABLE_KEY_HEX: &str =
9292/// Execute an offline wallet sub-command
9393///
9494/// Offline wallet sub-commands are described in [`OfflineWalletSubCommand`].
95- pub async fn handle_offline_wallet_subcommand (
95+ pub fn handle_offline_wallet_subcommand (
9696 wallet : & mut Wallet ,
9797 wallet_opts : & WalletOpts ,
9898 cli_opts : & CliOpts ,
@@ -586,56 +586,6 @@ pub async fn handle_offline_wallet_subcommand(
586586 & json ! ( { "psbt" : BASE64_STANDARD . encode( final_psbt. serialize( ) ) } ) ,
587587 ) ?)
588588 }
589- #[ cfg( feature = "hwi" ) ]
590- Hwi { subcommand } => match subcommand {
591- HwiSubCommand :: Devices => {
592- let device = crate :: utils:: connect_to_hardware_wallet (
593- wallet. network ( ) ,
594- wallet_opts,
595- Some ( wallet) ,
596- )
597- . await ?;
598- let device = if let Some ( device) = device {
599- json ! ( {
600- "type" : device. device_kind( ) . to_string( ) ,
601- "fingerprint" : device. get_master_fingerprint( ) . await ?. to_string( ) ,
602- "model" : device. device_kind( ) . to_string( ) ,
603- } )
604- } else {
605- json ! ( null)
606- } ;
607- Ok ( json ! ( { "devices" : device } ) )
608- }
609- HwiSubCommand :: Register => {
610- let policy = wallet_opts. ext_descriptor . clone ( ) . ok_or_else ( || {
611- Error :: Generic (
612- "External descriptor required for wallet registration" . to_string ( ) ,
613- )
614- } ) ?;
615- let wallet_name = wallet_opts. wallet . clone ( ) . ok_or_else ( || {
616- Error :: Generic ( "Wallet name is required for wallet registration" . to_string ( ) )
617- } ) ?;
618-
619- let device = crate :: utils:: connect_to_hardware_wallet (
620- wallet. network ( ) ,
621- wallet_opts,
622- Some ( wallet) ,
623- )
624- . await ?;
625- let hmac = if let Some ( device) = device {
626- let hmac = device. register_wallet ( & wallet_name, & policy) . await ?;
627- hmac. map ( |h| h. to_lower_hex_string ( ) )
628- } else {
629- None
630- } ;
631- //TODO: return status of wallet registration
632- Ok ( json ! ( { "hmac" : hmac } ) )
633- }
634- HwiSubCommand :: Address => {
635- let address = wallet. next_unused_address ( KeychainKind :: External ) ;
636- Ok ( json ! ( { "address" : address. address } ) )
637- }
638- } ,
639589 }
640590}
641591
@@ -1119,6 +1069,138 @@ pub(crate) fn handle_compile_subcommand(
11191069 }
11201070}
11211071
1072+ /// Handle hardware wallet operations
1073+ #[ cfg( feature = "hwi" ) ]
1074+ pub async fn handle_hwi_subcommand (
1075+ network : Network ,
1076+ wallet_opts : & WalletOpts ,
1077+ subcommand : HwiSubCommand ,
1078+ ) -> Result < serde_json:: Value , Error > {
1079+ match subcommand {
1080+ HwiSubCommand :: Devices => {
1081+ let devices = crate :: utils:: connect_to_hardware_wallet (
1082+ wallet. network ( ) ,
1083+ wallet_opts,
1084+ Some ( wallet) ,
1085+ )
1086+ . await ?;
1087+ let device = if let Some ( device) = device {
1088+ json ! ( {
1089+ "type" : device. device_kind( ) . to_string( ) ,
1090+ "fingerprint" : device. get_master_fingerprint( ) . await ?. to_string( ) ,
1091+ "model" : device. device_kind( ) . to_string( ) ,
1092+ } )
1093+ } else {
1094+ json ! ( null)
1095+ } ;
1096+ Ok ( json ! ( { "devices" : device } ) )
1097+ }
1098+ HwiSubCommand :: Register => {
1099+ let policy = wallet_opts. ext_descriptor . clone ( ) . ok_or_else ( || {
1100+ Error :: Generic ( "External descriptor required for wallet registration" . to_string ( ) )
1101+ } ) ?;
1102+ let wallet_name = wallet_opts. wallet . clone ( ) . ok_or_else ( || {
1103+ Error :: Generic ( "Wallet name is required for wallet registration" . to_string ( ) )
1104+ } ) ?;
1105+
1106+ let home_dir = prepare_home_dir ( None ) ?;
1107+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1108+ #[ cfg( feature = "sqlite" ) ]
1109+ let wallet = {
1110+ let mut persister = match & wallet_opts. database_type {
1111+ DatabaseType :: Sqlite => {
1112+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1113+ let connection = Connection :: open ( db_file) ?;
1114+ log:: debug!( "Sqlite database opened successfully" ) ;
1115+ connection
1116+ }
1117+ } ;
1118+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1119+ wallet. persist ( & mut persister) ?;
1120+ wallet
1121+ } ;
1122+ #[ cfg( not( feature = "sqlite" ) ) ]
1123+ let wallet = new_wallet ( network, wallet_opts) ?;
1124+
1125+ let device = crate :: utils:: connect_to_hardware_wallet (
1126+ wallet. network ( ) ,
1127+ wallet_opts,
1128+ Some ( wallet) ,
1129+ )
1130+ . await ?;
1131+ let hmac = if let Some ( device) = device {
1132+ let hmac = device. register_wallet ( & wallet_name, & policy) . await ?;
1133+ hmac. map ( |h| h. to_lower_hex_string ( ) )
1134+ } else {
1135+ None
1136+ } ;
1137+ Ok ( json ! ( { "hmac" : hmac } ) )
1138+ }
1139+ HwiSubCommand :: Address => {
1140+ let home_dir = prepare_home_dir ( None ) ?;
1141+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1142+ #[ cfg( feature = "sqlite" ) ]
1143+ let wallet = {
1144+ let mut persister = match & wallet_opts. database_type {
1145+ DatabaseType :: Sqlite => {
1146+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1147+ let connection = Connection :: open ( db_file) ?;
1148+ log:: debug!( "Sqlite database opened successfully" ) ;
1149+ connection
1150+ }
1151+ } ;
1152+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1153+ wallet. persist ( & mut persister) ?;
1154+ wallet
1155+ } ;
1156+ #[ cfg( not( feature = "sqlite" ) ) ]
1157+ let wallet = new_wallet ( network, wallet_opts) ?;
1158+
1159+ let address = wallet. next_unused_address ( KeychainKind :: External ) ;
1160+ Ok ( json ! ( { "address" : address. address } ) )
1161+ }
1162+ HwiSubCommand :: Sign { psbt } => {
1163+ let home_dir = prepare_home_dir ( None ) ?;
1164+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1165+ #[ cfg( feature = "sqlite" ) ]
1166+ let wallet = {
1167+ let mut persister = match & wallet_opts. database_type {
1168+ DatabaseType :: Sqlite => {
1169+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1170+ let connection = Connection :: open ( db_file) ?;
1171+ log:: debug!( "Sqlite database opened successfully" ) ;
1172+ connection
1173+ }
1174+ } ;
1175+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1176+ wallet. persist ( & mut persister) ?;
1177+ wallet
1178+ } ;
1179+ #[ cfg( not( feature = "sqlite" ) ) ]
1180+ let wallet = new_wallet ( network, wallet_opts) ?;
1181+
1182+ let mut psbt = Psbt :: from_str ( & psbt)
1183+ . map_err ( |e| Error :: Generic ( format ! ( "Failed to parse PSBT: {e}" ) ) ) ?;
1184+ let device = crate :: utils:: connect_to_hardware_wallet (
1185+ wallet. network ( ) ,
1186+ wallet_opts,
1187+ Some ( wallet) ,
1188+ )
1189+ . await ?;
1190+ let signed_psbt = if let Some ( device) = device {
1191+ device
1192+ . sign_tx ( & mut psbt)
1193+ . await
1194+ . map_err ( |e| Error :: Generic ( format ! ( "Failed to sign PSBT: {e}" ) ) ) ?;
1195+ Some ( psbt. to_string ( ) )
1196+ } else {
1197+ None
1198+ } ;
1199+ Ok ( json ! ( { "psbt" : signed_psbt } ) )
1200+ }
1201+ }
1202+ }
1203+
11221204/// The global top level handler.
11231205pub ( crate ) async fn handle_command ( cli_opts : CliOpts ) -> Result < String , Error > {
11241206 let network = cli_opts. network ;
@@ -1222,8 +1304,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
12221304
12231305 let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
12241306 let result =
1225- handle_offline_wallet_subcommand ( & mut wallet, wallet_opts, & cli_opts, offline_subcommand. clone ( ) )
1226- . await ?;
1307+ handle_offline_wallet_subcommand ( & mut wallet, wallet_opts, & cli_opts, offline_subcommand. clone ( ) ) ;
12271308 wallet. persist ( & mut persister) ?;
12281309 result
12291310 } ;
@@ -1237,7 +1318,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
12371318 offline_subcommand. clone ( ) ,
12381319 ) ?
12391320 } ;
1240- Ok ( result)
1321+ Ok ( result? )
12411322 }
12421323 CliSubCommand :: Key {
12431324 subcommand : key_subcommand,
@@ -1366,7 +1447,6 @@ async fn respond(
13661447 subcommand : WalletSubCommand :: OfflineWalletSubCommand ( offline_subcommand) ,
13671448 } => {
13681449 let value = handle_offline_wallet_subcommand ( wallet, wallet_opts, cli_opts, offline_subcommand)
1369- . await
13701450 . map_err ( |e| e. to_string ( ) ) ?;
13711451 Some ( value)
13721452 }
0 commit comments