// SPDX-License-Identifier: CC0-1.0

//! Types for methods found under the `== Wallet ==` section of the API docs.
//!
//! These structs model the types returned by the JSON-RPC API but have concrete types
//! and are not specific to a specific version of Bitcoin Core.

use alloc::collections::BTreeMap;

use bitcoin::address::NetworkUnchecked;
use bitcoin::bip32::{Xpriv, Xpub};
use bitcoin::hashes::hash160;
use bitcoin::{
    bip32, sign_message, Address, Amount, BlockHash, FeeRate, PrivateKey, Psbt, PublicKey,
    ScriptBuf, SignedAmount, Transaction, Txid, WitnessProgram, WitnessVersion,
};
use serde::{Deserialize, Serialize};

use super::SignRawTransaction;

/// The purpose of an address. Part of `getaddressesbylabel`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum AddressPurpose {
    /// A send-to address.
    Send,
    /// A receive-from address.
    Receive,
}

/// The category of a transaction. Part of `gettransaction`, `listsinceblock` and `listtransactions`.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
pub enum TransactionCategory {
    /// Transactions sent.
    Send,
    /// Non-coinbase transactions received.
    Receive,
    /// Coinbase transactions received with more than 100 confirmations.
    Generate,
    /// Coinbase transactions received with 100 or fewer confirmations.
    Immature,
    /// Orphaned coinbase transactions received.
    Orphan,
}

/// Whether this transaction can be RBF'ed. Part of `gettransaction`, `listsinceblock` and
/// `listtransactions`.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
pub enum Bip125Replaceable {
    /// Yes, can be replaced due to BIP-125 (RBF).
    Yes,
    /// No, cannot be replaced due to BIP-125 (RBF).
    No,
    /// RBF unknown.
    Unknown,
}

/// Models the result of JSON-RPC method `addmultisigaddress`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct AddMultisigAddress {
    /// The new multisig address.
    pub address: Address<NetworkUnchecked>,
    /// The redemption script.
    pub redeem_script: ScriptBuf,
    /// The descriptor for this multisig.
    pub descriptor: Option<String>,
    /// Any warnings resulting from the creation of this multisig.
    pub warnings: Option<Vec<String>>,
}

/// Models the result of JSON-RPC method `bumpfee`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct BumpFee {
    /// The id of the new transaction.
    pub txid: Txid,
    /// Fee of the replaced transaction.
    pub original_fee: Amount,
    /// Fee of the new transaction.
    pub fee: Amount,
    /// Errors encountered during processing (may be empty).
    pub errors: Vec<String>,
}

/// Models the result of JSON-RPC method `createwallet`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CreateWallet {
    /// The wallet name if created successfully.
    ///
    /// If the wallet was created using a full path, the wallet_name will be the full path.
    pub name: String,
    /// Warning messages, if any, related to creating and loading the wallet.
    pub warnings: Vec<String>,
}

/// Models the result of JSON-RPC method `dumpprivkey`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct DumpPrivKey(pub PrivateKey);

/// Models the result of JSON-RPC method `getaddressesbylabel`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetAddressesByLabel(pub BTreeMap<Address<NetworkUnchecked>, AddressInformation>);

/// Address information. Part of `getaddressesbylabel`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct AddressInformation {
    /// Purpose of address.
    pub purpose: AddressPurpose,
}

