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
use holochain_core_types::error::HolochainError;
use holochain_locksmith::RwLock;
use holochain_wasm_utils::api_serialization::crypto::CryptoMethod;
use jsonrpc_core::IoHandler;
use jsonrpc_lite::JsonRpc;
use serde_json::json;
use snowflake::ProcessUniqueId;
use std::{fmt, sync::Arc};
#[derive(Clone)]
pub struct ConductorApi(Arc<RwLock<IoHandler>>);
#[holochain_tracing_macros::newrelic_autotrace(HOLOCHAIN_CONDUCTOR_API)]
pub fn send_json_rpc(
handle: Arc<RwLock<IoHandler>>,
payload: String,
request_reponse: (String, String),
) -> Result<String, HolochainError> {
let handler = handle.write().unwrap();
let method = format!("agent/{}", request_reponse.0);
let id = format!("{}", ProcessUniqueId::new());
let request = json!({
"jsonrpc": "2.0",
"method": method,
"params": {
"payload": payload,
},
"id": id,
})
.to_string();
let response = handler
.handle_request_sync(&request)
.ok_or_else(|| format!("Conductor request agent/{} failed", request_reponse.0))?;
let response = JsonRpc::parse(&response)?;
match response {
JsonRpc::Success(_) => Ok(String::from(
response.get_result()?[request_reponse.1].as_str()?,
)),
JsonRpc::Error(_) => {
let err = response.get_error().unwrap();
if err.code == 1 {
Err(HolochainError::CryptoServiceError(err.message.to_string()))
} else {
Err(HolochainError::ErrorGeneric(serde_json::to_string(
&response.get_error()?,
)?))
}
}
_ => Err(HolochainError::ErrorGeneric(format!(
"agent/{} failed",
request_reponse.0
))),
}
}
#[holochain_tracing_macros::newrelic_autotrace(HOLOCHAIN_CONDUCTOR_API)]
impl ConductorApi {
pub fn new(conductor_api: Arc<RwLock<IoHandler>>) -> ConductorApi {
ConductorApi(conductor_api)
}
pub fn execute(&self, payload: String, method: CryptoMethod) -> Result<String, HolochainError> {
let request_response = match method {
CryptoMethod::Sign => (String::from("sign"), String::from("signature")),
CryptoMethod::Encrypt => (String::from("encrypt"), String::from("message")),
CryptoMethod::Decrypt => (String::from("decrypt"), String::from("message")),
};
let encoded_payload = base64::encode(&payload);
send_json_rpc(self.0.clone(), encoded_payload, request_response)
}
pub fn get(&self) -> &Arc<RwLock<IoHandler>> {
&self.0
}
pub fn reset(&self, api: IoHandler) {
*self.0.write().unwrap() = api;
}
}
impl PartialEq for ConductorApi {
fn eq(&self, _other: &ConductorApi) -> bool {
false
}
}
impl fmt::Debug for ConductorApi {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}