Skip to content

Commit 453fc48

Browse files
committed
Test and update getwalletinfo
`getwalletinfo` was implemented for v17 only and untested. There are return changes in v18, v19, v21, v23 and v26. Add the updated structs in all versions, update the model and add new `into_model()`. Add a test with version specific sections to test the new sub-structs. Update the types tables and reexports.
1 parent 5e09bbd commit 453fc48

File tree

29 files changed

+871
-170
lines changed

29 files changed

+871
-170
lines changed

integration_test/tests/wallet.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,31 @@ fn wallet__get_unconfirmed_balance__modelled() {
390390
model.unwrap();
391391
}
392392

393+
#[test]
394+
fn wallet__get_wallet_info__modelled() {
395+
let node = Node::with_wallet(Wallet::Default, &[]);
396+
node.mine_a_block();
397+
398+
let json: GetWalletInfo = node.client.get_wallet_info().expect("getwalletinfo");
399+
let model: Result<mtype::GetWalletInfo, GetWalletInfoError> = json.into_model();
400+
let wallet_info = model.unwrap();
401+
402+
assert!(!wallet_info.wallet_name.is_empty());
403+
404+
#[cfg(not(feature = "v18_and_below"))]
405+
{
406+
assert!(wallet_info.avoid_reuse.is_some());
407+
assert!(wallet_info.scanning.is_some());
408+
}
409+
410+
#[cfg(not(feature = "v25_and_below"))]
411+
{
412+
let last_processed = wallet_info.last_processed_block.as_ref().expect("last_processed_block");
413+
let best_hash = node.client.best_block_hash().expect("best_block_hash");
414+
assert_eq!(last_processed.hash, best_hash);
415+
}
416+
}
417+
393418
#[test]
394419
fn wallet__import_address() {
395420
let node = match () {

types/src/model/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ pub use self::{
5555
CreateWallet, DumpPrivKey, GetAddressInfo, GetAddressInfoEmbedded, GetAddressesByLabel,
5656
GetBalance, GetBalances, GetBalancesMine, GetBalancesWatchOnly, GetHdKeys, GetNewAddress,
5757
GetRawChangeAddress, GetReceivedByAddress, GetReceivedByLabel, GetTransaction,
58-
GetTransactionDetail, GetUnconfirmedBalance, GetWalletInfo, HdKey, HdKeyDescriptor,
59-
LastProcessedBlock, ListAddressGroupings, ListAddressGroupingsItem, ListLockUnspent,
60-
ListLockUnspentItem, ListReceivedByAddress, ListReceivedByAddressItem, ListReceivedByLabel,
61-
ListReceivedByLabelItem, ListSinceBlock, ListSinceBlockTransaction, ListTransactions,
62-
ListTransactionsItem, ListUnspent, ListUnspentItem, ListWallets, LoadWallet, PsbtBumpFee,
63-
RescanBlockchain, ScriptType, Send, SendAll, SendMany, SendManyVerbose, SendToAddress,
64-
SignMessage, SimulateRawTransaction, TransactionCategory, UnloadWallet,
65-
WalletCreateFundedPsbt, WalletDisplayAddress, WalletProcessPsbt,
58+
GetTransactionDetail, GetUnconfirmedBalance, GetWalletInfo, GetWalletInfoScanning, HdKey,
59+
HdKeyDescriptor, LastProcessedBlock, ListAddressGroupings, ListAddressGroupingsItem,
60+
ListLockUnspent, ListLockUnspentItem, ListReceivedByAddress, ListReceivedByAddressItem,
61+
ListReceivedByLabel, ListReceivedByLabelItem, ListSinceBlock, ListSinceBlockTransaction,
62+
ListTransactions, ListTransactionsItem, ListUnspent, ListUnspentItem, ListWallets,
63+
LoadWallet, PsbtBumpFee, RescanBlockchain, ScriptType, Send, SendAll, SendMany,
64+
SendManyVerbose, SendToAddress, SignMessage, SimulateRawTransaction, TransactionCategory,
65+
UnloadWallet, WalletCreateFundedPsbt, WalletDisplayAddress, WalletProcessPsbt,
6666
},
6767
};

types/src/model/wallet.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ pub struct GetWalletInfo {
455455
pub wallet_name: String,
456456
/// The wallet version.
457457
pub wallet_version: u32,
458+
/// Database format. v21 and later only.
459+
pub format: Option<String>,
458460
/// The total confirmed balance of the wallet in BTC.
459461
pub balance: Amount,
460462
/// The total unconfirmed balance of the wallet in BTC.
@@ -472,13 +474,40 @@ pub struct GetWalletInfo {
472474
pub keypool_size_hd_internal: u32,
473475
/// The timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked
474476
/// for transfers, or 0 if the wallet is locked.
475-
pub unlocked_until: u32,
477+
pub unlocked_until: Option<u32>,
476478
/// The transaction fee configuration.
477479
pub pay_tx_fee: Option<FeeRate>,
478480
/// The Hash160 of the HD seed (only present when HD is enabled).
479481
pub hd_seed_id: Option<hash160::Hash>,
480482
/// If privatekeys are disabled for this wallet (enforced watch-only wallet).
481483
pub private_keys_enabled: bool,
484+
/// Whether this wallet tracks clean/dirty coins in terms of reuse. v19 and later only.
485+
pub avoid_reuse: Option<bool>,
486+
/// Current scanning details, or false if no scan is in progress. v19 and later only.
487+
pub scanning: Option<GetWalletInfoScanning>,
488+
/// Whether wallet uses descriptors. v21 and later only.
489+
pub descriptors: Option<bool>,
490+
/// Whether this wallet is configured to use an external signer such as a hardware wallet. v23 and later only.
491+
pub external_signer: Option<bool>,
492+
/// Whether this wallet intentionally does not contain any keys, scripts, or descriptors. v26 and later only.
493+
pub blank: Option<bool>,
494+
/// The start time for blocks scanning. v26 and later only.
495+
pub birthtime: Option<u32>,
496+
/// Hash and height of the block this information was generated on. v26 and later only.
497+
pub last_processed_block: Option<LastProcessedBlock>,
498+
}
499+
500+
/// Models the `scanning` field of `getwalletinfo` (v19+). When not scanning Core returns `false`.
501+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
502+
#[serde(untagged)]
503+
pub enum GetWalletInfoScanning {
504+
Details {
505+
/// Elapsed seconds since scan start.
506+
duration: u64,
507+
/// Scanning progress percentage [0.0, 1.0].
508+
progress: f64,
509+
},
510+
NotScanning(bool),
482511
}
483512

484513
/// Models the result of JSON-RPC method `listaddressgroupings`.

types/src/v17/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@
171171
//! | getreceivedbyaddress | version + model | |
172172
//! | gettransaction | version + model | |
173173
//! | getunconfirmedbalance | version + model | |
174-
//! | getwalletinfo | version + model | UNTESTED |
174+
//! | getwalletinfo | version + model | |
175175
//! | importaddress | returns nothing | |
176176
//! | importmulti | version | |
177177
//! | importprivkey | returns nothing | |

types/src/v17/wallet/into.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ impl GetWalletInfo {
437437
Ok(model::GetWalletInfo {
438438
wallet_name: self.wallet_name,
439439
wallet_version,
440+
format: None,
440441
balance,
441442
unconfirmed_balance,
442443
immature_balance,
@@ -448,6 +449,13 @@ impl GetWalletInfo {
448449
pay_tx_fee,
449450
hd_seed_id,
450451
private_keys_enabled: self.private_keys_enabled,
452+
avoid_reuse: None,
453+
scanning: None,
454+
descriptors: None,
455+
external_signer: None,
456+
blank: None,
457+
birthtime: None,
458+
last_processed_block: None,
451459
})
452460
}
453461
}

types/src/v17/wallet/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ pub struct GetWalletInfo {
549549
pub keypool_size_hd_internal: i64,
550550
/// The timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked
551551
/// for transfers, or 0 if the wallet is locked.
552-
pub unlocked_until: u32,
552+
pub unlocked_until: Option<u32>,
553553
/// The transaction fee configuration, set in BTC/kB.
554554
#[serde(rename = "paytxfee")]
555555
pub pay_tx_fee: f64,

types/src/v18/mod.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
//! | getreceivedbylabel | version + model | |
176176
//! | gettransaction | version + model | |
177177
//! | getunconfirmedbalance | version + model | |
178-
//! | getwalletinfo | version + model | UNTESTED |
178+
//! | getwalletinfo | version + model | |
179179
//! | importaddress | returns nothing | |
180180
//! | importmulti | version | |
181181
//! | importprivkey | returns nothing | |
@@ -246,7 +246,7 @@ pub use self::{
246246
util::{DeriveAddresses, GetDescriptorInfo},
247247
wallet::{
248248
GetAddressInfo, GetAddressInfoEmbedded, GetAddressInfoError, GetReceivedByLabel,
249-
ImportMulti, ImportMultiEntry, JsonRpcError, ListReceivedByAddress,
249+
GetWalletInfo, ImportMulti, ImportMultiEntry, JsonRpcError, ListReceivedByAddress,
250250
ListReceivedByAddressItem, ListReceivedByLabel, ListReceivedByLabelError, ListUnspent,
251251
ListUnspentItem, ListWalletDir, ListWalletDirWallet,
252252
},
@@ -272,19 +272,18 @@ pub use crate::v17::{
272272
GetRawMempoolVerbose, GetRawTransaction, GetRawTransactionVerbose,
273273
GetRawTransactionVerboseError, GetReceivedByAddress, GetTransaction, GetTransactionDetail,
274274
GetTransactionDetailError, GetTransactionError, GetTxOut, GetTxOutError, GetTxOutSetInfo,
275-
GetTxOutSetInfoError, GetUnconfirmedBalance, GetWalletInfo, GetWalletInfoError,
276-
ListAddressGroupings, ListAddressGroupingsError, ListAddressGroupingsItem, ListBanned,
277-
ListLabels, ListLockUnspent, ListLockUnspentItem, ListLockUnspentItemError,
278-
ListReceivedByAddressError, ListSinceBlock, ListSinceBlockError, ListSinceBlockTransaction,
279-
ListSinceBlockTransactionError, ListTransactions, ListTransactionsItem,
280-
ListTransactionsItemError, ListUnspentItemError, ListWallets, LoadWallet, LockUnspent, Locked,
281-
Logging, MapMempoolEntryError, MempoolAcceptance, MempoolEntryError, MempoolEntryFees,
282-
MempoolEntryFeesError, PruneBlockchain, PsbtInput, PsbtOutput, PsbtScript, RawTransaction,
283-
RawTransactionError, RawTransactionInput, RawTransactionOutput, RescanBlockchain, ScriptType,
284-
SendMany, SendRawTransaction, SendToAddress, SetNetworkActive, SetTxFee, SignFail,
285-
SignFailError, SignMessage, SignMessageWithPrivKey, SignRawTransaction,
286-
SignRawTransactionError, Softfork, SoftforkReject, TestMempoolAccept, TransactionCategory,
287-
UploadTarget, ValidateAddress, ValidateAddressError, VerifyChain, VerifyMessage,
288-
VerifyTxOutProof, WalletCreateFundedPsbt, WalletCreateFundedPsbtError, WalletProcessPsbt,
289-
WitnessUtxo,
275+
GetTxOutSetInfoError, GetUnconfirmedBalance, GetWalletInfoError, ListAddressGroupings,
276+
ListAddressGroupingsError, ListAddressGroupingsItem, ListBanned, ListLabels, ListLockUnspent,
277+
ListLockUnspentItem, ListLockUnspentItemError, ListReceivedByAddressError, ListSinceBlock,
278+
ListSinceBlockError, ListSinceBlockTransaction, ListSinceBlockTransactionError,
279+
ListTransactions, ListTransactionsItem, ListTransactionsItemError, ListUnspentItemError,
280+
ListWallets, LoadWallet, LockUnspent, Locked, Logging, MapMempoolEntryError, MempoolAcceptance,
281+
MempoolEntryError, MempoolEntryFees, MempoolEntryFeesError, PruneBlockchain, PsbtInput,
282+
PsbtOutput, PsbtScript, RawTransaction, RawTransactionError, RawTransactionInput,
283+
RawTransactionOutput, RescanBlockchain, ScriptType, SendMany, SendRawTransaction,
284+
SendToAddress, SetNetworkActive, SetTxFee, SignFail, SignFailError, SignMessage,
285+
SignMessageWithPrivKey, SignRawTransaction, SignRawTransactionError, Softfork, SoftforkReject,
286+
TestMempoolAccept, TransactionCategory, UploadTarget, ValidateAddress, ValidateAddressError,
287+
VerifyChain, VerifyMessage, VerifyTxOutProof, WalletCreateFundedPsbt,
288+
WalletCreateFundedPsbtError, WalletProcessPsbt, WitnessUtxo,
290289
};

types/src/v18/wallet/into.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ use bitcoin::{
1010

1111
use super::{
1212
GetAddressInfo, GetAddressInfoEmbedded, GetAddressInfoEmbeddedError, GetAddressInfoError,
13-
GetReceivedByLabel, ListReceivedByAddress, ListReceivedByAddressError,
14-
ListReceivedByAddressItem, ListReceivedByLabel, ListReceivedByLabelError,
15-
ListReceivedByLabelItem, ListUnspent, ListUnspentItem, ListUnspentItemError,
13+
GetReceivedByLabel, GetWalletInfo, GetWalletInfoError, ListReceivedByAddress,
14+
ListReceivedByAddressError, ListReceivedByAddressItem, ListReceivedByLabel,
15+
ListReceivedByLabelError, ListReceivedByLabelItem, ListUnspent, ListUnspentItem,
16+
ListUnspentItemError,
1617
};
1718
use crate::model;
1819

@@ -166,6 +167,52 @@ impl GetReceivedByLabel {
166167
}
167168
}
168169

170+
impl GetWalletInfo {
171+
/// Converts version specific type to a version nonspecific, more strongly typed type.
172+
pub fn into_model(self) -> Result<model::GetWalletInfo, GetWalletInfoError> {
173+
use GetWalletInfoError as E;
174+
175+
let wallet_version = crate::to_u32(self.wallet_version, "wallet_version")?;
176+
let balance = Amount::from_btc(self.balance).map_err(E::Balance)?;
177+
let unconfirmed_balance =
178+
Amount::from_btc(self.unconfirmed_balance).map_err(E::UnconfirmedBalance)?;
179+
let immature_balance =
180+
Amount::from_btc(self.immature_balance).map_err(E::ImmatureBalance)?;
181+
let tx_count = crate::to_u32(self.tx_count, "tx_count")?;
182+
let keypool_oldest = crate::to_u32(self.keypool_oldest, "keypoo_oldest")?;
183+
let keypool_size = crate::to_u32(self.keypool_size, "keypoo_size")?;
184+
let keypool_size_hd_internal =
185+
crate::to_u32(self.keypool_size_hd_internal, "keypoo_size_hd_internal")?;
186+
let pay_tx_fee = crate::btc_per_kb(self.pay_tx_fee).map_err(E::PayTxFee)?;
187+
let hd_seed_id =
188+
self.hd_seed_id.map(|s| s.parse::<hash160::Hash>()).transpose().map_err(E::HdSeedId)?;
189+
190+
Ok(model::GetWalletInfo {
191+
wallet_name: self.wallet_name,
192+
wallet_version,
193+
format: None,
194+
balance,
195+
unconfirmed_balance,
196+
immature_balance,
197+
tx_count,
198+
keypool_oldest,
199+
keypool_size,
200+
keypool_size_hd_internal,
201+
unlocked_until: self.unlocked_until,
202+
pay_tx_fee,
203+
hd_seed_id,
204+
private_keys_enabled: self.private_keys_enabled,
205+
avoid_reuse: None,
206+
scanning: None,
207+
descriptors: None,
208+
external_signer: None,
209+
blank: None,
210+
birthtime: None,
211+
last_processed_block: None,
212+
})
213+
}
214+
}
215+
169216
impl ListReceivedByAddress {
170217
/// Converts version specific type to a version nonspecific, more strongly typed type.
171218
pub fn into_model(self) -> Result<model::ListReceivedByAddress, ListReceivedByAddressError> {

types/src/v18/wallet/mod.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use serde::{Deserialize, Serialize};
1111

1212
pub use self::error::{GetAddressInfoError, ListReceivedByLabelError};
1313
pub use super::{
14-
GetAddressInfoEmbeddedError, GetAddressInfoLabel, ListReceivedByAddressError,
15-
ListUnspentItemError, ScriptType,
14+
GetAddressInfoEmbeddedError, GetAddressInfoLabel, GetWalletInfoError,
15+
ListReceivedByAddressError, ListUnspentItemError, ScriptType,
1616
};
1717

1818
/// Result of the JSON-RPC method `getaddressinfo`.
@@ -152,6 +152,51 @@ pub struct GetAddressInfoEmbedded {
152152
#[serde(deny_unknown_fields)]
153153
pub struct GetReceivedByLabel(pub f64);
154154

155+
/// Result of the JSON-RPC method `getwalletinfo`.
156+
///
157+
/// > getwalletinfo
158+
/// > Returns an object containing various wallet state info.
159+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
160+
#[serde(deny_unknown_fields)]
161+
pub struct GetWalletInfo {
162+
/// The wallet name.
163+
#[serde(rename = "walletname")]
164+
pub wallet_name: String,
165+
/// The wallet version.
166+
#[serde(rename = "walletversion")]
167+
pub wallet_version: i64,
168+
/// The total confirmed balance of the wallet in BTC.
169+
pub balance: f64,
170+
/// The total unconfirmed balance of the wallet in BTC.
171+
pub unconfirmed_balance: f64,
172+
/// The total immature balance of the wallet in BTC.
173+
pub immature_balance: f64,
174+
/// The total number of transactions in the wallet
175+
#[serde(rename = "txcount")]
176+
pub tx_count: i64,
177+
/// The timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool.
178+
#[serde(rename = "keypoololdest")]
179+
pub keypool_oldest: i64,
180+
/// How many new keys are pre-generated (only counts external keys).
181+
#[serde(rename = "keypoolsize")]
182+
pub keypool_size: i64,
183+
/// How many new keys are pre-generated for internal use (used for change outputs, only appears
184+
/// if the wallet is using this feature, otherwise external keys are used).
185+
#[serde(rename = "keypoolsize_hd_internal")]
186+
pub keypool_size_hd_internal: i64,
187+
/// The timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked
188+
/// for transfers, or 0 if the wallet is locked.
189+
pub unlocked_until: Option<u32>,
190+
/// The transaction fee configuration, set in BTC/kB.
191+
#[serde(rename = "paytxfee")]
192+
pub pay_tx_fee: f64,
193+
/// The Hash160 of the HD seed (only present when HD is enabled).
194+
#[serde(rename = "hdseedid")]
195+
pub hd_seed_id: Option<String>,
196+
/// If privatekeys are disabled for this wallet (enforced watch-only wallet).
197+
pub private_keys_enabled: bool,
198+
}
199+
155200
/// Result of JSON-RPC method `importmulti`.
156201
///
157202
/// > importmulti requests ( options )

0 commit comments

Comments
 (0)