/// Models the result of JSON-RPC method `getaddressinfo`.
// TODO: Support serde (currently not supported by `WitnessProgram` or `WitnessVersion`)
// https://github.com/rust-bitcoin/rust-bitcoin/issues/3513
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GetAddressInfo {
    /// The bitcoin address validated.
    pub address: Address<NetworkUnchecked>,
    /// The hex encoded scriptPubKey generated by the address.
    pub script_pubkey: ScriptBuf,
    /// If the address is yours or not.
    pub is_mine: bool,
    /// If the address is watchonly.
    pub is_watch_only: bool,
    /// Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys.
    pub solvable: Option<bool>,
    /// A descriptor for spending coins sent to this address (only when solvable).
    pub descriptor: Option<String>,
    /// The descriptor used to derive this address if this is a descriptor wallet
    pub parent_descriptor: Option<String>,
    /// If the key is a script.
    pub is_script: Option<bool>,
    /// If the address was used for change output.
    pub is_change: Option<bool>,
    /// If the address is a witness address.
    pub is_witness: bool,
    /// The version number of the witness program.
    pub witness_version: Option<WitnessVersion>,
    /// The hex value of the witness program.
    pub witness_program: Option<WitnessProgram>,
    /// The output script type.
    ///
    /// Only if "is_script" is true and the redeemscript is known.
    pub script: Option<ScriptType>,
    /// The redeemscript for the p2sh address.
    // TODO: Should we rename this to redeem_script?
    pub hex: Option<ScriptBuf>,
    /// Array of pubkeys associated with the known redeemscript (only if "script" is "multisig").
    pub pubkeys: Option<Vec<PublicKey>>,
    /// Number of signatures required to spend multisig output (only if "script" is "multisig").
    pub sigs_required: Option<u32>,
    /// The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH).
    pub pubkey: Option<PublicKey>,
    /// Information about the address embedded in P2SH or P2WSH, if relevant and known.
    pub embedded: Option<GetAddressInfoEmbedded>,
    /// If the pubkey is compressed.
    pub is_compressed: Option<bool>,
    /// The label associated with the address, "" is the default account.
    pub label: Option<String>,
    /// The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT).
    pub timestamp: Option<u32>,
    /// The HD keypath if the key is HD and available.
    pub hd_key_path: Option<bip32::DerivationPath>,
    /// The Hash160 of the HD seed.
    pub hd_seed_id: Option<hash160::Hash>,
    /// The fingerprint of the master key.
    pub hd_master_fingerprint: Option<bip32::Fingerprint>,
    /// Labels associated with the address.
    pub labels: Vec<String>,
}

/// The script field. Part of `getaddressinfo` and `getaddressinfoembedded`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum ScriptType {
    /// Non-standard output script type.
    NonStandard,
    /// Pubkey output script.
    Pubkey,
    /// Pubkey hash output script.
    PubkeyHash,
    /// Script hash output script.
    ScriptHash,
    /// Multisig output script.
    Multisig,
    /// Null data for output script.
    NullData,
    /// Witness version 0 key hash output script.
    WitnessV0KeyHash,
    /// Witness version 0 script hash output script.
    WitnessV0ScriptHash,
    /// Witness unknown for output script.
    WitnessUnknown,
}

/// The `embedded` address info field. Part of `getaddressinfo`.
///
/// It includes all getaddressinfo output fields for the embedded address, excluding metadata
/// ("timestamp", "hdkeypath", "hdseedid") and relation to the wallet ("ismine", "iswatchonly",
/// "account").
// TODO: Support serde (currently not supported by `WitnessProgram` or `WitnessVersion`)
// https://github.com/rust-bitcoin/rust-bitcoin/issues/3513
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GetAddressInfoEmbedded {
    /// The bitcoin address validated.
    pub address: Address<NetworkUnchecked>,
    /// The hex encoded scriptPubKey generated by the address.
    pub script_pubkey: ScriptBuf,
    /// Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys.
    pub solvable: Option<bool>,
    /// A descriptor for spending coins sent to this address (only when solvable).
    pub descriptor: Option<String>,
    /// The descriptor used to derive this address if this is a descriptor wallet
    pub parent_descriptor: Option<String>,
    /// If the key is a script.
    pub is_script: Option<bool>,
    /// If the address was used for change output.
    pub is_change: Option<bool>,
    /// If the address is a witness address.
    pub is_witness: bool,
    /// The version number of the witness program.
    pub witness_version: Option<WitnessVersion>,
    /// The hex value of the witness program.
    pub witness_program: Option<WitnessProgram>,
    /// The output script type.
    ///
    /// Only if "is_script" is true and the redeemscript is known.
    pub script: Option<ScriptType>,
    /// The redeemscript for the p2sh address.
    pub hex: Option<ScriptBuf>,
    /// Array of pubkeys associated with the known redeemscript (only if "script" is "multisig").
    pub pubkeys: Option<Vec<PublicKey>>,
    /// Number of signatures required to spend multisig output (only if "script" is "multisig").
    pub sigs_required: Option<u32>,
    /// The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH).
    pub pubkey: Option<PublicKey>,
    /// If the address is compressed.
    pub is_compressed: Option<bool>,
    /// The label associated with the address, "" is the default account.
    pub label: Option<String>,
    /// Labels associated with the address.
    pub labels: Option<Vec<String>>,
}

