From 0ce957389be54b53ebf5dffcb3a335c78c862341 Mon Sep 17 00:00:00 2001
From: "hinto.janai" <hinto.janai@protonmail.com>
Date: Mon, 8 Jul 2024 16:49:29 -0400
Subject: [PATCH] separate misc module

---
 rpc/types/Cargo.toml                         |   5 +-
 rpc/types/README.md                          |   9 +-
 rpc/types/src/free.rs                        |  12 +-
 rpc/types/src/json.rs                        |   1 +
 rpc/types/src/lib.rs                         |  22 +-
 rpc/types/src/{ => misc}/binary_string.rs    |   2 +-
 rpc/types/src/misc/block_complete_entry.rs   |  37 +++
 rpc/types/src/misc/key_image_spent_status.rs |  43 +++
 rpc/types/src/{ => misc}/misc.rs             | 310 +------------------
 rpc/types/src/misc/mod.rs                    |  33 ++
 rpc/types/src/misc/pool_info_extent.rs       |  44 +++
 rpc/types/src/{ => misc}/status.rs           |   6 +-
 rpc/types/src/misc/tx_entry.rs               |  59 ++++
 13 files changed, 242 insertions(+), 341 deletions(-)
 rename rpc/types/src/{ => misc}/binary_string.rs (95%)
 create mode 100644 rpc/types/src/misc/block_complete_entry.rs
 create mode 100644 rpc/types/src/misc/key_image_spent_status.rs
 rename rpc/types/src/{ => misc}/misc.rs (57%)
 create mode 100644 rpc/types/src/misc/mod.rs
 create mode 100644 rpc/types/src/misc/pool_info_extent.rs
 rename rpc/types/src/{ => misc}/status.rs (97%)
 create mode 100644 rpc/types/src/misc/tx_entry.rs

diff --git a/rpc/types/Cargo.toml b/rpc/types/Cargo.toml
index ac5e15ed..c088e4df 100644
--- a/rpc/types/Cargo.toml
+++ b/rpc/types/Cargo.toml
@@ -9,10 +9,7 @@ repository  = "https://github.com/Cuprate/cuprate/tree/main/rpc/types"
 keywords    = ["cuprate", "rpc", "types", "monero"]
 
 [features]
-default = ["json", "bin", "other", "serde", "epee"]
-json    = []
-bin     = []
-other   = []
+default = ["serde", "epee"]
 serde   = ["dep:serde"]
 epee    = ["dep:cuprate-epee-encoding"]
 
diff --git a/rpc/types/README.md b/rpc/types/README.md
index 44fc20c1..4b337be4 100644
--- a/rpc/types/README.md
+++ b/rpc/types/README.md
@@ -40,9 +40,7 @@ For example:
 |-----------------|-------------------------|
 | [`get_block_count`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_block_count) | [`json::GetBlockCountRequest`] & [`json::GetBlockCountResponse`]
 | [`/get_blocks.bin`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_blockbin) | [`bin::GetBlocksRequest`] & [`bin::GetBlocksResponse`]
-| [`/get_height`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_height) | `other::GetHeightRequest` & `other::GetHeightResponse`
-
-TODO: fix doc links when types are ready.
+| [`/get_height`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_height) | [`other::GetHeightRequest`] & [`other::GetHeightResponse`]
 
 # Mixed types
 Note that some types mix JSON & binary together, i.e., the message overall is JSON,
