Skip to main content

drift_sdk/rpc/
core.rs

1use std::io::Cursor;
2
3use ciborium::Value;
4use serde::{Deserialize, Serialize};
5
6pub const DRIFTRPC_VERSION: &str = "0.1.0";
7
8#[derive(Serialize, Deserialize, Debug)]
9pub struct DriftRPCRequest {
10    pub drpc: String,
11    pub method: String,
12    pub params: Value,
13    pub id: Value,
14}
15
16impl DriftRPCRequest {
17    pub fn new(method: impl Into<String>, params: Value, id: impl Into<Value>) -> Self {
18        Self {
19            drpc: DRIFTRPC_VERSION.into(),
20            method: method.into(),
21            params,
22            id: id.into(),
23        }
24    }
25
26    pub fn maybe_from_cbor(vec: Vec<u8>) -> Option<Self> {
27        ciborium::de::from_reader(Cursor::new(vec)).ok()
28    }
29
30    /// Create a new notification, e.g. a request with id == null
31    pub fn notification(method: impl Into<String>, params: Value) -> Self {
32        Self {
33            drpc: DRIFTRPC_VERSION.into(),
34            method: method.into(),
35            params,
36            id: Value::Null,
37        }
38    }
39
40    /// Create a new call, e.g. a request with id == null and no parameters (params == null)
41    pub fn call(method: impl Into<String>) -> Self {
42        Self {
43            drpc: DRIFTRPC_VERSION.into(),
44            method: method.into(),
45            params: Value::Null,
46            id: Value::Null,
47        }
48    }
49}
50
51impl Into<Vec<u8>> for DriftRPCRequest {
52    /// Marshal this DriftRPCRequest into a series of bytes (i.e., literally, serialise)
53    fn into(self) -> Vec<u8> {
54        let mut cbor = Vec::new();
55        ciborium::ser::into_writer(&self, &mut cbor).expect("Failed to serialize DriftRPCRequest");
56        cbor
57    }
58}
59
60#[derive(Serialize, Deserialize, Debug)]
61pub struct DriftRPCResponse {
62    pub drpc: String,
63    pub result: Value,
64    pub id: Value,
65}
66
67#[derive(Serialize, Deserialize, Debug)]
68pub struct DriftRPCErrorDescription {
69    pub code: i64,
70    pub message: String,
71    pub data: Option<Value>,
72}
73
74#[derive(Serialize, Deserialize, Debug)]
75pub struct DriftRPCError {
76    pub drpc: String,
77    pub error: Value,
78    pub id: Value,
79}
80
81#[derive(Serialize, Deserialize, Debug)]
82#[serde(untagged)]
83pub enum DRPCMessage {
84    DriftRPCRequest(DriftRPCRequest),
85    DriftRPCResponse(DriftRPCResponse),
86    DriftRPCError(DriftRPCError),
87}
88
89#[derive(Debug)]
90pub enum DriftRPCErrorCode {
91    ParseError,
92    InvalidRequest,
93    MethodNotFound,
94    InvalidParams,
95    InternalError,
96}
97
98impl Into<i32> for DriftRPCErrorCode {
99    /// Turn DriftRPCErrorCode into an integer code that can be included in a DriftRPC message.
100    fn into(self) -> i32 {
101        match self {
102            DriftRPCErrorCode::ParseError => -32700,
103            DriftRPCErrorCode::InvalidRequest => -32600,
104            DriftRPCErrorCode::MethodNotFound => -32601,
105            DriftRPCErrorCode::InvalidParams => -32602,
106            DriftRPCErrorCode::InternalError => -32603,
107        }
108    }
109}
110
111impl Into<Value> for DriftRPCErrorCode {
112    /// Turn DriftRPCErrorCode into an integer code that can be included in a DriftRPC message, wrapped as a Value
113    fn into(self) -> Value {
114        let c: i32 = self.into();
115        c.into()
116    }
117}
118
119impl DriftRPCError {
120    pub fn new(code: DriftRPCErrorCode, message: String, id: Value) -> Self {
121        Self {
122            drpc: DRIFTRPC_VERSION.into(),
123            error: Value::Map(vec![
124                ("code".into(), code.into()),
125                ("message".into(), message.into()),
126            ]),
127            id,
128        }
129    }
130}