pub mod payload;
use crate::{error::RuntimeApiError, Metadata};
use alloc::{
format,
string::{String, ToString},
vec::Vec,
};
use payload::Payload;
use scale_decode::IntoVisitor;
pub fn validate<P: Payload>(payload: P, metadata: &Metadata) -> Result<(), RuntimeApiError> {
let Some(hash) = payload.validation_hash() else {
return Ok(());
};
let trait_name = payload.trait_name();
let method_name = payload.method_name();
let api_trait = metadata
.runtime_api_trait_by_name(trait_name)
.ok_or_else(|| RuntimeApiError::TraitNotFound(trait_name.to_string()))?;
let api_method =
api_trait
.method_by_name(method_name)
.ok_or_else(|| RuntimeApiError::MethodNotFound {
trait_name: trait_name.to_string(),
method_name: method_name.to_string(),
})?;
if hash != api_method.hash() {
Err(RuntimeApiError::IncompatibleCodegen)
} else {
Ok(())
}
}
pub fn call_name<P: Payload>(payload: P) -> String {
format!("{}_{}", payload.trait_name(), payload.method_name())
}
pub fn call_args<P: Payload>(payload: P, metadata: &Metadata) -> Result<Vec<u8>, RuntimeApiError> {
let value = frame_decode::runtime_apis::encode_runtime_api_inputs(
payload.trait_name(),
payload.method_name(),
payload.args(),
metadata,
metadata.types(),
)
.map_err(RuntimeApiError::CouldNotEncodeInputs)?;
Ok(value)
}
pub fn decode_value<P: Payload>(
bytes: &mut &[u8],
payload: P,
metadata: &Metadata,
) -> Result<P::ReturnType, RuntimeApiError> {
let value = frame_decode::runtime_apis::decode_runtime_api_response(
payload.trait_name(),
payload.method_name(),
bytes,
metadata,
metadata.types(),
P::ReturnType::into_visitor(),
)
.map_err(RuntimeApiError::CouldNotDecodeResponse)?;
Ok(value)
}