neptune-rpc-api 0.14.0

Neptune JSON-RPC API contract: the RpcApi trait and its data-transfer model types
use neptune_rpc_macros::Router;
use neptune_rpc_macros::Routes;
use serde::Deserialize;
use serde::Serialize;

use crate::api::client::transport::Transport;
use crate::api::rpc::RpcApi;
use crate::api::rpc::RpcResult;
use crate::api::server::router::RpcRouter;
use crate::model::json::JsonError;
use crate::model::message::*;

/// API version.
///
/// Must be bumped every time a breaking change to the RPC API is made. Adding
/// a new endpoint is not a breaking change. Neither is adding a new field to
/// a type that is returned by this API.
pub const RPC_API_VERSION: u16 = 2;

#[derive(
    Clone,
    Copy,
    Debug,
    PartialEq,
    Eq,
    Hash,
    Serialize,
    Deserialize,
    strum::EnumString,
    strum::Display,
)]
#[serde(rename_all = "camelCase")]
#[strum(ascii_case_insensitive, serialize_all = "camelCase")]
pub enum Namespace {
    Node,
    Network,
    Chain,
    Mining,
    Archival,

    /// Endpoints for inspecting the mempool status
    Mempool,

    /// Endpoints for serving external wallets
    Wallet,

    /// Endpoints for managing personal wallet
    Personal,

    /// Endpoints relating to and requiring a UTXO index
    Utxoindex,
}

#[derive(
    Router, Routes, Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, strum::Display,
)]
#[serde(rename_all = "camelCase")]
#[strum(serialize_all = "camelCase")]
pub enum RpcMethods {
    #[namespace(Namespace::Node)]
    Network,

    #[namespace(Namespace::Chain)]
    Height,

    #[namespace(Namespace::Chain)]
    TipDigest,

    #[namespace(Namespace::Chain)]
    Tip,

    #[namespace(Namespace::Chain)]
    TipProof,

    #[namespace(Namespace::Chain)]
    TipKernel,

    #[namespace(Namespace::Chain)]
    TipHeader,

    #[namespace(Namespace::Chain)]
    TipBody,

    #[namespace(Namespace::Chain)]
    TipTransactionKernel,

    #[namespace(Namespace::Chain)]
    TipAnnouncements,

    #[namespace(Namespace::Archival)]
    GetBlockDigest,

    #[namespace(Namespace::Archival)]
    GetBlockDigests,

    #[namespace(Namespace::Archival)]
    GetBlock,

    #[namespace(Namespace::Archival)]
    GetBlockProof,

    #[namespace(Namespace::Archival)]
    GetBlockKernel,

    #[namespace(Namespace::Archival)]
    GetBlockHeader,

    #[namespace(Namespace::Archival)]
    GetBlockBody,

    #[namespace(Namespace::Archival)]
    GetBlockTransactionKernel,

    #[namespace(Namespace::Archival)]
    GetBlockAnnouncements,

    #[namespace(Namespace::Archival)]
    IsBlockCanonical,

    #[namespace(Namespace::Archival)]
    GetUtxoDigest,

    #[namespace(Namespace::Archival)]
    FindUtxoOrigin,

    #[namespace(Namespace::Archival)]
    UtxoOriginFromAbsoluteIndices,

    #[namespace(Namespace::Archival)]
    AreBloomIndicesSet,

    #[namespace(Namespace::Archival)]
    BatchAreBloomIndicesSet,

    #[namespace(Namespace::Archival)]
    CirculatingSupply,

    #[namespace(Namespace::Archival)]
    MaxSupply,

    #[namespace(Namespace::Archival)]
    BurnedSupply,

    #[namespace(Namespace::Wallet)]
    ValidateAddress,

    #[namespace(Namespace::Wallet)]
    ValidateCoinsAmount,

    #[namespace(Namespace::Wallet)]
    ValidateNauAmount,

    #[namespace(Namespace::Wallet)]
    GetBlocks,

    #[namespace(Namespace::Wallet)]
    RestoreMembershipProof,

    #[namespace(Namespace::Wallet)]
    SubmitTransaction,

    #[namespace(Namespace::Personal)]
    RescanAnnounced,

    #[namespace(Namespace::Personal)]
    RescanExpected,

    #[namespace(Namespace::Personal)]
    RescanOutgoing,

    #[namespace(Namespace::Personal)]
    RescanGuesserRewards,

    #[namespace(Namespace::Personal)]
    DerivationIndex,

    #[namespace(Namespace::Personal)]
    SetDerivationIndex,

    #[namespace(Namespace::Personal)]
    GenerateAddress,

    #[namespace(Namespace::Personal)]
    IncomingHistory,

    #[namespace(Namespace::Personal)]
    OutgoingHistory,

    #[namespace(Namespace::Personal)]
    UnspentUtxos,

    #[namespace(Namespace::Personal)]
    GetBalance,

    #[namespace(Namespace::Personal)]
    CountSentTransactionsAtBlock,

    #[namespace(Namespace::Personal)]
    Send,

    #[namespace(Namespace::Personal)]
    ClaimUtxo,

    #[namespace(Namespace::Mining)]
    GetBlockTemplate,

    #[namespace(Namespace::Mining)]
    SubmitBlock,

    #[namespace(Namespace::Utxoindex)]
    BlockHeightsByFlags,

    #[namespace(Namespace::Utxoindex)]
    BlockHeightsByAdditionRecords,

    #[namespace(Namespace::Utxoindex)]
    BlockHeightsByAbsoluteIndexSets,

    #[namespace(Namespace::Utxoindex)]
    WasMined,

    #[namespace(Namespace::Mempool)]
    Transactions,

    #[namespace(Namespace::Mempool)]
    GetTransactionKernel,

    #[namespace(Namespace::Mempool)]
    GetTransactionProof,

    #[namespace(Namespace::Mempool)]
    GetTransactionsByAdditionRecords,

    #[namespace(Namespace::Mempool)]
    GetTransactionsByAbsoluteIndexSets,

    #[namespace(Namespace::Mempool)]
    BestTransactionForNextBlock,

    #[namespace(Namespace::Network)]
    Ban,
    #[namespace(Namespace::Network)]
    Unban,
    #[namespace(Namespace::Network)]
    UnbanAll,
    #[namespace(Namespace::Network)]
    Dial,
    #[namespace(Namespace::Network)]
    ProbeNat,
    #[namespace(Namespace::Network)]
    ResetRelayReservations,
    #[namespace(Namespace::Network)]
    NetworkOverview,
}

#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
    use super::*;

    #[test]
    fn namespace_parses_case_insensitively() {
        use std::str::FromStr;

        assert_eq!(Namespace::from_str("node").unwrap(), Namespace::Node);
        assert_eq!(Namespace::from_str("Node").unwrap(), Namespace::Node);
        assert_eq!(Namespace::from_str("NODE").unwrap(), Namespace::Node);
        assert_eq!(Namespace::from_str("NoDe").unwrap(), Namespace::Node);

        assert!(
            Namespace::from_str("nodewallet").is_err(),
            "Expected parse error for invalid namespace"
        );
    }

    #[test]
    fn display_names_use_camelcase() {
        assert_eq!("wallet".to_owned(), Namespace::Wallet.to_string());
        assert_eq!(
            "submitTransaction".to_owned(),
            RpcMethods::SubmitTransaction.to_string()
        );
    }
}