Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: update instantiation of cw721 with onchain metadata template #27

Merged
merged 3 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions cw721/on-chain-metadata/src/bin/schema.rs
Original file line number Diff line number Diff line change
@@ -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<Empty>,
query: QueryMsg,
}
}
95 changes: 51 additions & 44 deletions cw721/on-chain-metadata/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
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<String>,
pub trait_type: String,
pub value: String,
}

// 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<String>,
pub image_data: Option<String>,
Expand All @@ -31,9 +32,7 @@ pub type Extension = Option<Metadata>;

pub type Cw721MetadataContract<'a> = cw721_base::Cw721Contract<'a, Extension, Empty, Empty, Empty>;
pub type ExecuteMsg = cw721_base::ExecuteMsg<Extension, Empty>;

const CONTRACT_NAME: &str = "crates.io:{{project-name}}";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
pub type QueryMsg = cw721_base::QueryMsg<Empty>;

#[cfg(not(feature = "library"))]
pub mod entry {
Expand All @@ -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<Response> {
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]
Expand All @@ -75,7 +65,7 @@ pub mod entry {
}

#[entry_point]
pub fn query(deps: Deps, env: Env, msg: QueryMsg<Empty>) -> StdResult<Binary> {
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
Cw721MetadataContract::default().query(deps, env, msg)
}
}
Expand All @@ -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();
Expand All @@ -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);
}
}
Loading