diff --git a/cw721/on-chain-metadata/src/bin/schema.rs b/cw721/on-chain-metadata/src/bin/schema.rs index a01a7b9..c713a8b 100644 --- a/cw721/on-chain-metadata/src/bin/schema.rs +++ b/cw721/on-chain-metadata/src/bin/schema.rs @@ -1,12 +1,11 @@ use cosmwasm_schema::write_api; -use cosmwasm_std::Empty; use {{crate_name}}::{ExecuteMsg, InstantiateMsg, QueryMsg}; fn main() { write_api! { instantiate: InstantiateMsg, execute: ExecuteMsg, - query: QueryMsg, + query: QueryMsg, } } diff --git a/cw721/on-chain-metadata/src/lib.rs b/cw721/on-chain-metadata/src/lib.rs index cdb1779..8de57e1 100644 --- a/cw721/on-chain-metadata/src/lib.rs +++ b/cw721/on-chain-metadata/src/lib.rs @@ -1,12 +1,12 @@ -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - +use cosmwasm_schema::cw_serde; use cosmwasm_std::Empty; -use cw2::set_contract_version; -use cw721::ContractInfoResponse; -pub use cw721_base::{ContractError, InstantiateMsg, MinterResponse, QueryMsg}; +pub use cw721_base::{ContractError, InstantiateMsg, MinterResponse}; + +// Version info for migration +const CONTRACT_NAME: &str = "crates.io:cw721-metadata-onchain"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug, Default)] +#[cw_serde] pub struct Trait { pub display_type: Option, pub trait_type: String, @@ -14,7 +14,8 @@ pub struct Trait { } // see: https://docs.opensea.io/docs/metadata-standards -#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug, Default)] +#[cw_serde] +#[derive(Default)] pub struct Metadata { pub image: Option, pub image_data: Option, @@ -31,9 +32,7 @@ pub type Extension = Option; pub type Cw721MetadataContract<'a> = cw721_base::Cw721Contract<'a, Extension, Empty, Empty, Empty>; pub type ExecuteMsg = cw721_base::ExecuteMsg; - -const CONTRACT_NAME: &str = "crates.io:{{project-name}}"; -const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +pub type QueryMsg = cw721_base::QueryMsg; #[cfg(not(feature = "library"))] pub mod entry { @@ -42,26 +41,17 @@ pub mod entry { use cosmwasm_std::entry_point; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; - // This is a simple type to let us handle empty extensions - // This makes a conscious choice on the various generics used by the contract #[entry_point] pub fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, + mut deps: DepsMut, + env: Env, + info: MessageInfo, msg: InstantiateMsg, ) -> StdResult { - set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - let info = ContractInfoResponse { - name: msg.name, - symbol: msg.symbol, - }; - Cw721MetadataContract::default() - .contract_info - .save(deps.storage, &info)?; - Ok(Response::default()) + Cw721MetadataContract::default().instantiate(deps.branch(), env, info, msg) } #[entry_point] @@ -75,7 +65,7 @@ pub mod entry { } #[entry_point] - pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { Cw721MetadataContract::default().query(deps, env, msg) } } @@ -89,6 +79,29 @@ mod tests { const CREATOR: &str = "creator"; + /// Make sure cw2 version info is properly initialized during instantiation, + /// and NOT overwritten by the base contract. + #[test] + fn proper_cw2_initialization() { + let mut deps = mock_dependencies(); + + entry::instantiate( + deps.as_mut(), + mock_env(), + mock_info("larry", &[]), + InstantiateMsg { + name: "".into(), + symbol: "".into(), + minter: "larry".into(), + }, + ) + .unwrap(); + + let version = cw2::get_contract_version(deps.as_ref().storage).unwrap(); + assert_eq!(version.contract, CONTRACT_NAME); + assert_ne!(version.contract, cw721_base::CONTRACT_NAME); + } + #[test] fn use_metadata_extension() { let mut deps = mock_dependencies(); @@ -105,30 +118,24 @@ mod tests { .unwrap(); let token_id = "Enterprise"; - let mint_msg = ExecuteMsg::Mint { + let token_uri = Some("https://starships.example.com/Starship/Enterprise.json".into()); + let extension = Some(Metadata { + description: Some("Spaceship with Warp Drive".into()), + name: Some("Starship USS Enterprise".to_string()), + ..Metadata::default() + }); + let exec_msg = ExecuteMsg::Mint { token_id: token_id.to_string(), owner: "john".to_string(), - token_uri: Some("https://starships.example.com/Starship/Enterprise.json".into()), - extension: Some(Metadata { - description: Some("Spaceship with Warp Drive".into()), - name: Some("Starship USS Enterprise".to_string()), - ..Metadata::default() - }), + token_uri: token_uri.clone(), + extension: extension.clone(), }; contract - .execute(deps.as_mut(), mock_env(), info, mint_msg.clone()) + .execute(deps.as_mut(), mock_env(), info, exec_msg) .unwrap(); let res = contract.nft_info(deps.as_ref(), token_id.into()).unwrap(); - if let ExecuteMsg::Mint { - token_id: _, - owner: _, - token_uri, - extension, - } = mint_msg - { - assert_eq!(res.token_uri, token_uri); - assert_eq!(res.extension, extension); - } + assert_eq!(res.token_uri, token_uri); + assert_eq!(res.extension, extension); } }