diff --git a/Cargo.lock b/Cargo.lock index 237366b..036f704 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,6 +213,24 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw-multi-test" +version = "0.13.4" +source = "git+https://github.com/CosmWasm/cw-plus#14f4e922fac9e2097a8efa99e5b71d04747e340a" +dependencies = [ + "anyhow", + "cosmwasm-std", + "cosmwasm-storage", + "cw-storage-plus 0.13.4", + "cw-utils 0.13.4", + "derivative", + "itertools", + "prost", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "cw-storage-plus" version = "0.11.1" @@ -246,6 +264,16 @@ dependencies = [ "serde", ] +[[package]] +name = "cw-storage-plus" +version = "0.13.4" +source = "git+https://github.com/CosmWasm/cw-plus#14f4e922fac9e2097a8efa99e5b71d04747e340a" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "cw-utils" version = "0.11.1" @@ -282,6 +310,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw-utils" +version = "0.13.4" +source = "git+https://github.com/CosmWasm/cw-plus#14f4e922fac9e2097a8efa99e5b71d04747e340a" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "cw0" version = "0.10.3" @@ -390,6 +429,17 @@ dependencies = [ "serde", ] +[[package]] +name = "cw721" +version = "0.13.2" +source = "git+https://github.com/CosmWasm/cw-nfts?branch=main#4e26419bb02f4b871fda487964a80bd419207428" +dependencies = [ + "cosmwasm-std", + "cw-utils 0.13.2", + "schemars", + "serde", +] + [[package]] name = "cw721-base" version = "0.11.1" @@ -416,7 +466,22 @@ dependencies = [ "cw-storage-plus 0.13.2", "cw-utils 0.13.2", "cw2 0.13.2", - "cw721 0.13.2", + "cw721 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw721-base" +version = "0.13.2" +source = "git+https://github.com/CosmWasm/cw-nfts?branch=main#4e26419bb02f4b871fda487964a80bd419207428" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus 0.13.2", + "cw-utils 0.13.2", + "cw2 0.13.2", + "cw721 0.13.2 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", "schemars", "serde", "thiserror", @@ -646,7 +711,7 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cosmwasm-storage", - "cw-multi-test", + "cw-multi-test 0.13.2", "cw-storage-plus 0.11.1", "cw2 0.11.1", "cw721 0.11.1", @@ -664,13 +729,13 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cosmwasm-storage", - "cw-multi-test", + "cw-multi-test 0.13.2", "cw-storage-plus 0.13.2", "cw-utils 0.13.2", "cw2 0.13.2", "cw20", - "cw721 0.13.2", - "cw721-base 0.13.2", + "cw721 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "pg721", "schemars", "serde", @@ -690,12 +755,12 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cosmwasm-storage", - "cw-multi-test", + "cw-multi-test 0.13.2", "cw-storage-plus 0.13.2", "cw-utils 0.13.2", "cw2 0.13.2", - "cw721 0.13.2", - "cw721-base 0.13.2", + "cw721 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "pg721", "schemars", "serde", @@ -711,17 +776,16 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cosmwasm-storage", - "cw-multi-test", + "cw-multi-test 0.13.2", "cw-storage-plus 0.13.2", "cw-utils 0.13.2", "cw2 0.13.2", - "cw721 0.13.2", - "cw721-base 0.13.2", + "cw721 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "pg721-metadata-onchain", "schemars", "serde", "thiserror", - "url", "whitelist", ] @@ -756,14 +820,29 @@ dependencies = [ "cw-storage-plus 0.13.2", "cw-utils 0.13.2", "cw2 0.13.2", - "cw721 0.13.2", - "cw721-base 0.13.2", + "cw721 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "schemars", "serde", "thiserror", "url", ] +[[package]] +name = "pg721-legacy" +version = "0.2.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test 0.13.4", + "cw2 0.11.1", + "cw721 0.13.2 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", + "cw721-base 0.13.2 (git+https://github.com/CosmWasm/cw-nfts?branch=main)", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "pg721-metadata-onchain" version = "0.1.0" @@ -774,8 +853,8 @@ dependencies = [ "cw-storage-plus 0.13.2", "cw-utils 0.13.2", "cw2 0.13.2", - "cw721 0.13.2", - "cw721-base 0.13.2", + "cw721 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cw721-base 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "pg721", "schemars", "serde", diff --git a/contracts/minter-metadata-onchain/Cargo.toml b/contracts/minter-metadata-onchain/Cargo.toml index 671ab03..e2a0ec7 100644 --- a/contracts/minter-metadata-onchain/Cargo.toml +++ b/contracts/minter-metadata-onchain/Cargo.toml @@ -31,7 +31,6 @@ schemars = "0.8" serde = { version = "1.0", default-features = false, features = ["derive"] } pg721-metadata-onchain = { path = "../pg721-metadata-onchain", features = ["library"] } thiserror = { version = "1.0" } -url = "2.2.0" whitelist = { path = "../whitelist", features = ["library"] } cw721 = "0.13.1" cw721-base = { version = "0.13.1", features = ["library"] } diff --git a/contracts/minter-metadata-onchain/schema/config.json b/contracts/minter-metadata-onchain/schema/config.json index 7c98f74..4d12c8c 100644 --- a/contracts/minter-metadata-onchain/schema/config.json +++ b/contracts/minter-metadata-onchain/schema/config.json @@ -4,7 +4,6 @@ "type": "object", "required": [ "admin", - "base_token_uri", "cw721_code_id", "max_num_tokens", "per_address_limit", @@ -15,9 +14,6 @@ "admin": { "$ref": "#/definitions/Addr" }, - "base_token_uri": { - "type": "string" - }, "cw721_code_id": { "type": "integer", "format": "uint64", diff --git a/contracts/minter-metadata-onchain/schema/config_response.json b/contracts/minter-metadata-onchain/schema/config_response.json index 3fc8874..a3c33ff 100644 --- a/contracts/minter-metadata-onchain/schema/config_response.json +++ b/contracts/minter-metadata-onchain/schema/config_response.json @@ -4,7 +4,6 @@ "type": "object", "required": [ "admin", - "base_token_uri", "cw721_address", "cw721_code_id", "max_num_tokens", @@ -16,9 +15,6 @@ "admin": { "type": "string" }, - "base_token_uri": { - "type": "string" - }, "cw721_address": { "type": "string" }, diff --git a/contracts/minter-metadata-onchain/schema/instantiate_msg.json b/contracts/minter-metadata-onchain/schema/instantiate_msg.json index 957485c..8ac9499 100644 --- a/contracts/minter-metadata-onchain/schema/instantiate_msg.json +++ b/contracts/minter-metadata-onchain/schema/instantiate_msg.json @@ -3,7 +3,6 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "base_token_uri", "cw721_code_id", "cw721_instantiate_msg", "max_num_tokens", @@ -12,9 +11,6 @@ "unit_price" ], "properties": { - "base_token_uri": { - "type": "string" - }, "cw721_code_id": { "type": "integer", "format": "uint64", diff --git a/contracts/minter-metadata-onchain/src/contract.rs b/contracts/minter-metadata-onchain/src/contract.rs index 85ed678..5a38128 100644 --- a/contracts/minter-metadata-onchain/src/contract.rs +++ b/contracts/minter-metadata-onchain/src/contract.rs @@ -12,7 +12,6 @@ use cw_utils::{may_pay, parse_reply_instantiate_data}; use pg721_metadata_onchain::msg::{ InstantiateMsg as Pg721InstantiateMsg, ExecuteMsg as Pg721ExecuteMsg, Metadata }; -use url::Url; use crate::error::ContractError; use crate::msg::{ @@ -61,10 +60,6 @@ pub fn instantiate( }); } - // Check that base_token_uri is a valid IPFS uri - Url::parse(&msg.base_token_uri) - .or_else(|_err: url::ParseError| Err(ContractError::InvalidBaseTokenURI {}))?; - // If current time is beyond the provided start time return error if env.block.time > msg.start_time { return Err(ContractError::InvalidStartTime( @@ -80,7 +75,6 @@ pub fn instantiate( let config = Config { admin: info.sender.clone(), - base_token_uri: msg.base_token_uri, max_num_tokens: msg.max_num_tokens, cw721_code_id: msg.cw721_code_id, unit_price: msg.unit_price, @@ -425,7 +419,7 @@ fn _execute_mint( let mint_msg = Pg721ExecuteMsg::Mint(MintMsg::> { token_id: mintable_token_id.to_string(), owner: recipient_addr.to_string(), - token_uri: Some(format!("{}/{}", config.base_token_uri, mintable_token_id)), + token_uri: None, extension: Some(token_mint.metadata), }); let msg = CosmosMsg::Wasm(WasmMsg::Execute { @@ -569,7 +563,6 @@ fn query_config(deps: Deps) -> StdResult { Ok(ConfigResponse { admin: config.admin.to_string(), - base_token_uri: config.base_token_uri, cw721_address: cw721_address.to_string(), cw721_code_id: config.cw721_code_id, max_num_tokens: config.max_num_tokens, diff --git a/contracts/minter-metadata-onchain/src/contract_tests.rs b/contracts/minter-metadata-onchain/src/contract_tests.rs index cd3041f..c9fa8c3 100644 --- a/contracts/minter-metadata-onchain/src/contract_tests.rs +++ b/contracts/minter-metadata-onchain/src/contract_tests.rs @@ -115,7 +115,6 @@ fn setup_minter_contract( start_time: Timestamp::from_nanos(START_TIME), per_address_limit: 5, whitelist: None, - base_token_uri: "ipfs://QmYxw1rURvnbQbBRTfmVaZtxSrkrfsbodNzibgBrVrUrtN".to_string(), cw721_code_id, cw721_instantiate_msg: Pg721InstantiateMsg { name: String::from("TEST"), @@ -259,7 +258,6 @@ fn initialization() { start_time: Timestamp::from_nanos(START_TIME), per_address_limit: 0, whitelist: None, - base_token_uri: "ipfs://QmYxw1rURvnbQbBRTfmVaZtxSrkrfsbodNzibgBrVrUrtN".to_string(), cw721_code_id: 1, cw721_instantiate_msg: Pg721InstantiateMsg { name: String::from("TEST"), @@ -287,7 +285,6 @@ fn initialization() { start_time: Timestamp::from_nanos(START_TIME), per_address_limit: 5, whitelist: None, - base_token_uri: "ipfs://QmYxw1rURvnbQbBRTfmVaZtxSrkrfsbodNzibgBrVrUrtN".to_string(), cw721_code_id: 1, cw721_instantiate_msg: Pg721InstantiateMsg { name: String::from("TEST"), @@ -1152,7 +1149,6 @@ fn test_start_time_before_genesis() { start_time: Timestamp::from_nanos(START_TIME), per_address_limit: 5, whitelist: None, - base_token_uri: "ipfs://QmYxw1rURvnbQbBRTfmVaZtxSrkrfsbodNzibgBrVrUrtN".to_string(), cw721_code_id, cw721_instantiate_msg: Pg721InstantiateMsg { name: String::from("TEST"), @@ -1202,7 +1198,6 @@ fn test_update_start_time() { start_time: Timestamp::from_nanos(START_TIME), per_address_limit: 5, whitelist: None, - base_token_uri: "ipfs://QmYxw1rURvnbQbBRTfmVaZtxSrkrfsbodNzibgBrVrUrtN".to_string(), cw721_code_id, cw721_instantiate_msg: Pg721InstantiateMsg { name: String::from("TEST"), @@ -1260,7 +1255,6 @@ fn test_invalid_start_time() { start_time: Timestamp::from_nanos(START_TIME - 100), per_address_limit: 5, whitelist: None, - base_token_uri: "ipfs://QmYxw1rURvnbQbBRTfmVaZtxSrkrfsbodNzibgBrVrUrtN".to_string(), cw721_code_id, cw721_instantiate_msg: Pg721InstantiateMsg { name: String::from("TEST"), diff --git a/contracts/minter-metadata-onchain/src/error.rs b/contracts/minter-metadata-onchain/src/error.rs index 590de43..f20c5e7 100644 --- a/contracts/minter-metadata-onchain/src/error.rs +++ b/contracts/minter-metadata-onchain/src/error.rs @@ -1,7 +1,6 @@ use cosmwasm_std::{Coin, StdError, Timestamp}; use cw_utils::PaymentError; use thiserror::Error; -use url::ParseError; #[derive(Error, Debug, PartialEq)] pub enum ContractError { @@ -80,9 +79,3 @@ pub enum ContractError { #[error("{0}")] Payment(#[from] PaymentError), } - -impl From for ContractError { - fn from(_err: ParseError) -> ContractError { - ContractError::InvalidBaseTokenURI {} - } -} diff --git a/contracts/minter-metadata-onchain/src/msg.rs b/contracts/minter-metadata-onchain/src/msg.rs index 3a909cb..ea1008a 100644 --- a/contracts/minter-metadata-onchain/src/msg.rs +++ b/contracts/minter-metadata-onchain/src/msg.rs @@ -7,7 +7,6 @@ use crate::state::{TokenMint}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct InstantiateMsg { - pub base_token_uri: String, pub max_num_tokens: u32, pub cw721_code_id: u64, pub cw721_instantiate_msg: Pg721InstantiateMsg, @@ -50,7 +49,6 @@ pub enum QueryMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ConfigResponse { pub admin: String, - pub base_token_uri: String, pub max_num_tokens: u32, pub per_address_limit: u32, pub cw721_address: String, diff --git a/contracts/minter-metadata-onchain/src/state.rs b/contracts/minter-metadata-onchain/src/state.rs index 244a6bb..9ea82be 100644 --- a/contracts/minter-metadata-onchain/src/state.rs +++ b/contracts/minter-metadata-onchain/src/state.rs @@ -8,7 +8,6 @@ use pg721_metadata_onchain::msg::Metadata; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Config { pub admin: Addr, - pub base_token_uri: String, pub max_num_tokens: u32, pub cw721_code_id: u64, pub unit_price: Coin, diff --git a/contracts/pg721-legacy/.cargo/config b/contracts/pg721-legacy/.cargo/config new file mode 100644 index 0000000..d11b2aa --- /dev/null +++ b/contracts/pg721-legacy/.cargo/config @@ -0,0 +1,5 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +wasm-debug = "build --target wasm32-unknown-unknown" +unit-test = "test --lib -- --nocapture" +schema = "run --example schema" diff --git a/contracts/pg721-legacy/Cargo.toml b/contracts/pg721-legacy/Cargo.toml new file mode 100644 index 0000000..3b975fd --- /dev/null +++ b/contracts/pg721-legacy/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "pg721-legacy" +version = "0.2.0" +authors = ["Orkun Külçe "] +edition = "2018" + +exclude = [ + # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. + "artifacts/*", +] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# for more explicit tests, cargo test --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] +# use library feature to disable all instantiate/execute/query exports +library = [] + +[dependencies] +cw2 = "0.11" +cw721 = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main"} +cw721-base = { git = "https://github.com/CosmWasm/cw-nfts", branch = "main", features = ["library"] } +cosmwasm-std = { version = "1.0.0-beta3" } +schemars = "0.8" +serde = { version = "1.0", default-features = false, features = ["derive"] } +thiserror = { version = "1.0" } + +[dev-dependencies] +cosmwasm-schema = { version = "1.0.0-beta3" } +cw-multi-test = { git = "https://github.com/CosmWasm/cw-plus" } diff --git a/contracts/pg721-legacy/examples/schema.rs b/contracts/pg721-legacy/examples/schema.rs new file mode 100644 index 0000000..0c1922b --- /dev/null +++ b/contracts/pg721-legacy/examples/schema.rs @@ -0,0 +1,39 @@ +use std::env::current_dir; +use std::fs::create_dir_all; + +use cosmwasm_schema::{export_schema, export_schema_with_title, remove_schemas, schema_for}; + +use cw721::{ + AllNftInfoResponse, ApprovalResponse, ApprovalsResponse, ContractInfoResponse, NftInfoResponse, + NumTokensResponse, OperatorsResponse, OwnerOfResponse, TokensResponse, +}; +use pg721_legacy::{ExecuteMsg, Extension, InstantiateMsg, MinterResponse, QueryMsg}; + +fn main() { + let mut out_dir = current_dir().unwrap(); + out_dir.push("schema"); + create_dir_all(&out_dir).unwrap(); + remove_schemas(&out_dir).unwrap(); + + export_schema(&schema_for!(InstantiateMsg), &out_dir); + export_schema_with_title(&schema_for!(ExecuteMsg), &out_dir, "ExecuteMsg"); + export_schema(&schema_for!(QueryMsg), &out_dir); + export_schema_with_title( + &schema_for!(AllNftInfoResponse), + &out_dir, + "AllNftInfoResponse", + ); + export_schema(&schema_for!(ApprovalResponse), &out_dir); + export_schema(&schema_for!(ApprovalsResponse), &out_dir); + export_schema(&schema_for!(OperatorsResponse), &out_dir); + export_schema(&schema_for!(ContractInfoResponse), &out_dir); + export_schema(&schema_for!(MinterResponse), &out_dir); + export_schema_with_title( + &schema_for!(NftInfoResponse), + &out_dir, + "NftInfoResponse", + ); + export_schema(&schema_for!(NumTokensResponse), &out_dir); + export_schema(&schema_for!(OwnerOfResponse), &out_dir); + export_schema(&schema_for!(TokensResponse), &out_dir); +} diff --git a/contracts/pg721-legacy/schema/all_nft_info_response.json b/contracts/pg721-legacy/schema/all_nft_info_response.json new file mode 100644 index 0000000..574d1c9 --- /dev/null +++ b/contracts/pg721-legacy/schema/all_nft_info_response.json @@ -0,0 +1,240 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AllNftInfoResponse", + "type": "object", + "required": [ + "access", + "info" + ], + "properties": { + "access": { + "description": "Who can transfer the token", + "allOf": [ + { + "$ref": "#/definitions/OwnerOfResponse" + } + ] + }, + "info": { + "description": "Data on the token itself,", + "allOf": [ + { + "$ref": "#/definitions/NftInfoResponse_for_Nullable_Metadata" + } + ] + } + }, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + } + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "anyOf": [ + { + "$ref": "#/definitions/Trait" + }, + { + "type": "null" + } + ] + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + } + }, + "NftInfoResponse_for_Nullable_Metadata": { + "type": "object", + "properties": { + "extension": { + "description": "You can add any custom metadata here when you extend cw721-base", + "anyOf": [ + { + "$ref": "#/definitions/Metadata" + }, + { + "type": "null" + } + ] + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + } + }, + "OwnerOfResponse": { + "type": "object", + "required": [ + "approvals", + "owner" + ], + "properties": { + "approvals": { + "description": "If set this address is approved to transfer/send the token as well", + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + }, + "owner": { + "description": "Owner of the token", + "type": "string" + } + } + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Trait": { + "type": "object", + "required": [ + "accessory", + "background", + "base", + "name" + ], + "properties": { + "accessory": { + "type": "array", + "items": { + "type": "string" + } + }, + "background": { + "type": "string" + }, + "base": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/approval_response.json b/contracts/pg721-legacy/schema/approval_response.json new file mode 100644 index 0000000..4f45b42 --- /dev/null +++ b/contracts/pg721-legacy/schema/approval_response.json @@ -0,0 +1,94 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ApprovalResponse", + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "$ref": "#/definitions/Approval" + } + }, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + } + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/approvals_response.json b/contracts/pg721-legacy/schema/approvals_response.json new file mode 100644 index 0000000..8d8e39e --- /dev/null +++ b/contracts/pg721-legacy/schema/approvals_response.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ApprovalsResponse", + "type": "object", + "required": [ + "approvals" + ], + "properties": { + "approvals": { + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + } + }, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + } + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/contract_info_response.json b/contracts/pg721-legacy/schema/contract_info_response.json new file mode 100644 index 0000000..a167125 --- /dev/null +++ b/contracts/pg721-legacy/schema/contract_info_response.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ContractInfoResponse", + "type": "object", + "required": [ + "name", + "symbol" + ], + "properties": { + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/execute_msg.json b/contracts/pg721-legacy/schema/execute_msg.json new file mode 100644 index 0000000..10eb7be --- /dev/null +++ b/contracts/pg721-legacy/schema/execute_msg.json @@ -0,0 +1,395 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "description": "This is like Cw721ExecuteMsg but we add a Mint command for an owner to make this stand-alone. You will likely want to remove mint and use other control logic in any contract that inherits this.", + "oneOf": [ + { + "description": "Transfer is a base message to move a token to another account without triggering actions", + "type": "object", + "required": [ + "transfer_nft" + ], + "properties": { + "transfer_nft": { + "type": "object", + "required": [ + "recipient", + "token_id" + ], + "properties": { + "recipient": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Send is a base message to transfer a token to a contract and trigger an action on the receiving contract.", + "type": "object", + "required": [ + "send_nft" + ], + "properties": { + "send_nft": { + "type": "object", + "required": [ + "contract", + "msg", + "token_id" + ], + "properties": { + "contract": { + "type": "string" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Allows operator to transfer / send the token from the owner's account. If expiration is set, then this allowance has a time/height limit", + "type": "object", + "required": [ + "approve" + ], + "properties": { + "approve": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Remove previously granted Approval", + "type": "object", + "required": [ + "revoke" + ], + "properties": { + "revoke": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Allows operator to transfer / send any token from the owner's account. If expiration is set, then this allowance has a time/height limit", + "type": "object", + "required": [ + "approve_all" + ], + "properties": { + "approve_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "operator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Remove previously granted ApproveAll permission", + "type": "object", + "required": [ + "revoke_all" + ], + "properties": { + "revoke_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "operator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Mint a new NFT, can only be called by the contract minter", + "type": "object", + "required": [ + "mint" + ], + "properties": { + "mint": { + "$ref": "#/definitions/MintMsg_for_Nullable_Metadata" + } + }, + "additionalProperties": false + }, + { + "description": "Burn an NFT the sender has access to", + "type": "object", + "required": [ + "burn" + ], + "properties": { + "burn": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec", + "type": "string" + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "anyOf": [ + { + "$ref": "#/definitions/Trait" + }, + { + "type": "null" + } + ] + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + } + }, + "MintMsg_for_Nullable_Metadata": { + "type": "object", + "required": [ + "owner", + "token_id" + ], + "properties": { + "extension": { + "description": "Any custom extension used by this contract", + "anyOf": [ + { + "$ref": "#/definitions/Metadata" + }, + { + "type": "null" + } + ] + }, + "owner": { + "description": "The owner of the newly minter NFT", + "type": "string" + }, + "token_id": { + "description": "Unique ID of the NFT", + "type": "string" + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + } + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Trait": { + "type": "object", + "required": [ + "accessory", + "background", + "base", + "name" + ], + "properties": { + "accessory": { + "type": "array", + "items": { + "type": "string" + } + }, + "background": { + "type": "string" + }, + "base": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/instantiate_msg.json b/contracts/pg721-legacy/schema/instantiate_msg.json new file mode 100644 index 0000000..b024c82 --- /dev/null +++ b/contracts/pg721-legacy/schema/instantiate_msg.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "minter", + "name", + "symbol" + ], + "properties": { + "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": "Symbol of the NFT contract", + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/minter_response.json b/contracts/pg721-legacy/schema/minter_response.json new file mode 100644 index 0000000..a20e0d7 --- /dev/null +++ b/contracts/pg721-legacy/schema/minter_response.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MinterResponse", + "description": "Shows who can mint these tokens", + "type": "object", + "required": [ + "minter" + ], + "properties": { + "minter": { + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/nft_info_response.json b/contracts/pg721-legacy/schema/nft_info_response.json new file mode 100644 index 0000000..512345f --- /dev/null +++ b/contracts/pg721-legacy/schema/nft_info_response.json @@ -0,0 +1,116 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NftInfoResponse", + "type": "object", + "properties": { + "extension": { + "description": "You can add any custom metadata here when you extend cw721-base", + "anyOf": [ + { + "$ref": "#/definitions/Metadata" + }, + { + "type": "null" + } + ] + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + }, + "definitions": { + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "anyOf": [ + { + "$ref": "#/definitions/Trait" + }, + { + "type": "null" + } + ] + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + } + }, + "Trait": { + "type": "object", + "required": [ + "accessory", + "background", + "base", + "name" + ], + "properties": { + "accessory": { + "type": "array", + "items": { + "type": "string" + } + }, + "background": { + "type": "string" + }, + "base": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + } +} diff --git a/contracts/pg721-legacy/schema/num_tokens_response.json b/contracts/pg721-legacy/schema/num_tokens_response.json new file mode 100644 index 0000000..4647c23 --- /dev/null +++ b/contracts/pg721-legacy/schema/num_tokens_response.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NumTokensResponse", + "type": "object", + "required": [ + "count" + ], + "properties": { + "count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } +} diff --git a/contracts/pg721-legacy/schema/operators_response.json b/contracts/pg721-legacy/schema/operators_response.json new file mode 100644 index 0000000..5370307 --- /dev/null +++ b/contracts/pg721-legacy/schema/operators_response.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OperatorsResponse", + "type": "object", + "required": [ + "operators" + ], + "properties": { + "operators": { + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + } + }, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + } + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/owner_of_response.json b/contracts/pg721-legacy/schema/owner_of_response.json new file mode 100644 index 0000000..1258d67 --- /dev/null +++ b/contracts/pg721-legacy/schema/owner_of_response.json @@ -0,0 +1,103 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OwnerOfResponse", + "type": "object", + "required": [ + "approvals", + "owner" + ], + "properties": { + "approvals": { + "description": "If set this address is approved to transfer/send the token as well", + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + }, + "owner": { + "description": "Owner of the token", + "type": "string" + } + }, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + } + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/pg721-legacy/schema/query_msg.json b/contracts/pg721-legacy/schema/query_msg.json new file mode 100644 index 0000000..cd3a956 --- /dev/null +++ b/contracts/pg721-legacy/schema/query_msg.json @@ -0,0 +1,285 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "description": "Return the owner of the given token, error if token does not exist Return type: OwnerOfResponse", + "type": "object", + "required": [ + "owner_of" + ], + "properties": { + "owner_of": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "description": "unset or false will filter out expired approvals, you must set to true to see them", + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Return operator that can access all of the owner's tokens. Return type: `ApprovalResponse`", + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Return approvals that a token has Return type: `ApprovalsResponse`", + "type": "object", + "required": [ + "approvals" + ], + "properties": { + "approvals": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "List all operators that can access all of the owner's tokens Return type: `OperatorsResponse`", + "type": "object", + "required": [ + "all_operators" + ], + "properties": { + "all_operators": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "include_expired": { + "description": "unset or false will filter out expired items, you must set to true to see them", + "type": [ + "boolean", + "null" + ] + }, + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Total number of tokens issued", + "type": "object", + "required": [ + "num_tokens" + ], + "properties": { + "num_tokens": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "With MetaData Extension. Returns top-level metadata about the contract: `ContractInfoResponse`", + "type": "object", + "required": [ + "contract_info" + ], + "properties": { + "contract_info": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "With MetaData Extension. Returns metadata about one particular token, based on *ERC721 Metadata JSON Schema* but directly from the contract: `NftInfoResponse`", + "type": "object", + "required": [ + "nft_info" + ], + "properties": { + "nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "With MetaData Extension. Returns the result of both `NftInfo` and `OwnerOf` as one query as an optimization for clients: `AllNftInfo`", + "type": "object", + "required": [ + "all_nft_info" + ], + "properties": { + "all_nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "description": "unset or false will filter out expired approvals, you must set to true to see them", + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "With Enumerable extension. Returns all tokens owned by the given address, [] if unset. Return type: TokensResponse.", + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "With Enumerable extension. Requires pagination. Lists all token_ids controlled by the contract. Return type: TokensResponse.", + "type": "object", + "required": [ + "all_tokens" + ], + "properties": { + "all_tokens": { + "type": "object", + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minter" + ], + "properties": { + "minter": { + "type": "object" + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/pg721-legacy/schema/tokens_response.json b/contracts/pg721-legacy/schema/tokens_response.json new file mode 100644 index 0000000..b8e3d75 --- /dev/null +++ b/contracts/pg721-legacy/schema/tokens_response.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokensResponse", + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "description": "Contains all token_ids in lexicographical ordering If there are more than `limit`, use `start_from` in future queries to achieve pagination.", + "type": "array", + "items": { + "type": "string" + } + } + } +} diff --git a/contracts/pg721-legacy/src/lib.rs b/contracts/pg721-legacy/src/lib.rs new file mode 100644 index 0000000..cd16ff4 --- /dev/null +++ b/contracts/pg721-legacy/src/lib.rs @@ -0,0 +1,170 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use cosmwasm_std::Empty; +pub use cw721_base::{ContractError, InstantiateMsg, MintMsg, MinterResponse, QueryMsg}; + +#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug, Default)] +pub struct Trait { + pub name: String, + pub base: String, + pub accessory: Vec, + pub background: String, +} + +// see: https://docs.opensea.io/docs/metadata-standards +#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug, Default)] +pub struct Metadata { + pub image: Option, + pub image_data: Option, + pub external_url: Option, + pub description: Option, + pub name: Option, + pub attributes: Option, + pub background_color: Option, + pub animation_url: Option, + pub youtube_url: Option, +} + +pub type Extension = Option; + +pub type Cw721PassageContract<'a> = cw721_base::Cw721Contract<'a, Extension, Empty>; +pub type ExecuteMsg = cw721_base::ExecuteMsg; + +#[cfg(not(feature = "library"))] +pub mod entry { + + use crate::{Cw721PassageContract, ExecuteMsg}; + use cosmwasm_std::{entry_point, StdError}; + use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; + use cw2::set_contract_version; + use cw721_base::{ContractError, InstantiateMsg, QueryMsg}; + + // This is a simple type to let us handle empty extensions + + const CONTRACT_NAME: &str = "crates.io:cw721-passage"; + const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + + // This makes a conscious choice on the various generics used by the contract + #[entry_point] + pub fn instantiate( + mut deps: DepsMut, + env: Env, + info: MessageInfo, + msg: InstantiateMsg, + ) -> StdResult { + let res = Cw721PassageContract::default().instantiate(deps.branch(), env, info, msg)?; + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + Ok(res) + } + + #[entry_point] + pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, + ) -> Result { + if let ExecuteMsg::Burn { .. } = msg { + return Err(ContractError::Std(StdError::generic_err( + "Operation not allowed", + ))); + } + Cw721PassageContract::default().execute(deps, env, info, msg) + } + + #[entry_point] + pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + Cw721PassageContract::default().query(deps, env, msg) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::ExecuteMsg; + use cosmwasm_std::{to_binary, Addr, CosmosMsg, WasmMsg}; + use cw721::NftInfoResponse; + use cw721_base::helpers::Cw721Contract; + use cw_multi_test::{App, BasicApp, Contract, ContractWrapper, Executor}; + + const CREATOR: &str = "creator"; + + pub fn contract_cw721_passage() -> Box> { + let contract = ContractWrapper::new(entry::execute, entry::instantiate, entry::query); + Box::new(contract) + } + + const TOKEN_ID: &str = "Enterprise"; + + fn init() -> (BasicApp, Cw721Contract, MintMsg>) { + let mut app = App::default(); + let code_id = app.store_code(contract_cw721_passage()); + + let init_msg = InstantiateMsg { + name: "SpaceShips".to_string(), + symbol: "SPACE".to_string(), + minter: CREATOR.to_string(), + }; + let contract_addr = app + .instantiate_contract( + code_id, + Addr::unchecked(CREATOR), + &init_msg, + &[], + "passage", + None, + ) + .unwrap(); + let contract = Cw721Contract(contract_addr); + + let mint_msg = MintMsg { + 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() + }), + }; + let exec_msg = ExecuteMsg::Mint(mint_msg.clone()); + let cosmos_msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: contract.addr().to_string(), + msg: to_binary(&exec_msg).unwrap(), + funds: vec![], + }); + app.execute(Addr::unchecked(CREATOR), cosmos_msg).unwrap(); + (app, contract, mint_msg) + } + + #[test] + fn use_metadata_extension() { + let (app, contract, mint_msg) = init(); + + let res: NftInfoResponse = contract + .nft_info::(&app.wrap(), TOKEN_ID.into()) + .unwrap(); + assert_eq!(res.token_uri, mint_msg.token_uri); + assert_eq!(res.extension, mint_msg.extension); + } + + #[test] + fn burn_disallowed() { + let (mut app, contract, _) = init(); + + let exec_msg = ExecuteMsg::Burn { + token_id: TOKEN_ID.to_string(), + }; + let cosmos_msg = CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: contract.addr().to_string(), + msg: to_binary(&exec_msg).unwrap(), + funds: vec![], + }); + let res = app + .execute(Addr::unchecked("john"), cosmos_msg) + .unwrap_err(); + assert!(res.chain().any(|cause| cause.to_string().contains("Operation not allowed"))); + } +}