use console_log;
use std::{collections::HashMap, error::Error};
use vade::Vade;
use wasm_bindgen::prelude::*;
use crate::vade_utils::{get_vade as get_vade_from_utils, get_config_default};
use serde::Serialize;
macro_rules! handle_results {
($func_name:expr, $did_or_method:expr, $results:expr) => {
let err_msg = format!(
"'{}' did not return any result for '{}'",
$func_name, $did_or_method,
);
ensure($results.len() > 0, || (&err_msg).to_string())?;
let empty_result = &String::new();
return Ok(Some($results[0].as_ref().unwrap_or(empty_result).to_string()))
};
}
macro_rules! create_function {
($func_name:ident, $did_or_method:ident, $config:ident) => {
#[wasm_bindgen]
pub async fn $func_name(
did_or_method: String,
config: JsValue,
) -> Result<Option<String>, JsValue> {
let mut vade = get_vade(Some(&config)).map_err(jsify)?;
let results = vade.$func_name(&did_or_method).await.map_err(jsify)?;
handle_results!(stringify!($func_name), did_or_method, results);
}
};
($func_name:ident, $options:ident, $payload:ident, $config:ident) => {
#[wasm_bindgen]
pub async fn $func_name(
options: String,
payload: String,
config: JsValue,
) -> Result<Option<String>, JsValue> {
let mut vade = get_vade(Some(&config)).map_err(jsify)?;
let results = vade.$func_name(&options, &payload).await.map_err(jsify)?;
let name = stringify!($func_name);
handle_results!(&name, &name, results);
}
};
($func_name:ident, $did_or_method:ident, $options:ident, $payload:ident, $config:ident) => {
#[wasm_bindgen]
pub async fn $func_name(
did_or_method: String,
options: String,
payload: String,
config: JsValue,
) -> Result<Option<String>, JsValue> {
let mut vade = get_vade(Some(&config)).map_err(jsify)?;
let results = vade
.$func_name(&did_or_method, &options, &payload)
.await
.map_err(jsify)?;
handle_results!(stringify!($func_name), did_or_method, results);
}
};
($func_name:ident, $did_or_method:ident, $function:ident, $options:ident, $payload:ident, $config:ident) => {
#[wasm_bindgen]
pub async fn $func_name(
did_or_method: String,
custom_func_name: String,
options: String,
payload: String,
config: JsValue,
) -> Result<Option<String>, JsValue> {
let mut vade = get_vade(Some(&config)).map_err(jsify)?;
let results = vade
.$func_name(&did_or_method, &custom_func_name, &options, &payload)
.await
.map_err(jsify)?;
handle_results!(format!("{}: {}", stringify!($func_name), &custom_func_name), did_or_method, results);
}
};
}
fn ensure<F>(condition: bool, create_msg: F) -> Result<(), JsValue>
where
F: FnOnce() -> String,
{
if condition {
Ok(())
} else {
Err(JsValue::from(&create_msg().to_string()))
}
}
#[wasm_bindgen]
pub fn set_panic_hook() {
console_error_panic_hook::set_once();
}
#[wasm_bindgen]
pub fn set_log_level(log_level: String) {
let _ = match log_level.as_str() {
"trace" => console_log::init_with_level(log::Level::Trace),
"debug" => console_log::init_with_level(log::Level::Debug),
"info" => console_log::init_with_level(log::Level::Info),
"error" => console_log::init_with_level(log::Level::Error),
_ => console_log::init_with_level(log::Level::Error),
};
}
cfg_if::cfg_if! {
if #[cfg(feature = "did-read")] {
create_function!(did_resolve, did_or_method, config);
} else {
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "did-write")] {
create_function!(did_create, did_or_method, options, payload, config);
create_function!(did_update, did_or_method, options, payload, config);
} else {
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "didcomm")] {
create_function!(didcomm_receive, options, payload, config);
create_function!(didcomm_send, options, payload, config);
} else {
}
}
cfg_if::cfg_if! {
if #[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs", feature = "vc-jwt"))] {
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(run_custom_function, did_or_method, custom_func_name, options, payload, config);
#[cfg(feature = "vc-zkp-cl")]
create_function!(vc_zkp_create_credential_definition, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_create_credential_offer, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_create_credential_proposal, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_create_credential_schema, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_create_revocation_registry_definition, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_update_revocation_registry, did_or_method, options, payload, config);
create_function!(vc_zkp_issue_credential, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_finish_credential, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_present_proof, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_request_credential, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_request_proof, did_or_method, options, payload, config);
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
create_function!(vc_zkp_revoke_credential, did_or_method, options, payload, config);
create_function!(vc_zkp_verify_proof, did_or_method, options, payload, config);
} else {
}
}
fn get_config_values(
config: Option<&JsValue>,
keys: Vec<String>,
) -> Result<Vec<String>, Box<dyn Error>> {
let mut vec = Vec::new();
let mut config_undefined = true;
let config_hash_map: HashMap<String, String>;
match config {
Some(value) => {
if !value.is_undefined() {
config_hash_map = value.into_serde()?;
config_undefined = false;
} else {
config_hash_map = HashMap::<String, String>::new();
}
}
None => {
config_hash_map = HashMap::<String, String>::new();
}
};
for key in keys {
if config_undefined || !config_hash_map.contains_key(&key) {
vec.push(get_config_default(&key)?);
} else {
vec.push(
config_hash_map
.get(&key)
.ok_or_else(|| format!("could not get key '{}' from config", &key))?
.to_string(),
);
}
}
Ok(vec)
}
#[allow(unused_variables)] fn get_vade(config: Option<&JsValue>) -> Result<Vade, Box<dyn Error>> {
let config_values =
get_config_values(config, vec!["signer".to_string(), "target".to_string()])?;
let (signer_config, target) = match config_values.as_slice() {
[signer_config, target, ..] => (signer_config, target),
_ => {
return Err(Box::from("invalid vade config"));
}
};
return get_vade_from_utils(target, signer_config);
}
fn jsify(err: Box<dyn Error>) -> JsValue {
JsValue::from(format!("{}", err))
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Response {
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub response: Option<String>,
}
#[allow(unused_variables)] #[wasm_bindgen]
pub async fn execute_vade(
func_name: String,
did_or_method: String,
options: String,
payload: String,
custom_func_name: String,
config: JsValue,
) -> String {
let result = match func_name.as_str() {
#[cfg(feature = "did-read")]
"did_resolve" =>
did_resolve(did_or_method, config).await,
#[cfg(feature = "did-write")]
"did_create" =>
did_create(did_or_method, options, payload, config).await,
#[cfg(feature = "did-write")]
"did_update" =>
did_update(did_or_method, options, payload, config).await,
#[cfg(feature = "didcomm")]
"didcomm_receive" =>
didcomm_receive(options, payload, config).await,
#[cfg(feature = "didcomm")]
"didcomm_send" =>
didcomm_send(options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"run_custom_function" =>
run_custom_function(did_or_method, custom_func_name, options, payload, config).await,
#[cfg(feature = "vc-zkp-cl")]
"vc_zkp_create_credential_definition" =>
vc_zkp_create_credential_definition(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_create_credential_offer" =>
vc_zkp_create_credential_offer(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_create_credential_proposal" =>
vc_zkp_create_credential_proposal(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_create_credential_schema" =>
vc_zkp_create_credential_schema(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_create_revocation_registry_definition" =>
vc_zkp_create_revocation_registry_definition(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_update_revocation_registry" =>
vc_zkp_update_revocation_registry(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs", feature = "vc-jwt"))]
"vc_zkp_issue_credential" =>
vc_zkp_issue_credential(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_finish_credential" =>
vc_zkp_finish_credential(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_present_proof" =>
vc_zkp_present_proof(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_request_credential" =>
vc_zkp_request_credential(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_request_proof" =>
vc_zkp_request_proof(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs"))]
"vc_zkp_revoke_credential" =>
vc_zkp_revoke_credential(did_or_method, options, payload, config).await,
#[cfg(any(feature = "vc-zkp-cl", feature = "vc-zkp-bbs", feature = "vc-jwt"))]
"vc_zkp_verify_proof" =>
vc_zkp_verify_proof(did_or_method, options, payload, config).await,
_ => {
let empty_result = &String::new();
return empty_result.to_string();
}
};
let response = match result {
Ok(Some(value)) => Response {
response: Some(value.to_string()),
error: None,
},
Ok(None) => Response {
response: None,
error: Some("Got no result".to_string()),
},
Err(e) => Response {
response: None,
error: Some(e.as_string().unwrap_or_default()),
},
};
let serialized_response = serde_json::to_string(&response);
let string_response = match serialized_response {
Ok(string_result) => string_result,
_ => "{\"error\": \"Failed to serialize response\"}".to_string(),
};
return string_response;
}