use crate::ledger::block::Deployment;
use snarkvm_console::prelude::DeserializeExt;
use super::*;
pub struct DeployRequest<N: Network> {
deployment: Deployment<N>,
program_id: ProgramID<N>,
}
impl<N: Network> DeployRequest<N> {
pub fn new(deployment: Deployment<N>, program_id: ProgramID<N>) -> Self {
Self { deployment, program_id }
}
pub fn send(&self, endpoint: &str) -> Result<DeployResponse<N>> {
Ok(ureq::post(endpoint).send_json(self)?.body_mut().read_json()?)
}
pub const fn deployment(&self) -> &Deployment<N> {
&self.deployment
}
pub const fn program_id(&self) -> &ProgramID<N> {
&self.program_id
}
}
impl<N: Network> Serialize for DeployRequest<N> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut request = serializer.serialize_struct("DeployRequest", 2)?;
request.serialize_field("deployment", &self.deployment)?;
request.serialize_field("program_id", &self.program_id)?;
request.end()
}
}
impl<'de, N: Network> Deserialize<'de> for DeployRequest<N> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let mut request = serde_json::Value::deserialize(deserializer)?;
Ok(Self::new(
DeserializeExt::take_from_value::<D>(&mut request, "deployment")?,
DeserializeExt::take_from_value::<D>(&mut request, "program_id")?,
))
}
}
pub struct DeployResponse<N: Network> {
deployment: Deployment<N>,
}
impl<N: Network> DeployResponse<N> {
pub const fn new(deployment: Deployment<N>) -> Self {
Self { deployment }
}
pub const fn deployment(&self) -> &Deployment<N> {
&self.deployment
}
}
impl<N: Network> Serialize for DeployResponse<N> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut response = serializer.serialize_struct("DeployResponse", 1)?;
response.serialize_field("deployment", &self.deployment)?;
response.end()
}
}
impl<'de, N: Network> Deserialize<'de> for DeployResponse<N> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let mut response = serde_json::Value::deserialize(deserializer)?;
Ok(Self::new(
DeserializeExt::take_from_value::<D>(&mut response, "deployment")?,
))
}
}
impl<N: Network> Package<N> {
pub fn deploy<A: crate::circuit::Aleo<Network = N, BaseField = N::Field>>(
&self,
process: &Process<N>,
endpoint: Option<String>,
) -> Result<Deployment<N>> {
let program = self.program();
let program_id = program.id();
dev_println!("⏳ Deploying '{}'...\n", program_id.to_string());
let rng = &mut rand::thread_rng();
let deployment = process.get_stack(program_id)?.deploy::<A, _>(rng).unwrap();
match endpoint {
Some(ref endpoint) => {
let request = DeployRequest::new(deployment, *program_id);
let response = request.send(endpoint)?;
ensure!(
response.deployment.program_id() == program_id,
"Program ID mismatch: {} != {program_id}",
response.deployment.program_id()
);
Ok(response.deployment)
}
None => Ok(deployment),
}
}
}
#[cfg(test)]
mod tests {
type CurrentAleo = snarkvm_circuit::network::AleoV0;
#[test]
fn test_deploy() {
let (directory, package) = crate::package::test_helpers::sample_token_package();
let process = package.get_process().unwrap();
let deployment = package.deploy::<CurrentAleo>(&process, None).unwrap();
assert_eq!(0, deployment.edition());
assert_eq!(package.program().id(), deployment.program_id());
assert_eq!(package.program(), deployment.program());
std::fs::remove_dir_all(directory).unwrap();
}
#[test]
fn test_deploy_with_import() {
let (directory, package) = crate::package::test_helpers::sample_wallet_package();
let process = package.get_process().unwrap();
let deployment = package.deploy::<CurrentAleo>(&process, None).unwrap();
assert_eq!(0, deployment.edition());
assert_eq!(package.program().id(), deployment.program_id());
assert_eq!(package.program(), deployment.program());
std::fs::remove_dir_all(directory).unwrap();
}
}