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
35 changes: 35 additions & 0 deletions integration_test/tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,41 @@ fn wallet__list_received_by_address__modelled() {
assert!(model.0.iter().any(|item| &item.address == unchecked_addr));
}

#[test]
fn wallet__list_since_block__modelled() {
let node = Node::with_wallet(Wallet::Default, &[]);
node.fund_wallet();
let addr = node.client.new_address().expect("newaddress");
let amount = Amount::from_sat(5_000);
node.client.send_to_address(&addr, amount).expect("sendtoaddress");
node.mine_a_block();

let json: ListSinceBlock = node.client.list_since_block().expect("listsinceblock");
let model: Result<mtype::ListSinceBlock, ListSinceBlockError> = json.into_model();
let model = model.unwrap();

let first_tx: mtype::TransactionItem = model.transactions[0].clone();
assert_eq!(first_tx.txid.unwrap().to_string().len(), 64);
}

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

node.fund_wallet();
let addr = node.client.new_address().expect("newaddress");
let amount = Amount::from_sat(5_000);
node.client.send_to_address(&addr, amount).expect("sendtoaddress");
node.mine_a_block();

let json: ListTransactions = node.client.list_transactions().expect("listtransactions");
let model: Result<mtype::ListTransactions, TransactionItemError> = json.into_model();
let model = model.unwrap();

let first_tx: mtype::TransactionItem = model.0[0].clone();
assert_eq!(first_tx.txid.unwrap().to_string().len(), 64);
}