/// Models the result of JSON-RPC method `getbalance`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetBalance(pub Amount);

/// Models the result of JSON-RPC method `getbalances`.
///
/// Core version 0.19 onwards.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetBalances {
    /// Balances from outputs that the wallet can sign.
    pub mine: GetBalancesMine,
    /// Watchonly balances (not present if wallet does not watch anything).
    pub watch_only: Option<GetBalancesWatchOnly>,
    /// Hash and height of the block this information was generated on. v26 and later only.
    #[serde(rename = "lastprocessedblock")]
    pub last_processed_block: Option<LastProcessedBlock>,
}

/// Balances from outputs that the wallet can sign. Part of `getbalances`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetBalancesMine {
    /// Trusted balance (outputs created by the wallet or confirmed outputs).
    pub trusted: Amount,
    /// Untrusted pending balance (outputs created by others that are in the mempool).
    pub untrusted_pending: Amount,
    /// Balance from immature coinbase outputs.
    pub immature: Amount,
    /// Balance from coins sent to addresses that were previously spent from (potentially privacy violating).
    ///
    /// Only present if `avoid_reuse` is set.
    pub used: Option<Amount>,
}

/// Hash and height of the block this information was generated on. Part of `getbalances`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetBalancesWatchOnly {
    /// Trusted balance (outputs created by the wallet or confirmed outputs).
    pub trusted: Amount,
    /// Untrusted pending balance (outputs created by others that are in the mempool).
    pub untrusted_pending: Amount,
    /// Balance from immature coinbase outputs.
    pub immature: Amount,
}

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

/// An HD key entry. Part of `gethdkeys`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct HdKey {
    /// The extended public key.
    pub xpub: Xpub,
    /// Whether the wallet has the private key for this xpub.
    pub has_private: bool,
    /// The extended private key if "private" is true.
    pub xpriv: Option<Xpriv>,
    /// Array of descriptor objects that use this HD key.
    pub descriptors: Vec<HdKeyDescriptor>,
}

/// Descriptor object. Part of `gethdkeys`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct HdKeyDescriptor {
    /// Descriptor string representation.
    pub descriptor: String,
    /// Whether this descriptor is currently used to generate new addresses.
    pub active: bool,
}

/// Models the result of JSON-RPC method `getnewaddress`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetNewAddress(pub Address<NetworkUnchecked>);

/// Models the result of JSON-RPC method `getrawchangeaddress`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetRawChangeAddress(pub Address<NetworkUnchecked>);

/// Models the result of JSON-RPC method `getreceivedbyaddress`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetReceivedByAddress(pub Amount);

/// Models the result of JSON-RPC method `getreceivedbylabel`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetReceivedByLabel(pub Amount);

/// Models the result of JSON-RPC method `gettransaction`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetTransaction {
    /// The transaction amount.
    #[serde(default, with = "bitcoin::amount::serde::as_btc")]
    pub amount: SignedAmount,
    /// The amount of the fee.
    ///
    /// This is negative and only available for the 'send' category of transactions.
    #[serde(default, with = "bitcoin::amount::serde::as_btc::opt")]
    pub fee: Option<SignedAmount>,
    /// The number of confirmations.
    pub confirmations: i64, // Docs do not indicate what negative value means?
    /// Only present if the transaction's only input is a coinbase one. v20 and later only.
    pub generated: Option<bool>,
    /// Whether we consider the outputs of this unconfirmed transaction safe to spend.
    pub trusted: Option<bool>,
    /// The block hash.
    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.
    pub block_index: Option<u32>,
    /// The time in seconds since epoch (1 Jan 1970 GMT).
    pub block_time: Option<u32>,
    /// The transaction id.
    pub txid: Txid,
    /// The hash of serialized transaction, including witness data. v24 and later only.
    pub wtxid: Option<Txid>,
    /// Confirmed transactions that have been detected by the wallet to conflict with this transaction.
    pub wallet_conflicts: Vec<Txid>,
    /// Only if 'category' is 'send'. The txid if this tx was replaced. v23 and later only.
    pub replaced_by_txid: Option<Txid>,
    /// Only if 'category' is 'send'. The txid if this tx replaces another. 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. v23 and later only.
    pub to: Option<String>,
    /// The transaction time in seconds since epoch (1 Jan 1970 GMT).
    pub time: u32,
    /// The time received in seconds since epoch (1 Jan 1970 GMT).
    pub time_received: u32,
    /// If a comment is associated with the transaction, only present if not empty. v20 to v24 only.
    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 output script of this coin. v24 and later only.
    pub parent_descriptors: Option<Vec<String>>,
    /// Transaction details.
    pub details: Vec<GetTransactionDetail>,
    /// The decoded transaction (only present when `verbose` is passed). v19 and later only.
    pub decoded: Option<Transaction>,
    /// Hash and height of the block this information was generated on. v26 and later only.
    pub last_processed_block: Option<LastProcessedBlock>,
    /// The transaction, parsed from hex string.
    pub tx: Transaction,
}

