use p2panda_core::identity::Signer;
use p2panda_core::{AnyOperation, Body, Hash, Header, Operation, Topic, VerifyingKey};
use p2panda_store::logs::LogStore;
use p2panda_store::operations::OperationStore;
use p2panda_store::topics::TopicStore;
use p2panda_store::{SqliteError, SqliteStore, tx};
use serde::{Deserialize, Serialize};
pub type LogId = Hash;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CustomExtensions {
pub log_id: LogId,
}
pub async fn create_operation<S>(
store: &SqliteStore,
signer: &S,
topic: Topic,
body: &[u8],
) -> Result<AnyOperation, SqliteError>
where
S: Signer,
{
let log_id = LogId::digest(topic.as_bytes());
let extensions = CustomExtensions { log_id };
let operation = tx!(store, {
let verifying_key = signer.verifying_key();
let (seq_num, backlink) = store
.get_latest_entry_tx(&verifying_key, &log_id)
.await?
.map(|operation| (operation.header.seq_num + 1, Some(operation.hash)))
.unwrap_or((0, None));
let body = Body::from_bytes(body);
let header = Header::builder()
.seq_num(seq_num)
.backlink(backlink)
.body(&body)
.build(signer, extensions);
<SqliteStore as TopicStore<Topic, VerifyingKey, LogId>>::associate_tx(
&store,
&topic,
&verifying_key,
&log_id,
)
.await?;
let operation = Operation::from_parts(header, Some(body));
store
.insert_operation_tx(&operation.hash, &operation, &log_id)
.await?;
operation
});
Ok(operation.into())
}