@@ -23,8 +23,6 @@ use bdk_redb::Store as RedbStore;
2323use bdk_wallet:: bip39:: { Language , Mnemonic } ;
2424use bdk_wallet:: bitcoin:: base64:: Engine ;
2525use bdk_wallet:: bitcoin:: base64:: prelude:: BASE64_STANDARD ;
26- #[ cfg( feature = "hwi" ) ]
27- use bdk_wallet:: bitcoin:: hex:: DisplayHex ;
2826use bdk_wallet:: bitcoin:: {
2927 Address , Amount , FeeRate , Network , Psbt , Sequence , Txid ,
3028 bip32:: { DerivationPath , KeySource } ,
@@ -1203,135 +1201,68 @@ pub async fn handle_hwi_subcommand(
12031201 hwi_opts : & HwiOpts ,
12041202 subcommand : HwiSubCommand ,
12051203) -> Result < serde_json:: Value , Error > {
1204+ use async_hwi:: AddressScript ;
1205+ use bdk_wallet:: bitcoin:: hex:: DisplayHex ;
1206+
12061207 match subcommand {
12071208 HwiSubCommand :: Devices => {
1208- let devices = crate :: utils:: connect_to_hardware_wallet ( network, hwi_opts) . await ?;
1209- let device = if let Some ( device) = devices {
1209+ let device_opt = crate :: utils:: connect_hwi_device ( network, hwi_opts) . await ?;
1210+ let device = if let Some ( device) = device_opt . as_ref ( ) {
12101211 json ! ( {
1211- "fingerprint" : device. get_master_fingerprint( ) . await ?. to_string( ) ,
1212+ "fingerprint" : device. get_master_fingerprint( ) . await . map_err ( Error :: HwiError ) ?. to_string( ) ,
12121213 "model" : device. device_kind( ) . to_string( ) ,
12131214 } )
12141215 } else {
12151216 json ! ( null)
12161217 } ;
1217- Ok ( json ! ( { "devices " : device } ) )
1218+ Ok ( json ! ( { "device " : device } ) )
12181219 }
12191220 HwiSubCommand :: Register => {
1220- let policy = hwi_opts. ext_descriptor . clone ( ) . ok_or_else ( || {
1221- Error :: Generic ( "External descriptor required for wallet registration" . to_string ( ) )
1222- } ) ?;
1223- let wallet_name = hwi_opts. wallet . clone ( ) . ok_or_else ( || {
1224- Error :: Generic ( "Wallet name is required for wallet registration" . to_string ( ) )
1225- } ) ?;
1226-
1227- let device = crate :: utils:: connect_to_hardware_wallet ( network, hwi_opts) . await ?;
1228-
1229- match device {
1230- None => Ok ( json ! ( {
1231- "success" : false ,
1232- "error" : "No hardware wallet detected"
1233- } ) ) ,
1234- Some ( device) => match device. register_wallet ( & wallet_name, & policy) . await {
1235- Ok ( hmac_opt) => {
1236- let hmac_hex = hmac_opt. map ( |h| {
1237- let bytes: & [ u8 ] = & h;
1238- bytes. to_lower_hex_string ( )
1239- } ) ;
1240- Ok ( json ! ( {
1241- "success" : true ,
1242- "hmac" : hmac_hex
1243- } ) )
1244- }
1245- Err ( e) => Err ( Error :: Generic ( format ! ( "Wallet registration failed: {e}" ) ) ) ,
1246- } ,
1247- }
1221+ let policy = hwi_opts
1222+ . ext_descriptor
1223+ . clone ( )
1224+ . ok_or_else ( || Error :: Generic ( "External descriptor required" . to_string ( ) ) ) ?;
1225+ let wallet_name = hwi_opts
1226+ . wallet
1227+ . clone ( )
1228+ . ok_or_else ( || Error :: Generic ( "Wallet name required" . to_string ( ) ) ) ?;
1229+ let device_opt = crate :: utils:: connect_hwi_device ( network, hwi_opts) . await ?;
1230+ let device = device_opt
1231+ . ok_or_else ( || Error :: Generic ( "No hardware wallet detected" . to_string ( ) ) ) ?;
1232+ tracing:: debug!(
1233+ "Registering wallet '{}' with policy '{}'" ,
1234+ wallet_name,
1235+ policy
1236+ ) ;
1237+ let hmac_opt = device
1238+ . register_wallet ( & wallet_name, & policy)
1239+ . await
1240+ . map_err ( Error :: HwiError ) ?;
1241+ let hmac_hex = hmac_opt. map ( |h| h. to_lower_hex_string ( ) ) ;
1242+ Ok ( json ! ( { "success" : true , "hmac" : hmac_hex } ) )
12481243 }
12491244 HwiSubCommand :: Address => {
1250- let ext_descriptor = hwi_opts. ext_descriptor . clone ( ) . ok_or_else ( || {
1251- Error :: Generic ( "External descriptor required for address generation" . to_string ( ) )
1252- } ) ?;
1253- let wallet_name = hwi_opts. wallet . clone ( ) . ok_or_else ( || {
1254- Error :: Generic ( "Wallet name is required for address generation" . to_string ( ) )
1255- } ) ?;
1256-
1257- let database = hwi_opts. database_type . clone ( ) . ok_or_else ( || {
1258- Error :: Generic ( "Database type is required for address generation" . to_string ( ) )
1259- } ) ?;
1260-
1261- let home_dir = prepare_home_dir ( None ) ?;
1262- let database_path = prepare_wallet_db_dir ( & home_dir, wallet_name. as_str ( ) ) ?;
1263-
1264- let wallet_opts = WalletOpts {
1265- wallet : Some ( wallet_name) ,
1266- verbose : false ,
1267- ext_descriptor : ext_descriptor,
1268- int_descriptor : None ,
1269- #[ cfg( any(
1270- feature = "electrum" ,
1271- feature = "esplora" ,
1272- feature = "rpc" ,
1273- feature = "cbf"
1274- ) ) ]
1275- client_type : {
1276- if cfg ! ( feature = "electrum" ) {
1277- ClientType :: Electrum
1278- } else if cfg ! ( feature = "esplora" ) {
1279- ClientType :: Esplora
1280- } else if cfg ! ( feature = "rpc" ) {
1281- ClientType :: Rpc
1282- } else {
1283- ClientType :: Cbf
1284- }
1285- } ,
1286- #[ cfg( any( feature = "sqlite" , feature = "redb" ) ) ]
1287- database_type : database,
1288- #[ cfg( any( feature = "electrum" , feature = "esplora" , feature = "rpc" ) ) ]
1289- url : String :: new ( ) ,
1290- #[ cfg( feature = "electrum" ) ]
1291- batch_size : 10 ,
1292- #[ cfg( feature = "esplora" ) ]
1293- parallel_requests : 5 ,
1294- #[ cfg( feature = "rpc" ) ]
1295- basic_auth : ( String :: new ( ) , String :: new ( ) ) ,
1296- #[ cfg( feature = "rpc" ) ]
1297- cookie : None ,
1298- #[ cfg( feature = "cbf" ) ]
1299- compactfilter_opts : CompactFilterOpts { conn_count : 2 } ,
1245+ let device_opt = crate :: utils:: connect_hwi_device ( network, hwi_opts) . await ?;
1246+ let device = device_opt
1247+ . ok_or_else ( || Error :: Generic ( "No hardware wallet detected" . to_string ( ) ) ) ?;
1248+ let address_script = AddressScript :: Miniscript {
1249+ index : 0 ,
1250+ change : false ,
13001251 } ;
1301-
1302- #[ cfg( feature = "sqlite" ) ]
1303- let mut wallet = if hwi_opts. database_type . is_some ( ) {
1304- let db_file = database_path. join ( "wallet.sqlite" ) ;
1305- let mut persister = Connection :: open ( db_file) ?;
1306- let mut wallet = new_persisted_wallet ( network, & mut persister, & wallet_opts) ?;
1307- wallet. persist ( & mut persister) ?;
1308- wallet
1309- } else {
1310- return Err ( Error :: Generic (
1311- "Could not connect to sqlite database" . to_string ( ) ,
1312- ) ) ;
1313- } ;
1314-
1315- #[ cfg( not( feature = "sqlite" ) ) ]
1316- let mut wallet = new_wallet ( network, & wallet_opts) ?;
1317-
1318- let address = wallet. next_unused_address ( KeychainKind :: External ) ;
1319- Ok ( json ! ( { "address" : address. address } ) )
1252+ device
1253+ . display_address ( & address_script)
1254+ . await
1255+ . map_err ( Error :: HwiError ) ?;
1256+ Ok ( json ! ( { "success" : true , "message" : "Address displayed and verified on device" } ) )
13201257 }
13211258 HwiSubCommand :: Sign { psbt } => {
13221259 let mut psbt = Psbt :: from_str ( & psbt)
13231260 . map_err ( |e| Error :: Generic ( format ! ( "Failed to parse PSBT: {e}" ) ) ) ?;
1324- let device = crate :: utils:: connect_to_hardware_wallet ( network, hwi_opts) . await ?;
1325- let signed_psbt = if let Some ( device) = device {
1326- device
1327- . sign_tx ( & mut psbt)
1328- . await
1329- . map_err ( |e| Error :: Generic ( format ! ( "Failed to sign PSBT: {e}" ) ) ) ?;
1330- Some ( psbt. to_string ( ) )
1331- } else {
1332- None
1333- } ;
1334- Ok ( json ! ( { "psbt" : signed_psbt } ) )
1261+ let device_opt = crate :: utils:: connect_hwi_device ( network, hwi_opts) . await ?;
1262+ let device = device_opt
1263+ . ok_or_else ( || Error :: Generic ( "No hardware wallet detected" . to_string ( ) ) ) ?;
1264+ device. sign_tx ( & mut psbt) . await . map_err ( Error :: HwiError ) ?;
1265+ Ok ( json ! ( { "psbt" : psbt. to_string( ) } ) )
13351266 }
13361267 }
13371268}
@@ -1570,7 +1501,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
15701501 subcommand,
15711502 } => {
15721503 let result = handle_hwi_subcommand ( network, & hwi_opts, subcommand) . await ?;
1573- Ok ( serde_json:: to_string_pretty ( & result) . map_err ( |e| Error :: SerdeJson ( e ) ) ?)
1504+ Ok ( serde_json:: to_string_pretty ( & result) . map_err ( Error :: SerdeJson ) ?)
15741505 }
15751506 } ;
15761507 result
0 commit comments