cosm_tome_wasm_deploy_fork/modules/cosmwasm/
model.rs

1use cosmrs::proto::cosmwasm::wasm::v1::MsgStoreCode;
2use cosmrs::proto::traits::MessageExt;
3use cosmrs::proto::{
4    cosmwasm::wasm::v1::{
5        AccessConfig as ProtoAccessConfig, AccessType as ProtoAccessType, MsgExecuteContract,
6        MsgInstantiateContract, MsgMigrateContract, QuerySmartContractStateResponse,
7    },
8    Any,
9};
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12
13use crate::chain::error::DeserializeError;
14use crate::{
15    chain::{
16        coin::Coin,
17        error::ChainError,
18        response::{ChainResponse, ChainTxResponse, Code},
19    },
20    modules::auth::model::Address,
21};
22
23use super::error::CosmwasmError;
24
25#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
26pub struct StoreCodeRequest {
27    pub wasm_data: Vec<u8>,
28    pub instantiate_perms: Option<AccessConfig>,
29}
30
31impl StoreCodeRequest {
32    pub fn to_proto(self, signer_addr: Address) -> Result<StoreCodeProto, CosmwasmError> {
33        Ok(StoreCodeProto {
34            signer_addr,
35            wasm_data: self.wasm_data,
36            instantiate_perms: self.instantiate_perms,
37        })
38    }
39}
40
41#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
42pub struct StoreCodeProto {
43    pub signer_addr: Address,
44    pub wasm_data: Vec<u8>,
45    pub instantiate_perms: Option<AccessConfig>,
46}
47
48impl TryFrom<StoreCodeProto> for Any {
49    type Error = CosmwasmError;
50
51    fn try_from(req: StoreCodeProto) -> Result<Self, Self::Error> {
52        let proto: MsgStoreCode = req.try_into()?;
53        Ok(proto.to_any().map_err(ChainError::prost_proto_encoding)?)
54    }
55}
56
57impl TryFrom<Any> for StoreCodeProto {
58    type Error = CosmwasmError;
59
60    fn try_from(any: Any) -> Result<Self, Self::Error> {
61        MsgStoreCode::from_any(&any)
62            .map_err(ChainError::prost_proto_decoding)?
63            .try_into()
64    }
65}
66
67impl TryFrom<MsgStoreCode> for StoreCodeProto {
68    type Error = CosmwasmError;
69
70    fn try_from(msg: MsgStoreCode) -> Result<Self, Self::Error> {
71        Ok(Self {
72            signer_addr: msg.sender.parse()?,
73            wasm_data: msg.wasm_byte_code,
74            instantiate_perms: msg
75                .instantiate_permission
76                .map(TryFrom::try_from)
77                .transpose()?,
78        })
79    }
80}
81
82impl TryFrom<StoreCodeProto> for MsgStoreCode {
83    type Error = CosmwasmError;
84
85    fn try_from(req: StoreCodeProto) -> Result<Self, Self::Error> {
86        Ok(Self {
87            sender: req.signer_addr.into(),
88            wasm_byte_code: req.wasm_data,
89            instantiate_permission: req.instantiate_perms.map(Into::into),
90        })
91    }
92}
93
94#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
95pub struct StoreCodeResponse {
96    pub code_id: u64,
97    pub res: ChainTxResponse,
98}
99
100impl StoreCodeResponse {
101    pub fn data<'a, T: Deserialize<'a>>(&'a self) -> Result<T, DeserializeError> {
102        self.res.res.data()
103    }
104}
105
106impl AsRef<ChainTxResponse> for StoreCodeResponse {
107    fn as_ref(&self) -> &ChainTxResponse {
108        &self.res
109    }
110}
111
112#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
113pub struct StoreCodeBatchResponse {
114    pub code_ids: Vec<u64>,
115    pub res: ChainTxResponse,
116}
117
118impl StoreCodeBatchResponse {
119    pub fn data<'a, T: Deserialize<'a>>(&'a self) -> Result<T, DeserializeError> {
120        self.res.res.data()
121    }
122}
123
124impl AsRef<ChainTxResponse> for StoreCodeBatchResponse {
125    fn as_ref(&self) -> &ChainTxResponse {
126        &self.res
127    }
128}
129
130#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
131pub struct InstantiateRequest<S: Serialize> {
132    pub code_id: u64,
133    pub msg: S,
134    pub label: String,
135    pub admin: Option<Address>,
136    pub funds: Vec<Coin>,
137}
138
139impl<S: Serialize> InstantiateRequest<S> {
140    pub fn to_proto(self, signer_addr: Address) -> Result<InstantiateRequestProto, CosmwasmError> {
141        let payload = serde_json::to_vec(&self.msg).map_err(CosmwasmError::json)?;
142
143        Ok(InstantiateRequestProto {
144            signer_addr,
145            code_id: self.code_id,
146            msg: payload,
147            label: self.label,
148            admin: self.admin,
149            funds: self.funds,
150        })
151    }
152}
153
154#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
155pub struct InstantiateRequestProto {
156    pub signer_addr: Address,
157    pub code_id: u64,
158    pub msg: Vec<u8>,
159    pub label: String,
160    pub admin: Option<Address>,
161    pub funds: Vec<Coin>,
162}
163
164impl TryFrom<InstantiateRequestProto> for Any {
165    type Error = CosmwasmError;
166
167    fn try_from(req: InstantiateRequestProto) -> Result<Self, Self::Error> {
168        let proto: MsgInstantiateContract = req.try_into()?;
169        Ok(proto.to_any().map_err(ChainError::prost_proto_encoding)?)
170    }
171}
172
173impl TryFrom<Any> for InstantiateRequestProto {
174    type Error = CosmwasmError;
175
176    fn try_from(any: Any) -> Result<Self, Self::Error> {
177        MsgInstantiateContract::from_any(&any)
178            .map_err(ChainError::prost_proto_decoding)?
179            .try_into()
180    }
181}
182
183impl TryFrom<MsgInstantiateContract> for InstantiateRequestProto {
184    type Error = CosmwasmError;
185
186    fn try_from(msg: MsgInstantiateContract) -> Result<Self, Self::Error> {
187        let admin = if msg.admin.is_empty() {
188            None
189        } else {
190            Some(msg.admin.parse()?)
191        };
192
193        Ok(Self {
194            signer_addr: msg.sender.parse()?,
195            code_id: msg.code_id,
196            msg: msg.msg,
197            label: msg.label,
198            admin,
199            funds: msg
200                .funds
201                .into_iter()
202                .map(TryInto::try_into)
203                .collect::<Result<Vec<_>, _>>()?,
204        })
205    }
206}
207
208impl TryFrom<InstantiateRequestProto> for MsgInstantiateContract {
209    type Error = CosmwasmError;
210
211    fn try_from(req: InstantiateRequestProto) -> Result<Self, Self::Error> {
212        Ok(Self {
213            sender: req.signer_addr.into(),
214            admin: req.admin.map(Into::into).unwrap_or_default(),
215            code_id: req.code_id,
216            label: req.label,
217            msg: req.msg,
218            funds: req.funds.into_iter().map(Into::into).collect(),
219        })
220    }
221}
222
223#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
224pub struct InstantiateResponse {
225    pub address: Address,
226    pub res: ChainTxResponse,
227}
228
229impl InstantiateResponse {
230    pub fn data<'a, T: Deserialize<'a>>(&'a self) -> Result<T, DeserializeError> {
231        self.res.res.data()
232    }
233}
234
235impl AsRef<ChainTxResponse> for InstantiateResponse {
236    fn as_ref(&self) -> &ChainTxResponse {
237        &self.res
238    }
239}
240
241#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
242pub struct InstantiateBatchResponse {
243    pub addresses: Vec<Address>,
244    pub res: ChainTxResponse,
245}
246
247impl InstantiateBatchResponse {
248    pub fn data<'a, T: Deserialize<'a>>(&'a self) -> Result<T, DeserializeError> {
249        self.res.res.data()
250    }
251}
252
253impl AsRef<ChainTxResponse> for InstantiateBatchResponse {
254    fn as_ref(&self) -> &ChainTxResponse {
255        &self.res
256    }
257}
258
259#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
260pub struct ExecRequest<S: Serialize> {
261    pub address: Address,
262    pub msg: S,
263    pub funds: Vec<Coin>,
264}
265
266impl<S: Serialize> ExecRequest<S> {
267    pub fn to_proto(self, signer_addr: Address) -> Result<ExecRequestProto, CosmwasmError> {
268        let payload = serde_json::to_vec(&self.msg).map_err(CosmwasmError::json)?;
269
270        Ok(ExecRequestProto {
271            signer_addr,
272            contract_addr: self.address,
273            msg: payload,
274            funds: self.funds,
275        })
276    }
277}
278
279#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
280pub struct ExecRequestProto {
281    pub signer_addr: Address,
282    pub contract_addr: Address,
283    pub msg: Vec<u8>,
284    pub funds: Vec<Coin>,
285}
286
287impl TryFrom<ExecRequestProto> for Any {
288    type Error = CosmwasmError;
289
290    fn try_from(req: ExecRequestProto) -> Result<Self, Self::Error> {
291        let proto: MsgExecuteContract = req.try_into()?;
292        Ok(proto.to_any().map_err(ChainError::prost_proto_encoding)?)
293    }
294}
295
296impl TryFrom<Any> for ExecRequestProto {
297    type Error = CosmwasmError;
298
299    fn try_from(any: Any) -> Result<Self, Self::Error> {
300        MsgExecuteContract::from_any(&any)
301            .map_err(ChainError::prost_proto_decoding)?
302            .try_into()
303    }
304}
305
306impl TryFrom<MsgExecuteContract> for ExecRequestProto {
307    type Error = CosmwasmError;
308
309    fn try_from(msg: MsgExecuteContract) -> Result<Self, Self::Error> {
310        Ok(Self {
311            signer_addr: msg.sender.parse()?,
312            contract_addr: msg.contract.parse()?,
313            msg: msg.msg,
314            funds: msg
315                .funds
316                .into_iter()
317                .map(TryInto::try_into)
318                .collect::<Result<Vec<_>, _>>()?,
319        })
320    }
321}
322
323impl TryFrom<ExecRequestProto> for MsgExecuteContract {
324    type Error = CosmwasmError;
325
326    fn try_from(req: ExecRequestProto) -> Result<Self, Self::Error> {
327        Ok(Self {
328            sender: req.signer_addr.into(),
329            contract: req.contract_addr.into(),
330            msg: req.msg,
331            funds: req.funds.into_iter().map(Into::into).collect(),
332        })
333    }
334}
335
336#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
337pub struct ExecResponse {
338    pub res: ChainTxResponse,
339}
340
341impl ExecResponse {
342    pub fn data<'a, T: Deserialize<'a>>(&'a self) -> Result<T, DeserializeError> {
343        self.res.res.data()
344    }
345}
346
347impl AsRef<ChainTxResponse> for ExecResponse {
348    fn as_ref(&self) -> &ChainTxResponse {
349        &self.res
350    }
351}
352
353#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
354pub struct QueryResponse {
355    pub res: ChainResponse,
356}
357
358impl QueryResponse {
359    pub fn data<'a, T: Deserialize<'a>>(&'a self) -> Result<T, DeserializeError> {
360        self.res.data()
361    }
362}
363
364impl AsRef<ChainResponse> for QueryResponse {
365    fn as_ref(&self) -> &ChainResponse {
366        &self.res
367    }
368}
369
370#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
371pub struct MigrateRequest<S: Serialize> {
372    pub address: Address,
373    pub new_code_id: u64,
374    pub msg: S,
375}
376
377impl<S: Serialize> MigrateRequest<S> {
378    pub fn to_proto(self, signer_addr: Address) -> Result<MigrateRequestProto, CosmwasmError> {
379        let payload = serde_json::to_vec(&self.msg).map_err(CosmwasmError::json)?;
380
381        Ok(MigrateRequestProto {
382            signer_addr,
383            contract_addr: self.address,
384            new_code_id: self.new_code_id,
385            msg: payload,
386        })
387    }
388}
389
390#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
391pub struct MigrateRequestProto {
392    pub signer_addr: Address,
393    pub contract_addr: Address,
394    pub new_code_id: u64,
395    pub msg: Vec<u8>,
396}
397
398impl TryFrom<MigrateRequestProto> for Any {
399    type Error = CosmwasmError;
400
401    fn try_from(req: MigrateRequestProto) -> Result<Self, Self::Error> {
402        let proto: MsgMigrateContract = req.try_into()?;
403        Ok(proto.to_any().map_err(ChainError::prost_proto_encoding)?)
404    }
405}
406
407impl TryFrom<Any> for MigrateRequestProto {
408    type Error = CosmwasmError;
409
410    fn try_from(any: Any) -> Result<Self, Self::Error> {
411        MsgMigrateContract::from_any(&any)
412            .map_err(ChainError::prost_proto_decoding)?
413            .try_into()
414    }
415}
416
417impl TryFrom<MsgMigrateContract> for MigrateRequestProto {
418    type Error = CosmwasmError;
419
420    fn try_from(msg: MsgMigrateContract) -> Result<Self, Self::Error> {
421        Ok(Self {
422            signer_addr: msg.sender.parse()?,
423            contract_addr: msg.contract.parse()?,
424            new_code_id: msg.code_id,
425            msg: msg.msg,
426        })
427    }
428}
429
430impl TryFrom<MigrateRequestProto> for MsgMigrateContract {
431    type Error = CosmwasmError;
432
433    fn try_from(req: MigrateRequestProto) -> Result<Self, Self::Error> {
434        Ok(Self {
435            sender: req.signer_addr.into(),
436            contract: req.contract_addr.into(),
437            code_id: req.new_code_id,
438            msg: req.msg,
439        })
440    }
441}
442
443#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
444pub struct MigrateResponse {
445    pub res: ChainTxResponse,
446}
447
448impl MigrateResponse {
449    pub fn data<'a, T: Deserialize<'a>>(&'a self) -> Result<T, DeserializeError> {
450        self.res.res.data()
451    }
452}
453
454impl AsRef<ChainTxResponse> for MigrateResponse {
455    fn as_ref(&self) -> &ChainTxResponse {
456        &self.res
457    }
458}
459
460impl From<QuerySmartContractStateResponse> for ChainResponse {
461    fn from(res: QuerySmartContractStateResponse) -> ChainResponse {
462        ChainResponse {
463            code: Code::Ok,
464            data: Some(res.data),
465            ..Default::default()
466        }
467    }
468}
469
470#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
471pub struct AccessConfig {
472    pub permission: AccessType,
473    pub account: Address,
474}
475
476impl From<AccessConfig> for cosmrs::cosmwasm::AccessConfig {
477    fn from(config: AccessConfig) -> Self {
478        Self {
479            permission: config.permission.into(),
480            address: config.account.into(),
481        }
482    }
483}
484
485impl From<cosmrs::cosmwasm::AccessConfig> for AccessConfig {
486    fn from(config: cosmrs::cosmwasm::AccessConfig) -> Self {
487        Self {
488            permission: config.permission.into(),
489            account: config.address.into(),
490        }
491    }
492}
493
494impl From<AccessConfig> for ProtoAccessConfig {
495    fn from(config: AccessConfig) -> Self {
496        Self {
497            permission: config.permission as i32,
498            address: config.account.into(),
499        }
500    }
501}
502
503impl TryFrom<ProtoAccessConfig> for AccessConfig {
504    type Error = CosmwasmError;
505
506    fn try_from(config: ProtoAccessConfig) -> Result<Self, Self::Error> {
507        Ok(Self {
508            permission: config.permission.try_into()?,
509            account: config.address.parse()?,
510        })
511    }
512}
513
514#[derive(
515    Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq, Hash, PartialOrd, Ord,
516)]
517#[repr(i32)]
518pub enum AccessType {
519    /// ACCESS_TYPE_UNSPECIFIED placeholder for empty value
520    Unspecified = 0,
521    /// ACCESS_TYPE_NOBODY forbidden TODO: better comments that explains what it actually does like we do in BroadcastMode
522    Nobody = 1,
523    /// ACCESS_TYPE_ONLY_ADDRESS restricted to an address
524    OnlyAddress = 2,
525    /// ACCESS_TYPE_EVERYBODY unrestricted
526    Everybody = 3,
527}
528
529impl AsRef<str> for AccessType {
530    fn as_ref(&self) -> &str {
531        match self {
532            AccessType::Unspecified => "ACCESS_TYPE_UNSPECIFIED",
533            AccessType::Nobody => "ACCESS_TYPE_NOBODY",
534            AccessType::OnlyAddress => "ACCESS_TYPE_ONLY_ADDRESS",
535            AccessType::Everybody => "ACCESS_TYPE_EVERYBODY",
536        }
537    }
538}
539
540impl TryFrom<i32> for AccessType {
541    type Error = CosmwasmError;
542
543    fn try_from(v: i32) -> Result<Self, Self::Error> {
544        match v {
545            x if x == AccessType::Unspecified as i32 => Ok(AccessType::Unspecified),
546            x if x == AccessType::Nobody as i32 => Ok(AccessType::Nobody),
547            x if x == AccessType::OnlyAddress as i32 => Ok(AccessType::OnlyAddress),
548            x if x == AccessType::Everybody as i32 => Ok(AccessType::Everybody),
549            _ => Err(CosmwasmError::AccessType { i: v }),
550        }
551    }
552}
553
554impl From<AccessType> for ProtoAccessType {
555    fn from(perm: AccessType) -> Self {
556        match perm {
557            AccessType::Unspecified => ProtoAccessType::Unspecified,
558            AccessType::Nobody => ProtoAccessType::Nobody,
559            AccessType::OnlyAddress => ProtoAccessType::OnlyAddress,
560            AccessType::Everybody => ProtoAccessType::Everybody,
561        }
562    }
563}
564
565impl From<ProtoAccessType> for AccessType {
566    fn from(perm: ProtoAccessType) -> Self {
567        match perm {
568            ProtoAccessType::Unspecified => AccessType::Unspecified,
569            ProtoAccessType::Nobody => AccessType::Nobody,
570            ProtoAccessType::OnlyAddress => AccessType::OnlyAddress,
571            ProtoAccessType::Everybody => AccessType::Everybody,
572        }
573    }
574}