mod convert;
mod jsonrpc;
pub mod method;
use std::fmt;
use std::str::FromStr;
use ckb_jsonrpc_types::{BlockView, HeaderView, JsonBytes, Script, Transaction};
use ckb_types::{H160, H256};
use serde_derive::{Deserialize, Serialize};
pub use jsonrpc::{
CellIndex, JsonrpcError, JsonrpcRequest, JsonrpcResponse, LiveCellInfo, JSONRPC_VERSION,
};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PluginConfig {
pub name: String,
pub description: String,
pub daemon: bool,
pub roles: Vec<PluginRole>,
}
impl PluginConfig {
pub fn validate(&self) -> Result<(), String> {
if self.roles.is_empty() {
return Err(String::from("Role list can not be empty"));
}
for role in &self.roles {
role.validate()?;
}
Ok(())
}
pub fn is_normal_daemon(&self) -> bool {
if !self.daemon {
return false;
}
for role in &self.roles {
match role {
PluginRole::KeyStore { .. } => (),
PluginRole::Indexer => (),
_ => {
return true;
}
}
}
false
}
}
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
#[serde(tag = "role", rename_all = "snake_case")]
pub enum PluginRole {
KeyStore { require_password: bool },
Indexer,
SubCommand { name: String },
Callback { name: CallbackName },
}
impl PluginRole {
pub fn validate(&self) -> Result<(), String> {
match self {
Self::SubCommand { .. } => {
Ok(())
}
_ => Ok(()),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum PluginRequest {
Quit,
GetConfig,
RpcUrlChanged(String),
SubCommand(String),
Callback(CallbackRequest),
Rpc(RpcRequest),
ReadPassword(String),
PrintStdout(String),
PrintStderr(String),
KeyStore(KeyStoreRequest),
Indexer {
genesis_hash: H256,
request: IndexerRequest,
},
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "snake_case", content = "content")]
pub enum PluginResponse {
Error(JsonrpcError),
Ok,
PluginConfig(PluginConfig),
JsonValue(serde_json::Value),
Boolean(bool),
String(String),
Integer64(u64),
H256Opt(Option<H256>),
H160(H160),
H160Vec(Vec<H160>),
HeaderView(Box<HeaderView>),
HeaderViewOpt(Box<Option<HeaderView>>),
BlockViewOpt(Box<Option<BlockView>>),
Bytes(JsonBytes),
BytesVec(Vec<JsonBytes>),
Callback(CallbackResponse),
MasterPrivateKey {
privkey: JsonBytes,
chain_code: JsonBytes,
},
DerivedKeySet {
external: Vec<(String, H160)>,
change: Vec<(String, H160)>,
},
LiveCells(Vec<LiveCellInfo>),
TopN(Vec<(H256, Option<Script>, u64)>),
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum CallbackName {
SendTransaction,
}
impl fmt::Display for CallbackName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let repr = match self {
CallbackName::SendTransaction => "send_transaction",
};
write!(f, "{}", repr)
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum CallbackRequest {
SendTransaction {
tx: Transaction,
sub_command: String,
},
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "snake_case", content = "content")]
pub enum CallbackResponse {
SendTransaction {
accepted: bool,
error_message: String,
},
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "snake_case", content = "content")]
pub enum SignTarget {
Transaction {
tx: Transaction,
inputs: Vec<Transaction>,
change_path: String,
},
AnyMessage(H256),
AnyString(String),
AnyData(JsonBytes),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum KeyStoreRequest {
ListAccount,
HasAccount(H160),
CreateAccount(Option<String>),
UpdatePassword {
hash160: H160,
password: String,
new_password: String,
},
Import {
privkey: [u8; 32],
chain_code: [u8; 32],
password: Option<String>,
},
ImportAccount {
account_id: JsonBytes,
password: Option<String>,
},
Export {
hash160: H160,
password: Option<String>,
},
Sign {
hash160: H160,
path: String,
message: H256,
target: Box<SignTarget>,
recoverable: bool,
password: Option<String>,
},
ExtendedPubkey {
hash160: H160,
path: String,
password: Option<String>,
},
DerivedKeySet {
hash160: H160,
external_max_len: u32,
change_last: H160,
change_max_len: u32,
password: Option<String>,
},
DerivedKeySetByIndex {
hash160: H160,
external_start: u32,
external_length: u32,
change_start: u32,
change_length: u32,
password: Option<String>,
},
Any(serde_json::Value),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum RpcRequest {
GetBlock { hash: H256 },
GetBlockByNumber { number: u64 },
GetBlockHash { number: u64 },
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum LiveCellIndexType {
LockHash,
TypeHash,
CodeHash,
}
impl fmt::Display for LiveCellIndexType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let repr = match self {
LiveCellIndexType::LockHash => "lock_hash",
LiveCellIndexType::TypeHash => "type_hash",
LiveCellIndexType::CodeHash => "code_hash",
};
write!(f, "{}", repr)
}
}
impl FromStr for LiveCellIndexType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"lock_hash" => Ok(LiveCellIndexType::LockHash),
"type_hash" => Ok(LiveCellIndexType::TypeHash),
"code_hash" => Ok(LiveCellIndexType::CodeHash),
_ => Err(format!("Invalid index type: {}", s)),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum IndexerRequest {
TipHeader,
LastHeader,
GetCapacity(H256),
LiveCells {
index: LiveCellIndexType,
hash: H256,
from_number: Option<u64>,
to_number: Option<u64>,
limit: u64,
},
TopN(u64),
IndexerInfo,
Any(serde_json::Value),
}