@@ -57,7 +55,7 @@ however some fields contain binary values inside JSON strings, for example:
 }
 ```
 
-`binary` here is (de)serialized as a normal [`String`]. In order to be clear on which fields contain binary data, the struct fields that have them will use [`crate::BinaryString`] instead of [`String`].
+`binary` here is (de)serialized as a normal [`String`]. In order to be clear on which fields contain binary data, the struct fields that have them will use [`crate::misc::BinaryString`] instead of [`String`].
 
 - TODO: list the specific types.
 - TODO: we need to figure out a type that (de)serializes correctly, `String` errors with `serde_json`
@@ -69,8 +67,5 @@ All are enabled by default.
 
 | Feature flag | Does what |
 |--------------|-----------|
-| `json`       | Enables the `crate::json` module
-| `bin`        | Enables the `crate::bin` module
-| `other`      | Enables the `crate::other` module
 | `serde`      | Implements `serde` on all types
 | `epee`       | Implements `cuprate_epee_encoding` on all types
\ No newline at end of file
diff --git a/rpc/types/src/free.rs b/rpc/types/src/free.rs
index 1457eaa6..043a5209 100644
--- a/rpc/types/src/free.rs
+++ b/rpc/types/src/free.rs
@@ -1,13 +1,17 @@
-//! Macros.
+//! Free functions.
 
-//---------------------------------------------------------------------------------------------------- TODO
-/// TODO
+//---------------------------------------------------------------------------------------------------- Serde
+// These are functions used for conditionally (de)serialization.
+
+/// Returns `true` if the input `u` is equal to `0`.
+#[inline]
 #[allow(clippy::trivially_copy_pass_by_ref)] // serde needs `&`
 pub(crate) const fn is_zero(u: &u64) -> bool {
     *u == 0
 }
 
-/// TODO
+/// Returns `true` the input `u` is equal to `1`.
+#[inline]
 #[allow(clippy::trivially_copy_pass_by_ref)] // serde needs `&`
 pub(crate) const fn is_one(u: &u64) -> bool {
     *u == 1
diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs
index 4abca39f..a4a0f6c1 100644
--- a/rpc/types/src/json.rs
+++ b/rpc/types/src/json.rs
@@ -545,6 +545,7 @@ define_request_and_response! {
     GetTransactionPoolBacklog,
     Request {},
     ResponseBase {
+        // TODO: this is a [`BinaryString`].
         backlog: Vec<TxBacklogEntry>,
     }
 }
diff --git a/rpc/types/src/lib.rs b/rpc/types/src/lib.rs
index 268e3875..ce3711ae 100644
--- a/rpc/types/src/lib.rs
+++ b/rpc/types/src/lib.rs
@@ -104,28 +104,20 @@
 // TODO: remove me after finishing impl
 #![allow(dead_code)]
 
-//---------------------------------------------------------------------------------------------------- Use
-mod binary_string;
+//---------------------------------------------------------------------------------------------------- Mod
 mod constants;
 mod defaults;
 mod free;
 mod macros;
 
-pub use binary_string::BinaryString;
+pub mod base;
+pub mod bin;
+pub mod json;
+pub mod misc;
+pub mod other;
+
 pub use constants::{
     CORE_RPC_STATUS_BUSY, CORE_RPC_STATUS_NOT_MINING, CORE_RPC_STATUS_OK,
     CORE_RPC_STATUS_PAYMENT_REQUIRED, CORE_RPC_STATUS_UNKNOWN, CORE_RPC_VERSION,
     CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR,
 };
-
-pub mod base;
-#[cfg(feature = "bin")]
-#[cfg_attr(docsrs, doc(cfg(feature = "bin")))]
-pub mod bin;
-#[cfg(feature = "json")]
-#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
-pub mod json;
-pub mod misc;
-#[cfg(feature = "other")]
-#[cfg_attr(docsrs, doc(cfg(feature = "other")))]
-pub mod other;
diff --git a/rpc/types/src/binary_string.rs b/rpc/types/src/misc/binary_string.rs
similarity index 95%
rename from rpc/types/src/binary_string.rs
rename to rpc/types/src/misc/binary_string.rs
index f9e69bfc..5c3908dd 100644
--- a/rpc/types/src/binary_string.rs
+++ b/rpc/types/src/misc/binary_string.rs
@@ -8,7 +8,7 @@
 /// ```rust
 /// use serde::Deserialize;
 /// use serde_json::from_str;
-/// use cuprate_rpc_types::BinaryString;
+/// use cuprate_rpc_types::misc::BinaryString;
 ///
 /// #[derive(Deserialize)]
 /// struct Key {
