#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct GetInfoResponse {
pub build: String,
pub subversion: String,
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct GetBlockchainInfoResponse {
pub chain: String,
pub blocks: zebra_chain::block::Height,
#[serde(rename = "bestblockhash", with = "hex")]
pub best_block_hash: zebra_chain::block::Hash,
#[serde(rename = "estimatedheight")]
pub estimated_height: zebra_chain::block::Height,
pub upgrades: indexmap::IndexMap<
zebra_rpc::methods::ConsensusBranchIdHex,
zebra_rpc::methods::NetworkUpgradeInfo,
>,
pub consensus: zebra_rpc::methods::TipConsensusBranch,
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct GetBalanceResponse {
pub balance: u64,
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct SendTransactionResponse(#[serde(with = "hex")] pub zebra_chain::transaction::Hash);
#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct GetBlockHash(#[serde(with = "hex")] pub zebra_chain::block::Hash);
impl Default for GetBlockHash {
fn default() -> Self {
GetBlockHash(zebra_chain::block::Hash([0; 32]))
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct SerializedBlock(zebra_chain::block::SerializedBlock);
impl std::ops::Deref for SerializedBlock {
type Target = zebra_chain::block::SerializedBlock;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for SerializedBlock {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<Vec<u8>> for SerializedBlock {
fn from(bytes: Vec<u8>) -> Self {
Self(zebra_chain::block::SerializedBlock::from(bytes))
}
}
impl From<zebra_chain::block::SerializedBlock> for SerializedBlock {
fn from(inner: zebra_chain::block::SerializedBlock) -> Self {
SerializedBlock(inner)
}
}
impl hex::FromHex for SerializedBlock {
type Error = hex::FromHexError;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
hex::decode(hex).map(SerializedBlock::from)
}
}
impl<'de> serde::Deserialize<'de> for SerializedBlock {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct HexVisitor;
impl<'de> serde::de::Visitor<'de> for HexVisitor {
type Value = SerializedBlock;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("a hex-encoded string")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let bytes = hex::decode(value).map_err(serde::de::Error::custom)?;
Ok(SerializedBlock::from(bytes))
}
}
deserializer.deserialize_str(HexVisitor)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct SaplingTrees {
size: u64,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct OrchardTrees {
size: u64,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct GetBlockTrees {
sapling: Option<SaplingTrees>,
orchard: Option<OrchardTrees>,
}
impl GetBlockTrees {
pub fn sapling(&self) -> u64 {
self.sapling.map_or(0, |s| s.size)
}
pub fn orchard(&self) -> u64 {
self.orchard.map_or(0, |o| o.size)
}
}
impl Into<zebra_rpc::methods::GetBlockTrees> for GetBlockTrees {
fn into(self) -> zebra_rpc::methods::GetBlockTrees {
zebra_rpc::methods::GetBlockTrees::new(self.sapling(), self.orchard())
}
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(untagged)]
pub enum GetBlockResponse {
Raw(#[serde(with = "hex")] SerializedBlock),
Object {
hash: GetBlockHash,
confirmations: i64,
#[serde(skip_serializing_if = "Option::is_none")]
height: Option<zebra_chain::block::Height>,
#[serde(skip_serializing_if = "Option::is_none")]
time: Option<i64>,
tx: Vec<String>,
trees: GetBlockTrees,
},
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub struct TxidsResponse {
pub transactions: Vec<String>,
}
impl<'de> serde::Deserialize<'de> for TxidsResponse {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = serde_json::Value::deserialize(deserializer)?;
let transactions = v
.as_array()
.ok_or_else(|| serde::de::Error::custom("Expected the JSON to be an array"))?
.iter()
.filter_map(|item| item.as_str().map(String::from))
.collect::<Vec<String>>();
Ok(TxidsResponse { transactions })
}
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub struct GetTreestateResponse {
pub height: i32,
pub hash: String,
pub time: u32,
pub sapling: zebra_rpc::methods::trees::Treestate<String>,
pub orchard: zebra_rpc::methods::trees::Treestate<String>,
}
impl<'de> serde::Deserialize<'de> for GetTreestateResponse {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = serde_json::Value::deserialize(deserializer)?;
let height = v["height"]
.as_i64()
.ok_or_else(|| serde::de::Error::missing_field("height"))? as i32;
let hash = v["hash"]
.as_str() .ok_or_else(|| serde::de::Error::missing_field("hash"))? .to_string();
let time = v["time"]
.as_i64()
.ok_or_else(|| serde::de::Error::missing_field("time"))? as u32;
let sapling_final_state = v["sapling"]["commitments"]["finalState"]
.as_str()
.ok_or_else(|| serde::de::Error::missing_field("sapling final state"))?
.to_string();
let orchard_final_state = v["orchard"]["commitments"]["finalState"]
.as_str()
.ok_or_else(|| serde::de::Error::missing_field("orchard final state"))?
.to_string();
Ok(GetTreestateResponse {
height,
hash,
time,
sapling: zebra_rpc::methods::trees::Treestate::new(
zebra_rpc::methods::trees::Commitments::new(sapling_final_state),
),
orchard: zebra_rpc::methods::trees::Treestate::new(
zebra_rpc::methods::trees::Commitments::new(orchard_final_state),
),
})
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SerializedTransaction(zebra_chain::transaction::SerializedTransaction);
impl std::ops::Deref for SerializedTransaction {
type Target = zebra_chain::transaction::SerializedTransaction;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for SerializedTransaction {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<Vec<u8>> for SerializedTransaction {
fn from(bytes: Vec<u8>) -> Self {
Self(zebra_chain::transaction::SerializedTransaction::from(bytes))
}
}
impl From<zebra_chain::transaction::SerializedTransaction> for SerializedTransaction {
fn from(inner: zebra_chain::transaction::SerializedTransaction) -> Self {
SerializedTransaction(inner)
}
}
impl hex::FromHex for SerializedTransaction {
type Error = <Vec<u8> as hex::FromHex>::Error;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
let bytes = <Vec<u8>>::from_hex(hex)?;
Ok(bytes.into())
}
}
impl<'de> serde::Deserialize<'de> for SerializedTransaction {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = serde_json::Value::deserialize(deserializer)?;
if let Some(hex_str) = v.as_str() {
let bytes = hex::decode(hex_str).map_err(serde::de::Error::custom)?;
Ok(SerializedTransaction(
zebra_chain::transaction::SerializedTransaction::from(bytes),
))
} else {
Err(serde::de::Error::custom("expected a hex string"))
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub enum GetTransactionResponse {
Raw(#[serde(with = "hex")] SerializedTransaction),
Object {
#[serde(with = "hex")]
hex: SerializedTransaction,
height: i32,
confirmations: u32,
},
}
impl<'de> serde::Deserialize<'de> for GetTransactionResponse {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = serde_json::Value::deserialize(deserializer)?;
if v.get("height").is_some() && v.get("confirmations").is_some() {
let hex = serde_json::from_value(v["hex"].clone()).map_err(serde::de::Error::custom)?;
let height = v["height"]
.as_i64()
.ok_or_else(|| serde::de::Error::custom("Missing or invalid height"))?
as i32;
let confirmations = v["confirmations"]
.as_u64()
.ok_or_else(|| serde::de::Error::custom("Missing or invalid confirmations"))?
as u32;
let obj = GetTransactionResponse::Object {
hex,
height,
confirmations,
};
Ok(obj)
} else if v.get("hex").is_some() && v.get("txid").is_some() {
let hex = serde_json::from_value(v["hex"].clone()).map_err(serde::de::Error::custom)?;
let obj = GetTransactionResponse::Object {
hex,
height: -1,
confirmations: 0,
};
Ok(obj)
} else {
let raw = GetTransactionResponse::Raw(
serde_json::from_value(v.clone()).map_err(serde::de::Error::custom)?,
);
Ok(raw)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
pub struct SubtreeRpcData(zebra_rpc::methods::trees::SubtreeRpcData);
impl std::ops::Deref for SubtreeRpcData {
type Target = zebra_rpc::methods::trees::SubtreeRpcData;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<zebra_rpc::methods::trees::SubtreeRpcData> for SubtreeRpcData {
fn from(inner: zebra_rpc::methods::trees::SubtreeRpcData) -> Self {
SubtreeRpcData(inner)
}
}
impl hex::FromHex for SubtreeRpcData {
type Error = hex::FromHexError;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
let hex_str = std::str::from_utf8(hex.as_ref())
.map_err(|_| hex::FromHexError::InvalidHexCharacter { c: '�', index: 0 })?;
if hex_str.len() < 8 {
return Err(hex::FromHexError::OddLength);
}
let root_end_index = hex_str.len() - 8;
let (root_hex, height_hex) = hex_str.split_at(root_end_index);
let root = root_hex.to_string();
let height = u32::from_str_radix(height_hex, 16)
.map_err(|_| hex::FromHexError::InvalidHexCharacter { c: '�', index: 0 })?;
Ok(SubtreeRpcData(zebra_rpc::methods::trees::SubtreeRpcData {
root,
end_height: zebra_chain::block::Height(height),
}))
}
}
impl<'de> serde::Deserialize<'de> for SubtreeRpcData {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(serde::Deserialize)]
struct SubtreeDataHelper {
root: String,
end_height: u32,
}
let helper = SubtreeDataHelper::deserialize(deserializer)?;
Ok(SubtreeRpcData(zebra_rpc::methods::trees::SubtreeRpcData {
root: helper.root,
end_height: zebra_chain::block::Height(helper.end_height),
}))
}
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct GetSubtreesResponse {
pub pool: String,
pub start_index: zebra_chain::subtree::NoteCommitmentSubtreeIndex,
pub subtrees: Vec<SubtreeRpcData>,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)]
pub struct Script(zebra_chain::transparent::Script);
impl std::ops::Deref for Script {
type Target = zebra_chain::transparent::Script;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for Script {
fn as_ref(&self) -> &[u8] {
self.0.as_raw_bytes()
}
}
impl From<Vec<u8>> for Script {
fn from(bytes: Vec<u8>) -> Self {
Self(zebra_chain::transparent::Script::new(bytes.as_ref()))
}
}
impl From<zebra_chain::transparent::Script> for Script {
fn from(inner: zebra_chain::transparent::Script) -> Self {
Script(inner)
}
}
impl hex::FromHex for Script {
type Error = <Vec<u8> as hex::FromHex>::Error;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
let bytes = Vec::from_hex(hex)?;
let inner = zebra_chain::transparent::Script::new(&bytes);
Ok(Script(inner))
}
}
impl<'de> serde::Deserialize<'de> for Script {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let v = serde_json::Value::deserialize(deserializer)?;
if let Some(hex_str) = v.as_str() {
let bytes = hex::decode(hex_str).map_err(serde::de::Error::custom)?;
let inner = zebra_chain::transparent::Script::new(&bytes);
Ok(Script(inner))
} else {
Err(serde::de::Error::custom("expected a hex string"))
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct GetUtxosResponse {
pub address: zebra_chain::transparent::Address,
#[serde(with = "hex")]
pub txid: zebra_chain::transaction::Hash,
#[serde(rename = "outputIndex")]
pub output_index: u32,
#[serde(with = "hex")]
pub script: Script,
pub satoshis: u64,
pub height: zebra_chain::block::Height,
}