1use super::{
18 events::CodeRemoved,
19 submit_extrinsic,
20 ContractMessageTranscoder,
21 ErrorVariant,
22};
23use crate::{
24 extrinsic_calls::RemoveCode,
25 extrinsic_opts::ExtrinsicOpts,
26};
27
28use anyhow::Result;
29use ink_env::Environment;
30use subxt::{
31 backend::{
32 legacy::LegacyRpcMethods,
33 rpc::RpcClient,
34 },
35 blocks::ExtrinsicEvents,
36 config::{
37 DefaultExtrinsicParams,
38 ExtrinsicParams,
39 },
40 ext::{
41 scale_decode::IntoVisitor,
42 scale_encode::EncodeAsType,
43 },
44 tx,
45 Config,
46 OnlineClient,
47};
48
49pub struct RemoveCommandBuilder<C: Config, E: Environment, Signer: Clone> {
51 code_hash: Option<C::Hash>,
52 extrinsic_opts: ExtrinsicOpts<C, E, Signer>,
53}
54
55impl<C: Config, E: Environment, Signer> RemoveCommandBuilder<C, E, Signer>
56where
57 Signer: tx::Signer<C> + Clone,
58{
59 pub fn new(
61 extrinsic_opts: ExtrinsicOpts<C, E, Signer>,
62 ) -> RemoveCommandBuilder<C, E, Signer> {
63 RemoveCommandBuilder {
64 code_hash: None,
65 extrinsic_opts,
66 }
67 }
68
69 pub fn code_hash(self, code_hash: Option<C::Hash>) -> Self {
71 let mut this = self;
72 this.code_hash = code_hash;
73 this
74 }
75}
76
77impl<C: Config, E: Environment, Signer> RemoveCommandBuilder<C, E, Signer>
78where
79 C::Hash: From<[u8; 32]>,
80 Signer: tx::Signer<C> + Clone,
81{
82 pub async fn done(self) -> Result<RemoveExec<C, E, Signer>> {
93 let artifacts = self.extrinsic_opts.contract_artifacts()?;
94 let transcoder = artifacts.contract_transcoder()?;
95
96 let artifacts_path = artifacts.artifact_path().to_path_buf();
97
98 let final_code_hash = match (self.code_hash.as_ref(), artifacts.code.as_ref()) {
99 (Some(code_h), _) => Ok(*code_h),
100 (None, Some(_)) => artifacts.code_hash().map(|h| h.into() ),
101 (None, None) => Err(anyhow::anyhow!(
102 "No code_hash was provided or contract code was not found from artifact \
103 file {}. Please provide a code hash with --code-hash argument or specify the \
104 path for artifacts files with --manifest-path",
105 artifacts_path.display()
106 )),
107 }?;
108
109 let url = self.extrinsic_opts.url();
110 let rpc_cli = RpcClient::from_url(&url).await?;
111 let client = OnlineClient::<C>::from_rpc_client(rpc_cli.clone()).await?;
112 let rpc = LegacyRpcMethods::<C>::new(rpc_cli);
113
114 Ok(RemoveExec {
115 final_code_hash,
116 opts: self.extrinsic_opts,
117 rpc,
118 client,
119 transcoder,
120 })
121 }
122}
123
124pub struct RemoveExec<C: Config, E: Environment, Signer: Clone> {
125 final_code_hash: C::Hash,
126 opts: ExtrinsicOpts<C, E, Signer>,
127 rpc: LegacyRpcMethods<C>,
128 client: OnlineClient<C>,
129 transcoder: ContractMessageTranscoder,
130}
131
132impl<C: Config, E: Environment, Signer> RemoveExec<C, E, Signer>
133where
134 C::Hash: IntoVisitor + EncodeAsType,
135 C::AccountId: IntoVisitor,
136 <C::ExtrinsicParams as ExtrinsicParams<C>>::Params:
137 From<<DefaultExtrinsicParams<C> as ExtrinsicParams<C>>::Params>,
138 Signer: tx::Signer<C> + Clone,
139{
140 pub async fn remove_code(&self) -> Result<RemoveResult<C, E>, ErrorVariant>
150 where
151 E::Balance: IntoVisitor + Into<u128>,
152 {
153 let code_hash = self.final_code_hash;
154
155 let call = RemoveCode::new(code_hash).build();
156
157 let events =
158 submit_extrinsic(&self.client, &self.rpc, &call, self.opts.signer()).await?;
159
160 let code_removed =
161 events.find_first::<CodeRemoved<C::Hash, C::AccountId, E::Balance>>()?;
162 Ok(RemoveResult {
163 code_removed,
164 events,
165 })
166 }
167
168 pub fn final_code_hash(&self) -> C::Hash {
170 self.final_code_hash
171 }
172
173 pub fn opts(&self) -> &ExtrinsicOpts<C, E, Signer> {
175 &self.opts
176 }
177
178 pub fn client(&self) -> &OnlineClient<C> {
180 &self.client
181 }
182
183 pub fn transcoder(&self) -> &ContractMessageTranscoder {
185 &self.transcoder
186 }
187}
188
189pub struct RemoveResult<C: Config, E: Environment> {
191 pub code_removed: Option<CodeRemoved<C::Hash, C::AccountId, E::Balance>>,
192 pub events: ExtrinsicEvents<C>,
193}