diff --git a/rpc/types/src/misc/block_complete_entry.rs b/rpc/types/src/misc/block_complete_entry.rs
new file mode 100644
index 00000000..ca791b0a
--- /dev/null
+++ b/rpc/types/src/misc/block_complete_entry.rs
@@ -0,0 +1,37 @@
+//! TODO
+
+//---------------------------------------------------------------------------------------------------- Use
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+
+#[cfg(feature = "epee")]
+use cuprate_epee_encoding::epee_object;
+
+use crate::misc::TxBlobEntry;
+
+//---------------------------------------------------------------------------------------------------- BlockCompleteEntry
+#[doc = crate::macros::monero_definition_link!(
+    cc73fe71162d564ffda8e549b79a350bca53c454,
+    "rpc/core_rpc_server_commands_defs.h",
+    210..=221
+)]
+/// Used in [`crate::bin::GetBlocksResponse`].
+#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct BlockCompleteEntry {
+    pub pruned: bool,
+    pub block: String,
+    pub block_weight: u64,
+    pub txs: Vec<TxBlobEntry>,
+}
+
+// TODO: custom epee
+// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L138-L163>
+#[cfg(feature = "epee")]
+epee_object! {
+    BlockCompleteEntry,
+    pruned: bool,
+    block: String,
+    block_weight: u64,
+    txs: Vec<TxBlobEntry>,
+}
diff --git a/rpc/types/src/misc/key_image_spent_status.rs b/rpc/types/src/misc/key_image_spent_status.rs
new file mode 100644
index 00000000..ede2382a
--- /dev/null
+++ b/rpc/types/src/misc/key_image_spent_status.rs
@@ -0,0 +1,43 @@
+//! TODO
+
+//---------------------------------------------------------------------------------------------------- Use
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+
+#[cfg(feature = "epee")]
+use cuprate_epee_encoding::{
+    macros::bytes::{Buf, BufMut},
+    EpeeValue, Marker,
+};
+
+//---------------------------------------------------------------------------------------------------- KeyImageSpentStatus
+/// Used in [`crate::other::IsKeyImageSpentResponse`].
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[repr(u8)]
+pub enum KeyImageSpentStatus {
+    Unspent = 0,
+    SpentInBlockchain = 1,
+    SpentInPool = 2,
+}
+
+#[cfg(feature = "epee")]
+impl EpeeValue for KeyImageSpentStatus {
+    const MARKER: Marker = <String as EpeeValue>::MARKER;
+
+    fn read<B: Buf>(r: &mut B, marker: &Marker) -> cuprate_epee_encoding::Result<Self> {
+        todo!()
+    }
+
+    fn should_write(&self) -> bool {
+        todo!()
+    }
+
+    fn epee_default_value() -> Option<Self> {
+        todo!()
+    }
+
+    fn write<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::Result<()> {
+        todo!()
+    }
+}
diff --git a/rpc/types/src/misc.rs b/rpc/types/src/misc/misc.rs
similarity index 57%
rename from rpc/types/src/misc.rs
rename to rpc/types/src/misc/misc.rs
index 634fc97b..bf9b47ec 100644
--- a/rpc/types/src/misc.rs
+++ b/rpc/types/src/misc/misc.rs
@@ -4,12 +4,6 @@
 //! For example, [`crate::json::GetConnectionsResponse`] contains
 //! the [`crate::misc::ConnectionInfo`] struct defined here.
 
-//---------------------------------------------------------------------------------------------------- Lints
-#![allow(
-    missing_docs, // Docs are at: <https://www.getmonero.org/resources/developer-guides/daemon-rpc.html>
-    clippy::struct_excessive_bools, // hey man, tell that to the people who wrote `monerod`
-)]
-
 //---------------------------------------------------------------------------------------------------- Import
 use std::fmt::Display;
 
@@ -539,308 +533,6 @@ define_struct_and_impl_epee! {
     }
 }
 
