use codec::{Decode, Encode};
use jsonrpsee::core::{async_trait, RpcResult};
pub use sc_rpc_api::statement::{error::Error, StatementApiServer};
use sc_rpc_api::DenyUnsafe;
use sp_core::Bytes;
use sp_statement_store::{StatementSource, SubmitResult};
use std::sync::Arc;
pub struct StatementStore {
store: Arc<dyn sp_statement_store::StatementStore>,
deny_unsafe: DenyUnsafe,
}
impl StatementStore {
pub fn new(
store: Arc<dyn sp_statement_store::StatementStore>,
deny_unsafe: DenyUnsafe,
) -> Self {
StatementStore { store, deny_unsafe }
}
}
#[async_trait]
impl StatementApiServer for StatementStore {
fn dump(&self) -> RpcResult<Vec<Bytes>> {
self.deny_unsafe.check_if_safe()?;
let statements =
self.store.statements().map_err(|e| Error::StatementStore(e.to_string()))?;
Ok(statements.into_iter().map(|(_, s)| s.encode().into()).collect())
}
fn broadcasts(&self, match_all_topics: Vec<[u8; 32]>) -> RpcResult<Vec<Bytes>> {
Ok(self
.store
.broadcasts(&match_all_topics)
.map_err(|e| Error::StatementStore(e.to_string()))?
.into_iter()
.map(Into::into)
.collect())
}
fn posted(&self, match_all_topics: Vec<[u8; 32]>, dest: [u8; 32]) -> RpcResult<Vec<Bytes>> {
Ok(self
.store
.posted(&match_all_topics, dest)
.map_err(|e| Error::StatementStore(e.to_string()))?
.into_iter()
.map(Into::into)
.collect())
}
fn posted_clear(
&self,
match_all_topics: Vec<[u8; 32]>,
dest: [u8; 32],
) -> RpcResult<Vec<Bytes>> {
Ok(self
.store
.posted_clear(&match_all_topics, dest)
.map_err(|e| Error::StatementStore(e.to_string()))?
.into_iter()
.map(Into::into)
.collect())
}
fn submit(&self, encoded: Bytes) -> RpcResult<()> {
let statement = Decode::decode(&mut &*encoded)
.map_err(|e| Error::StatementStore(format!("Eror decoding statement: {:?}", e)))?;
match self.store.submit(statement, StatementSource::Local) {
SubmitResult::New(_) | SubmitResult::Known => Ok(()),
SubmitResult::KnownExpired =>
Err(Error::StatementStore("Submitted an expired statement.".into()).into()),
SubmitResult::Bad(e) => Err(Error::StatementStore(e.into()).into()),
SubmitResult::Ignored => Err(Error::StatementStore("Store is full.".into()).into()),
SubmitResult::InternalError(e) => Err(Error::StatementStore(e.to_string()).into()),
}
}
fn remove(&self, hash: [u8; 32]) -> RpcResult<()> {
Ok(self.store.remove(&hash).map_err(|e| Error::StatementStore(e.to_string()))?)
}
}