#[test]
fn wallet__import_multi() {
let node = match () {
Expand Down
10 changes: 5 additions & 5 deletions types/src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ pub use self::{
GetTransactionDetail, GetUnconfirmedBalance, GetWalletInfo, GetWalletInfoScanning, HdKey,
HdKeyDescriptor, LastProcessedBlock, ListAddressGroupings, ListAddressGroupingsItem,
ListLockUnspent, ListLockUnspentItem, ListReceivedByAddress, ListReceivedByAddressItem,
ListReceivedByLabel, ListReceivedByLabelItem, ListSinceBlock, ListSinceBlockTransaction,
ListTransactions, ListTransactionsItem, ListUnspent, ListUnspentItem, ListWallets,
LoadWallet, PsbtBumpFee, RescanBlockchain, ScriptType, Send, SendAll, SendMany,
SendManyVerbose, SendToAddress, SignMessage, SimulateRawTransaction, TransactionCategory,
UnloadWallet, WalletCreateFundedPsbt, WalletDisplayAddress, WalletProcessPsbt,
ListReceivedByLabel, ListReceivedByLabelItem, ListSinceBlock, ListTransactions,
ListUnspent, ListUnspentItem, ListWallets, LoadWallet, PsbtBumpFee, RescanBlockchain,
ScriptType, Send, SendAll, SendMany, SendManyVerbose, SendToAddress, SignMessage,
SimulateRawTransaction, TransactionCategory, TransactionItem, UnloadWallet,
WalletCreateFundedPsbt, WalletDisplayAddress, WalletProcessPsbt,
},
};
97 changes: 33 additions & 64 deletions types/src/model/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,12 +590,12 @@ pub struct ListReceivedByLabelItem {
#[serde(deny_unknown_fields)]
pub struct ListSinceBlock {
/// All the transactions.
pub transactions: Vec<ListSinceBlockTransaction>,
pub transactions: Vec<TransactionItem>,
/// Only present if `include_removed=true`.
///
/// Note: transactions that were re-added in the active chain will appear as-is in this array,
/// and may thus have a positive confirmation count.
pub removed: Vec<ListSinceBlockTransaction>,
pub removed: Vec<TransactionItem>,
/// The hash of the block (target_confirmations-1) from the best block on the main chain.
///
/// This is typically used to feed back into listsinceblock the next time you call it. So you
Expand All @@ -604,11 +604,12 @@ pub struct ListSinceBlock {
pub last_block: BlockHash,
}

/// Transaction list item, part of `ListSinceBlock`.
// https://github.com/rust-bitcoin/rust-bitcoin/issues/3516
/// Transaction item, part of `listsinceblock` and `listtransactions`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListSinceBlockTransaction {
pub struct TransactionItem {
/// Only returns true if imported addresses were involved in transaction.
pub involves_watch_only: Option<bool>,
/// The bitcoin address of the transaction.
pub address: Option<Address<NetworkUnchecked>>,
/// The transaction category.
Expand All @@ -631,96 +632,64 @@ pub struct ListSinceBlockTransaction {
/// Available for 'send' and 'receive' category of transactions. When it's < 0, it means the
/// transaction conflicted that many blocks ago.
pub confirmations: i64,
/// Only present if the transaction's only input is a coinbase one. Only documented from v0.20 and later.
pub generated: Option<bool>,
/// Whether we consider the transaction to be trusted and safe to spend from. Only present
/// when the transaction has 0 confirmations (or negative confirmations, if conflicted). v0.20 and later only.
pub trusted: Option<bool>,
/// The block hash containing the transaction.
///
/// Available for 'send' and 'receive' category of transactions.
pub block_hash: BlockHash,
pub block_hash: Option<BlockHash>,
/// The block height containing the transaction. v20 and later only.
pub block_height: Option<u32>,
/// The index of the transaction in the block that includes it.
///
/// Available for 'send' and 'receive' category of transactions.
pub block_index: u32,
pub block_index: Option<u32>,
/// The block time in seconds since epoch (1 Jan 1970 GMT).
pub block_time: u32,
pub block_time: Option<u32>,
/// The transaction id.
///
/// Available for 'send' and 'receive' category of transactions.
pub txid: Option<Txid>,
/// The hash of serialized transaction, including witness data. v24 and later only.
pub wtxid: Option<Txid>,
/// Conflicting transaction ids. Only documented from v0.20 and later.
pub wallet_conflicts: Option<Vec<Txid>>,
/// The txid if this tx was replaced. v23 and later only.
pub replaced_by_txid: Option<Txid>,
/// The txid if this tx replaces one. v23 and later only.
pub replaces_txid: Option<Txid>,
/// Transactions in the mempool that directly conflict with either this transaction or an ancestor transaction. v28 and later only.
pub mempool_conflicts: Option<Vec<Txid>>,
/// If a comment to is associated with the transaction.
pub to: Option<String>,
/// The transaction time in seconds since epoch (Jan 1 1970 GMT).
pub time: u32,
/// The time received in seconds since epoch (Jan 1 1970 GMT).
///
/// Available for 'send' and 'receive' category of transactions.
pub time_received: u32,
/// If a comment is associated with the transaction.
pub comment: Option<String>,
/// Whether this transaction could be replaced due to BIP125 (replace-by-fee);
/// may be unknown for unconfirmed transactions not in the mempool
pub bip125_replaceable: Bip125Replaceable,
/// Only if 'category' is 'received'. List of parent descriptors for the scriptPubKey of this coin. v24 and later only.
pub parent_descriptors: Option<Vec<String>>,
/// If the transaction has been abandoned (inputs are respendable).
///
/// Only available for the 'send' category of transactions.
pub abandoned: Option<bool>,
/// If a comment is associated with the transaction.
pub comment: Option<String>,
/// A comment for the address/transaction, if any.
pub label: Option<String>,
/// If a comment to is associated with the transaction.
pub to: Option<String>,
}

/// Models the result of JSON-RPC method `listtransactions`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListTransactions(pub Vec<ListTransactionsItem>);

/// Transaction list item, part of `ListTransactions`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListTransactionsItem {
/// The bitcoin address of the transaction.
pub address: Address<NetworkUnchecked>,
/// The transaction category.
pub category: TransactionCategory,
/// The amount.
///
/// This is negative for the 'send' category, and is positive for the 'receive' category.
#[serde(default, with = "bitcoin::amount::serde::as_btc")]
pub amount: SignedAmount,
/// A comment for the address/transaction, if any.
pub label: Option<String>,
/// The vout value.
pub vout: u32,
/// The amount of the fee in BTC.
///
/// This is negative and only available for the 'send' category of transactions.
#[serde(default, with = "bitcoin::amount::serde::as_btc")]
pub fee: SignedAmount,
/// The number of confirmations for the transaction.
///
/// Negative confirmations indicate the transaction conflicts with the block chain.
pub confirmations: i64,
/// Whether we consider the outputs of this unconfirmed transaction safe to spend.
pub trusted: bool,
/// The block hash containing the transaction.
pub block_hash: BlockHash,
/// The index of the transaction in the block that includes it.
pub block_index: u32,
/// The block time in seconds since epoch (1 Jan 1970 GMT).
pub block_time: u32,
/// The transaction id.
pub txid: Txid,
/// The transaction time in seconds since epoch (Jan 1 1970 GMT).
pub time: u32,
/// The time received in seconds since epoch (Jan 1 1970 GMT).
pub time_received: u32,
/// If a comment is associated with the transaction.
pub comment: Option<String>,
/// Whether this transaction could be replaced due to BIP125 (replace-by-fee);
/// may be unknown for unconfirmed transactions not in the mempool
pub bip125_replaceable: Bip125Replaceable,
/// If the transaction has been abandoned (inputs are respendable).
///
/// Only available for the 'send' category of transactions.
pub abandoned: Option<bool>,
}
pub struct ListTransactions(pub Vec<TransactionItem>);

/// Models the result of JSON-RPC method `listunspent`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
Expand Down
11 changes: 5 additions & 6 deletions types/src/v17/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@
//! | listlockunspent | version + model | |
//! | listreceivedbyaccount | returns nothing | |
//! | listreceivedbyaddress | version + model | |
//! | listsinceblock | version + model | UNTESTED |
//! | listtransactions | version + model | UNTESTED |
//! | listsinceblock | version + model | |
//! | listtransactions | version + model | |
//! | listunspent | version + model | |
//! | listwallets | version + model | |
//! | loadwallet | version + model | |
Expand Down Expand Up @@ -281,10 +281,9 @@ pub use self::{
ListAddressGroupingsError, ListAddressGroupingsItem, ListLabels, ListLockUnspent,
ListLockUnspentItem, ListLockUnspentItemError, ListReceivedByAddress,
ListReceivedByAddressError, ListReceivedByAddressItem, ListSinceBlock, ListSinceBlockError,
ListSinceBlockTransaction, ListSinceBlockTransactionError, ListTransactions,
ListTransactionsItem, ListTransactionsItemError, ListUnspent, ListUnspentItem,
ListUnspentItemError, ListWallets, LoadWallet, LockUnspent, RescanBlockchain, ScriptType,
SendMany, SendToAddress, SetTxFee, SignMessage, TransactionCategory,
ListTransactions, ListUnspent, ListUnspentItem, ListUnspentItemError, ListWallets,
LoadWallet, LockUnspent, RescanBlockchain, ScriptType, SendMany, SendToAddress, SetTxFee,
SignMessage, TransactionCategory, TransactionItem, TransactionItemError,
WalletCreateFundedPsbt, WalletCreateFundedPsbtError, WalletProcessPsbt,
},
zmq::GetZmqNotifications,
Expand Down
70 changes: 9 additions & 61 deletions types/src/v17/wallet/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,9 @@ impl std::error::Error for ListReceivedByAddressError {
#[derive(Debug)]
pub enum ListSinceBlockError {
/// Conversion of item in `transactions` list failed.
Transactions(ListSinceBlockTransactionError),
Transactions(TransactionItemError),
/// Conversion of item in `removed` list failed.
Removed(ListSinceBlockTransactionError),
Removed(TransactionItemError),
/// Conversion of the `last_block` field failed.
LastBlock(hex::HexToArrayError),
}
Expand Down Expand Up @@ -529,9 +529,9 @@ impl std::error::Error for ListSinceBlockError {
}
}

/// Error when converting a `ListSinceBlockTransaction` type into the model type.
/// Error when converting a `TransactionItem` type into the model type.
#[derive(Debug)]
pub enum ListSinceBlockTransactionError {
pub enum TransactionItemError {
/// Conversion of numeric type to expected type failed.
Numeric(NumericError),
/// Conversion of the `address` field failed.
Expand All @@ -546,9 +546,9 @@ pub enum ListSinceBlockTransactionError {
Txid(hex::HexToArrayError),
}

impl fmt::Display for ListSinceBlockTransactionError {
impl fmt::Display for TransactionItemError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ListSinceBlockTransactionError as E;
use TransactionItemError as E;

match *self {
E::Numeric(ref e) => write_err!(f, "numeric"; e),
Expand All @@ -562,9 +562,9 @@ impl fmt::Display for ListSinceBlockTransactionError {
}

#[cfg(feature = "std")]
impl std::error::Error for ListSinceBlockTransactionError {
impl std::error::Error for TransactionItemError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use ListSinceBlockTransactionError as E;
use TransactionItemError as E;

match *self {
E::Numeric(ref e) => Some(e),
Expand All @@ -577,59 +577,7 @@ impl std::error::Error for ListSinceBlockTransactionError {
}
}

impl From<NumericError> for ListSinceBlockTransactionError {
fn from(e: NumericError) -> Self { Self::Numeric(e) }
}

/// Error when converting a `ListTransactionsItem` type into the model type.
#[derive(Debug)]
pub enum ListTransactionsItemError {
/// Conversion of numeric type to expected type failed.
Numeric(NumericError),
/// Conversion of the `address` field failed.
Address(address::ParseError),
/// Conversion of the `amount` field failed.
Amount(ParseAmountError),
/// Conversion of the `fee` field failed.
Fee(ParseAmountError),
/// Conversion of the `block_hash` field failed.
BlockHash(hex::HexToArrayError),
/// Conversion of the `txid` field failed.
Txid(hex::HexToArrayError),
}

impl fmt::Display for ListTransactionsItemError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ListTransactionsItemError as E;

match *self {
E::Numeric(ref e) => write_err!(f, "numeric"; e),
E::Address(ref e) => write_err!(f, "conversion of the `address` field failed"; e),
E::Amount(ref e) => write_err!(f, "conversion of the `amount` field failed"; e),
E::Fee(ref e) => write_err!(f, "conversion of the `fee` field failed"; e),
E::BlockHash(ref e) => write_err!(f, "conversion of the `block_hash` field failed"; e),
E::Txid(ref e) => write_err!(f, "conversion of the `txid` field failed"; e),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for ListTransactionsItemError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use ListTransactionsItemError as E;

match *self {
E::Numeric(ref e) => Some(e),
E::Address(ref e) => Some(e),
E::Amount(ref e) => Some(e),
E::Fee(ref e) => Some(e),
E::BlockHash(ref e) => Some(e),
E::Txid(ref e) => Some(e),
}
}
}

impl From<NumericError> for ListTransactionsItemError {
impl From<NumericError> for TransactionItemError {
fn from(e: NumericError) -> Self { Self::Numeric(e) }
}

Expand Down
Loading