-//---------------------------------------------------------------------------------------------------- TODO
-// TODO - weird types.
-
-#[doc = monero_definition_link!(
-    cc73fe71162d564ffda8e549b79a350bca53c454,
-    "rpc/core_rpc_server_commands_defs.h",
-    210..=221
-)]
-/// Used in [`crate::bin::GetBlocksResponse`].
-#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-pub struct BlockCompleteEntry {
-    pub pruned: bool,
-    pub block: String,
-    pub block_weight: u64,
-    pub txs: Vec<TxBlobEntry>,
-}
-
-// TODO: custom epee
-// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L138-L163>
-#[cfg(feature = "epee")]
-epee_object! {
-    BlockCompleteEntry,
-    pruned: bool,
-    block: String,
-    block_weight: u64,
-    txs: Vec<TxBlobEntry>,
-}
-
-/// Used in [`crate::bin::GetBlocksResponse`].
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[repr(u8)]
-pub enum PoolInfoExtent {
-    None = 0,
-    Incremental = 1,
-    Full = 2,
-}
-
-// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L138-L163>
-#[cfg(feature = "epee")]
-impl EpeeValue for PoolInfoExtent {
-    const MARKER: Marker = <String as EpeeValue>::MARKER;
-
-    fn read<B: Buf>(r: &mut B, marker: &Marker) -> cuprate_epee_encoding::Result<Self> {
-        todo!()
-    }
-
-    fn should_write(&self) -> bool {
-        todo!()
-    }
-
-    fn epee_default_value() -> Option<Self> {
-        todo!()
-    }
-
-    fn write<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::Result<()> {
-        todo!()
-    }
-}
-
-#[doc = monero_definition_link!(
-    cc73fe71162d564ffda8e549b79a350bca53c454,
-    "rpc/core_rpc_server_commands_defs.h",
-    389..=428
-)]
-/// Used in [`crate::other::GetTransactionsResponse`].
-#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-pub struct TxEntry {
-    pub as_hex: String,
-    pub as_json: String,
-    pub block_height: u64,
-    pub block_timestamp: u64,
-    pub confirmations: u64,
-    pub double_spend_seen: bool,
-    pub in_pool: bool,
-    pub output_indices: Vec<u64>,
-    pub prunable_as_hex: String,
-    pub prunable_hash: String,
-    pub pruned_as_hex: String,
-    pub received_timestamp: u64,
-    pub relayed: bool,
-    pub tx_hash: String,
-}
-
-// TODO: custom epee
-// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L406-427>
-#[cfg(feature = "epee")]
-epee_object! {
-    TxEntry,
-    as_hex: String,
-    as_json: String, // TODO: should be its own struct
-    block_height: u64,
-    block_timestamp: u64,
-    confirmations: u64,
-    double_spend_seen: bool,
-    in_pool: bool,
-    output_indices: Vec<u64>,
-    prunable_as_hex: String,
-    prunable_hash: String,
-    pruned_as_hex: String,
-    received_timestamp: u64,
-    relayed: bool,
-    tx_hash: String,
-}
-
-//---------------------------------------------------------------------------------------------------- TODO
-/// Used in [`crate::other::IsKeyImageSpentResponse`].
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[repr(u8)]
-pub enum KeyImageSpentStatus {
-    Unspent = 0,
-    SpentInBlockchain = 1,
-    SpentInPool = 2,
-}
-
-#[cfg(feature = "epee")]
-impl EpeeValue for KeyImageSpentStatus {
-    const MARKER: Marker = <String as EpeeValue>::MARKER;
-
-    fn read<B: Buf>(r: &mut B, marker: &Marker) -> cuprate_epee_encoding::Result<Self> {
-        todo!()
-    }
-
-    fn should_write(&self) -> bool {
-        todo!()
-    }
-
-    fn epee_default_value() -> Option<Self> {
-        todo!()
-    }
-
-    fn write<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::Result<()> {
-        todo!()
-    }
-}
-
-//---------------------------------------------------------------------------------------------------- Status
-/// RPC response status.
-///
-/// This type represents `monerod`'s frequently appearing string field, `status`.
-///
-/// This field appears within RPC [JSON response](crate::json) types.
-///
-/// Reference: <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h#L78-L81>.
-///
-/// ## Serialization and string formatting
-/// ```rust
-/// use cuprate_rpc_types::{
-///     misc::Status,
-///     CORE_RPC_STATUS_BUSY, CORE_RPC_STATUS_NOT_MINING, CORE_RPC_STATUS_OK,
-///     CORE_RPC_STATUS_PAYMENT_REQUIRED, CORE_RPC_STATUS_UNKNOWN
-/// };
-/// use serde_json::to_string;
-///
-/// let unknown = Status::Unknown;
-///
-/// assert_eq!(to_string(&Status::Ok).unwrap(),              r#""OK""#);
-/// assert_eq!(to_string(&Status::Busy).unwrap(),            r#""BUSY""#);
-/// assert_eq!(to_string(&Status::NotMining).unwrap(),       r#""NOT MINING""#);
-/// assert_eq!(to_string(&Status::PaymentRequired).unwrap(), r#""PAYMENT REQUIRED""#);
-/// assert_eq!(to_string(&unknown).unwrap(),                 r#""UNKNOWN""#);
-///
-/// assert_eq!(Status::Ok.as_ref(),              CORE_RPC_STATUS_OK);
-/// assert_eq!(Status::Busy.as_ref(),            CORE_RPC_STATUS_BUSY);
-/// assert_eq!(Status::NotMining.as_ref(),       CORE_RPC_STATUS_NOT_MINING);
-/// assert_eq!(Status::PaymentRequired.as_ref(), CORE_RPC_STATUS_PAYMENT_REQUIRED);
-/// assert_eq!(unknown.as_ref(),                 CORE_RPC_STATUS_UNKNOWN);
-///
-/// assert_eq!(format!("{}", Status::Ok),              CORE_RPC_STATUS_OK);
-/// assert_eq!(format!("{}", Status::Busy),            CORE_RPC_STATUS_BUSY);
-/// assert_eq!(format!("{}", Status::NotMining),       CORE_RPC_STATUS_NOT_MINING);
-/// assert_eq!(format!("{}", Status::PaymentRequired), CORE_RPC_STATUS_PAYMENT_REQUIRED);
-/// assert_eq!(format!("{}", unknown),                 CORE_RPC_STATUS_UNKNOWN);
-///
-/// assert_eq!(format!("{:?}", Status::Ok),              "Ok");
-/// assert_eq!(format!("{:?}", Status::Busy),            "Busy");
-/// assert_eq!(format!("{:?}", Status::NotMining),       "NotMining");
-/// assert_eq!(format!("{:?}", Status::PaymentRequired), "PaymentRequired");
-/// assert_eq!(format!("{:?}", unknown),                 "Unknown");
-/// ```
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-pub enum Status {
-    // FIXME:
-    // `#[serde(rename = "")]` only takes raw string literals?
-    // We have to re-type the constants here...
-    /// Successful RPC response, everything is OK; [`CORE_RPC_STATUS_OK`].
-    #[cfg_attr(feature = "serde", serde(rename = "OK"))]
-    #[default]
-    Ok,
-
-    /// The daemon is busy, try later; [`CORE_RPC_STATUS_BUSY`].
-    #[cfg_attr(feature = "serde", serde(rename = "BUSY"))]
-    Busy,
-
-    /// The daemon is not mining; [`CORE_RPC_STATUS_NOT_MINING`].
-    #[cfg_attr(feature = "serde", serde(rename = "NOT MINING"))]
-    NotMining,
-
-    /// Payment is required for RPC; [`CORE_RPC_STATUS_PAYMENT_REQUIRED`].
-    #[cfg_attr(feature = "serde", serde(rename = "PAYMENT REQUIRED"))]
-    PaymentRequired,
-
-    /// Some unknown other string; [`CORE_RPC_STATUS_UNKNOWN`].
-    ///
-    /// This exists to act as a catch-all if `monerod` adds
-    /// a string and a Cuprate node hasn't updated yet.
-    ///
-    /// The reason this isn't `Unknown(String)` is because that
-    /// disallows [`Status`] to be [`Copy`], and thus other types
-    /// that contain it.
-    #[cfg_attr(feature = "serde", serde(other))]
-    #[cfg_attr(feature = "serde", serde(rename = "UNKNOWN"))]
-    Unknown,
-}
-
-impl From<String> for Status {
-    fn from(s: String) -> Self {
-        match s.as_str() {
-            CORE_RPC_STATUS_OK => Self::Ok,
-            CORE_RPC_STATUS_BUSY => Self::Busy,
-            CORE_RPC_STATUS_NOT_MINING => Self::NotMining,
-            CORE_RPC_STATUS_PAYMENT_REQUIRED => Self::PaymentRequired,
-            _ => Self::Unknown,
-        }
-    }
-}
-
-impl AsRef<str> for Status {
-    fn as_ref(&self) -> &str {
-        match self {
-            Self::Ok => CORE_RPC_STATUS_OK,
-            Self::Busy => CORE_RPC_STATUS_BUSY,
-            Self::NotMining => CORE_RPC_STATUS_NOT_MINING,
-            Self::PaymentRequired => CORE_RPC_STATUS_PAYMENT_REQUIRED,
-            Self::Unknown => CORE_RPC_STATUS_UNKNOWN,
-        }
-    }
-}
-
-impl Display for Status {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.write_str(self.as_ref())
-    }
-}
-
-// [`Status`] is essentially a [`String`] when it comes to
-// (de)serialization, except when writing we usually have
-// access to a `&'static str` and don't need to allocate.
-//
-// See below for more impl info:
-// <https://github.com/Cuprate/cuprate/blob/bef2a2cbd4e1194991751d1fbc96603cba8c7a51/net/epee-encoding/src/value.rs#L366-L392>.
-#[cfg(feature = "epee")]
-impl EpeeValue for Status {
-    const MARKER: Marker = <String as EpeeValue>::MARKER;
-
-    fn read<B: Buf>(r: &mut B, marker: &Marker) -> cuprate_epee_encoding::Result<Self> {
-        let string = <String as EpeeValue>::read(r, marker)?;
-        Ok(Self::from(string))
-    }
-
-    fn should_write(&self) -> bool {
-        true
-    }
-
-    fn epee_default_value() -> Option<Self> {
-        // <https://github.com/Cuprate/cuprate/pull/147#discussion_r1654992559>
-        Some(Self::Unknown)
-    }
-
-    fn write<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::Result<()> {
-        cuprate_epee_encoding::write_bytes(self.as_ref(), w)
-    }
-}
-
 //---------------------------------------------------------------------------------------------------- Tests
 #[cfg(test)]
