lsp_primitives/
methods.rs

1/// Defines all RPC-methods
2///
3///
4///
5use crate::json_rpc::{DefaultError, JsonRpcMethod, NoParams};
6pub use crate::lsps0::schema::ListprotocolsResponse;
7pub use crate::lsps1::schema::{
8    Lsps1CreateOrderRequest, Lsps1CreateOrderResponse, Lsps1GetInfoResponse, Lsps1GetOrderRequest,
9    Lsps1GetOrderResponse, Lsps1InfoRequest,
10};
11pub use crate::lsps2::schema::{
12    Lsps2BuyRequest, Lsps2BuyResponse, Lsps2GetInfoRequest, Lsps2GetInfoResponse,
13    Lsps2GetVersionsResponse,
14};
15
16use serde::de::{Deserializer, Visitor};
17use serde::ser::Serializer;
18use serde::{Deserialize, Serialize};
19
20use anyhow::{anyhow, Result};
21
22// Every time I read this file I am tempted to write a macro that
23// generates it. I've tried it a few times but the result never improved
24// the code-base.
25//
26// If you can write a macro that makes this code more readable, shorter and
27// easier to maintain let me know. I'd be happy to merge
28
29// All rpc-methods defined in the LSPS standard
30// The generics are <I,O,E> where
31// - I represents the params
32// - O represents the result data
33// - E represents the error if present
34//
35// To create language bindings for a new rpc-call you must
36// 1. Add it to the JsonRpcMethodEnum
37// 2. Add it to the from_method_name function
38// 3. Add it to the ref_erase function
39pub type Lsps0ListProtocols = JsonRpcMethod<'static, NoParams, ListprotocolsResponse, DefaultError>;
40
41pub type Lsps1GetInfo =
42    JsonRpcMethod<'static, Lsps1InfoRequest, Lsps1GetInfoResponse, DefaultError>;
43pub type Lsps1CreateOrder =
44    JsonRpcMethod<'static, Lsps1CreateOrderRequest, Lsps1CreateOrderResponse, DefaultError>;
45
46pub type Lsps1GetOrder =
47    JsonRpcMethod<'static, Lsps1GetOrderRequest, Lsps1GetOrderResponse, DefaultError>;
48
49// LSPS0: Transport layer
50pub const LSPS0_LIST_PROTOCOLS: Lsps0ListProtocols =
51    Lsps0ListProtocols::new("lsps0.list_protocols");
52
53// LSPS1: Buy Channels
54pub const LSPS1_GETINFO: Lsps1GetInfo = Lsps1GetInfo::new("lsps1.get_info");
55pub const LSPS1_CREATE_ORDER: Lsps1CreateOrder = Lsps1CreateOrder::new("lsps1.create_order");
56pub const LSPS1_GET_ORDER: Lsps1GetOrder = Lsps1GetOrder::new("lsps1.get_order");
57
58pub enum JsonRpcMethodEnum {
59    Lsps0ListProtocols(Lsps0ListProtocols),
60    Lsps1Info(Lsps1GetInfo),
61    Lsps1CreateOrder(Lsps1CreateOrder),
62    Lsps1GetOrder(Lsps1GetOrder),
63}
64
65impl Serialize for JsonRpcMethodEnum {
66    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67    where
68        S: Serializer,
69    {
70        serializer.serialize_str(self.name())
71    }
72}
73
74impl<'de> Deserialize<'de> for JsonRpcMethodEnum {
75    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
76    where
77        D: Deserializer<'de>,
78    {
79        struct JsonRpcMethodEnumVisitor;
80
81        impl<'de> Visitor<'de> for JsonRpcMethodEnumVisitor {
82            type Value = JsonRpcMethodEnum;
83
84            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
85                formatter.write_str("A valid rpc-method name")
86            }
87
88            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
89            where
90                E: serde::de::Error,
91            {
92                let result = JsonRpcMethodEnum::from_method_name(value);
93                result.map_err(|_| E::custom(format!("Unknown method '{}'", value)))
94            }
95        }
96
97        deserializer.deserialize_str(JsonRpcMethodEnumVisitor)
98    }
99}
100
101impl JsonRpcMethodEnum {
102    pub fn from_method_name(value: &str) -> Result<JsonRpcMethodEnum> {
103        match value {
104            "lsps0.list_protocols" => Ok(Self::Lsps0ListProtocols(LSPS0_LIST_PROTOCOLS)),
105            "lsps1.get_info" => Ok(Self::Lsps1Info(LSPS1_GETINFO)),
106            "lsps1.create_order" => Ok(Self::Lsps1CreateOrder(LSPS1_CREATE_ORDER)),
107            "lsps1.get_order" => Ok(Self::Lsps1GetOrder(LSPS1_GET_ORDER)),
108            default => Err(anyhow!("Unknown method '{}'", default)),
109        }
110    }
111
112    pub fn name(&self) -> &'static str {
113        match self {
114            Self::Lsps0ListProtocols(x) => x.name(),
115            Self::Lsps1Info(x) => x.name(),
116            Self::Lsps1CreateOrder(x) => x.name(),
117            Self::Lsps1GetOrder(x) => x.name(),
118        }
119    }
120}