@@ -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
@@ -1100,6 +1050,138 @@ pub(crate) fn handle_compile_subcommand(
11001050 }
11011051}
11021052
1053+ /// Handle hardware wallet operations
1054+ #[ cfg( feature = "hwi" ) ]
1055+ pub async fn handle_hwi_subcommand (
1056+ network : Network ,
1057+ wallet_opts : & WalletOpts ,
1058+ subcommand : HwiSubCommand ,
1059+ ) -> Result < serde_json:: Value , Error > {
1060+ match subcommand {
1061+ HwiSubCommand :: Devices => {
1062+ let devices = crate :: utils:: connect_to_hardware_wallet (
1063+ wallet. network ( ) ,
1064+ wallet_opts,
1065+ Some ( wallet) ,
1066+ )
1067+ . await ?;
1068+ let device = if let Some ( device) = device {
1069+ json ! ( {
1070+ "type" : device. device_kind( ) . to_string( ) ,
1071+ "fingerprint" : device. get_master_fingerprint( ) . await ?. to_string( ) ,
1072+ "model" : device. device_kind( ) . to_string( ) ,
1073+ } )
1074+ } else {
1075+ json ! ( null)
1076+ } ;
1077+ Ok ( json ! ( { "devices" : device } ) )
1078+ }
1079+ HwiSubCommand :: Register => {
1080+ let policy = wallet_opts. ext_descriptor . clone ( ) . ok_or_else ( || {
1081+ Error :: Generic ( "External descriptor required for wallet registration" . to_string ( ) )
1082+ } ) ?;
1083+ let wallet_name = wallet_opts. wallet . clone ( ) . ok_or_else ( || {
1084+ Error :: Generic ( "Wallet name is required for wallet registration" . to_string ( ) )
1085+ } ) ?;
1086+
1087+ let home_dir = prepare_home_dir ( None ) ?;
1088+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1089+ #[ cfg( feature = "sqlite" ) ]
1090+ let wallet = {
1091+ let mut persister = match & wallet_opts. database_type {
1092+ DatabaseType :: Sqlite => {
1093+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1094+ let connection = Connection :: open ( db_file) ?;
1095+ log:: debug!( "Sqlite database opened successfully" ) ;
1096+ connection
1097+ }
1098+ } ;
1099+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1100+ wallet. persist ( & mut persister) ?;
1101+ wallet
1102+ } ;
1103+ #[ cfg( not( feature = "sqlite" ) ) ]
1104+ let wallet = new_wallet ( network, wallet_opts) ?;
1105+
1106+ let device = crate :: utils:: connect_to_hardware_wallet (
1107+ wallet. network ( ) ,
1108+ wallet_opts,
1109+ Some ( wallet) ,
1110+ )
1111+ . await ?;
1112+ let hmac = if let Some ( device) = device {
1113+ let hmac = device. register_wallet ( & wallet_name, & policy) . await ?;
1114+ hmac. map ( |h| h. to_lower_hex_string ( ) )
1115+ } else {
1116+ None
1117+ } ;
1118+ Ok ( json ! ( { "hmac" : hmac } ) )
1119+ }
1120+ HwiSubCommand :: Address => {
1121+ let home_dir = prepare_home_dir ( None ) ?;
1122+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1123+ #[ cfg( feature = "sqlite" ) ]
1124+ let wallet = {
1125+ let mut persister = match & wallet_opts. database_type {
1126+ DatabaseType :: Sqlite => {
1127+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1128+ let connection = Connection :: open ( db_file) ?;
1129+ log:: debug!( "Sqlite database opened successfully" ) ;
1130+ connection
1131+ }
1132+ } ;
1133+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1134+ wallet. persist ( & mut persister) ?;
1135+ wallet
1136+ } ;
1137+ #[ cfg( not( feature = "sqlite" ) ) ]
1138+ let wallet = new_wallet ( network, wallet_opts) ?;
1139+
1140+ let address = wallet. next_unused_address ( KeychainKind :: External ) ;
1141+ Ok ( json ! ( { "address" : address. address } ) )
1142+ }
1143+ HwiSubCommand :: Sign { psbt } => {
1144+ let home_dir = prepare_home_dir ( None ) ?;
1145+ let database_path = prepare_wallet_db_dir ( & wallet_opts. wallet , & home_dir) ?;
1146+ #[ cfg( feature = "sqlite" ) ]
1147+ let wallet = {
1148+ let mut persister = match & wallet_opts. database_type {
1149+ DatabaseType :: Sqlite => {
1150+ let db_file = database_path. join ( "wallet.sqlite" ) ;
1151+ let connection = Connection :: open ( db_file) ?;
1152+ log:: debug!( "Sqlite database opened successfully" ) ;
1153+ connection
1154+ }
1155+ } ;
1156+ let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
1157+ wallet. persist ( & mut persister) ?;
1158+ wallet
1159+ } ;
1160+ #[ cfg( not( feature = "sqlite" ) ) ]
1161+ let wallet = new_wallet ( network, wallet_opts) ?;
1162+
1163+ let mut psbt = Psbt :: from_str ( & psbt)
1164+ . map_err ( |e| Error :: Generic ( format ! ( "Failed to parse PSBT: {e}" ) ) ) ?;
1165+ let device = crate :: utils:: connect_to_hardware_wallet (
1166+ wallet. network ( ) ,
1167+ wallet_opts,
1168+ Some ( wallet) ,
1169+ )
1170+ . await ?;
1171+ let signed_psbt = if let Some ( device) = device {
1172+ device
1173+ . sign_tx ( & mut psbt)
1174+ . await
1175+ . map_err ( |e| Error :: Generic ( format ! ( "Failed to sign PSBT: {e}" ) ) ) ?;
1176+ Some ( psbt. to_string ( ) )
1177+ } else {
1178+ None
1179+ } ;
1180+ Ok ( json ! ( { "psbt" : signed_psbt } ) )
1181+ }
1182+ }
1183+ }
1184+
11031185/// The global top level handler.
11041186pub ( crate ) async fn handle_command ( cli_opts : CliOpts ) -> Result < String , Error > {
11051187 let network = cli_opts. network ;
@@ -1203,8 +1285,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
12031285
12041286 let mut wallet = new_persisted_wallet ( network, & mut persister, wallet_opts) ?;
12051287 let result =
1206- handle_offline_wallet_subcommand ( & mut wallet, wallet_opts, & cli_opts, offline_subcommand. clone ( ) )
1207- . await ?;
1288+ handle_offline_wallet_subcommand ( & mut wallet, wallet_opts, & cli_opts, offline_subcommand. clone ( ) ) ;
12081289 wallet. persist ( & mut persister) ?;
12091290 result
12101291 } ;
@@ -1218,7 +1299,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
12181299 offline_subcommand. clone ( ) ,
12191300 ) ?
12201301 } ;
1221- Ok ( result)
1302+ Ok ( result? )
12221303 }
12231304 CliSubCommand :: Key {
12241305 subcommand : key_subcommand,
@@ -1347,7 +1428,6 @@ async fn respond(
13471428 subcommand : WalletSubCommand :: OfflineWalletSubCommand ( offline_subcommand) ,
13481429 } => {
13491430 let value = handle_offline_wallet_subcommand ( wallet, wallet_opts, cli_opts, offline_subcommand)
1350- . await
13511431 . map_err ( |e| e. to_string ( ) ) ?;
13521432 Some ( value)
13531433 }
0 commit comments