use crate::API_URL;
use snarkvm::{
console::network::Network,
ledger::block::Transaction,
prelude::{de, Deserialize, DeserializeExt, Deserializer, Serialize, SerializeStruct, Serializer},
synthesizer::Authorization,
};
use anyhow::{bail, Result};
#[cfg(test)]
use rand::{CryptoRng, Rng};
#[cfg(test)]
use snarkvm::circuit::Aleo;
pub struct Authorized<N: Network> {
function: Authorization<N>,
fee: Option<Authorization<N>>,
broadcast: bool,
}
impl<N: Network> Authorized<N> {
pub const fn new(function: Authorization<N>, fee: Option<Authorization<N>>, broadcast: bool) -> Self {
Self { function, fee, broadcast }
}
pub fn execute(self) -> Result<Transaction<N>> {
let response = reqwest::blocking::Client::new()
.post(format!("{API_URL}/execute"))
.header("Content-Type", "application/json")
.body(serde_json::to_string(&self)?)
.send()?;
match response.status().is_success() {
true => Ok(response.json()?),
false => bail!(response.text()?),
}
}
#[cfg(test)]
pub fn execute_local<A: Aleo<Network = N>, R: Rng + CryptoRng>(self, rng: &mut R) -> Result<Transaction<N>> {
use snarkvm::{
ledger::store::{helpers::memory::ConsensusMemory, ConsensusStore},
synthesizer::VM,
};
let vm = VM::from(ConsensusStore::<_, ConsensusMemory<_>>::open(None)?)?;
vm.execute_authorization(self.function, self.fee, None, rng)
}
}
impl<N: Network> Serialize for Authorized<N> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut authorization = serializer.serialize_struct("Authorized", 3)?;
authorization.serialize_field("function", &self.function)?;
if let Some(fee) = &self.fee {
authorization.serialize_field("fee", fee)?;
}
authorization.serialize_field("broadcast", &self.broadcast)?;
authorization.end()
}
}
impl<'de, N: Network> Deserialize<'de> for Authorized<N> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let mut authorization = serde_json::Value::deserialize(deserializer)?;
let function: Authorization<_> = DeserializeExt::take_from_value::<D>(&mut authorization, "function")?;
let fee = serde_json::from_value(authorization.get_mut("fee").unwrap_or(&mut serde_json::Value::Null).take())
.map_err(de::Error::custom)?;
let broadcast = DeserializeExt::take_from_value::<D>(&mut authorization, "broadcast")?;
Ok(Self { function, fee, broadcast })
}
}