1mod convert;
2mod jsonrpc;
3pub mod method;
4
5use std::fmt;
6use std::str::FromStr;
7
8use ckb_jsonrpc_types::{BlockView, HeaderView, JsonBytes, Script, Transaction};
9use ckb_types::{H160, H256};
10use serde_derive::{Deserialize, Serialize};
11
12pub use jsonrpc::{
13 CellIndex, JsonrpcError, JsonrpcRequest, JsonrpcResponse, LiveCellInfo, JSONRPC_VERSION,
14};
15
16#[derive(Clone, Debug, Serialize, Deserialize)]
17pub struct PluginConfig {
18 pub name: String,
19 pub description: String,
20 pub daemon: bool,
21 pub roles: Vec<PluginRole>,
22}
23
24impl PluginConfig {
25 pub fn validate(&self) -> Result<(), String> {
26 if self.roles.is_empty() {
28 return Err(String::from("Role list can not be empty"));
29 }
30 for role in &self.roles {
31 role.validate()?;
32 }
33 Ok(())
34 }
35
36 pub fn is_normal_daemon(&self) -> bool {
37 if !self.daemon {
38 return false;
39 }
40 for role in &self.roles {
41 match role {
42 PluginRole::KeyStore { .. } => (),
43 PluginRole::Indexer => (),
44 _ => {
45 return true;
46 }
47 }
48 }
49 false
50 }
51}
52
53#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
54#[serde(tag = "role", rename_all = "snake_case")]
55pub enum PluginRole {
56 KeyStore { require_password: bool },
58 Indexer,
59 SubCommand { name: String },
61 Callback { name: CallbackName },
63}
64
65impl PluginRole {
66 pub fn validate(&self) -> Result<(), String> {
67 match self {
68 Self::SubCommand { .. } => {
69 Ok(())
71 }
72 _ => Ok(()),
73 }
74 }
75}
76
77#[derive(Serialize, Deserialize, Debug, Clone)]
78pub enum PluginRequest {
79 Quit,
82 GetConfig,
83 RpcUrlChanged(String),
85 SubCommand(String),
87 Callback(CallbackRequest),
88 Rpc(RpcRequest),
90 ReadPassword(String),
91 PrintStdout(String),
92 PrintStderr(String),
93 KeyStore(KeyStoreRequest),
95 Indexer {
96 genesis_hash: H256,
97 request: IndexerRequest,
98 },
99}
100
101#[derive(Serialize, Deserialize, Debug, Clone)]
102#[serde(tag = "type", rename_all = "snake_case", content = "content")]
103pub enum PluginResponse {
104 Error(JsonrpcError),
105 Ok,
106 PluginConfig(PluginConfig),
108 JsonValue(serde_json::Value),
109 Boolean(bool),
110 String(String),
111 Integer64(u64),
112
113 H256Opt(Option<H256>),
114 H160(H160),
115 H160Vec(Vec<H160>),
116 HeaderView(Box<HeaderView>),
117 HeaderViewOpt(Box<Option<HeaderView>>),
118 BlockViewOpt(Box<Option<BlockView>>),
119 Bytes(JsonBytes),
120 BytesVec(Vec<JsonBytes>),
121
122 Callback(CallbackResponse),
123 MasterPrivateKey {
124 privkey: JsonBytes,
125 chain_code: JsonBytes,
126 },
127 DerivedKeySet {
128 external: Vec<(String, H160)>,
129 change: Vec<(String, H160)>,
130 },
131
132 LiveCells(Vec<LiveCellInfo>),
133 TopN(Vec<(H256, Option<Script>, u64)>),
134}
135
136#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
137#[serde(rename_all = "snake_case")]
138pub enum CallbackName {
139 SendTransaction,
140}
141impl fmt::Display for CallbackName {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 let repr = match self {
144 CallbackName::SendTransaction => "send_transaction",
145 };
146 write!(f, "{}", repr)
147 }
148}
149#[derive(Serialize, Deserialize, Debug, Clone)]
150pub enum CallbackRequest {
151 SendTransaction {
152 tx: Transaction,
153 sub_command: String,
155 },
156 }
158
159#[derive(Serialize, Deserialize, Debug, Clone)]
160#[serde(tag = "type", rename_all = "snake_case", content = "content")]
161pub enum CallbackResponse {
162 SendTransaction {
163 accepted: bool,
164 error_message: String,
165 },
166}
167
168#[derive(Serialize, Deserialize, Debug, Clone)]
169#[serde(tag = "type", rename_all = "snake_case", content = "content")]
170pub enum SignTarget {
171 Transaction {
172 tx: Transaction,
173 inputs: Vec<Transaction>,
174 change_path: String,
175 },
176 AnyMessage(H256),
177 AnyString(String),
178 AnyData(JsonBytes),
179}
180
181#[derive(Serialize, Deserialize, Debug, Clone)]
182pub enum KeyStoreRequest {
183 ListAccount,
185 HasAccount(H160),
187 CreateAccount(Option<String>),
189 UpdatePassword {
191 hash160: H160,
192 password: String,
193 new_password: String,
194 },
195 Import {
197 privkey: [u8; 32],
198 chain_code: [u8; 32],
199 password: Option<String>,
200 },
201 ImportAccount {
203 account_id: JsonBytes,
204 password: Option<String>,
205 },
206 Export {
208 hash160: H160,
209 password: Option<String>,
210 },
211 Sign {
213 hash160: H160,
214 path: String,
215 message: H256,
216 target: Box<SignTarget>,
217 recoverable: bool,
218 password: Option<String>,
219 },
220 ExtendedPubkey {
222 hash160: H160,
223 path: String,
224 password: Option<String>,
225 },
226 DerivedKeySet {
228 hash160: H160,
229 external_max_len: u32,
230 change_last: H160,
231 change_max_len: u32,
232 password: Option<String>,
233 },
234 DerivedKeySetByIndex {
236 hash160: H160,
237 external_start: u32,
238 external_length: u32,
239 change_start: u32,
240 change_length: u32,
241 password: Option<String>,
242 },
243 Any(serde_json::Value),
246}
247
248#[derive(Serialize, Deserialize, Debug, Clone)]
249pub enum RpcRequest {
250 GetBlock { hash: H256 },
251 GetBlockByNumber { number: u64 },
252 GetBlockHash { number: u64 },
253 }
255
256#[derive(Serialize, Deserialize, Debug, Clone)]
257#[serde(rename_all = "snake_case")]
258pub enum LiveCellIndexType {
259 LockHash,
260 TypeHash,
261 CodeHash,
263}
264impl fmt::Display for LiveCellIndexType {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 let repr = match self {
267 LiveCellIndexType::LockHash => "lock_hash",
268 LiveCellIndexType::TypeHash => "type_hash",
269 LiveCellIndexType::CodeHash => "code_hash",
270 };
271 write!(f, "{}", repr)
272 }
273}
274impl FromStr for LiveCellIndexType {
275 type Err = String;
276
277 fn from_str(s: &str) -> Result<Self, Self::Err> {
278 match s {
279 "lock_hash" => Ok(LiveCellIndexType::LockHash),
280 "type_hash" => Ok(LiveCellIndexType::TypeHash),
281 "code_hash" => Ok(LiveCellIndexType::CodeHash),
282 _ => Err(format!("Invalid index type: {}", s)),
283 }
284 }
285}
286#[derive(Serialize, Deserialize, Debug, Clone)]
287pub enum IndexerRequest {
288 TipHeader,
289 LastHeader,
290 GetCapacity(H256),
292 LiveCells {
293 index: LiveCellIndexType,
294 hash: H256,
295 from_number: Option<u64>,
296 to_number: Option<u64>,
297 limit: u64,
298 },
299 TopN(u64),
300 IndexerInfo,
301 Any(serde_json::Value),
303}