bitcoins_provider/rpc/
common.rs

1use async_trait::async_trait;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use std::{
5    fmt,
6    sync::atomic::{AtomicU64, Ordering},
7};
8use thiserror::Error;
9
10use crate::provider::ProviderError;
11
12#[derive(Serialize, Deserialize, Debug, Clone, Error)]
13/// A JSON-RPC 2.0 error
14pub struct ErrorResponse {
15    /// The error code
16    pub code: i64,
17    /// The error message
18    pub message: String,
19    /// Additional data
20    pub data: Option<Value>,
21}
22
23impl fmt::Display for ErrorResponse {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(
26            f,
27            "(code: {}, message: {}, data: {:?})",
28            self.code, self.message, self.data
29        )
30    }
31}
32
33impl From<ErrorResponse> for ProviderError {
34    fn from(e: ErrorResponse) -> Self {
35        ProviderError::RpcErrorResponse(e)
36    }
37}
38
39#[derive(Serialize, Deserialize, Debug)]
40/// A JSON-RPC request
41pub struct Request<'a, T> {
42    id: u64,
43    jsonrpc: &'a str,
44    method: &'a str,
45    params: T,
46}
47
48impl<'a, T> Request<'a, T> {
49    /// Creates a new JSON RPC request
50    pub fn new(id: u64, method: &'a str, params: T) -> Self {
51        Self {
52            id,
53            jsonrpc: "2.0",
54            method,
55            params,
56        }
57    }
58}
59
60// In case the node doesn't conform properly
61static RPC2: &str = "2.0";
62fn rpc_version() -> String {
63    RPC2.to_owned()
64}
65
66#[derive(Serialize, Deserialize, Debug, Clone)]
67/// A succesful response
68pub struct Response<T> {
69    id: u64,
70    #[serde(default = "rpc_version")]
71    jsonrpc: String,
72    /// The response payload
73    #[serde(flatten)]
74    pub data: ResponseData<T>,
75}
76
77#[derive(Serialize, Deserialize, Debug, Clone)]
78#[serde(untagged)]
79/// The two possible responses from the API
80pub enum ResponseData<R> {
81    /// Error Response
82    Error {
83        /// The Error
84        error: ErrorResponse,
85    },
86    /// Succesful response
87    Success {
88        /// The response
89        result: R,
90    },
91}
92
93impl<R> ResponseData<R> {
94    /// Consume response and return value
95    pub fn into_result(self) -> Result<R, ErrorResponse> {
96        match self {
97            ResponseData::Success { result } => Ok(result),
98            ResponseData::Error { error } => Err(error),
99        }
100    }
101}
102
103/// A JSON RPC transport
104#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
105#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
106pub trait JsonRpcTransport: Default {
107    /// Return a reference to the underlying AtomicU64 used for creating request IDs
108    fn id(&self) -> &AtomicU64;
109
110    /// Get the next request ID
111    fn next_id(&self) -> u64 {
112        self.id().fetch_add(1, Ordering::SeqCst)
113    }
114
115    /// Make a request, and receive a future with the response
116    async fn request<T: Serialize + Send + Sync, R: for<'a> Deserialize<'a>>(
117        &self,
118        method: &str,
119        params: T,
120    ) -> Result<R, ProviderError>;
121}
122
123/*
124
125    https://github.com/gakonst/ethers-rs
126
127    Copyright (c) 2020 Georgios Konstantopoulos
128
129    Permission is hereby granted, free of charge, to any
130    person obtaining a copy of this software and associated
131    documentation files (the "Software"), to deal in the
132    Software without restriction, including without
133    limitation the rights to use, copy, modify, merge,
134    publish, distribute, sublicense, and/or sell copies of
135    the Software, and to permit persons to whom the Software
136    is furnished to do so, subject to the following
137    conditions:
138
139    The above copyright notice and this permission notice
140    shall be included in all copies or substantial portions
141    of the Software.
142
143    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
144    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
145    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
146    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
147    SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
148    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
149    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
150    IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER
151    DEALINGS IN THE SOFTWARE.R
152*/