-mod test {
-    use super::*;
-
-    // Test epee (de)serialization works.
-    #[test]
-    #[cfg(feature = "epee")]
-    fn epee() {
-        for status in [
-            Status::Ok,
-            Status::Busy,
-            Status::NotMining,
-            Status::PaymentRequired,
-            Status::Unknown,
-        ] {
-            let mut buf = vec![];
-
-            <Status as EpeeValue>::write(status, &mut buf).unwrap();
-            let status2 =
-                <Status as EpeeValue>::read(&mut buf.as_slice(), &<Status as EpeeValue>::MARKER)
-                    .unwrap();
-
-            assert_eq!(status, status2);
-        }
-    }
-}
+mod test {}
diff --git a/rpc/types/src/misc/mod.rs b/rpc/types/src/misc/mod.rs
new file mode 100644
index 00000000..14820ab1
--- /dev/null
+++ b/rpc/types/src/misc/mod.rs
@@ -0,0 +1,33 @@
+//! Miscellaneous types.
+//!
+//! These are `struct`s that appear in request/response types.
+//! For example, [`crate::json::GetConnectionsResponse`] contains
+//! the [`crate::misc::ConnectionInfo`] struct defined here.
+
+//---------------------------------------------------------------------------------------------------- Lints
+#![allow(
+    missing_docs, // Docs are at: <https://www.getmonero.org/resources/developer-guides/daemon-rpc.html>
+    clippy::struct_excessive_bools, // hey man, tell that to the people who wrote `monerod`
+)]
+
+//---------------------------------------------------------------------------------------------------- Mod
+mod binary_string;
+mod block_complete_entry;
+mod key_image_spent_status;
+mod misc;
+mod pool_info_extent;
+mod status;
+mod tx_entry;
+
+pub use binary_string::BinaryString;
+pub use block_complete_entry::BlockCompleteEntry;
+pub use key_image_spent_status::KeyImageSpentStatus;
+pub use misc::{
+    AuxPow, BlockHeader, BlockOutputIndices, ChainInfo, ConnectionInfo, GetBan,
+    GetMinerDataTxBacklogEntry, GetOutputsOut, HardforkEntry, HistogramEntry, OutKey, OutKeyBin,
+    OutputDistributionData, Peer, PoolTxInfo, PublicNode, SetBan, Span, SpentKeyImageInfo,
+    SyncInfoPeer, TxBacklogEntry, TxBlobEntry, TxInfo, TxOutputIndices, TxpoolHisto, TxpoolStats,
+};
+pub use pool_info_extent::PoolInfoExtent;
+pub use status::Status;
+pub use tx_entry::TxEntry;
diff --git a/rpc/types/src/misc/pool_info_extent.rs b/rpc/types/src/misc/pool_info_extent.rs
new file mode 100644
index 00000000..cf8c995a
--- /dev/null
+++ b/rpc/types/src/misc/pool_info_extent.rs
@@ -0,0 +1,44 @@
+//! TODO
+
+//---------------------------------------------------------------------------------------------------- Use
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+
+#[cfg(feature = "epee")]
+use cuprate_epee_encoding::{
+    macros::bytes::{Buf, BufMut},
+    EpeeValue, Marker,
+};
+
+//---------------------------------------------------------------------------------------------------- PoolInfoExtent
+/// Used in [`crate::bin::GetBlocksResponse`].
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[repr(u8)]
+pub enum PoolInfoExtent {
+    None = 0,
+    Incremental = 1,
+    Full = 2,
+}
+
+// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L138-L163>
+#[cfg(feature = "epee")]
+impl EpeeValue for PoolInfoExtent {
+    const MARKER: Marker = <String as EpeeValue>::MARKER;
+
+    fn read<B: Buf>(r: &mut B, marker: &Marker) -> cuprate_epee_encoding::Result<Self> {
+        todo!()
+    }
+
+    fn should_write(&self) -> bool {
+        todo!()
+    }
+
+    fn epee_default_value() -> Option<Self> {
+        todo!()
+    }
+
+    fn write<B: BufMut>(self, w: &mut B) -> cuprate_epee_encoding::Result<()> {
+        todo!()
+    }
+}
diff --git a/rpc/types/src/status.rs b/rpc/types/src/misc/status.rs
similarity index 97%
rename from rpc/types/src/status.rs
rename to rpc/types/src/misc/status.rs
index 86cf4b92..cf83b269 100644
--- a/rpc/types/src/status.rs
+++ b/rpc/types/src/misc/status.rs
@@ -18,6 +18,10 @@ use crate::constants::{
 };
 
 //---------------------------------------------------------------------------------------------------- Status
