1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use std::fmt::Display;

use jsonrpc_core::ErrorCode;
use serde::Deserialize;
use serde::Serialize;

#[derive(Deserialize, Serialize)]
pub struct GetBlockchainInfoRes {
    pub best_block: String,
    pub height: u32,
    pub ibd: bool,
    pub validated: u32,
    pub latest_work: String,
    pub latest_block_time: u32,
    pub leaf_count: u32,
    pub root_count: u32,
    pub root_hashes: Vec<String>,
    pub chain: String,
    pub progress: f32,
    pub difficulty: u64,
}

#[derive(Deserialize, Serialize)]
pub struct RawTxJson {
    pub in_active_chain: bool,
    pub hex: String,
    pub txid: String,
    pub hash: String,
    pub size: u32,
    pub vsize: u32,
    pub weight: u32,
    pub version: u32,
    pub locktime: u32,
    pub vin: Vec<TxInJson>,
    pub vout: Vec<TxOutJson>,
    pub blockhash: String,
    pub confirmations: u32,
    pub blocktime: u32,
    pub time: u32,
}

#[derive(Deserialize, Serialize)]
pub struct TxOutJson {
    pub value: u64,
    pub n: u32,
    pub script_pub_key: ScriptPubKeyJson,
}

#[derive(Deserialize, Serialize)]
pub struct ScriptPubKeyJson {
    pub asm: String,
    pub hex: String,
    pub req_sigs: u32,
    #[serde(rename = "type")]
    pub type_: String,
    pub address: String,
}

#[derive(Deserialize, Serialize)]
pub struct TxInJson {
    pub txid: String,
    pub vout: u32,
    pub script_sig: ScriptSigJson,
    pub sequence: u32,
    pub witness: Vec<String>,
}

#[derive(Deserialize, Serialize)]
pub struct ScriptSigJson {
    pub asm: String,
    pub hex: String,
}

#[derive(Deserialize, Serialize)]
pub struct BlockJson {
    pub hash: String,
    pub confirmations: u32,
    pub strippedsize: usize,
    pub size: usize,
    pub weight: usize,
    pub height: u32,
    pub version: i32,
    #[serde(rename = "versionHex")]
    pub version_hex: String,
    pub merkleroot: String,
    pub tx: Vec<String>,
    pub time: u32,
    pub mediantime: u32,
    pub nonce: u32,
    pub bits: String,
    pub difficulty: u128,
    pub chainwork: String,
    pub n_tx: usize,
    pub previousblockhash: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub nextblockhash: Option<String>,
}

#[derive(Debug)]
pub enum Error {
    TxNotFound,
    InvalidScript,
    InvalidDescriptor,
    BlockNotFound,
    Chain,
    InvalidPort,
    InvalidAddress,
    Node,
    NoBlockFilters,
    InvalidNetwork,
    InInitialBlockDownload,
    Encode,
}

impl Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let msg = match self {
            Error::TxNotFound => "Transaction not found",
            Error::InvalidDescriptor => "Invalid descriptor",
            Error::BlockNotFound => "Block not found",
            Error::Chain => "Chain error",
            Error::InvalidPort => "Invalid port",
            Error::InvalidAddress => "Invalid address",
            Error::Node => "Node returned an error",
            Error::NoBlockFilters => "You don't have block filters enabled, please start florestad with --cfilters to run this RPC",
            Error::InvalidNetwork => "Invalid network",
            Error::InInitialBlockDownload => "Node is in initial block download, wait until it's finished",
            Error::Encode => "Error encoding response",
            Error::InvalidScript => "Invalid script",
        };
        write!(f, "{}", msg)
    }
}

impl From<Error> for i64 {
    fn from(val: Error) -> Self {
        match val {
            Error::BlockNotFound => 1,
            Error::Chain => 2,
            Error::TxNotFound => 3,
            Error::InvalidDescriptor => 4,
            Error::InvalidPort => 5,
            Error::InvalidAddress => 6,
            Error::Node => 7,
            Error::NoBlockFilters => 8,
            Error::InvalidNetwork => 9,
            Error::InInitialBlockDownload => 10,
            Error::Encode => 11,
            Error::InvalidScript => 12,
        }
    }
}

impl From<Error> for ErrorCode {
    fn from(val: Error) -> Self {
        let code = val.into();
        ErrorCode::ServerError(code)
    }
}

impl From<Error> for jsonrpc_core::Error {
    fn from(value: Error) -> Self {
        jsonrpc_core::Error {
            message: value.to_string(),
            code: value.into(),
            data: None,
        }
    }
}