identity_iota_core/rebased/
transaction.rsuse std::ops::Deref;
#[cfg(not(target_arch = "wasm32"))]
use identity_iota_interaction::rpc_types::IotaTransactionBlockResponse;
#[cfg(not(target_arch = "wasm32"))]
use identity_iota_interaction::types::transaction::ProgrammableTransaction;
#[cfg(target_arch = "wasm32")]
use iota_interaction_ts::ProgrammableTransaction;
use crate::iota_interaction_adapter::IotaTransactionBlockResponseAdaptedTraitObj;
use crate::rebased::client::IdentityClient;
use crate::rebased::Error;
use async_trait::async_trait;
use identity_iota_interaction::IotaKeySignature;
use identity_iota_interaction::ProgrammableTransactionBcs;
use secret_storage::Signer;
#[cfg(not(target_arch = "wasm32"))]
#[derive(Debug, Clone)]
pub struct TransactionOutput<T> {
pub output: T,
pub response: IotaTransactionBlockResponse,
}
#[cfg(not(target_arch = "wasm32"))]
impl<T> Deref for TransactionOutput<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.output
}
}
#[cfg(not(target_arch = "wasm32"))]
#[async_trait::async_trait]
pub trait Transaction: Sized {
type Output;
async fn execute_with_opt_gas<S: Signer<IotaKeySignature> + Sync>(
self,
gas_budget: Option<u64>,
client: &IdentityClient<S>,
) -> Result<TransactionOutput<Self::Output>, Error>;
async fn execute<S: Signer<IotaKeySignature> + Sync>(
self,
client: &IdentityClient<S>,
) -> Result<TransactionOutput<Self::Output>, Error> {
self.execute_with_opt_gas(None, client).await
}
async fn execute_with_gas<S: Signer<IotaKeySignature> + Sync>(
self,
gas_budget: u64,
client: &IdentityClient<S>,
) -> Result<TransactionOutput<Self::Output>, Error> {
self.execute_with_opt_gas(Some(gas_budget), client).await
}
}
pub(crate) struct TransactionOutputInternal<T> {
pub output: T,
pub response: IotaTransactionBlockResponseAdaptedTraitObj,
}
impl<T> Deref for TransactionOutputInternal<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.output
}
}
#[cfg(not(target_arch = "wasm32"))]
impl<T> From<TransactionOutputInternal<T>> for TransactionOutput<T> {
fn from(value: TransactionOutputInternal<T>) -> Self {
let TransactionOutputInternal::<T> {
output: out,
response: internal_response,
} = value;
let response = internal_response.clone_native_response();
TransactionOutput { output: out, response }
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub(crate) trait TransactionInternal: Sized {
type Output;
async fn execute_with_opt_gas_internal<S: Signer<IotaKeySignature> + Sync>(
self,
gas_budget: Option<u64>,
client: &IdentityClient<S>,
) -> Result<TransactionOutputInternal<Self::Output>, Error>;
#[cfg(target_arch = "wasm32")]
async fn execute<S: Signer<IotaKeySignature> + Sync>(
self,
client: &IdentityClient<S>,
) -> Result<TransactionOutputInternal<Self::Output>, Error> {
self.execute_with_opt_gas_internal(None, client).await
}
#[cfg(target_arch = "wasm32")]
async fn execute_with_gas<S: Signer<IotaKeySignature> + Sync>(
self,
gas_budget: u64,
client: &IdentityClient<S>,
) -> Result<TransactionOutputInternal<Self::Output>, Error> {
self.execute_with_opt_gas_internal(Some(gas_budget), client).await
}
}
#[cfg(not(target_arch = "wasm32"))]
#[async_trait::async_trait]
impl<T: TransactionInternal<Output = O> + Send, O> Transaction for T {
type Output = O;
async fn execute_with_opt_gas<S: Signer<IotaKeySignature> + Sync>(
self,
gas_budget: Option<u64>,
client: &IdentityClient<S>,
) -> Result<TransactionOutput<O>, Error> {
let tx_output = self.execute_with_opt_gas_internal(gas_budget, client).await?;
Ok(tx_output.into())
}
}
#[cfg(not(target_arch = "wasm32"))]
#[async_trait::async_trait]
impl TransactionInternal for ProgrammableTransaction {
type Output = ();
async fn execute_with_opt_gas_internal<S>(
self,
gas_budget: Option<u64>,
client: &IdentityClient<S>,
) -> Result<TransactionOutputInternal<Self::Output>, Error>
where
S: Signer<IotaKeySignature> + Sync,
{
let tx_bcs = bcs::to_bytes(&self)?;
let response = client.execute_transaction(tx_bcs, gas_budget).await?;
Ok(TransactionOutputInternal { output: (), response })
}
}
#[cfg(target_arch = "wasm32")]
#[async_trait::async_trait(?Send)]
impl TransactionInternal for ProgrammableTransaction {
type Output = ();
async fn execute_with_opt_gas_internal<S>(
self,
gas_budget: Option<u64>,
client: &IdentityClient<S>,
) -> Result<TransactionOutputInternal<Self::Output>, Error>
where
S: Signer<IotaKeySignature> + Sync,
{
unimplemented!("TransactionInternal::execute_with_opt_gas_internal for ProgrammableTransaction");
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl TransactionInternal for ProgrammableTransactionBcs {
type Output = ();
async fn execute_with_opt_gas_internal<S: Signer<IotaKeySignature> + Sync>(
self,
gas_budget: Option<u64>,
client: &IdentityClient<S>,
) -> Result<TransactionOutputInternal<Self::Output>, Error> {
let self_tx = bcs::from_bytes::<ProgrammableTransaction>(&self)?;
self_tx.execute_with_opt_gas_internal(gas_budget, client).await
}
}
pub trait ProtoTransaction {
type Input;
type Tx: ProtoTransaction;
fn with(self, input: Self::Input) -> Self::Tx;
}
impl<T> ProtoTransaction for T
where
T: TransactionInternal,
{
type Input = ();
type Tx = Self;
fn with(self, _: Self::Input) -> Self::Tx {
self
}
}