/// Transaction detail. Part of the `gettransaction`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetTransactionDetail {
    /// Only returns true if imported addresses were involved in transaction. v20 and later only.
    pub involves_watch_only: Option<bool>,
    /// DEPRECATED. The account name involved in the transaction, can be "" for the default account.
    pub account: Option<String>, // Docs are wrong, this is not documented as optional.
    /// The bitcoin address involved in the transaction.
    pub address: Address<NetworkUnchecked>,
    /// The category, either 'send' or 'receive'.
    pub category: TransactionCategory,
    ///  The amount.
    #[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.
    ///
    /// This is negative and only available for the 'send' category of transactions.
    #[serde(default, with = "bitcoin::amount::serde::as_btc::opt")]
    pub fee: Option<SignedAmount>,
    /// If the transaction has been abandoned (inputs are respendable).
    ///
    /// Only available for the 'send' category of transactions.
    pub abandoned: Option<bool>,
    /// Only if 'category' is 'received'. List of parent descriptors for the output script of this
    /// coin. v24 and later only.
    pub parent_descriptors: Option<Vec<String>>,
}

/// Last processed block item. Part of of `gettransaction`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LastProcessedBlock {
    /// Hash of the block this information was generated on.
    pub hash: BlockHash,
    /// Height of the block this information was generated on.
    pub height: u32,
}

/// Models the result of JSON-RPC method `getunconfirmedbalance`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetUnconfirmedBalance(pub Amount);

/// Models the result of JSON-RPC method `getwalletinfo`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct GetWalletInfo {
    /// The wallet name.
    pub wallet_name: String,
    /// The wallet version.
    pub wallet_version: u32,
    /// Database format. v21 and later only.
    pub format: Option<String>,
    /// The total confirmed balance of the wallet in BTC.
    pub balance: Amount,
    /// The total unconfirmed balance of the wallet in BTC.
    pub unconfirmed_balance: Amount,
    /// The total immature balance of the wallet in BTC.
    pub immature_balance: Amount,
    /// The total number of transactions in the wallet
    pub tx_count: u32,
    /// The timestamp (seconds since Unix epoch) of the oldest pre-generated key in the key pool.
    pub keypool_oldest: u32,
    /// How many new keys are pre-generated (only counts external keys).
    pub keypool_size: u32,
    /// How many new keys are pre-generated for internal use (used for change outputs, only appears
    /// if the wallet is using this feature, otherwise external keys are used).
    pub keypool_size_hd_internal: u32,
    /// The timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked
    /// for transfers, or 0 if the wallet is locked.
    pub unlocked_until: Option<u32>,
    /// The transaction fee configuration.
    pub pay_tx_fee: Option<FeeRate>,
    /// The Hash160 of the HD seed (only present when HD is enabled).
    pub hd_seed_id: Option<hash160::Hash>,
    /// If privatekeys are disabled for this wallet (enforced watch-only wallet).
    pub private_keys_enabled: bool,
    /// Whether this wallet tracks clean/dirty coins in terms of reuse. v19 and later only.
    pub avoid_reuse: Option<bool>,
    /// Current scanning details, or false if no scan is in progress. v19 and later only.
    pub scanning: Option<GetWalletInfoScanning>,
    /// Whether wallet uses descriptors. v21 and later only.
    pub descriptors: Option<bool>,
    /// Whether this wallet is configured to use an external signer such as a hardware wallet. v23 and later only.
    pub external_signer: Option<bool>,
    /// Whether this wallet intentionally does not contain any keys, scripts, or descriptors. v26 and later only.
    pub blank: Option<bool>,
    /// The start time for blocks scanning. v26 and later only.
    pub birthtime: Option<u32>,
    /// Hash and height of the block this information was generated on. v26 and later only.
    pub last_processed_block: Option<LastProcessedBlock>,
}

