iota_transaction_builder/
package.rs1use std::result::Result;
6
7use anyhow::{Ok, anyhow, bail};
8use iota_json_rpc_types::IotaObjectDataOptions;
9use iota_types::{
10 base_types::{Identifier, IotaAddress, ObjectID},
11 move_package::MovePackage,
12 object::Owner,
13 programmable_transaction_builder::ProgrammableTransactionBuilder,
14 transaction::{Argument, ObjectArg, TransactionData, TransactionKind},
15};
16
17use crate::TransactionBuilder;
18
19impl TransactionBuilder {
20 pub async fn publish_tx_kind(
23 &self,
24 sender: IotaAddress,
25 modules: Vec<Vec<u8>>,
26 dep_ids: Vec<ObjectID>,
27 ) -> Result<TransactionKind, anyhow::Error> {
28 let pt = {
29 let mut builder = ProgrammableTransactionBuilder::new();
30 let upgrade_cap = builder.publish_upgradeable(modules, dep_ids);
31 builder.transfer_arg(sender, upgrade_cap);
32 builder.finish()
33 };
34 Ok(TransactionKind::programmable(pt))
35 }
36
37 pub async fn publish(
39 &self,
40 sender: IotaAddress,
41 compiled_modules: Vec<Vec<u8>>,
42 dep_ids: Vec<ObjectID>,
43 gas: impl Into<Option<ObjectID>>,
44 gas_budget: u64,
45 ) -> anyhow::Result<TransactionData> {
46 let gas_price = self.0.get_reference_gas_price().await?;
47 let gas = self
48 .select_gas(sender, gas, gas_budget, vec![], gas_price)
49 .await?;
50 Ok(TransactionData::new_module(
51 sender,
52 gas,
53 compiled_modules,
54 dep_ids,
55 gas_budget,
56 gas_price,
57 ))
58 }
59
60 pub async fn upgrade_tx_kind(
63 &self,
64 package_id: ObjectID,
65 modules: Vec<Vec<u8>>,
66 dep_ids: Vec<ObjectID>,
67 upgrade_capability: ObjectID,
68 upgrade_policy: u8,
69 digest: Vec<u8>,
70 ) -> Result<TransactionKind, anyhow::Error> {
71 let upgrade_capability = self
72 .0
73 .get_object_with_options(
74 upgrade_capability,
75 IotaObjectDataOptions::new().with_owner(),
76 )
77 .await?
78 .into_object()?;
79 let capability_owner = upgrade_capability
80 .owner
81 .ok_or_else(|| anyhow!("Unable to determine ownership of upgrade capability"))?;
82 let pt = {
83 let mut builder = ProgrammableTransactionBuilder::new();
84 let capability_arg = match capability_owner {
85 Owner::Address(_) => ObjectArg::ImmOrOwnedObject(upgrade_capability.object_ref()),
86 Owner::Shared(initial_shared_version) => ObjectArg::SharedObject {
87 id: upgrade_capability.object_ref().object_id,
88 initial_shared_version,
89 mutable: true,
90 },
91 Owner::Immutable => {
92 bail!("Upgrade capability is stored immutably and cannot be used for upgrades")
93 }
94 Owner::Object(_) => {
97 bail!("Upgrade capability controlled by object");
98 }
99 _ => unimplemented!("a new Owner enum variant was added and needs to be handled"),
100 };
101 builder.obj(capability_arg).unwrap();
102 let upgrade_arg = builder.pure(upgrade_policy).unwrap();
103 let digest_arg = builder.pure(digest).unwrap();
104 let upgrade_ticket = builder.programmable_move_call(
105 ObjectID::FRAMEWORK,
106 Identifier::PACKAGE_MODULE,
107 Identifier::from_static("authorize_upgrade"),
108 vec![],
109 vec![Argument::Input(0), upgrade_arg, digest_arg],
110 );
111 let upgrade_receipt = builder.upgrade(package_id, upgrade_ticket, dep_ids, modules);
112
113 builder.programmable_move_call(
114 ObjectID::FRAMEWORK,
115 Identifier::PACKAGE_MODULE,
116 Identifier::from_static("commit_upgrade"),
117 vec![],
118 vec![Argument::Input(0), upgrade_receipt],
119 );
120
121 builder.finish()
122 };
123
124 Ok(TransactionKind::programmable(pt))
125 }
126
127 pub async fn upgrade(
129 &self,
130 sender: IotaAddress,
131 package_id: ObjectID,
132 compiled_modules: Vec<Vec<u8>>,
133 dep_ids: Vec<ObjectID>,
134 upgrade_capability: ObjectID,
135 upgrade_policy: u8,
136 gas: impl Into<Option<ObjectID>>,
137 gas_budget: u64,
138 ) -> anyhow::Result<TransactionData> {
139 let gas_price = self.0.get_reference_gas_price().await?;
140 let gas = self
141 .select_gas(sender, gas, gas_budget, vec![], gas_price)
142 .await?;
143 let upgrade_cap = self
144 .0
145 .get_object_with_options(
146 upgrade_capability,
147 IotaObjectDataOptions::new().with_owner(),
148 )
149 .await?
150 .into_object()?;
151 let cap_owner = upgrade_cap
152 .owner
153 .ok_or_else(|| anyhow!("Unable to determine ownership of upgrade capability"))?;
154 let digest =
155 MovePackage::compute_digest_for_modules_and_deps(&compiled_modules, &dep_ids).to_vec();
156 TransactionData::new_upgrade(
157 sender,
158 gas,
159 package_id,
160 compiled_modules,
161 dep_ids,
162 (upgrade_cap.object_ref(), cap_owner),
163 upgrade_policy,
164 digest,
165 gas_budget,
166 gas_price,
167 )
168 }
169}