1use core::fmt;
2use std::io;
3
4use sonic_rs::{Value, json};
5use thiserror::Error;
6
7#[derive(Debug, Error)]
9pub enum RpcError {
10 #[error("parse error: {0}")]
12 Parse(String),
13 #[error("invalid request: {0}")]
15 InvalidRequest(&'static str),
16 #[error("method not found: {0}")]
18 MethodNotFound(String),
19 #[error("invalid params: {0}")]
21 InvalidParams(&'static str),
22 #[error("invalid type: {0}")]
24 InvalidType(&'static str),
25 #[error("not found: {0}")]
27 NotFound(&'static str),
28 #[error("{0}")]
30 MethodDisabled(&'static str),
31 #[error("internal error: {0}")]
33 Internal(String),
34}
35
36impl RpcError {
37 pub const PARSE_ERROR: i64 = -32_700;
39 pub const INVALID_REQUEST: i64 = -32_600;
41 pub const METHOD_NOT_FOUND: i64 = -32_601;
43 pub const INVALID_PARAMS: i64 = -32_602;
45 pub const INTERNAL_ERROR: i64 = -32_603;
47 pub const CORE_INVALID_TYPE: i64 = -3;
49 pub const CORE_NOT_FOUND: i64 = -5;
51 pub const CORE_INVALID_PARAMETER: i64 = -8;
53
54 #[must_use]
56 pub const fn method_disabled(message: &'static str) -> Self {
57 Self::MethodDisabled(message)
58 }
59
60 #[must_use]
62 pub const fn code(&self) -> i64 {
63 match self {
64 Self::Parse(_) => Self::PARSE_ERROR,
65 Self::InvalidRequest(_) => Self::INVALID_REQUEST,
66 Self::MethodNotFound(_) => Self::METHOD_NOT_FOUND,
67 Self::InvalidParams(_) => Self::INVALID_PARAMS,
68 Self::InvalidType(_) => Self::CORE_INVALID_TYPE,
69 Self::NotFound(_) => Self::CORE_NOT_FOUND,
70 Self::MethodDisabled(_) | Self::Internal(_) => Self::INTERNAL_ERROR,
71 }
72 }
73
74 #[must_use]
76 pub fn response(&self, id: &Value) -> Value {
77 json!({
78 "jsonrpc": "2.0",
79 "result": null,
80 "error": {"code": self.code(), "message": self.to_string()},
81 "id": id
82 })
83 }
84}
85
86impl From<sonic_rs::Error> for RpcError {
87 fn from(error: sonic_rs::Error) -> Self {
88 Self::Parse(error.to_string())
89 }
90}
91
92impl From<serde_json::Error> for RpcError {
93 fn from(error: serde_json::Error) -> Self {
94 Self::Internal(error.to_string())
95 }
96}
97
98impl From<io::Error> for RpcError {
99 fn from(error: io::Error) -> Self {
100 Self::Internal(error.to_string())
101 }
102}
103
104impl From<bitcoin::consensus::encode::Error> for RpcError {
105 fn from(_error: bitcoin::consensus::encode::Error) -> Self {
106 Self::InvalidParams("consensus decoding failed")
107 }
108}
109
110impl From<bitcoin::hex::HexToBytesError> for RpcError {
111 fn from(_error: bitcoin::hex::HexToBytesError) -> Self {
112 Self::InvalidParams("hex string is invalid")
113 }
114}
115
116impl From<core::str::Utf8Error> for RpcError {
117 fn from(error: core::str::Utf8Error) -> Self {
118 Self::Parse(error.to_string())
119 }
120}
121
122impl From<fmt::Error> for RpcError {
123 fn from(error: fmt::Error) -> Self {
124 Self::Internal(error.to_string())
125 }
126}