use bitcoin::{Amount, FeeRate, Txid};
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct CreateRawTransactionArguments {
pub inputs: Vec<CreateRawTransactionInput>,
pub outputs: Vec<CreateRawTransactionOutput>,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct CreateRawTransactionInput {
pub txid: String,
pub vout: u32,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(untagged)]
pub enum CreateRawTransactionOutput {
AddressAmount {
address: String,
amount: f64,
},
Data {
data: String,
},
}
impl Serialize for CreateRawTransactionOutput {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
CreateRawTransactionOutput::AddressAmount { address, amount } => {
let mut map = serde_json::Map::new();
map.insert(
address.clone(),
serde_json::Value::Number(serde_json::Number::from_f64(*amount).unwrap()),
);
map.serialize(serializer)
}
CreateRawTransactionOutput::Data { data } => {
let mut map = serde_json::Map::new();
map.insert("data".to_string(), serde_json::Value::String(data.clone()));
map.serialize(serializer)
}
}
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct PreviousTransactionOutput {
#[serde(deserialize_with = "deserialize_txid")]
pub txid: Txid,
pub vout: u32,
#[serde(rename = "scriptPubKey")]
pub script_pubkey: String,
#[serde(rename = "redeemScript")]
pub redeem_script: Option<String>,
#[serde(rename = "witnessScript")]
pub witness_script: Option<String>,
pub amount: Option<f64>,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct ImportDescriptorInput {
pub desc: String,
pub active: Option<bool>,
pub timestamp: String,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct CreateWalletArguments {
pub name: String,
pub load_on_startup: Option<bool>,
}
fn serialize_option_bitcoin<S>(amount: &Option<Amount>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match amount {
Some(amt) => serializer.serialize_some(&amt.to_btc()),
None => serializer.serialize_none(),
}
}
fn deserialize_txid<'d, D>(deserializer: D) -> Result<Txid, D::Error>
where
D: Deserializer<'d>,
{
struct TxidVisitor;
impl Visitor<'_> for TxidVisitor {
type Value = Txid;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "a transaction id string expected")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let txid = v.parse::<Txid>().expect("invalid txid");
Ok(txid)
}
}
deserializer.deserialize_any(TxidVisitor)
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum SighashType {
Default,
All,
None,
Single,
#[serde(rename = "ALL|ANYONECANPAY")]
AllPlusAnyoneCanPay,
#[serde(rename = "NONE|ANYONECANPAY")]
NonePlusAnyoneCanPay,
#[serde(rename = "SINGLE|ANYONECANPAY")]
SinglePlusAnyoneCanPay,
}
#[derive(Clone, Debug, PartialEq, Serialize, Default)]
pub struct WalletCreateFundedPsbtOptions {
#[serde(default, rename = "fee_rate", skip_serializing_if = "Option::is_none")]
pub fee_rate: Option<f64>,
#[serde(
default,
rename = "lockUnspents",
skip_serializing_if = "Option::is_none"
)]
pub lock_unspents: Option<bool>,
#[serde(
default,
rename = "conf_target",
skip_serializing_if = "Option::is_none"
)]
pub conf_target: Option<u16>,
#[serde(
default,
rename = "replaceable",
skip_serializing_if = "Option::is_none"
)]
pub replaceable: Option<bool>,
}
#[derive(Clone, Debug, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListUnspentQueryOptions {
#[serde(serialize_with = "serialize_option_bitcoin")]
pub minimum_amount: Option<Amount>,
#[serde(serialize_with = "serialize_option_bitcoin")]
pub maximum_amount: Option<Amount>,
pub maximum_count: Option<u32>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
pub struct PsbtBumpFeeOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub conf_target: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fee_rate: Option<FeeRate>,
#[serde(skip_serializing_if = "Option::is_none")]
pub replaceable: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub estimate_mode: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub outputs: Option<Vec<CreateRawTransactionOutput>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub original_change_index: Option<u32>,
}