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

Contract level metadata #75

Closed
wants to merge 17 commits into from
Closed
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
294 changes: 252 additions & 42 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ in the CosmWasm ecosystem. `cw721` and `cw721-base` were moved from
[`cw-plus`](https://github.com/CosmWasm/cw-plus) to start this repo, but it shall evolve
as driven by the community's needs.

Please feel free to modify `cw721-base` as you need to support these projects and add many extensions
and additional standards (like [cw-2981](https://github.com/CosmWasm/cw-plus/pull/414)) to meet
Please feel free to modify [cw721-base](/contracts/cw721-base) as you need to support these projects and add many extensions
and additional standards (like [cw2981-royalties](/contracts/cw2981-royalties) to meet
the demands of the various NFT projects springing forth.

## Maintainers
Expand Down
4 changes: 4 additions & 0 deletions contracts/cw2981-royalties/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ cw721-base = { path = "../cw721-base", version = "0.15.0", features = [
] }
schemars = "0.8.10"
serde = { version = "1.0.140", default-features = false, features = ["derive"] }

[dev-dependencies]
cw-multi-test = "0.14.0"
cw2981-royalties-v0134-contract = { package = "cw2981-royalties", version = "0.13.4", git = "https://github.com/cosmwasm/cw-nfts", tag = "v0.13.4" }
4 changes: 2 additions & 2 deletions contracts/cw2981-royalties/examples/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fn main() {
create_dir_all(&out_dir).unwrap();
remove_schemas(&out_dir).unwrap();

export_schema(&schema_for!(InstantiateMsg), &out_dir);
export_schema(&schema_for!(InstantiateMsg<Empty>), &out_dir);
export_schema_with_title(
&schema_for!(ExecuteMsg<Extension, Empty>),
&out_dir,
Expand All @@ -31,7 +31,7 @@ fn main() {
"AllNftInfoResponse",
);
export_schema(&schema_for!(OperatorsResponse), &out_dir);
export_schema(&schema_for!(ContractInfoResponse), &out_dir);
export_schema(&schema_for!(ContractInfoResponse<Empty>), &out_dir);
export_schema(&schema_for!(MinterResponse), &out_dir);
export_schema_with_title(
&schema_for!(NftInfoResponse<Extension>),
Expand Down
18 changes: 0 additions & 18 deletions contracts/cw2981-royalties/schema/contract_info_response.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ContractInfoResponse_for_Empty",
"type": "object",
"required": [
"metadata",
"name",
"symbol"
],
"properties": {
"collection_uri": {
"description": "Universal resource identifier for this NFT Collection Should point to a JSON file that conforms to contract level metadata schema: https://docs.opensea.io/docs/contract-level-metadata",
"type": [
"string",
"null"
]
},
"metadata": {
"description": "Metadata extension for custom on-chain metadata",
"allOf": [
{
"$ref": "#/definitions/Empty"
}
]
},
"name": {
"description": "Name of the NFT contract",
"type": "string"
},
"symbol": {
"description": "Part of the OG ERC721 standard even though no one uses it",
"type": "string"
}
},
"additionalProperties": false,
"definitions": {
"Empty": {
"description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)",
"type": "object"
}
}
}
25 changes: 0 additions & 25 deletions contracts/cw2981-royalties/schema/instantiate_msg.json

This file was deleted.

47 changes: 47 additions & 0 deletions contracts/cw2981-royalties/schema/instantiate_msg_for__empty.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "InstantiateMsg_for_Empty",
"type": "object",
"required": [
"metadata",
"minter",
"name",
"symbol"
],
"properties": {
"collection_uri": {
"description": "Universal resource identifier for this NFT Collection Should point to a JSON file that conforms to contract level metadata schema: https://docs.opensea.io/docs/contract-level-metadata",
"type": [
"string",
"null"
]
},
"metadata": {
"description": "Metadata extension for custom on-chain metadata",
"allOf": [
{
"$ref": "#/definitions/Empty"
}
]
},
"minter": {
"description": "The minter is the only one who can create new NFTs. This is designed for a base NFT that is controlled by an external program or contract. You will likely replace this with custom logic in custom NFTs",
"type": "string"
},
"name": {
"description": "Name of the NFT contract",
"type": "string"
},
"symbol": {
"description": "Part of the OG ERC721 standard even though no one uses it",
"type": "string"
}
},
"additionalProperties": false,
"definitions": {
"Empty": {
"description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)",
"type": "object"
}
}
}
112 changes: 95 additions & 17 deletions contracts/cw2981-royalties/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ pub mod query;

pub use query::{check_royalties, query_royalties_info};

use crate::msg::Cw2981QueryMsg;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{to_binary, Empty};
use cw2::set_contract_version;
use cw721_base::Cw721Contract;
pub use cw721_base::{ContractError, InstantiateMsg, MintMsg, MinterResponse};

use crate::msg::Cw2981QueryMsg;
pub use cw721_base::{ContractError, InstantiateMsg, MigrateMsg, MintMsg, MinterResponse};

// Version info for migration
const CONTRACT_NAME: &str = "crates.io:cw2981-royalties";
Expand Down Expand Up @@ -48,7 +47,7 @@ pub type Extension = Option<Metadata>;

pub type MintExtension = Option<Extension>;

pub type Cw2981Contract<'a> = Cw721Contract<'a, Extension, Empty, Empty, Cw2981QueryMsg>;
pub type Cw2981Contract<'a> = Cw721Contract<'a, Extension, Empty, Empty, Empty, Cw2981QueryMsg>;
pub type ExecuteMsg = cw721_base::ExecuteMsg<Extension, Empty>;
pub type QueryMsg = cw721_base::QueryMsg<Cw2981QueryMsg>;

Expand All @@ -64,7 +63,7 @@ pub mod entry {
mut deps: DepsMut,
env: Env,
info: MessageInfo,
msg: InstantiateMsg,
msg: InstantiateMsg<Empty>,
) -> Result<Response, ContractError> {
let res = Cw2981Contract::default().instantiate(deps.branch(), env, info, msg)?;
// Explicitly set contract name and version, otherwise set to cw721-base info
Expand Down Expand Up @@ -96,29 +95,61 @@ pub mod entry {
_ => Cw2981Contract::default().query(deps, env, msg),
}
}

#[entry_point]
pub fn migrate(
deps: DepsMut,
env: Env,
msg: MigrateMsg<Empty>,
) -> Result<Response, ContractError> {
Cw2981Contract::default().migrate(deps, env, msg)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::msg::{CheckRoyaltiesResponse, RoyaltiesInfoResponse};

use cosmwasm_std::{from_binary, Uint128};

use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{from_binary, Addr, CosmosMsg, Uint128, WasmMsg};
use cw721::Cw721Query;
use cw_multi_test::{App, Contract, ContractWrapper, Executor};

fn cw2981_royalties_v0134_contract_contract() -> Box<dyn Contract<Empty>> {
let contract = ContractWrapper::new(
cw2981_royalties_v0134_contract::entry::execute,
cw2981_royalties_v0134_contract::entry::instantiate,
cw2981_royalties_v0134_contract::entry::query,
);
Box::new(contract)
}

fn cw721_base_contract() -> Box<dyn Contract<Empty>> {
let contract = ContractWrapper::new(
crate::entry::execute,
crate::entry::instantiate,
crate::entry::query,
)
.with_migrate(crate::entry::migrate);
Box::new(contract)
}

const CREATOR: &str = "creator";
const CONTRACT_NAME: &str = "Magic Power";
const CONTRACT_URI: &str = "https://example.com/example.jpg";
const SYMBOL: &str = "MGK";

#[test]
fn use_metadata_extension() {
let mut deps = mock_dependencies();
let contract = Cw2981Contract::default();

let info = mock_info(CREATOR, &[]);
let init_msg = InstantiateMsg {
name: "SpaceShips".to_string(),
symbol: "SPACE".to_string(),
let init_msg = InstantiateMsg::<Empty> {
name: CONTRACT_NAME.to_string(),
symbol: SYMBOL.to_string(),
collection_uri: Some(String::from(CONTRACT_URI)),
metadata: Empty {},
minter: CREATOR.to_string(),
};
entry::instantiate(deps.as_mut(), mock_env(), info.clone(), init_msg).unwrap();
Expand Down Expand Up @@ -148,9 +179,11 @@ mod tests {
let _contract = Cw2981Contract::default();

let info = mock_info(CREATOR, &[]);
let init_msg = InstantiateMsg {
name: "SpaceShips".to_string(),
symbol: "SPACE".to_string(),
let init_msg = InstantiateMsg::<Empty> {
name: CONTRACT_NAME.to_string(),
symbol: SYMBOL.to_string(),
collection_uri: Some(String::from(CONTRACT_URI)),
metadata: Empty {},
minter: CREATOR.to_string(),
};
entry::instantiate(deps.as_mut(), mock_env(), info.clone(), init_msg).unwrap();
Expand Down Expand Up @@ -189,9 +222,11 @@ mod tests {
let mut deps = mock_dependencies();

let info = mock_info(CREATOR, &[]);
let init_msg = InstantiateMsg {
name: "SpaceShips".to_string(),
symbol: "SPACE".to_string(),
let init_msg = InstantiateMsg::<Empty> {
name: CONTRACT_NAME.to_string(),
symbol: SYMBOL.to_string(),
collection_uri: Some(String::from(CONTRACT_URI)),
metadata: Empty {},
minter: CREATOR.to_string(),
};
entry::instantiate(deps.as_mut(), mock_env(), info.clone(), init_msg).unwrap();
Expand Down Expand Up @@ -264,4 +299,47 @@ mod tests {
.unwrap();
assert_eq!(res, voyager_expected);
}

#[test]
fn test_migrate_from_v0134() {
const CREATOR: &str = "creator";

let mut app = App::default();
let v0134_code_id = app.store_code(cw2981_royalties_v0134_contract_contract());

// Instantiate old NFT contract
let v0134_addr = app
.instantiate_contract(
v0134_code_id,
Addr::unchecked(CREATOR),
&cw2981_royalties_v0134_contract::InstantiateMsg {
name: "Test".to_string(),
symbol: "TEST".to_string(),
minter: CREATOR.to_string(),
},
&[],
"Old cw721-base",
Some(CREATOR.to_string()),
)
.unwrap();

let cw721_base_code_id = app.store_code(cw721_base_contract());

// Now we can migrate!
app.execute(
Addr::unchecked(CREATOR),
CosmosMsg::Wasm(WasmMsg::Migrate {
contract_addr: v0134_addr.to_string(),
new_code_id: cw721_base_code_id,
msg: to_binary(&MigrateMsg::<Empty> {
name: "Test".to_string(),
symbol: "TEST".to_string(),
collection_uri: Some("https://ipfs.io/hash".to_string()),
metadata: Empty {},
})
.unwrap(),
}),
)
.unwrap();
}
}
3 changes: 1 addition & 2 deletions contracts/cw2981-royalties/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Uint128;
use cw721::CustomMsg;
use cosmwasm_std::{CustomMsg, Uint128};

#[cw_serde]
pub enum Cw2981QueryMsg {
Expand Down
4 changes: 4 additions & 0 deletions contracts/cw721-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ cw-storage-plus = "0.15.0"
schemars = "0.8.10"
serde = { version = "1.0.140", default-features = false, features = ["derive"] }
thiserror = "1.0.31"

[dev-dependencies]
cw-multi-test = "0.14.0"
cw721-base-v0132-contract = { package = "cw721-base", version = "0.13.2", git = "https://github.com/cosmwasm/cw-nfts", tag = "v0.13.2" }
Loading