Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions integration_test/tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,24 @@ fn wallet__keypool_refill() {
let _: () = node.client.key_pool_refill().expect("keypoolrefill");
}

#[test]
fn wallet__list_address_groupings__modelled() {
let node = Node::with_wallet(Wallet::Default, &[]);
node.fund_wallet();

let address = node.client.new_address().expect("failed to create new address");
let amount = Amount::from_sat(10_000);
node.client.send_to_address(&address, amount).expect("sendtoaddress").txid().unwrap();
node.mine_a_block();

let json: ListAddressGroupings =
node.client.list_address_groupings().expect("listaddressgroupings");
let model: Result<mtype::ListAddressGroupings, _> = json.into_model();
let groupings = model.unwrap();

assert!(!groupings.0.is_empty());
}

#[cfg(not(feature = "v17"))]
#[test]
fn wallet__list_received_by_label__modelled() {
Expand Down
26 changes: 20 additions & 6 deletions types/src/v17/wallet/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,19 +450,33 @@ impl GetWalletInfo {
impl ListAddressGroupings {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::ListAddressGroupings, ListAddressGroupingsError> {
todo!() // Don't do this till we work out what the docs mean.
let groups = self
.0
.into_iter()
.map(|group| {
group.into_iter().map(|item| item.into_model()).collect::<Result<Vec<_>, _>>()
})
.collect::<Result<Vec<_>, _>>()?;
Ok(model::ListAddressGroupings(groups))
}
}

impl ListAddressGroupingsItem {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::ListAddressGroupingsItem, ListAddressGroupingsError> {
use ListAddressGroupingsError as E;

let address = self.address.parse::<Address<_>>().map_err(E::Address)?;
let amount = Amount::from_btc(self.amount).map_err(E::Amount)?;

Ok(model::ListAddressGroupingsItem { address, amount, label: self.label })
match self {
ListAddressGroupingsItem::Two(addr, amt) => {
let address = addr.parse::<Address<_>>().map_err(E::Address)?;
let amount = Amount::from_btc(amt).map_err(E::Amount)?;
Ok(model::ListAddressGroupingsItem { address, amount, label: None })
}
ListAddressGroupingsItem::Three(addr, amt, label) => {
let address = addr.parse::<Address<_>>().map_err(E::Address)?;
let amount = Amount::from_btc(amt).map_err(E::Amount)?;
Ok(model::ListAddressGroupingsItem { address, amount, label: Some(label) })
}
}
}
}

Expand Down
19 changes: 10 additions & 9 deletions types/src/v17/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,16 +612,17 @@ pub struct JsonRpcError {
pub struct ListAddressGroupings(pub Vec<Vec<ListAddressGroupingsItem>>);

/// List item type returned as part of `listaddressgroupings`.
// FIXME: The Core docs seem wrong, not sure what shape this should be?
///
/// Core encodes items as a JSON array with either 2 elements `[address, amount]` when there is no
/// label or 3 elements `[address, amount, label]` when a label is present. Represent this as an
/// untagged enum of tuple variants so Serde can match either length without custom code.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListAddressGroupingsItem {
/// The bitcoin address.
pub address: String,
/// The amount in BTC.
pub amount: f64,
/// The label.
pub label: Option<String>,
#[serde(untagged)]
pub enum ListAddressGroupingsItem {
/// Entry without label.
Two(String, f64),
/// Entry with label.
Three(String, f64, String),
}

/// Result of the JSON-RPC method `listlabels`.
Expand Down