-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6ce083e
commit bb79b81
Showing
4 changed files
with
221 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,215 +1,5 @@ | ||
#[cfg(unix)] | ||
mod api; | ||
#[cfg(unix)] | ||
pub mod rpc; | ||
pub mod server; | ||
|
||
use crate::commands; | ||
|
||
use std::{error, fmt}; | ||
|
||
use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
#[serde(deny_unknown_fields)] | ||
#[serde(untagged)] | ||
pub enum Params { | ||
Array(Vec<serde_json::Value>), | ||
Map(serde_json::Map<String, serde_json::Value>), | ||
} | ||
|
||
impl Params { | ||
/// Get the parameter supposed to be at a given index / of a given name. | ||
pub fn get<Q>(&self, index: usize, name: &Q) -> Option<&serde_json::Value> | ||
where | ||
String: std::borrow::Borrow<Q>, | ||
Q: ?Sized + Ord + Eq + std::hash::Hash, | ||
{ | ||
match self { | ||
Params::Array(vec) => vec.get(index), | ||
Params::Map(map) => map.get(name), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
#[serde(deny_unknown_fields)] | ||
#[serde(untagged)] | ||
pub enum ReqId { | ||
Num(u64), | ||
Str(String), | ||
} | ||
|
||
/// A JSONRPC2 request. See https://www.jsonrpc.org/specification#request_object. | ||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
#[serde(deny_unknown_fields)] | ||
pub struct Request { | ||
/// Version. Must be "2.0". | ||
pub jsonrpc: String, | ||
/// Command name. | ||
pub method: String, | ||
/// Command parameters. | ||
pub params: Option<Params>, | ||
/// Request identifier. | ||
pub id: ReqId, | ||
} | ||
|
||
/// A failure to broadcast a transaction to the P2P network. | ||
const BROADCAST_ERROR: i64 = 1_000; | ||
|
||
/// JSONRPC2 error codes. See https://www.jsonrpc.org/specification#error_object. | ||
#[derive(Debug, PartialEq, Eq, Clone)] | ||
pub enum ErrorCode { | ||
/// The method does not exist / is not available. | ||
MethodNotFound, | ||
/// Invalid method parameter(s). | ||
InvalidParams, | ||
/// Internal error while handling the command. | ||
InternalError, | ||
/// Reserved for implementation-defined server-errors. | ||
ServerError(i64), | ||
} | ||
|
||
impl From<&ErrorCode> for i64 { | ||
fn from(code: &ErrorCode) -> i64 { | ||
match code { | ||
ErrorCode::MethodNotFound => -32601, | ||
ErrorCode::InvalidParams => -32602, | ||
ErrorCode::InternalError => -32603, | ||
ErrorCode::ServerError(code) => *code, | ||
} | ||
} | ||
} | ||
|
||
impl From<i64> for ErrorCode { | ||
fn from(code: i64) -> ErrorCode { | ||
match code { | ||
-32601 => ErrorCode::MethodNotFound, | ||
-32602 => ErrorCode::InvalidParams, | ||
-32603 => ErrorCode::InternalError, | ||
code => ErrorCode::ServerError(code), | ||
} | ||
} | ||
} | ||
|
||
impl<'a> Deserialize<'a> for ErrorCode { | ||
fn deserialize<D>(deserializer: D) -> Result<ErrorCode, D::Error> | ||
where | ||
D: Deserializer<'a>, | ||
{ | ||
let code: i64 = Deserialize::deserialize(deserializer)?; | ||
Ok(code.into()) | ||
} | ||
} | ||
|
||
impl Serialize for ErrorCode { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: Serializer, | ||
{ | ||
serializer.serialize_i64(self.into()) | ||
} | ||
} | ||
|
||
/// JSONRPC2 error response. See https://www.jsonrpc.org/specification#error_object. | ||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] | ||
#[serde(deny_unknown_fields)] | ||
pub struct Error { | ||
pub code: ErrorCode, | ||
pub message: String, | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub data: Option<serde_json::Value>, | ||
} | ||
|
||
impl Error { | ||
pub fn new(code: ErrorCode, message: impl Into<String>) -> Error { | ||
Error { | ||
message: message.into(), | ||
code, | ||
data: None, | ||
} | ||
} | ||
|
||
pub fn method_not_found() -> Error { | ||
Error::new(ErrorCode::MethodNotFound, "Method not found") | ||
} | ||
|
||
pub fn invalid_params(message: impl Into<String>) -> Error { | ||
Error::new( | ||
ErrorCode::InvalidParams, | ||
format!("Invalid params: {}", message.into()), | ||
) | ||
} | ||
} | ||
|
||
impl fmt::Display for Error { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
let code: i64 = (&self.code).into(); | ||
write!(f, "{}: {}", code, self.message) | ||
} | ||
} | ||
|
||
impl error::Error for Error {} | ||
|
||
impl From<commands::CommandError> for Error { | ||
fn from(e: commands::CommandError) -> Error { | ||
match e { | ||
commands::CommandError::NoOutpointForSelfSend | ||
| commands::CommandError::UnknownOutpoint(..) | ||
| commands::CommandError::InvalidFeerate(..) | ||
| commands::CommandError::AlreadySpent(..) | ||
| commands::CommandError::ImmatureCoinbase(..) | ||
| commands::CommandError::Address(..) | ||
| commands::CommandError::SpendCreation(..) | ||
| commands::CommandError::InsufficientFunds(..) | ||
| commands::CommandError::UnknownSpend(..) | ||
| commands::CommandError::SpendFinalization(..) | ||
| commands::CommandError::InsaneRescanTimestamp(..) | ||
| commands::CommandError::AlreadyRescanning | ||
| commands::CommandError::InvalidDerivationIndex | ||
| commands::CommandError::RbfError(..) | ||
| commands::CommandError::EmptyFilterList | ||
| commands::CommandError::RecoveryNotAvailable => { | ||
Error::new(ErrorCode::InvalidParams, e.to_string()) | ||
} | ||
commands::CommandError::RescanTrigger(..) => { | ||
Error::new(ErrorCode::InternalError, e.to_string()) | ||
} | ||
commands::CommandError::TxBroadcast(_) => { | ||
Error::new(ErrorCode::ServerError(BROADCAST_ERROR), e.to_string()) | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// JSONRPC2 response. See https://www.jsonrpc.org/specification#response_object. | ||
#[derive(Clone, Debug, PartialEq, Eq, Serialize)] | ||
#[serde(deny_unknown_fields)] | ||
pub struct Response { | ||
/// Version. Must be "2.0". | ||
jsonrpc: String, | ||
/// Required on success. Must not exist on error. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
result: Option<serde_json::Value>, | ||
/// Required on error. Must not exist on success. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
error: Option<Error>, | ||
/// Request identifier. | ||
id: ReqId, | ||
} | ||
|
||
impl Response { | ||
fn new(id: ReqId, result: Option<serde_json::Value>, error: Option<Error>) -> Response { | ||
Response { | ||
jsonrpc: "2.0".to_string(), | ||
result, | ||
error, | ||
id, | ||
} | ||
} | ||
|
||
pub fn success(id: ReqId, result: serde_json::Value) -> Response { | ||
Response::new(id, Some(result), None) | ||
} | ||
|
||
pub fn error(id: ReqId, error: Error) -> Response { | ||
Response::new(id, None, Some(error)) | ||
} | ||
} |
Oops, something went wrong.