/// Current scanning details. Part of `getwalletinfo`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum GetWalletInfoScanning {
    Details {
        /// Elapsed seconds since scan start.
        duration: u64,
        /// Scanning progress percentage [0.0, 1.0].
        progress: f64,
    },
    NotScanning(bool),
}

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

/// List address item. Part of `listaddressgroupings`.
// FIXME: The Core docs seem wrong, not sure what shape this should be?
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListAddressGroupingsItem {
    /// The bitcoin address.
    pub address: Address<NetworkUnchecked>,
    /// The amount.
    pub amount: Amount,
    /// The label.
    pub label: Option<String>,
}

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

/// List lock unspent item. Part of of `listlockunspent`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListLockUnspentItem {
    /// The transaction id locked.
    pub txid: Txid,
    /// The vout value.
    pub vout: u32,
}

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

/// List received by address item. Part of of `listreceivedbyaddress`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListReceivedByAddressItem {
    /// Only returned if imported addresses were involved in transaction.
    pub involves_watch_only: Option<bool>,
    /// The receiving address.
    pub address: Address<NetworkUnchecked>,
    /// The total amount received by the address.
    pub amount: Amount,
    /// The number of confirmations of the most recent transaction included.
    pub confirmations: i64, // Docs do not indicate what negative value means?
    /// The label of the receiving address. The default label is "".
    pub label: String,
    /// The ids of transactions received with the address.
    pub txids: Vec<Txid>,
}

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

/// List received by label item. Part of of `listreceivedbyaddress`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListReceivedByLabelItem {
    /// Only returned if imported addresses were involved in transaction.
    pub involves_watch_only: Option<bool>,
    /// The total amount received by addresses with this label.
    pub amount: Amount,
    /// The number of confirmations of the most recent transaction included.
    pub confirmations: u32,
    /// The label of the receiving address. The default label is "".
    pub label: String,
}

/// Models the result of JSON-RPC method `listsinceblock`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListSinceBlock {
    /// All the transactions.
    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<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
    /// would generally use a target_confirmations of say 6, so you will be continually
    /// re-notified of transactions until they've reached 6 confirmations plus any new ones.
    pub last_block: BlockHash,
}

/// Transaction item. Part of `listsinceblock` and `listtransactions`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
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.
    pub category: TransactionCategory,
    /// The amount in BTC.
    ///
    /// This is negative for the 'send' category, and for the 'move' category for moves outbound. It
    /// is positive for the 'receive' category, and for the 'move' category for inbound funds.
    #[serde(default, with = "bitcoin::amount::serde::as_btc")]
    pub amount: SignedAmount,
    /// 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.
    ///
    /// 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: 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: Option<u32>,
    /// The block time in seconds since epoch (1 Jan 1970 GMT).
    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>,
    /// A comment for the address/transaction, if any.
    pub label: 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<TransactionItem>);

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

/// Unspent transaction output. Part of `listunspent`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ListUnspentItem {
    /// The transaction id.
    pub txid: Txid,
    /// The vout value.
    pub vout: u32,
    /// The bitcoin address of the transaction.
    pub address: Address<NetworkUnchecked>,
    /// The associated label, or "" for the default label.
    pub label: String,
    /// The script key.
    pub script_pubkey: ScriptBuf,
    /// The transaction amount.
    #[serde(default, with = "bitcoin::amount::serde::as_btc")]
    pub amount: SignedAmount,
    /// The number of confirmations.
    pub confirmations: u32, // Docs do not indicate what negative value means?
    /// The redeemScript if scriptPubKey is P2SH.
    pub redeem_script: Option<ScriptBuf>,
    /// Whether we have the private keys to spend this output.
    pub spendable: bool,
    /// Whether we know how to spend this output, ignoring the lack of keys.
    pub solvable: bool,
    /// A descriptor for spending this output (only when solvable)
    pub descriptor: Option<String>,
    /// Whether this output is considered safe to spend. Unconfirmed transactions from outside keys
    /// and unconfirmed replacement transactions are considered unsafe and are not eligible for
    /// spending by fundrawtransaction and sendtoaddress.
    pub safe: bool,
    /// List of parent descriptors for the scriptPubKey of this coin. v24 and later only.
    #[serde(rename = "parent_descs")]
    pub parent_descriptors: Option<Vec<String>>,
}

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

