vectis_wallet/types/plugin/
types.rs

1use crate::types::error::PluginRegError;
2use cosmwasm_schema::cw_serde;
3use cosmwasm_std::{Binary, CanonicalAddr, Coin, Deps};
4use std::collections::BTreeMap;
5
6/// Input for migrating a plugin
7#[cw_serde]
8pub struct PluginMigrateParams {
9    /// The existing plugin addr to migrate
10    pub plugin_addr: String,
11    /// The existing plugin permission; this will not change in the migration
12    /// It is included here to help the contract find the plugin
13    pub plugin_permission: PluginPermission,
14    /// The new src; this should only be different to existing if it is not vectis registry
15    pub target_src: PluginSource,
16    pub migration_msg: Binary,
17    pub funds: Vec<Coin>,
18}
19
20/// Input for installing a plugin
21#[cw_serde]
22pub struct PluginInstallParams {
23    pub src: PluginSource,
24    pub instantiate_msg: Binary,
25    pub permission: PluginPermission,
26    pub label: String,
27    pub funds: Vec<Coin>,
28}
29
30#[cw_serde]
31pub struct PluginCodeData {
32    pub latest_contract_version: String, // Must update version to the cw2 contract version
33    pub new_code_id: u64,                // Version must match new code
34    pub new_code_hash: String,           // Code_id must point to this code_hash
35}
36
37#[cw_serde]
38pub struct PluginMetadataData {
39    pub creator: String,
40    pub display_name: String,
41    pub ipfs_hash: String,
42}
43
44#[cw_serde]
45pub struct PluginInfo {
46    pub src: PluginSource,
47    pub version: String,
48    pub permission: PluginPermission,
49}
50
51/// Permission of the plugin on the proxy
52#[cw_serde]
53pub enum PluginPermission {
54    /// Can Exec through Proxy
55    Exec,
56    /// Is used to check tx before execution
57    // TODO: Impl
58    PreTxCheck,
59    /// Hooks post tx
60    // TODO: Impl
61    PostTxHook,
62}
63
64/// The source of the plugin code.
65/// Currently only support VectisRegistry but this can be others in the future
66#[cw_serde]
67pub enum PluginSource {
68    /// Plugin registry id and version (latest if not provided)
69    VectisRegistry(u64, Option<String>),
70}
71
72impl std::fmt::Display for PluginSource {
73    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
74        write!(f, "{self:?}")
75    }
76}
77
78#[cw_serde]
79pub struct VersionDetails {
80    /// Uploaded Plugin code id
81    pub code_id: u64,
82    /// code_hash of the contract
83    pub code_hash: String,
84    /// Useful for storing display data
85    pub ipfs_hash: String,
86}
87
88#[cw_serde]
89pub struct Plugin {
90    /// Identifier of the plugin, does not change over time
91    pub id: u64,
92    /// Reference Addr onchain to the creator
93    pub creator: CanonicalAddr,
94    /// Display name, creator can define this
95    pub display_name: String,
96    /// Latest cw2 contract version
97    pub latest_contract_version: String,
98    /// Mapping of all versions to the details
99    pub versions: BTreeMap<String, VersionDetails>,
100}
101
102impl Plugin {
103    pub fn get_latest_version_details(&self) -> Result<VersionDetails, PluginRegError> {
104        self.versions
105            .get(&self.latest_contract_version)
106            .map(|l| l.to_owned())
107            .ok_or_else(|| {
108                PluginRegError::PluginVersionNotFound(self.latest_contract_version.clone())
109            })
110    }
111
112    pub fn get_version_details(&self, version: &str) -> Result<VersionDetails, PluginRegError> {
113        self.versions
114            .get(version)
115            .map(|l| l.to_owned())
116            .ok_or_else(|| PluginRegError::PluginVersionNotFound(version.to_string()))
117    }
118
119    #[allow(clippy::too_many_arguments)]
120    pub fn new(
121        deps: Deps,
122        id: u64,
123        creator: String,
124        display_name: String,
125        ipfs_hash: String,
126        latest_contract_version: String,
127        code_id: u64,
128        code_hash: String,
129    ) -> Result<Plugin, PluginRegError> {
130        let mut record = BTreeMap::new();
131        record.insert(
132            latest_contract_version.clone(),
133            VersionDetails {
134                code_id,
135                code_hash,
136                ipfs_hash,
137            },
138        );
139
140        // validate creator
141        let validated_addr = deps.api.addr_validate(&creator)?;
142
143        Ok(Plugin {
144            id,
145            creator: deps.api.addr_canonicalize(validated_addr.as_str())?,
146            display_name,
147            latest_contract_version,
148            versions: record,
149        })
150    }
151}