1use std::str::FromStr;
4
5use anyhow::{bail, ensure, Error};
6
7use crate::agent::Agent;
8use crate::program::ProgramManager;
9
10use super::*;
11
12impl Agent {
13 pub fn deploy_program(
23 &self,
24 program: &Program,
25 priority_fee: u64,
26 fee_record: Option<PlaintextRecord>,
27 ) -> anyhow::Result<String> {
28 let program_id = program.id();
30 ensure!(
31 ProgramManager::get_program_from_chain(program_id).is_err(),
32 "❌ Program {:?} already deployed on chain, cancelling deployment",
33 program_id
34 );
35
36 program.imports().keys().try_for_each(|program_id| {
38 if ProgramManager::get_program_from_chain(program_id).is_err() {
39 bail!("❌ Imported program {program_id:?} could not be found on the Aleo Network, please deploy this imported program first before continuing with deployment of {program_id:?}");
40 }
41 Ok(())
42 })?;
43
44 let private_key = self.account().private_key();
45
46 let transaction = self.create_deploy_transaction(
48 program,
49 private_key,
50 self.base_url(),
51 priority_fee,
52 fee_record,
53 )?;
54
55 self.broadcast_transaction(&transaction)
56 }
57
58 fn create_deploy_transaction(
60 &self,
61 program: &Program,
62 private_key: &PrivateKey,
63 node_url: &String,
64 priority_fee: u64,
65 fee_record: Option<PlaintextRecord>,
66 ) -> anyhow::Result<Transaction> {
67 let rng = &mut rand::thread_rng();
69 let query = Query::from(node_url);
70
71 let vm = Self::initialize_vm(program)?;
73
74 vm.deploy(
76 private_key,
77 program,
78 fee_record,
79 priority_fee,
80 Some(query),
81 rng,
82 )
83 }
84
85 fn initialize_vm(program: &Program) -> anyhow::Result<VM> {
86 let store = ConsensusStore::open(None)?;
89 let vm = VM::from(store)?;
90
91 let credits_id = ProgramID::from_str("credits.aleo")?;
93 ProgramManager::get_import_programs_from_chain(program)?
94 .iter()
95 .try_for_each(|(_, import)| {
96 if import.id() != &credits_id {
97 vm.process().write().add_program(import)?
98 }
99 Ok::<_, Error>(())
100 })?;
101 Ok(vm)
102 }
103}