/// Models the result of JSON-RPC method `loadwallet`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LoadWallet {
    /// The wallet name if loaded successfully.
    pub name: String,
    /// Warning messages, if any, related to loading the wallet.
    pub warnings: Vec<String>,
}

/// Models the result of JSON-RPC method `psbtbumpfee`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct PsbtBumpFee {
    /// The base64-encoded unsigned PSBT of the new transaction.
    pub psbt: Psbt,
    /// The fee of the replaced transaction.
    pub original_fee: Amount,
    /// The fee of the new transaction.
    pub fee: Amount,
    /// Errors encountered during processing (may be empty).
    pub errors: Vec<String>,
}

/// Models the result of JSON-RPC method `rescanblockchain`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct RescanBlockchain {
    /// The block height where the rescan has started.
    pub start_height: u32,
    /// The height of the last rescanned block.
    pub stop_height: u32,
}

/// Models the result of JSON-RPC method `send`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Send {
    /// If the transaction has a complete set of signatures.
    pub complete: bool,
    /// The transaction id for the send.
    pub txid: Option<Txid>,
    /// If add_to_wallet is false, the hex-encoded raw transaction with signature(s).
    pub hex: Option<Transaction>,
    /// If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially)
    /// signed transaction.
    pub psbt: Option<Psbt>,
}

/// Models the result of JSON-RPC method `sendall`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct SendAll {
    /// If the transaction has a complete set of signatures.
    pub complete: bool,
    /// The transaction id for the send. Only 1 transaction is created regardless of the number of addresses.
    pub txid: Option<Txid>,
    /// If add_to_wallet is false, the hex-encoded raw transaction with signature(s).
    pub hex: Option<Transaction>,
    /// If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially)
    /// signed transaction.
    pub psbt: Option<Psbt>,
}

/// Models the result of JSON-RPC method `sendmany`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct SendMany(pub Txid);

/// Models the verbose result of JSON-RPC method `sendmany` when `verbose=true`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct SendManyVerbose {
    /// The transaction id for the send. Only 1 transaction is created regardless of the number of addresses.
    pub txid: Txid,
    /// The transaction fee reason.
    pub fee_reason: String,
}

/// Models the result of JSON-RPC method `sendtoaddress`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct SendToAddress {
    pub txid: Txid,
}

/// Models the result of JSON-RPC method `signmessage`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SignMessage(pub sign_message::MessageSignature);

/// Models the result of JSON-RPC method `signrawtransactionwithwallet`.
///
/// **Note:** This is a type alias of [`SignRawTransaction`] because the RPC response
/// shape is identical, and our policy is to have a return type for every RPC method.
pub type SignRawTransactionWithWallet = SignRawTransaction;

/// Models the result of JSON-RPC method `simulaterawtransaction`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct SimulateRawTransaction {
    /// The wallet balance change (negative means decrease).
    #[serde(default, with = "bitcoin::amount::serde::as_btc")]
    pub balance_change: SignedAmount,
}

/// Models the result of JSON-RPC method `unloadwallet`.
///
/// Core version v0.21 onwards.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct UnloadWallet {
    /// Warning messages, if any, related to unloading the wallet.
    // Changes from single string to vector in Core v25
    pub warnings: Vec<String>,
}

/// Models the result of JSON-RPC method `walletcreatefundedpsbt`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct WalletCreateFundedPsbt {
    /// The resulting PSBT.
    pub psbt: Psbt,
    /// Fee the resulting transaction pays.
    #[serde(default, with = "bitcoin::amount::serde::as_btc")]
    pub fee: SignedAmount,
    /// The position of the added change output, or -1.
    pub change_position: u32,
}

/// Models the result of JSON-RPC method `walletdisplayaddress`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct WalletDisplayAddress {
    /// The address as confirmed by the signer
    pub address: Address<NetworkUnchecked>,
}

/// Models the result of JSON-RPC method `walletprocesspsbt`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct WalletProcessPsbt {
    /// The partially signed transaction.
    pub psbt: Psbt,
    /// If the transaction has a complete set of signatures.
    pub complete: bool,
    /// The hex-encoded network transaction if complete.
    pub hex: Option<Transaction>,
}