+// TODO: this type needs to expand more.
+// There are a lot of RPC calls that will return a random
+// string inside, which isn't compatible with [`Status`].
+
 /// RPC response status.
 ///
 /// This type represents `monerod`'s frequently appearing string field, `status`.
@@ -29,7 +33,7 @@ use crate::constants::{
 /// ## Serialization and string formatting
 /// ```rust
 /// use cuprate_rpc_types::{
-///     Status,
+///     misc::Status,
 ///     CORE_RPC_STATUS_BUSY, CORE_RPC_STATUS_NOT_MINING, CORE_RPC_STATUS_OK,
 ///     CORE_RPC_STATUS_PAYMENT_REQUIRED, CORE_RPC_STATUS_UNKNOWN
 /// };
diff --git a/rpc/types/src/misc/tx_entry.rs b/rpc/types/src/misc/tx_entry.rs
new file mode 100644
index 00000000..fafa3814
--- /dev/null
+++ b/rpc/types/src/misc/tx_entry.rs
@@ -0,0 +1,59 @@
+//! TODO
+
+//---------------------------------------------------------------------------------------------------- Use
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+
+#[cfg(feature = "epee")]
+use cuprate_epee_encoding::{
+    epee_object,
+    macros::bytes::{Buf, BufMut},
+    EpeeValue, Marker,
+};
+
+//---------------------------------------------------------------------------------------------------- TxEntry
+#[doc = crate::macros::monero_definition_link!(
+    cc73fe71162d564ffda8e549b79a350bca53c454,
+    "rpc/core_rpc_server_commands_defs.h",
+    389..=428
+)]
+/// Used in [`crate::other::GetTransactionsResponse`].
+#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct TxEntry {
+    pub as_hex: String,
+    pub as_json: String,
+    pub block_height: u64,
+    pub block_timestamp: u64,
+    pub confirmations: u64,
+    pub double_spend_seen: bool,
+    pub in_pool: bool,
+    pub output_indices: Vec<u64>,
+    pub prunable_as_hex: String,
+    pub prunable_hash: String,
+    pub pruned_as_hex: String,
+    pub received_timestamp: u64,
+    pub relayed: bool,
+    pub tx_hash: String,
+}
+
+// TODO: custom epee
+// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/cryptonote_protocol/cryptonote_protocol_defs.h#L406-427>
+#[cfg(feature = "epee")]
+epee_object! {
+    TxEntry,
+    as_hex: String,
+    as_json: String, // TODO: should be its own struct
+    block_height: u64,
+    block_timestamp: u64,
+    confirmations: u64,
+    double_spend_seen: bool,
+    in_pool: bool,
+    output_indices: Vec<u64>,
+    prunable_as_hex: String,
+    prunable_hash: String,
+    pruned_as_hex: String,
+    received_timestamp: u64,
+    relayed: bool,
+    tx_hash: String,
+}