@@ -11,8 +11,7 @@ use bdk::{
11
11
DerivableKey , ExtendedKey , GeneratableKey , GeneratedKey ,
12
12
} ,
13
13
miniscript:: Tap ,
14
- template:: Bip84 ,
15
- KeychainKind , LocalOutput ,
14
+ KeychainKind ,
16
15
} ;
17
16
use jsonrpsee:: { core:: async_trait, proc_macros:: rpc, server:: Server , types:: ErrorObjectOwned } ;
18
17
use log:: info;
@@ -35,16 +34,18 @@ use tokio::{
35
34
task:: JoinSet ,
36
35
} ;
37
36
use wallet:: {
38
- bdk_wallet as bdk, bitcoin:: hashes:: Hash , derivation :: SpaceDerivation , DoubleUtxo ,
39
- SpacesWallet , WalletConfig , WalletExport , WalletInfo ,
37
+ bdk_wallet as bdk, bdk_wallet :: template :: Bip86 , bitcoin:: hashes:: Hash , export :: WalletExport ,
38
+ DoubleUtxo , SpacesWallet , WalletConfig , WalletDescriptors , WalletInfo ,
40
39
} ;
41
40
42
41
use crate :: {
43
42
config:: ExtendedNetwork ,
44
43
node:: BlockMeta ,
45
44
source:: BitcoinRpc ,
46
45
store:: { ChainState , LiveSnapshot } ,
47
- wallets:: { AddressKind , JointBalance , RpcWallet , TxResponse , WalletCommand , WalletResponse } ,
46
+ wallets:: {
47
+ AddressKind , Balance , RpcWallet , TxResponse , WalletCommand , WalletOutput , WalletResponse ,
48
+ } ,
48
49
} ;
49
50
50
51
pub ( crate ) type Responder < T > = oneshot:: Sender < T > ;
@@ -129,13 +130,13 @@ pub trait Rpc {
129
130
async fn wallet_load ( & self , name : & str ) -> Result < ( ) , ErrorObjectOwned > ;
130
131
131
132
#[ method( name = "walletimport" ) ]
132
- async fn wallet_import ( & self , content : & str ) -> Result < ( ) , ErrorObjectOwned > ;
133
+ async fn wallet_import ( & self , wallet : WalletExport ) -> Result < ( ) , ErrorObjectOwned > ;
133
134
134
135
#[ method( name = "walletgetinfo" ) ]
135
136
async fn wallet_get_info ( & self , name : & str ) -> Result < WalletInfo , ErrorObjectOwned > ;
136
137
137
138
#[ method( name = "walletexport" ) ]
138
- async fn wallet_export ( & self , name : & str ) -> Result < String , ErrorObjectOwned > ;
139
+ async fn wallet_export ( & self , name : & str ) -> Result < WalletExport , ErrorObjectOwned > ;
139
140
140
141
#[ method( name = "walletcreate" ) ]
141
142
async fn wallet_create ( & self , name : & str ) -> Result < ( ) , ErrorObjectOwned > ;
@@ -164,11 +165,13 @@ pub trait Rpc {
164
165
165
166
#[ method( name = "walletlistspaces" ) ]
166
167
async fn wallet_list_spaces ( & self , wallet : & str )
167
- -> Result < Vec < FullSpaceOut > , ErrorObjectOwned > ;
168
+ -> Result < Vec < WalletOutput > , ErrorObjectOwned > ;
168
169
169
170
#[ method( name = "walletlistunspent" ) ]
170
- async fn wallet_list_unspent ( & self , wallet : & str )
171
- -> Result < Vec < LocalOutput > , ErrorObjectOwned > ;
171
+ async fn wallet_list_unspent (
172
+ & self ,
173
+ wallet : & str ,
174
+ ) -> Result < Vec < WalletOutput > , ErrorObjectOwned > ;
172
175
173
176
#[ method( name = "walletlistauctionoutputs" ) ]
174
177
async fn wallet_list_auction_outputs (
@@ -177,7 +180,7 @@ pub trait Rpc {
177
180
) -> Result < Vec < DoubleUtxo > , ErrorObjectOwned > ;
178
181
179
182
#[ method( name = "walletgetbalance" ) ]
180
- async fn wallet_get_balance ( & self , wallet : & str ) -> Result < JointBalance , ErrorObjectOwned > ;
183
+ async fn wallet_get_balance ( & self , wallet : & str ) -> Result < Balance , ErrorObjectOwned > ;
181
184
}
182
185
183
186
#[ derive( Clone , Serialize , Deserialize ) ]
@@ -283,10 +286,8 @@ impl WalletManager {
283
286
pub async fn import_wallet (
284
287
& self ,
285
288
client : & reqwest:: Client ,
286
- content : & str ,
289
+ wallet : WalletExport ,
287
290
) -> anyhow:: Result < ( ) > {
288
- let wallet = WalletExport :: from_str ( content) ?;
289
-
290
291
let wallet_path = self . data_dir . join ( & wallet. label ) ;
291
292
if wallet_path. exists ( ) {
292
293
return Err ( anyhow ! ( format!(
@@ -304,12 +305,14 @@ impl WalletManager {
304
305
Ok ( ( ) )
305
306
}
306
307
307
- pub async fn export_wallet ( & self , name : & str ) -> anyhow:: Result < String > {
308
+ pub async fn export_wallet ( & self , name : & str ) -> anyhow:: Result < WalletExport > {
308
309
let wallet_dir = self . data_dir . join ( name) ;
309
310
if !wallet_dir. exists ( ) {
310
311
return Err ( anyhow ! ( "Wallet does not exist" ) ) ;
311
312
}
312
- Ok ( fs:: read_to_string ( wallet_dir. join ( "wallet.json" ) ) ?)
313
+ let wallet = fs:: read_to_string ( wallet_dir. join ( "wallet.json" ) ) ?;
314
+ let export: WalletExport = serde_json:: from_str ( & wallet) ?;
315
+ Ok ( export)
313
316
}
314
317
315
318
pub async fn create_wallet ( & self , client : & reqwest:: Client , name : & str ) -> anyhow:: Result < ( ) > {
@@ -351,16 +354,10 @@ impl WalletManager {
351
354
let ( network, _) = self . fallback_network ( ) ;
352
355
let xpriv = Self :: descriptor_from_mnemonic ( network, & mnemonic. to_string ( ) ) ?;
353
356
354
- let coins_descriptors = Self :: default_coin_descriptors ( xpriv) ;
355
- let space_descriptors = Self :: default_spaces_descriptors ( xpriv) ;
356
-
357
- let export = WalletExport :: from_descriptors (
358
- name,
359
- start_block. height ,
360
- network,
361
- coins_descriptors. 0 ,
362
- space_descriptors. 0 ,
363
- ) ?;
357
+ let ( external, internal) = Self :: default_descriptors ( xpriv) ;
358
+ let tmp = bdk:: wallet:: Wallet :: new_or_load ( external, internal, None , network) ?;
359
+ let export =
360
+ WalletExport :: export_wallet ( & tmp, & name, start_block. height ) . map_err ( |e| anyhow ! ( e) ) ?;
364
361
365
362
Ok ( export)
366
363
}
@@ -403,54 +400,10 @@ impl WalletManager {
403
400
( network, genesis_hash)
404
401
}
405
402
406
- // TODO: remove in the next update
407
- pub async fn migrate_legacy_v0_0_1_wallet (
408
- & self ,
409
- name : String ,
410
- wallet_dir : PathBuf ,
411
- ) -> anyhow:: Result < bool > {
412
- let legacy_secret = wallet_dir
413
- . join ( "insecure_secret" )
414
- . to_str ( )
415
- . unwrap ( )
416
- . replace ( "/testnet/wallets/" , "/test/wallets/" ) ;
417
- let legacy_secret = std:: path:: PathBuf :: from ( legacy_secret) ;
418
-
419
- if !legacy_secret. exists ( ) {
420
- return Ok ( false ) ;
421
- }
422
-
423
- let mnemonic = fs:: read_to_string ( legacy_secret) ?. trim ( ) . to_string ( ) ;
424
- let start_block = match self . network {
425
- ExtendedNetwork :: Testnet => ChainAnchor :: TESTNET ( ) ,
426
- ExtendedNetwork :: Testnet4 => ChainAnchor :: TESTNET4 ( ) ,
427
- ExtendedNetwork :: Regtest => ChainAnchor :: REGTEST ( ) ,
428
- _ => panic ! ( "could not migrate legacy wallet: unsupported network" ) ,
429
- } ;
430
-
431
- self . setup_new_wallet (
432
- name,
433
- mnemonic,
434
- BlockId {
435
- height : start_block. height ,
436
- hash : start_block. hash ,
437
- } ,
438
- ) ?;
439
-
440
- Ok ( true )
441
- }
442
-
443
403
pub async fn load_wallet ( & self , client : & reqwest:: Client , name : & str ) -> anyhow:: Result < ( ) > {
444
404
let wallet_dir = self . data_dir . join ( name) ;
445
405
if !wallet_dir. exists ( ) {
446
- if self
447
- . migrate_legacy_v0_0_1_wallet ( name. to_string ( ) , wallet_dir. clone ( ) )
448
- . await ?
449
- {
450
- info ! ( "Migrated legacy wallet {}" , name) ;
451
- } else {
452
- return Err ( anyhow ! ( "Wallet does not exist" ) ) ;
453
- }
406
+ return Err ( anyhow ! ( "Wallet does not exist" ) ) ;
454
407
}
455
408
456
409
let file = fs:: File :: open ( wallet_dir. join ( "wallet.json" ) ) ?;
@@ -459,20 +412,23 @@ impl WalletManager {
459
412
let export: WalletExport = serde_json:: from_reader ( file) ?;
460
413
461
414
let mut wallet = SpacesWallet :: new ( WalletConfig {
462
- start_block : export. block_height ,
415
+ start_block : export. blockheight ,
463
416
data_dir : wallet_dir,
464
417
name : name. to_string ( ) ,
465
418
network,
466
419
genesis_hash,
467
- coins_descriptors : export. descriptors ( ) ,
468
- space_descriptors : export. space_descriptors ( ) ,
420
+ space_descriptors : WalletDescriptors {
421
+ external : export. descriptor ( ) ,
422
+ internal : export
423
+ . change_descriptor ( )
424
+ . expect ( "expected a change descriptor" ) ,
425
+ } ,
469
426
} ) ?;
470
427
471
- let wallet_tip = wallet. coins . local_chain ( ) . tip ( ) . height ( ) ;
428
+ let wallet_tip = wallet. spaces . local_chain ( ) . tip ( ) . height ( ) ;
472
429
473
- if wallet_tip < export. block_height {
474
- let block_id = self . get_block_hash ( client, export. block_height ) . await ?;
475
- wallet. coins . insert_checkpoint ( block_id) ?;
430
+ if wallet_tip < export. blockheight {
431
+ let block_id = self . get_block_hash ( client, export. blockheight ) . await ?;
476
432
wallet. spaces . insert_checkpoint ( block_id) ?;
477
433
wallet. commit ( ) ?;
478
434
}
@@ -520,17 +476,10 @@ impl WalletManager {
520
476
Ok ( xkey. into_xprv ( network) . expect ( "xpriv" ) )
521
477
}
522
478
523
- fn default_coin_descriptors ( x : Xpriv ) -> ( Bip84 < Xpriv > , Bip84 < Xpriv > ) {
524
- (
525
- Bip84 ( x, KeychainKind :: External ) ,
526
- Bip84 ( x, KeychainKind :: Internal ) ,
527
- )
528
- }
529
-
530
- fn default_spaces_descriptors ( x : Xpriv ) -> ( SpaceDerivation < Xpriv > , SpaceDerivation < Xpriv > ) {
479
+ fn default_descriptors ( x : Xpriv ) -> ( Bip86 < Xpriv > , Bip86 < Xpriv > ) {
531
480
(
532
- SpaceDerivation ( x, KeychainKind :: External ) ,
533
- SpaceDerivation ( x, KeychainKind :: Internal ) ,
481
+ Bip86 ( x, KeychainKind :: External ) ,
482
+ Bip86 ( x, KeychainKind :: Internal ) ,
534
483
)
535
484
}
536
485
}
@@ -693,7 +642,7 @@ impl RpcServer for RpcServerImpl {
693
642
} )
694
643
}
695
644
696
- async fn wallet_import ( & self , content : & str ) -> Result < ( ) , ErrorObjectOwned > {
645
+ async fn wallet_import ( & self , content : WalletExport ) -> Result < ( ) , ErrorObjectOwned > {
697
646
self . wallet_manager
698
647
. import_wallet ( & self . client , content)
699
648
. await
@@ -710,7 +659,7 @@ impl RpcServer for RpcServerImpl {
710
659
. map_err ( |error| ErrorObjectOwned :: owned ( -1 , error. to_string ( ) , None :: < String > ) )
711
660
}
712
661
713
- async fn wallet_export ( & self , name : & str ) -> Result < String , ErrorObjectOwned > {
662
+ async fn wallet_export ( & self , name : & str ) -> Result < WalletExport , ErrorObjectOwned > {
714
663
self . wallet_manager
715
664
. export_wallet ( name)
716
665
. await
@@ -769,7 +718,7 @@ impl RpcServer for RpcServerImpl {
769
718
async fn wallet_list_spaces (
770
719
& self ,
771
720
wallet : & str ,
772
- ) -> Result < Vec < FullSpaceOut > , ErrorObjectOwned > {
721
+ ) -> Result < Vec < WalletOutput > , ErrorObjectOwned > {
773
722
self . wallet ( & wallet)
774
723
. await ?
775
724
. send_list_spaces ( )
@@ -780,7 +729,7 @@ impl RpcServer for RpcServerImpl {
780
729
async fn wallet_list_unspent (
781
730
& self ,
782
731
wallet : & str ,
783
- ) -> Result < Vec < LocalOutput > , ErrorObjectOwned > {
732
+ ) -> Result < Vec < WalletOutput > , ErrorObjectOwned > {
784
733
self . wallet ( & wallet)
785
734
. await ?
786
735
. send_list_unspent ( )
@@ -799,7 +748,7 @@ impl RpcServer for RpcServerImpl {
799
748
. map_err ( |error| ErrorObjectOwned :: owned ( -1 , error. to_string ( ) , None :: < String > ) )
800
749
}
801
750
802
- async fn wallet_get_balance ( & self , wallet : & str ) -> Result < JointBalance , ErrorObjectOwned > {
751
+ async fn wallet_get_balance ( & self , wallet : & str ) -> Result < Balance , ErrorObjectOwned > {
803
752
self . wallet ( & wallet)
804
753
. await ?
805
754
. send_get_balance ( )
@@ -825,11 +774,10 @@ impl AsyncChainState {
825
774
. await
826
775
. map_err ( |e| anyhow ! ( "Could not retrieve tx ({})" , e) ) ?;
827
776
828
- let block_hash = BlockHash :: from_str (
829
- info. get ( "blockhash" )
830
- . and_then ( |t| t. as_str ( ) )
831
- . ok_or_else ( || anyhow ! ( "Could not retrieve block hash for tx (is it in the mempool?)" ) ) ?,
832
- ) ?;
777
+ let block_hash =
778
+ BlockHash :: from_str ( info. get ( "blockhash" ) . and_then ( |t| t. as_str ( ) ) . ok_or_else (
779
+ || anyhow ! ( "Could not retrieve block hash for tx (is it in the mempool?)" ) ,
780
+ ) ?) ?;
833
781
let block = Self :: get_indexed_block ( index, & block_hash, client, rpc, chain_state) . await ?;
834
782
835
783
if let Some ( block) = block {
0 commit comments