use crate::synthesizer::Deployment;
use snarkvm_console::types::Address;
use super::*;
pub struct DeployRequest<N: Network> {
deployment: Deployment<N>,
address: Address<N>,
program_id: ProgramID<N>,
}
impl<N: Network> DeployRequest<N> {
pub fn new(deployment: Deployment<N>, address: Address<N>, program_id: ProgramID<N>) -> Self {
Self { deployment, address, program_id }
}
pub fn send(&self, endpoint: &str) -> Result<DeployResponse<N>> {
Ok(ureq::post(endpoint).send_json(self)?.into_json()?)
}
pub const fn deployment(&self) -> &Deployment<N> {
&self.deployment
}
pub const fn address(&self) -> &Address<N> {
&self.address
}
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", 3)?;
request.serialize_field("deployment", &self.deployment)?;
request.serialize_field("address", &self.address)?;
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(
serde_json::from_value(request["deployment"].take()).map_err(de::Error::custom)?,
serde_json::from_value(request["address"].take()).map_err(de::Error::custom)?,
serde_json::from_value(request["program_id"].take()).map_err(de::Error::custom)?,
))
}
}
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(
serde_json::from_value(response["deployment"].take()).map_err(de::Error::custom)?,
))
}
}
impl<N: Network> Package<N> {
pub fn deploy<A: crate::circuit::Aleo<Network = N, BaseField = N::Field>>(
&self,
endpoint: Option<String>,
) -> Result<Deployment<N>> {
let program = self.program();
let program_id = program.id();
let caller = self.manifest_file().development_address();
#[cfg(feature = "aleo-cli")]
println!("⏳ Deploying '{}'...\n", program_id.to_string().bold());
let mut process = Process::<N>::load()?;
let imports_directory = self.imports_directory();
program.imports().keys().try_for_each(|program_id| {
let import_program_file = AleoFile::open(&imports_directory, program_id, false)?;
process.add_program(import_program_file.program())?;
Ok::<_, Error>(())
})?;
let rng = &mut rand::thread_rng();
let deployment = process.deploy::<A, _>(program, rng).unwrap();
match endpoint {
Some(ref endpoint) => {
let request = DeployRequest::new(deployment, *caller, *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 {
use super::*;
type CurrentNetwork = snarkvm_console::network::Testnet3;
type CurrentAleo = snarkvm_circuit::network::AleoV0;
#[test]
fn test_deploy() {
let (directory, package) = crate::package::test_helpers::sample_package();
let deployment = package.deploy::<CurrentAleo>(None).unwrap();
assert_eq!(<CurrentNetwork as Network>::EDITION, 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_package_with_import();
let deployment = package.deploy::<CurrentAleo>(None).unwrap();
assert_eq!(<CurrentNetwork as Network>::EDITION, deployment.edition());
assert_eq!(package.program().id(), deployment.program_id());
assert_eq!(package.program(), deployment.program());
std::fs::remove_dir_all(directory).unwrap();
}
}