use super::*;
use crate::wallet::error::WalletError;
use crate::wallet::interfaces::*;
use crate::wallet::types::{BooleanDefaultFalse, BooleanDefaultTrue};
const TAG_QUERY_MODE_ALL: u8 = 1;
const TAG_QUERY_MODE_ANY: u8 = 2;
const OUTPUT_INCLUDE_LOCKING_SCRIPTS: u8 = 1;
const OUTPUT_INCLUDE_ENTIRE_TRANSACTIONS: u8 = 2;
pub fn serialize_list_outputs_args(args: &ListOutputsArgs) -> Result<Vec<u8>, WalletError> {
serialize_to_vec(|w| {
write_string(w, &args.basket)?;
write_string_slice(
w,
&if args.tags.is_empty() {
None
} else {
Some(args.tags.clone())
},
)?;
match args.tag_query_mode {
Some(QueryMode::All) => write_byte(w, TAG_QUERY_MODE_ALL)?,
Some(QueryMode::Any) => write_byte(w, TAG_QUERY_MODE_ANY)?,
None => write_byte(w, NEGATIVE_ONE_BYTE)?,
}
match args.include {
Some(OutputInclude::LockingScripts) => write_byte(w, OUTPUT_INCLUDE_LOCKING_SCRIPTS)?,
Some(OutputInclude::EntireTransactions) => {
write_byte(w, OUTPUT_INCLUDE_ENTIRE_TRANSACTIONS)?
}
None => write_byte(w, NEGATIVE_ONE_BYTE)?,
}
write_optional_bool(w, args.include_custom_instructions.0)?;
write_optional_bool(w, args.include_tags.0)?;
write_optional_bool(w, args.include_labels.0)?;
write_optional_uint32(w, args.limit)?;
write_optional_uint32(w, args.offset)?;
write_optional_bool(w, args.seek_permission.0)
})
}
pub fn deserialize_list_outputs_args(data: &[u8]) -> Result<ListOutputsArgs, WalletError> {
let mut r = std::io::Cursor::new(data);
let basket = read_string(&mut r)?;
let tags = read_string_slice(&mut r)?.unwrap_or_default();
let tq_byte = read_byte(&mut r)?;
let tag_query_mode = match tq_byte {
TAG_QUERY_MODE_ALL => Some(QueryMode::All),
TAG_QUERY_MODE_ANY => Some(QueryMode::Any),
_ => None,
};
let inc_byte = read_byte(&mut r)?;
let include = match inc_byte {
OUTPUT_INCLUDE_LOCKING_SCRIPTS => Some(OutputInclude::LockingScripts),
OUTPUT_INCLUDE_ENTIRE_TRANSACTIONS => Some(OutputInclude::EntireTransactions),
_ => None,
};
let include_custom_instructions = BooleanDefaultFalse(read_optional_bool(&mut r)?);
let include_tags = BooleanDefaultFalse(read_optional_bool(&mut r)?);
let include_labels = BooleanDefaultFalse(read_optional_bool(&mut r)?);
let limit = read_optional_uint32(&mut r)?;
let offset = read_optional_uint32(&mut r)?;
let seek_permission = BooleanDefaultTrue(read_optional_bool(&mut r)?);
Ok(ListOutputsArgs {
basket,
tags,
tag_query_mode,
include,
include_custom_instructions,
include_tags,
include_labels,
limit,
offset,
seek_permission,
})
}
pub fn serialize_list_outputs_result(result: &ListOutputsResult) -> Result<Vec<u8>, WalletError> {
serialize_to_vec(|w| {
write_varint(w, result.total_outputs as u64)?;
if let Some(ref beef) = result.beef {
write_bytes(w, beef)?;
} else {
write_varint(w, NEGATIVE_ONE)?;
}
for output in &result.outputs {
write_outpoint(w, &output.outpoint)?;
write_varint(w, output.satoshis)?;
if let Some(ref script) = output.locking_script {
write_bytes(w, script)?;
} else {
write_varint(w, NEGATIVE_ONE)?;
}
write_string_optional(w, &output.custom_instructions.clone().unwrap_or_default())?;
write_string_slice(
w,
&if output.tags.is_empty() {
None
} else {
Some(output.tags.clone())
},
)?;
write_string_slice(
w,
&if output.labels.is_empty() {
None
} else {
Some(output.labels.clone())
},
)?;
}
Ok(())
})
}
pub fn deserialize_list_outputs_result(data: &[u8]) -> Result<ListOutputsResult, WalletError> {
let mut r = std::io::Cursor::new(data);
let total_outputs = read_varint(&mut r)? as u32;
let beef_len = read_varint(&mut r)?;
let beef = if beef_len == NEGATIVE_ONE {
None
} else {
Some(read_raw_bytes(&mut r, beef_len as usize)?)
};
let mut outputs = Vec::with_capacity(total_outputs as usize);
for _ in 0..total_outputs {
let outpoint = read_outpoint(&mut r)?;
let satoshis = read_varint(&mut r)?;
let ls_len = read_varint(&mut r)?;
let locking_script = if ls_len == NEGATIVE_ONE {
None
} else {
Some(read_raw_bytes(&mut r, ls_len as usize)?)
};
let custom_str = read_string(&mut r)?;
let custom_instructions = if custom_str.is_empty() {
None
} else {
Some(custom_str)
};
let tags = read_string_slice(&mut r)?.unwrap_or_default();
let labels = read_string_slice(&mut r)?.unwrap_or_default();
outputs.push(Output {
satoshis,
locking_script,
spendable: true, custom_instructions,
tags,
outpoint,
labels,
});
}
Ok(ListOutputsResult {
total_outputs,
beef,
outputs,
})
}