diff --git a/Cargo.lock b/Cargo.lock index 8e55544..d195d72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -325,7 +325,7 @@ checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" [[package]] name = "marketpalace-raise-contract" -version = "0.1.1" +version = "1.0.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", diff --git a/Cargo.toml b/Cargo.toml index 007ad72..3a863c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "marketpalace-raise-contract" -version = "0.1.1" +version = "1.0.0" authors = ["Thomas Silva "] edition = "2018" diff --git a/examples/schema.rs b/examples/schema.rs index 27e153a..719769f 100644 --- a/examples/schema.rs +++ b/examples/schema.rs @@ -3,7 +3,7 @@ use std::fs::create_dir_all; use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; -use marketpalace_raise_contract::msg::{HandleMsg, InstantiateMsg, QueryMsg}; +use marketpalace_raise_contract::msg::{HandleMsg, InstantiateMsg, MigrateMsg, QueryMsg}; use marketpalace_raise_contract::state::State; fn main() { @@ -13,6 +13,7 @@ fn main() { remove_schemas(&out_dir).unwrap(); export_schema(&schema_for!(InstantiateMsg), &out_dir); + export_schema(&schema_for!(MigrateMsg), &out_dir); export_schema(&schema_for!(HandleMsg), &out_dir); export_schema(&schema_for!(QueryMsg), &out_dir); export_schema(&schema_for!(State), &out_dir); diff --git a/schema/migrate_msg.json b/schema/migrate_msg.json new file mode 100644 index 0000000..65f319f --- /dev/null +++ b/schema/migrate_msg.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MigrateMsg", + "type": "object", + "required": [ + "subscription_code_id" + ], + "properties": { + "subscription_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } +} diff --git a/src/migrate.rs b/src/migrate.rs index 45daf82..aa151e0 100644 --- a/src/migrate.rs +++ b/src/migrate.rs @@ -1,26 +1,57 @@ use crate::contract::ContractResponse; +use crate::error::ContractError; use crate::msg::MigrateMsg; +use crate::state::config; +use crate::state::config_read; use crate::version::CONTRACT_NAME; use crate::version::CONTRACT_VERSION; use cosmwasm_std::entry_point; +use cosmwasm_std::to_binary; use cosmwasm_std::DepsMut; use cosmwasm_std::Env; use cosmwasm_std::Response; use cw2::set_contract_version; +use serde::Serialize; + +#[derive(Serialize)] +struct EmptyArgs {} #[entry_point] -pub fn migrate(deps: DepsMut, _: Env, _: MigrateMsg) -> ContractResponse { +pub fn migrate(deps: DepsMut, _: Env, msg: MigrateMsg) -> ContractResponse { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - Ok(Response::default()) + let state = config_read(deps.storage).load()?; + + if state.subscription_code_id != msg.subscription_code_id { + config(deps.storage).update(|mut state| -> Result<_, ContractError> { + state.subscription_code_id = msg.subscription_code_id; + Ok(state) + })?; + + let sub_migrations = state + .pending_review_subs + .union(&state.accepted_subs) + .map(|addr| cosmwasm_std::WasmMsg::Migrate { + contract_addr: addr.to_string(), + new_code_id: msg.subscription_code_id, + msg: to_binary(&EmptyArgs {}).unwrap(), + }); + + Ok(Response::default().add_messages(sub_migrations)) + } else { + Ok(Response::default()) + } } #[cfg(test)] mod tests { + use super::*; + use crate::contract::tests::default_deps; use crate::state::State; use crate::state::Status; use crate::state::Withdrawal; use cosmwasm_std::testing::mock_dependencies; + use cosmwasm_std::testing::mock_env; use cosmwasm_std::Addr; use cosmwasm_storage::{singleton, singleton_read}; use schemars::JsonSchema; @@ -50,6 +81,42 @@ mod tests { pub static CONFIG_KEY: &[u8] = b"config"; + #[test] + fn new_sub_code_migration() { + let mut deps = default_deps(Some(|state| { + state.accepted_subs = vec![Addr::unchecked("sub_1")].into_iter().collect(); + })); + + let res = migrate( + deps.as_mut(), + mock_env(), + MigrateMsg { + subscription_code_id: 1, + }, + ) + .unwrap(); + + assert_eq!(1, res.messages.len()); + } + + #[test] + fn same_sub_code_migration() { + let mut deps = default_deps(Some(|state| { + state.accepted_subs = vec![Addr::unchecked("sub_1")].into_iter().collect(); + })); + + let res = migrate( + deps.as_mut(), + mock_env(), + MigrateMsg { + subscription_code_id: 0, + }, + ) + .unwrap(); + + assert_eq!(0, res.messages.len()); + } + #[test] fn read_from_old_state() { let mut deps = mock_dependencies(&[]); diff --git a/src/msg.rs b/src/msg.rs index 7113576..80fb15a 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -20,7 +20,9 @@ pub struct InstantiateMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub struct MigrateMsg {} +pub struct MigrateMsg { + pub subscription_code_id: u64, +} #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")]