diff --git a/Cargo.lock b/Cargo.lock index a6e2086..abafc3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema" -version = "1.5.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df41ea55f2946b6b43579659eec048cc2f66e8c8e2e3652fc5e5e476f673856" +checksum = "ac3e3a2136e2a60e8b6582f5dffca5d1a683ed77bf38537d330bc1dfccd69010" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.5.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43609e92ce1b9368aa951b334dd354a2d0dd4d484931a5f83ae10e12a26c8ba9" +checksum = "f5d803bea6bd9ed61bd1ee0b4a2eb09ee20dbb539cc6e0b8795614d20952ebb1" dependencies = [ "proc-macro2", "quote", @@ -552,6 +552,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "factory-types" +version = "0.0.1" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw721-base 0.18.0", + "omniflix-std", + "serde", + "thiserror", +] + [[package]] name = "ff" version = "0.13.0" @@ -640,6 +654,7 @@ dependencies = [ "cw-utils 1.0.3", "cw2 1.1.1", "derivative", + "factory-types", "itertools 0.12.0", "minter-types", "omniflix-minter", @@ -650,7 +665,6 @@ dependencies = [ "omniflix-round-whitelist-factory", "omniflix-std", "omniflix-testing", - "open-edition-minter-types", "pauser", "prost 0.12.3", "schemars", @@ -717,19 +731,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "multi-mint-open-edition-minter-types" -version = "0.0.1" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils 1.0.3", - "cw721-base 0.18.0", - "minter-types", - "serde", - "thiserror", -] - [[package]] name = "num-traits" version = "0.2.17" @@ -776,6 +777,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.1", + "factory-types", "minter-types", "omniflix-std", "serde", @@ -794,7 +796,6 @@ dependencies = [ "cw-utils 1.0.3", "cw2 1.1.1", "minter-types", - "multi-mint-open-edition-minter-types", "omniflix-open-edition-minter-factory", "omniflix-round-whitelist", "omniflix-std", @@ -821,7 +822,6 @@ dependencies = [ "omniflix-open-edition-minter-factory", "omniflix-round-whitelist", "omniflix-std", - "open-edition-minter-types", "pauser", "schemars", "serde", @@ -841,9 +841,9 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.1", + "factory-types", "minter-types", "omniflix-std", - "open-edition-minter-types", "serde", "thiserror", ] @@ -878,6 +878,7 @@ dependencies = [ "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.1", + "factory-types", "omniflix-std", "serde", "thiserror", @@ -950,19 +951,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "open-edition-minter-types" -version = "0.0.1" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils 1.0.3", - "cw721-base 0.18.0", - "minter-types", - "serde", - "thiserror", -] - [[package]] name = "pauser" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index f4e232c..c9c3423 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ repository = "" license = "Apache-2.0" [workspace.dependencies] -cosmwasm-schema = "1.5.0" +cosmwasm-schema = "1.5.3" cosmwasm-std = "1.2.1" omniflix-std = "0.1.3" cw-controllers = "1.1.0" @@ -33,8 +33,7 @@ semver = "1" cw-ownable = "0.5.1" cosmwasm-storage = "1.5.0" serde = { version = "1.0.145", default-features = false, features = ["derive"] } -whitelist-types = { version = "0.0.1", path = "packages/whitelist-types" } -minter-types = { version = "0.0.1", path = "packages/minter-types" } -open-edition-minter-types = { version = "0.0.1", path = "packages/open-edition-minter-types" } -multi-mint-open-edition-minter-types = { version = "0.0.1", path = "packages/multi-mint-oem-types" } -pauser = { path = "packages/pauser" } \ No newline at end of file +whitelist-types = { path = "packages/whitelist-types" } +minter-types = { path = "packages/minter-types" } +factory-types = { path = "packages/factory-types" } +pauser = { path = "packages/pauser" } diff --git a/README.md b/README.md index 4b6fd13..2f7ad29 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This repository contains the smart contracts for the Omniflix Launchpad platform ## Factories -Launchpad utilizes a singleton structure for each collection that is released through this launchpad. The purpose of the factories is to create an instance of minters and whitelist contracts, while also configuring the creation price and payment collection. +Launchpad utilizes a singleton structure for each collection that is released through this launchpad. The purpose of the factories is to create an instance of minters and whitelist contracts. ## Design diff --git a/artifacts/checksums.txt b/artifacts/checksums.txt index df1f388..64845cb 100644 --- a/artifacts/checksums.txt +++ b/artifacts/checksums.txt @@ -1,8 +1,8 @@ -558e67e59f1d3db5c8be13a50f0211efa09e8600ab1f036c8dcaeb5697cc39aa omniflix_minter.wasm -b2dec2afb46e45653b043af85d002952f23675a203919db41a4b15f9788f0c97 omniflix_minter_factory.wasm -07a694bc39c177d7667daa18c5877d303231b728c8c2bdbdad7aace446a1d944 omniflix_multi_mint_open_edition_minter.wasm -a8d9f72e5e442c498a94c1d6cdedb52ccdfea1e201f994cca163103f410c2074 omniflix_open_edition_minter.wasm +433cd724fa9863f244b4dcfcf8dd63b8925e9c812ad7f8693cf1f4742918316d omniflix_minter.wasm +6d9047339a8289cf0a353d06ea7317472d421a1e92548c128629699a384301dd omniflix_minter_factory.wasm +582f94b015f272ba75fe5a6414929411aa82eac2a082738f4933201e6918fb63 omniflix_multi_mint_open_edition_minter.wasm +96649782494a4fa73fb3154dc3af0f87759865790caae82be9c33870cd4117a9 omniflix_open_edition_minter.wasm ca1121e0137961ae9a7838413b5b0cda4fc800ed50cc717cc3c1796bdbe9e4e2 omniflix_open_edition_minter_copy.wasm -bc7d65185edda56da91890676fa543be424ad472441db8b0fb9896f3a32608ac omniflix_open_edition_minter_factory.wasm -bb76845f51ecea7329728b8b4705da863f9b7f2dfe735e6a3261abddd45399e5 omniflix_round_whitelist.wasm -fefb305d96bb3f5b33bbedeb2e5ab49123c6506201955d948574675402032888 omniflix_round_whitelist_factory.wasm +dc6fcb2312463c61966b2b660c8626c1139aac09052cf71d3dcffdb0bcbc25cf omniflix_open_edition_minter_factory.wasm +6857583230ddcec6d9fefb3e648a9a0a179d821fa7a7f96efda3d6a4186f5d77 omniflix_round_whitelist.wasm +6cd989d33877aa51a89069aa33d2b50ed9b1b64be390dd45a1cb09ff4a1dfd92 omniflix_round_whitelist_factory.wasm diff --git a/artifacts/checksums_intermediate.txt b/artifacts/checksums_intermediate.txt index 2ae9de5..e44f63c 100644 --- a/artifacts/checksums_intermediate.txt +++ b/artifacts/checksums_intermediate.txt @@ -1,8 +1,8 @@ -fa6e1825c5002194b5c7e875b43f6c850b894f23fc0527500bb7e43a7f1bb93c target/wasm32-unknown-unknown/release/omniflix_round_whitelist.wasm -851c3edf8799cf5d82775b02a334915242dacd0ca649d930f014a5ec0594013e target/wasm32-unknown-unknown/release/omniflix_round_whitelist_factory.wasm -87fbc32b3305eff444d72930673b578ffeb011e70aa5550f3cc643593744855b target/wasm32-unknown-unknown/release/omniflix_minter.wasm -833db6329b7c6b9e36b95776928e87662e1175479a14e32b8117b4a3a56f29fa target/wasm32-unknown-unknown/release/omniflix_minter_factory.wasm -c8e2f4825780a93511fbe80ee055b0f30fe7f519708e45ac5fe6034d4e77af62 target/wasm32-unknown-unknown/release/omniflix_multi_mint_open_edition_minter.wasm -81c7ef31fe4d332ccc7fdee62a771f81525e3e8788cc830d7992c6cf55f9e46b target/wasm32-unknown-unknown/release/omniflix_open_edition_minter.wasm +0ff723cd6bcf7c3067ff0df7d9bf1f227efe4fff2b0c2324bc84b95216eb2e72 target/wasm32-unknown-unknown/release/omniflix_minter.wasm +2ce6b8be1a56977db759b79ce638db6d70cf655d477ece99d1b52be4a37035af target/wasm32-unknown-unknown/release/omniflix_minter_factory.wasm +fab80e19deab3b947612593c762e04817dbf07b0445d88e95fbdae2c16d26efa target/wasm32-unknown-unknown/release/omniflix_multi_mint_open_edition_minter.wasm +55b6dd86e2cd23a6643ec812ec709ce81ea990a360ab6b4ebb4bd14776495133 target/wasm32-unknown-unknown/release/omniflix_open_edition_minter.wasm c20531d46d46c57955320f9e1464a4a4cc87fd0aa6c139355b6b866735125ee0 target/wasm32-unknown-unknown/release/omniflix_open_edition_minter_copy.wasm -36670c3cedfe1b4adc8b380e0e8101907818cec4e6530e12a15771d7db8a8907 target/wasm32-unknown-unknown/release/omniflix_open_edition_minter_factory.wasm +3ddff97914a8380acea013271838754552904e07d58a9e4d8d6e2d08756cefb8 target/wasm32-unknown-unknown/release/omniflix_open_edition_minter_factory.wasm +d1ea2c4ac7e9bebd4a4ebd70d8f0ce6436979c7f5e9bcbbdaf255ab79e9f38b6 target/wasm32-unknown-unknown/release/omniflix_round_whitelist.wasm +36dd84428a9c11c9b2ae07be2f02def5b1a7b3a78bfb2093ed76f90b1fee3643 target/wasm32-unknown-unknown/release/omniflix_round_whitelist_factory.wasm diff --git a/artifacts/omniflix_minter.wasm b/artifacts/omniflix_minter.wasm index 8e7e579..48a2220 100644 Binary files a/artifacts/omniflix_minter.wasm and b/artifacts/omniflix_minter.wasm differ diff --git a/artifacts/omniflix_minter_factory.wasm b/artifacts/omniflix_minter_factory.wasm index dc00a0b..2840f0b 100644 Binary files a/artifacts/omniflix_minter_factory.wasm and b/artifacts/omniflix_minter_factory.wasm differ diff --git a/artifacts/omniflix_multi_mint_open_edition_minter.wasm b/artifacts/omniflix_multi_mint_open_edition_minter.wasm index fd7f518..7d0b1af 100644 Binary files a/artifacts/omniflix_multi_mint_open_edition_minter.wasm and b/artifacts/omniflix_multi_mint_open_edition_minter.wasm differ diff --git a/artifacts/omniflix_open_edition_minter.wasm b/artifacts/omniflix_open_edition_minter.wasm index 5f5dfdc..8503609 100644 Binary files a/artifacts/omniflix_open_edition_minter.wasm and b/artifacts/omniflix_open_edition_minter.wasm differ diff --git a/artifacts/omniflix_open_edition_minter_factory.wasm b/artifacts/omniflix_open_edition_minter_factory.wasm index 667aa96..98a7671 100644 Binary files a/artifacts/omniflix_open_edition_minter_factory.wasm and b/artifacts/omniflix_open_edition_minter_factory.wasm differ diff --git a/artifacts/omniflix_round_whitelist.wasm b/artifacts/omniflix_round_whitelist.wasm index 16b1a8a..cf48670 100644 Binary files a/artifacts/omniflix_round_whitelist.wasm and b/artifacts/omniflix_round_whitelist.wasm differ diff --git a/artifacts/omniflix_round_whitelist_factory.wasm b/artifacts/omniflix_round_whitelist_factory.wasm index 4da844f..662351e 100644 Binary files a/artifacts/omniflix_round_whitelist_factory.wasm and b/artifacts/omniflix_round_whitelist_factory.wasm differ diff --git a/contracts/factories/minter-factory/.cargo/config b/contracts/factories/minter-factory/.cargo/config new file mode 100644 index 0000000..5b8deaa --- /dev/null +++ b/contracts/factories/minter-factory/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run schema" diff --git a/contracts/factories/minter-factory/Cargo.toml b/contracts/factories/minter-factory/Cargo.toml index 6dae223..17d88f0 100644 --- a/contracts/factories/minter-factory/Cargo.toml +++ b/contracts/factories/minter-factory/Cargo.toml @@ -43,7 +43,7 @@ library = [] cosmwasm-storage = { workspace = true } omniflix-std = { workspace = true } thiserror = { workspace = true } -cosmwasm-schema = { workspace = true } +cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } cw-controllers = { workspace = true } cw2 = { workspace = true } @@ -51,4 +51,5 @@ cw-storage-plus = { workspace = true } cw-utils = { workspace = true } serde = { workspace = true } minter-types = {workspace = true} +factory-types = {workspace = true} diff --git a/contracts/factories/minter-factory/README.md b/contracts/factories/minter-factory/README.md deleted file mode 100644 index 2547462..0000000 --- a/contracts/factories/minter-factory/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## Minter factory -Simple factory contract. Stores params for minter creation and creates minters. - -### Parameters -- `minter_creation_fee`: The fee to create a minter -- `fee_collector_address`: The address to send the fee to -- `minter_code_id`: The code id of the minter contract -- `allowed_minter_mint_denoms`: The denoms that creator can set as minting price denom -- `admin`: The admin address of the minter contract if not sent its the creator of the factory - - - diff --git a/contracts/factories/minter-factory/schema/omniflix-minter-factory.json b/contracts/factories/minter-factory/schema/omniflix-minter-factory.json index 13d9459..00ad4af 100644 --- a/contracts/factories/minter-factory/schema/omniflix-minter-factory.json +++ b/contracts/factories/minter-factory/schema/omniflix-minter-factory.json @@ -7,31 +7,19 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "fee_collector_address", - "minter_code_id", - "minter_creation_fee" + "params" ], "properties": { - "admin": { - "type": [ - "string", - "null" - ] - }, - "fee_collector_address": { - "type": "string" - }, - "minter_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "minter_creation_fee": { - "$ref": "#/definitions/Coin" + "params": { + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -47,6 +35,44 @@ } } }, + "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" + }, + "FactoryParams_for_Empty": { + "type": "object", + "required": [ + "admin", + "contract_id", + "creation_fee", + "fee_collector_address", + "init", + "product_label" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -184,45 +210,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -234,34 +249,39 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "MinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", "num_tokens", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -293,13 +313,13 @@ ] }, "per_address_limit": { - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "type": "string" - }, "start_time": { "$ref": "#/definitions/Timestamp" }, @@ -316,7 +336,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -324,6 +345,9 @@ }, "init": { "$ref": "#/definitions/MinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false @@ -336,6 +360,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -392,7 +466,7 @@ ], "properties": { "params": { - "$ref": "#/definitions/Params" + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, @@ -416,28 +490,40 @@ } } }, - "Params": { + "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" + }, + "FactoryParams_for_Empty": { "type": "object", "required": [ "admin", + "contract_id", + "creation_fee", "fee_collector_address", - "minter_code_id", - "minter_creation_fee" + "init", + "product_label" ], "properties": { "admin": { "$ref": "#/definitions/Addr" }, - "fee_collector_address": { - "$ref": "#/definitions/Addr" - }, - "minter_code_id": { + "contract_id": { "type": "integer", "format": "uint64", "minimum": 0.0 }, - "minter_creation_fee": { + "creation_fee": { "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" } }, "additionalProperties": false diff --git a/contracts/factories/minter-factory/schema/raw/execute.json b/contracts/factories/minter-factory/schema/raw/execute.json index b69b9dd..885f5e1 100644 --- a/contracts/factories/minter-factory/schema/raw/execute.json +++ b/contracts/factories/minter-factory/schema/raw/execute.json @@ -129,45 +129,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -179,34 +168,39 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "MinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", "num_tokens", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -238,13 +232,13 @@ ] }, "per_address_limit": { - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "type": "string" - }, "start_time": { "$ref": "#/definitions/Timestamp" }, @@ -261,7 +255,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -269,6 +264,9 @@ }, "init": { "$ref": "#/definitions/MinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false @@ -281,6 +279,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/factories/minter-factory/schema/raw/instantiate.json b/contracts/factories/minter-factory/schema/raw/instantiate.json index 7553005..cfd786b 100644 --- a/contracts/factories/minter-factory/schema/raw/instantiate.json +++ b/contracts/factories/minter-factory/schema/raw/instantiate.json @@ -3,31 +3,19 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "fee_collector_address", - "minter_code_id", - "minter_creation_fee" + "params" ], "properties": { - "admin": { - "type": [ - "string", - "null" - ] - }, - "fee_collector_address": { - "type": "string" - }, - "minter_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "minter_creation_fee": { - "$ref": "#/definitions/Coin" + "params": { + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -43,6 +31,44 @@ } } }, + "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" + }, + "FactoryParams_for_Empty": { + "type": "object", + "required": [ + "admin", + "contract_id", + "creation_fee", + "fee_collector_address", + "init", + "product_label" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/factories/minter-factory/schema/raw/response_to_params.json b/contracts/factories/minter-factory/schema/raw/response_to_params.json index f8d7aa1..a5901bc 100644 --- a/contracts/factories/minter-factory/schema/raw/response_to_params.json +++ b/contracts/factories/minter-factory/schema/raw/response_to_params.json @@ -7,7 +7,7 @@ ], "properties": { "params": { - "$ref": "#/definitions/Params" + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, @@ -31,28 +31,40 @@ } } }, - "Params": { + "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" + }, + "FactoryParams_for_Empty": { "type": "object", "required": [ "admin", + "contract_id", + "creation_fee", "fee_collector_address", - "minter_code_id", - "minter_creation_fee" + "init", + "product_label" ], "properties": { "admin": { "$ref": "#/definitions/Addr" }, - "fee_collector_address": { - "$ref": "#/definitions/Addr" - }, - "minter_code_id": { + "contract_id": { "type": "integer", "format": "uint64", "minimum": 0.0 }, - "minter_creation_fee": { + "creation_fee": { "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" } }, "additionalProperties": false diff --git a/contracts/factories/minter-factory/src/contract.rs b/contracts/factories/minter-factory/src/contract.rs index aa83980..64793f0 100644 --- a/contracts/factories/minter-factory/src/contract.rs +++ b/contracts/factories/minter-factory/src/contract.rs @@ -2,15 +2,14 @@ use std::str::FromStr; use crate::error::ContractError; use crate::msg::{CreateMinterMsg, ExecuteMsg, InstantiateMsg, ParamsResponse, QueryMsg}; -use crate::state::{Params, PARAMS}; -use crate::utils::check_payment; +use crate::state::PARAMS; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, BankMsg, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint128, WasmMsg, }; -use cw_utils::maybe_addr; +use factory_types::check_payment; use omniflix_std::types::omniflix::onft::v1beta1::OnftQuerier; #[cfg(not(test))] const CREATION_FEE: Uint128 = Uint128::new(0); @@ -29,17 +28,16 @@ pub fn instantiate( info: MessageInfo, msg: InstantiateMsg, ) -> Result { - let admin = maybe_addr(deps.api, msg.admin)?.unwrap_or(info.sender); - let fee_collector_address = deps.api.addr_validate(&msg.fee_collector_address)?; - if msg.minter_code_id == 0 { - return Err(ContractError::InvalidMinterCodeId {}); - } - let params = Params { - admin: admin.clone(), - fee_collector_address, - minter_code_id: msg.minter_code_id, - minter_creation_fee: msg.minter_creation_fee, - }; + let _admin = deps + .api + .addr_validate(&msg.params.clone().admin.into_string()) + .unwrap_or(info.sender.clone()); + let _fee_collector_address = deps + .api + .addr_validate(&msg.params.fee_collector_address.clone().into_string()) + .unwrap_or(info.sender.clone()); + + let params = msg.params; PARAMS.save(deps.storage, ¶ms)?; Ok(Response::default()) } @@ -89,22 +87,22 @@ fn create_minter( }; check_payment( &info.funds, - &[nft_creation_fee.clone(), params.minter_creation_fee.clone()], + &[nft_creation_fee.clone(), params.creation_fee.clone()], )?; - - let msgs: Vec = vec![ - CosmosMsg::Wasm(WasmMsg::Instantiate { - admin: Some(params.admin.to_string()), - code_id: params.minter_code_id, - msg: to_json_binary(&msg)?, - funds: vec![nft_creation_fee], - label: "omniflix-nft-minter".to_string(), - }), - CosmosMsg::Bank(BankMsg::Send { - amount: vec![params.minter_creation_fee], + let mut msgs = Vec::::new(); + msgs.push(CosmosMsg::Wasm(WasmMsg::Instantiate { + admin: Some(msg.init.admin.to_string()), + code_id: params.contract_id, + msg: to_json_binary(&msg)?, + funds: vec![nft_creation_fee], + label: params.product_label, + })); + if params.creation_fee.amount > Uint128::new(0) { + msgs.push(CosmosMsg::Bank(BankMsg::Send { + amount: vec![params.creation_fee], to_address: params.fee_collector_address.to_string(), - }), - ]; + })); + } let res = Response::new() .add_messages(msgs) .add_attribute("action", "create_minter"); @@ -158,7 +156,7 @@ fn update_params_minter_code_id( if params.admin != info.sender { return Err(ContractError::Unauthorized {}); } - params.minter_code_id = minter_code_id; + params.contract_id = minter_code_id; PARAMS.save(deps.storage, ¶ms)?; Ok(Response::default() .add_attribute("action", "update_minter_code_id") @@ -175,7 +173,7 @@ fn update_params_minter_creation_fee( if params.admin != info.sender { return Err(ContractError::Unauthorized {}); } - params.minter_creation_fee = minter_creation_fee.clone(); + params.creation_fee = minter_creation_fee.clone(); PARAMS.save(deps.storage, ¶ms)?; Ok(Response::default() .add_attribute("action", "update_minter_creation_fee") @@ -201,20 +199,25 @@ mod tests { use super::*; use cosmwasm_std::{ testing::{mock_dependencies, mock_env, mock_info}, - Addr, Decimal, Timestamp, + Addr, Decimal, Empty, Timestamp, }; + use factory_types::CustomPaymentError; use minter_types::CollectionDetails; #[test] fn test_instantiate() { let mut deps = mock_dependencies(); let msg = InstantiateMsg { - admin: None, - fee_collector_address: "fee_collector_address".to_string(), - minter_code_id: 1, - minter_creation_fee: Coin { - amount: Uint128::new(100), - denom: "uusd".to_string(), + params: factory_types::FactoryParams:: { + admin: Addr::unchecked("admin"), + fee_collector_address: Addr::unchecked("fee_collector_address"), + contract_id: 1, + creation_fee: Coin { + amount: Uint128::new(100), + denom: "uusd".to_string(), + }, + product_label: "omniflix-nft-minter".to_string(), + init: Empty {}, }, }; let info = mock_info("creator", &[]); @@ -224,14 +227,16 @@ mod tests { let params = query_params(deps.as_ref()).unwrap(); assert_eq!( params.params, - Params { - admin: Addr::unchecked("creator"), + factory_types::FactoryParams:: { + admin: Addr::unchecked("admin"), fee_collector_address: Addr::unchecked("fee_collector_address"), - minter_code_id: 1, - minter_creation_fee: Coin { + contract_id: 1, + creation_fee: Coin { amount: Uint128::new(100), denom: "uusd".to_string(), }, + product_label: "omniflix-nft-minter".to_string(), + init: Empty {}, } ); } @@ -240,33 +245,43 @@ mod tests { fn test_execute_create_minter() { let mut deps = mock_dependencies(); let msg = InstantiateMsg { - admin: None, - fee_collector_address: "fee_collector_address".to_string(), - minter_code_id: 1, - minter_creation_fee: Coin { - amount: Uint128::new(100), - denom: "uusd".to_string(), + params: factory_types::FactoryParams:: { + admin: Addr::unchecked("admin"), + fee_collector_address: Addr::unchecked("fee_collector_address"), + contract_id: 1, + creation_fee: Coin { + amount: Uint128::new(100), + denom: "uusd".to_string(), + }, + product_label: "omniflix-nft-minter".to_string(), + init: Empty {}, }, }; let info = mock_info("creator", &[]); let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); let collection_details = CollectionDetails { - name: "My Collection".to_string(), - description: "This is a collection of unique tokens.".to_string(), - preview_uri: "https://example.com/preview".to_string(), - schema: "https://example.com/schema".to_string(), + collection_name: "Collection Name".to_string(), + description: Some("This is a collection of unique tokens.".to_string()), + preview_uri: Some("https://example.com/preview".to_string()), + schema: Some("https://example.com/schema".to_string()), symbol: "SYM".to_string(), id: "collection_id".to_string(), - extensible: true, - nsfw: false, - base_uri: "https://example.com/base".to_string(), - uri: "https://example.com/collection".to_string(), + uri: Some("https://example.com/collection".to_string()), uri_hash: Some("".to_string()), - data: "Additional data for the collection".to_string(), - transferable: true, - token_name: "token_name".to_string(), + data: Some("Additional data for the collection".to_string()), royalty_receivers: None, }; + let token_details = minter_types::TokenDetails { + token_name: "Token Name".to_string(), + description: Some("This is a unique token.".to_string()), + base_token_uri: "https://example.com/token".to_string(), + transferable: true, + extensible: false, + nsfw: false, + royalty_ratio: Decimal::percent(10), + preview_uri: Some("https://example.com/preview".to_string()), + data: Some("Additional data for the token".to_string()), + }; // Send additional funds let msg = ExecuteMsg::CreateMinter { msg: CreateMinterMsg { @@ -279,12 +294,12 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, num_tokens: 100, }, + token_details: token_details.clone(), }, }; @@ -308,7 +323,7 @@ mod tests { let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap_err(); assert_eq!( res, - ContractError::IncorrectFunds { + ContractError::PaymentError(CustomPaymentError::InsufficientFunds { expected: vec![ Coin { amount: Uint128::new(100_000_000), @@ -333,13 +348,14 @@ mod tests { denom: "additional".to_string(), }, ], - } + }) ); // Missing funds let msg = ExecuteMsg::CreateMinter { msg: CreateMinterMsg { collection_details: collection_details.clone(), + token_details: token_details.clone(), init: MinterInitExtention { admin: "admin".to_string(), whitelist_address: None, @@ -348,9 +364,8 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, num_tokens: 100, }, @@ -367,7 +382,7 @@ mod tests { let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap_err(); assert_eq!( res, - ContractError::IncorrectFunds { + ContractError::PaymentError(CustomPaymentError::InsufficientFunds { expected: vec![ Coin { amount: Uint128::new(100_000_000), @@ -381,8 +396,8 @@ mod tests { actual: vec![Coin { amount: Uint128::new(100_000_000), denom: "uflix".to_string(), - },], - } + }], + }) ); // Happy path @@ -397,12 +412,12 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, num_tokens: 100, }, + token_details: token_details.clone(), }, }; @@ -425,7 +440,7 @@ mod tests { assert_eq!( res.messages[0].msg, CosmosMsg::Wasm(WasmMsg::Instantiate { - admin: Some("creator".to_string()), + admin: Some("admin".to_string()), code_id: 1, msg: to_json_binary(&CreateMinterMsg { collection_details: collection_details.clone(), @@ -437,12 +452,12 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, num_tokens: 100, }, + token_details: token_details.clone(), }) .unwrap(), funds: vec![Coin { diff --git a/contracts/factories/minter-factory/src/error.rs b/contracts/factories/minter-factory/src/error.rs index b83b8d5..5b7e3e2 100644 --- a/contracts/factories/minter-factory/src/error.rs +++ b/contracts/factories/minter-factory/src/error.rs @@ -1,6 +1,5 @@ -use cosmwasm_std::{ - Coin, StdError, -}; +use cosmwasm_std::StdError; +use factory_types::CustomPaymentError; use thiserror::Error; #[derive(Error, Debug, PartialEq)] @@ -9,17 +8,15 @@ pub enum ContractError { #[error("{0}")] Std(#[from] StdError), + #[error("Payment error")] + PaymentError(#[from] CustomPaymentError), + #[error("Unauthorized")] Unauthorized {}, #[error("Invalid minter code id")] InvalidMinterCodeId {}, - #[error("Inncorrect funds")] - IncorrectFunds { - expected: Vec, - actual: Vec, - }, #[error("Invalid Mint Denom")] InvalidMintDenom {}, diff --git a/contracts/factories/minter-factory/src/lib.rs b/contracts/factories/minter-factory/src/lib.rs index 8153c2f..a5abdbb 100644 --- a/contracts/factories/minter-factory/src/lib.rs +++ b/contracts/factories/minter-factory/src/lib.rs @@ -2,4 +2,3 @@ pub mod contract; pub mod error; pub mod msg; pub mod state; -pub mod utils; diff --git a/contracts/factories/minter-factory/src/msg.rs b/contracts/factories/minter-factory/src/msg.rs index 032ffec..8cf82ce 100644 --- a/contracts/factories/minter-factory/src/msg.rs +++ b/contracts/factories/minter-factory/src/msg.rs @@ -1,14 +1,10 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Coin, Timestamp}; +use cosmwasm_std::{Coin, Empty, Timestamp}; +use factory_types::FactoryParams; use minter_types::MinterInstantiateMsg; - -use crate::state::Params; #[cw_serde] pub struct InstantiateMsg { - pub admin: Option, - pub fee_collector_address: String, - pub minter_code_id: u64, - pub minter_creation_fee: Coin, + pub params: FactoryParams, } #[cw_serde] @@ -18,10 +14,9 @@ pub struct MinterInitExtention { // Public minting start time pub start_time: Timestamp, pub end_time: Option, - pub per_address_limit: u32, + pub per_address_limit: Option, // We expect user to send a string between 0 and 1 // FE "0.1" - pub royalty_ratio: String, pub payment_collector: Option, // Whitelist address if any pub whitelist_address: Option, @@ -41,7 +36,7 @@ pub enum ExecuteMsg { #[cw_serde] pub struct ParamsResponse { - pub params: Params, + pub params: FactoryParams, } #[cw_serde] diff --git a/contracts/factories/minter-factory/src/state.rs b/contracts/factories/minter-factory/src/state.rs index 072f8ae..8e8d165 100644 --- a/contracts/factories/minter-factory/src/state.rs +++ b/contracts/factories/minter-factory/src/state.rs @@ -1,13 +1,5 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Coin}; +use cosmwasm_std::Empty; use cw_storage_plus::Item; +use factory_types::FactoryParams; -#[cw_serde] -pub struct Params { - pub minter_creation_fee: Coin, - pub fee_collector_address: Addr, - pub minter_code_id: u64, - pub admin: Addr, -} - -pub const PARAMS: Item = Item::new("params"); +pub const PARAMS: Item> = Item::new("params"); diff --git a/contracts/factories/open-edition-minter-factory/.cargo/config b/contracts/factories/open-edition-minter-factory/.cargo/config new file mode 100644 index 0000000..5b8deaa --- /dev/null +++ b/contracts/factories/open-edition-minter-factory/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run schema" diff --git a/contracts/factories/open-edition-minter-factory/Cargo.toml b/contracts/factories/open-edition-minter-factory/Cargo.toml index 7ac6f98..b7b593f 100644 --- a/contracts/factories/open-edition-minter-factory/Cargo.toml +++ b/contracts/factories/open-edition-minter-factory/Cargo.toml @@ -50,6 +50,6 @@ cw2 = { workspace = true } cw-storage-plus = { workspace = true } cw-utils = { workspace = true } serde = { workspace = true } -open-edition-minter-types = {workspace = true} minter-types = {workspace = true} +factory-types = {workspace = true} diff --git a/contracts/factories/open-edition-minter-factory/schema/omniflix-open-edition-minter-factory.json b/contracts/factories/open-edition-minter-factory/schema/omniflix-open-edition-minter-factory.json index 6675a26..0a1b7cd 100644 --- a/contracts/factories/open-edition-minter-factory/schema/omniflix-open-edition-minter-factory.json +++ b/contracts/factories/open-edition-minter-factory/schema/omniflix-open-edition-minter-factory.json @@ -7,31 +7,19 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "fee_collector_address", - "minter_creation_fee", - "open_edition_minter_code_id" + "params" ], "properties": { - "admin": { - "type": [ - "string", - "null" - ] - }, - "fee_collector_address": { - "type": "string" - }, - "minter_creation_fee": { - "$ref": "#/definitions/Coin" - }, - "open_edition_minter_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 + "params": { + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -47,6 +35,44 @@ } } }, + "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" + }, + "FactoryParams_for_Empty": { + "type": "object", + "required": [ + "admin", + "contract_id", + "creation_fee", + "fee_collector_address", + "init", + "product_label" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -184,45 +210,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -234,31 +249,39 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "MinterInstantiateMsg_for_OpenEditionMinterInitExtention": { "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -266,6 +289,9 @@ }, "init": { "$ref": "#/definitions/OpenEditionMinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false @@ -275,8 +301,6 @@ "required": [ "admin", "mint_price", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -296,6 +320,14 @@ "mint_price": { "$ref": "#/definitions/Coin" }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, "payment_collector": { "type": [ "string", @@ -303,17 +335,6 @@ ] }, "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "royalty_ratio": { - "type": "string" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { "type": [ "integer", "null" @@ -321,6 +342,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "type": [ "string", @@ -338,6 +362,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -394,7 +468,7 @@ ], "properties": { "params": { - "$ref": "#/definitions/Params" + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, @@ -418,28 +492,40 @@ } } }, - "Params": { + "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" + }, + "FactoryParams_for_Empty": { "type": "object", "required": [ "admin", + "contract_id", + "creation_fee", "fee_collector_address", - "minter_creation_fee", - "open_edition_minter_code_id" + "init", + "product_label" ], "properties": { "admin": { "$ref": "#/definitions/Addr" }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, "fee_collector_address": { "$ref": "#/definitions/Addr" }, - "minter_creation_fee": { - "$ref": "#/definitions/Coin" + "init": { + "$ref": "#/definitions/Empty" }, - "open_edition_minter_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 + "product_label": { + "type": "string" } }, "additionalProperties": false diff --git a/contracts/factories/open-edition-minter-factory/schema/raw/execute.json b/contracts/factories/open-edition-minter-factory/schema/raw/execute.json index d4fd12f..2b5308b 100644 --- a/contracts/factories/open-edition-minter-factory/schema/raw/execute.json +++ b/contracts/factories/open-edition-minter-factory/schema/raw/execute.json @@ -129,45 +129,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -179,31 +168,39 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "MinterInstantiateMsg_for_OpenEditionMinterInitExtention": { "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -211,6 +208,9 @@ }, "init": { "$ref": "#/definitions/OpenEditionMinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false @@ -220,8 +220,6 @@ "required": [ "admin", "mint_price", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -241,6 +239,14 @@ "mint_price": { "$ref": "#/definitions/Coin" }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, "payment_collector": { "type": [ "string", @@ -248,17 +254,6 @@ ] }, "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "royalty_ratio": { - "type": "string" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { "type": [ "integer", "null" @@ -266,6 +261,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "type": [ "string", @@ -283,6 +281,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/factories/open-edition-minter-factory/schema/raw/instantiate.json b/contracts/factories/open-edition-minter-factory/schema/raw/instantiate.json index 4f77c13..cfd786b 100644 --- a/contracts/factories/open-edition-minter-factory/schema/raw/instantiate.json +++ b/contracts/factories/open-edition-minter-factory/schema/raw/instantiate.json @@ -3,31 +3,19 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "fee_collector_address", - "minter_creation_fee", - "open_edition_minter_code_id" + "params" ], "properties": { - "admin": { - "type": [ - "string", - "null" - ] - }, - "fee_collector_address": { - "type": "string" - }, - "minter_creation_fee": { - "$ref": "#/definitions/Coin" - }, - "open_edition_minter_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 + "params": { + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -43,6 +31,44 @@ } } }, + "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" + }, + "FactoryParams_for_Empty": { + "type": "object", + "required": [ + "admin", + "contract_id", + "creation_fee", + "fee_collector_address", + "init", + "product_label" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/factories/open-edition-minter-factory/schema/raw/response_to_params.json b/contracts/factories/open-edition-minter-factory/schema/raw/response_to_params.json index 9e7c23b..a5901bc 100644 --- a/contracts/factories/open-edition-minter-factory/schema/raw/response_to_params.json +++ b/contracts/factories/open-edition-minter-factory/schema/raw/response_to_params.json @@ -7,7 +7,7 @@ ], "properties": { "params": { - "$ref": "#/definitions/Params" + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, @@ -31,28 +31,40 @@ } } }, - "Params": { + "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" + }, + "FactoryParams_for_Empty": { "type": "object", "required": [ "admin", + "contract_id", + "creation_fee", "fee_collector_address", - "minter_creation_fee", - "open_edition_minter_code_id" + "init", + "product_label" ], "properties": { "admin": { "$ref": "#/definitions/Addr" }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, "fee_collector_address": { "$ref": "#/definitions/Addr" }, - "minter_creation_fee": { - "$ref": "#/definitions/Coin" + "init": { + "$ref": "#/definitions/Empty" }, - "open_edition_minter_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 + "product_label": { + "type": "string" } }, "additionalProperties": false diff --git a/contracts/factories/open-edition-minter-factory/src/contract.rs b/contracts/factories/open-edition-minter-factory/src/contract.rs index ed0a55d..13df760 100644 --- a/contracts/factories/open-edition-minter-factory/src/contract.rs +++ b/contracts/factories/open-edition-minter-factory/src/contract.rs @@ -2,15 +2,14 @@ use crate::error::ContractError; use crate::msg::{ ExecuteMsg, InstantiateMsg, OpenEditionMinterCreateMsg, ParamsResponse, QueryMsg, }; -use crate::state::{Params, PARAMS}; -use crate::utils::check_payment; +use crate::state::PARAMS; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, BankMsg, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint128, WasmMsg, }; -use cw_utils::maybe_addr; +use factory_types::check_payment; use omniflix_std::types::omniflix::onft::v1beta1::OnftQuerier; use std::str::FromStr; #[cfg(not(test))] @@ -30,20 +29,18 @@ pub fn instantiate( info: MessageInfo, msg: InstantiateMsg, ) -> Result { - let admin = maybe_addr(deps.api, msg.admin)?.unwrap_or(info.sender); - let fee_collector_address = deps.api.addr_validate(&msg.fee_collector_address)?; - if msg.open_edition_minter_code_id == 0 { - return Err(ContractError::InvalidMinterCodeId {}); - } - let params = Params { - admin: admin.clone(), - fee_collector_address, - open_edition_minter_code_id: msg.open_edition_minter_code_id, - minter_creation_fee: msg.minter_creation_fee, - }; - PARAMS.save(deps.storage, ¶ms)?; + let _admin = deps + .api + .addr_validate(&msg.params.clone().admin.into_string()) + .unwrap_or(info.sender.clone()); + let _fee_collector_address = deps + .api + .addr_validate(&msg.params.fee_collector_address.clone().into_string()) + .unwrap_or(info.sender.clone()); - Ok(Response::default().add_attribute("action", "instantiate")) + let params = msg.params; + PARAMS.save(deps.storage, ¶ms)?; + Ok(Response::default()) } #[cfg_attr(not(feature = "library"), entry_point)] @@ -91,21 +88,22 @@ fn create_minter( }; check_payment( &info.funds, - &[nft_creation_fee.clone(), params.minter_creation_fee.clone()], + &[nft_creation_fee.clone(), params.creation_fee.clone()], )?; - let msgs: Vec = vec![ - CosmosMsg::Wasm(WasmMsg::Instantiate { - admin: Some(params.admin.to_string()), - code_id: params.open_edition_minter_code_id, - msg: to_json_binary(&msg)?, - funds: vec![nft_creation_fee], - label: "omniflix-nft-minter".to_string(), - }), - CosmosMsg::Bank(BankMsg::Send { - amount: vec![params.minter_creation_fee], + let mut msgs = Vec::::new(); + msgs.push(CosmosMsg::Wasm(WasmMsg::Instantiate { + admin: Some(msg.init.admin.to_string()), + code_id: params.contract_id, + msg: to_json_binary(&msg)?, + funds: vec![nft_creation_fee], + label: params.product_label, + })); + if params.creation_fee.amount > Uint128::new(0) { + msgs.push(CosmosMsg::Bank(BankMsg::Send { to_address: params.fee_collector_address.to_string(), - }), - ]; + amount: vec![params.creation_fee.clone()], + })); + } let res = Response::new() .add_messages(msgs) .add_attribute("action", "create_minter"); @@ -159,7 +157,7 @@ fn update_params_minter_code_id( if params.admin != info.sender { return Err(ContractError::Unauthorized {}); } - params.open_edition_minter_code_id = minter_code_id; + params.contract_id = minter_code_id; PARAMS.save(deps.storage, ¶ms)?; Ok(Response::default() .add_attribute("action", "update_minter_code_id") @@ -176,7 +174,8 @@ fn update_params_minter_creation_fee( if params.admin != info.sender { return Err(ContractError::Unauthorized {}); } - params.minter_creation_fee = minter_creation_fee.clone(); + params.creation_fee = minter_creation_fee.clone(); + PARAMS.save(deps.storage, ¶ms)?; Ok(Response::default() .add_attribute("action", "update_minter_creation_fee") @@ -202,20 +201,25 @@ mod tests { use super::*; use cosmwasm_std::{ testing::{mock_dependencies, mock_env, mock_info}, - Addr, Decimal, Timestamp, + Addr, Decimal, Empty, Timestamp, }; - use minter_types::CollectionDetails; + use factory_types::CustomPaymentError; + use minter_types::{CollectionDetails, TokenDetails}; #[test] fn test_instantiate() { let mut deps = mock_dependencies(); let msg = InstantiateMsg { - admin: None, - fee_collector_address: "fee_collector_address".to_string(), - open_edition_minter_code_id: 1, - minter_creation_fee: Coin { - amount: Uint128::new(100), - denom: "uusd".to_string(), + params: factory_types::FactoryParams:: { + admin: Addr::unchecked("creator"), + fee_collector_address: Addr::unchecked("fee_collector_address"), + contract_id: 1, + creation_fee: Coin { + amount: Uint128::new(100), + denom: "uusd".to_string(), + }, + product_label: "omniflix-open-edition-minter".to_string(), + init: Empty {}, }, }; let info = mock_info("creator", &[]); @@ -225,14 +229,16 @@ mod tests { let params = query_params(deps.as_ref()).unwrap(); assert_eq!( params.params, - Params { + factory_types::FactoryParams:: { admin: Addr::unchecked("creator"), fee_collector_address: Addr::unchecked("fee_collector_address"), - open_edition_minter_code_id: 1, - minter_creation_fee: Coin { + contract_id: 1, + creation_fee: Coin { amount: Uint128::new(100), denom: "uusd".to_string(), }, + product_label: "omniflix-open-edition-minter".to_string(), + init: Empty {}, } ); } @@ -241,37 +247,49 @@ mod tests { fn test_execute_create_open_edition_minter() { let mut deps = mock_dependencies(); let msg = InstantiateMsg { - admin: None, - fee_collector_address: "fee_collector_address".to_string(), - open_edition_minter_code_id: 1, - minter_creation_fee: Coin { - amount: Uint128::new(100), - denom: "uusd".to_string(), + params: factory_types::FactoryParams:: { + admin: Addr::unchecked("creator"), + fee_collector_address: Addr::unchecked("fee_collector_address"), + contract_id: 1, + creation_fee: Coin { + amount: Uint128::new(100), + denom: "uusd".to_string(), + }, + product_label: "omniflix-open-edition-minter".to_string(), + init: Empty {}, }, }; + let info = mock_info("creator", &[]); let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); let collection_details = CollectionDetails { - name: "My Collection".to_string(), - description: "This is a collection of unique tokens.".to_string(), - preview_uri: "https://example.com/preview".to_string(), - schema: "https://example.com/schema".to_string(), + collection_name: "My Collection".to_string(), + description: Some("This is a collection of unique tokens.".to_string()), + preview_uri: Some("https://example.com/preview".to_string()), + schema: Some("https://example.com/schema".to_string()), symbol: "SYM".to_string(), id: "collection_id".to_string(), + uri: Some("https://example.com/collection".to_string()), + uri_hash: Some("hash123".to_string()), + data: Some("Additional data for the collection".to_string()), + royalty_receivers: None, + }; + let token_details = TokenDetails { + token_name: "My Token".to_string(), + description: Some("This is a unique token.".to_string()), + base_token_uri: "https://example.com/token".to_string(), + preview_uri: Some("https://example.com/preview".to_string()), extensible: true, nsfw: false, - base_uri: "https://example.com/base".to_string(), - uri: "https://example.com/collection".to_string(), - uri_hash: Some("hash123".to_string()), - data: "Additional data for the collection".to_string(), + royalty_ratio: Decimal::percent(10), transferable: true, - token_name: "token_name".to_string(), - royalty_receivers: None, + data: Some("Additional data for the token".to_string()), }; // Send additional funds let msg = ExecuteMsg::CreateMinter { msg: OpenEditionMinterCreateMsg { collection_details: collection_details.clone(), + token_details: token_details.clone(), init: OpenEditionMinterInitExtention { admin: "admin".to_string(), whitelist_address: None, @@ -280,11 +298,10 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, - token_limit: None, + num_tokens: None, }, }, }; @@ -309,7 +326,7 @@ mod tests { let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap_err(); assert_eq!( res, - ContractError::IncorrectFunds { + ContractError::PaymentError(CustomPaymentError::InsufficientFunds { expected: vec![ Coin { amount: Uint128::new(100_000_000), @@ -333,14 +350,15 @@ mod tests { amount: Uint128::new(100), denom: "additional".to_string(), }, - ], - } + ] + }) ); // Missing funds let msg = ExecuteMsg::CreateMinter { msg: OpenEditionMinterCreateMsg { collection_details: collection_details.clone(), + token_details: token_details.clone(), init: OpenEditionMinterInitExtention { admin: "admin".to_string(), whitelist_address: None, @@ -349,11 +367,10 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, - token_limit: None, + num_tokens: None, }, }, }; @@ -368,7 +385,7 @@ mod tests { let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap_err(); assert_eq!( res, - ContractError::IncorrectFunds { + ContractError::PaymentError(CustomPaymentError::InsufficientFunds { expected: vec![ Coin { amount: Uint128::new(100_000_000), @@ -382,14 +399,15 @@ mod tests { actual: vec![Coin { amount: Uint128::new(100_000_000), denom: "uflix".to_string(), - },], - } + },] + }) ); // Happy path let msg = ExecuteMsg::CreateMinter { msg: OpenEditionMinterCreateMsg { collection_details: collection_details.clone(), + token_details: token_details.clone(), init: OpenEditionMinterInitExtention { admin: "admin".to_string(), whitelist_address: None, @@ -398,11 +416,10 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, - token_limit: None, + num_tokens: None, }, }, }; @@ -426,10 +443,11 @@ mod tests { assert_eq!( res.messages[0].msg, CosmosMsg::Wasm(WasmMsg::Instantiate { - admin: Some("creator".to_string()), + admin: Some("admin".to_string()), code_id: 1, msg: to_json_binary(&OpenEditionMinterCreateMsg { collection_details: collection_details.clone(), + token_details: token_details.clone(), init: OpenEditionMinterInitExtention { admin: "admin".to_string(), whitelist_address: None, @@ -438,11 +456,10 @@ mod tests { denom: "uusd".to_string(), }, start_time: Timestamp::from_seconds(0), - royalty_ratio: Decimal::percent(10).to_string(), payment_collector: None, - per_address_limit: 3, + per_address_limit: Some(3), end_time: None, - token_limit: None, + num_tokens: None, }, }) .unwrap(), @@ -450,7 +467,7 @@ mod tests { amount: Uint128::new(100_000_000), denom: "uflix".to_string(), }], - label: "omniflix-nft-minter".to_string(), + label: "omniflix-open-edition-minter".to_string(), }) ); assert_eq!( diff --git a/contracts/factories/open-edition-minter-factory/src/error.rs b/contracts/factories/open-edition-minter-factory/src/error.rs index b83b8d5..5b7e3e2 100644 --- a/contracts/factories/open-edition-minter-factory/src/error.rs +++ b/contracts/factories/open-edition-minter-factory/src/error.rs @@ -1,6 +1,5 @@ -use cosmwasm_std::{ - Coin, StdError, -}; +use cosmwasm_std::StdError; +use factory_types::CustomPaymentError; use thiserror::Error; #[derive(Error, Debug, PartialEq)] @@ -9,17 +8,15 @@ pub enum ContractError { #[error("{0}")] Std(#[from] StdError), + #[error("Payment error")] + PaymentError(#[from] CustomPaymentError), + #[error("Unauthorized")] Unauthorized {}, #[error("Invalid minter code id")] InvalidMinterCodeId {}, - #[error("Inncorrect funds")] - IncorrectFunds { - expected: Vec, - actual: Vec, - }, #[error("Invalid Mint Denom")] InvalidMintDenom {}, diff --git a/contracts/factories/open-edition-minter-factory/src/lib.rs b/contracts/factories/open-edition-minter-factory/src/lib.rs index 8153c2f..a5abdbb 100644 --- a/contracts/factories/open-edition-minter-factory/src/lib.rs +++ b/contracts/factories/open-edition-minter-factory/src/lib.rs @@ -2,4 +2,3 @@ pub mod contract; pub mod error; pub mod msg; pub mod state; -pub mod utils; diff --git a/contracts/factories/open-edition-minter-factory/src/msg.rs b/contracts/factories/open-edition-minter-factory/src/msg.rs index abbaa9f..8e7b734 100644 --- a/contracts/factories/open-edition-minter-factory/src/msg.rs +++ b/contracts/factories/open-edition-minter-factory/src/msg.rs @@ -1,14 +1,10 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Coin, Timestamp}; +use cosmwasm_std::{Coin, Empty, Timestamp}; +use factory_types::FactoryParams; use minter_types::MinterInstantiateMsg; - -use crate::state::Params; #[cw_serde] pub struct InstantiateMsg { - pub admin: Option, - pub fee_collector_address: String, - pub open_edition_minter_code_id: u64, - pub minter_creation_fee: Coin, + pub params: FactoryParams, } #[cw_serde] @@ -17,9 +13,8 @@ pub struct OpenEditionMinterInitExtention { pub mint_price: Coin, pub start_time: Timestamp, pub end_time: Option, - pub token_limit: Option, - pub per_address_limit: u32, - pub royalty_ratio: String, + pub num_tokens: Option, + pub per_address_limit: Option, pub payment_collector: Option, pub whitelist_address: Option, } @@ -37,7 +32,7 @@ pub enum ExecuteMsg { #[cw_serde] pub struct ParamsResponse { - pub params: Params, + pub params: FactoryParams, } #[cw_serde] diff --git a/contracts/factories/open-edition-minter-factory/src/state.rs b/contracts/factories/open-edition-minter-factory/src/state.rs index ebd778d..8e8d165 100644 --- a/contracts/factories/open-edition-minter-factory/src/state.rs +++ b/contracts/factories/open-edition-minter-factory/src/state.rs @@ -1,13 +1,5 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Coin}; +use cosmwasm_std::Empty; use cw_storage_plus::Item; +use factory_types::FactoryParams; -#[cw_serde] -pub struct Params { - pub minter_creation_fee: Coin, - pub fee_collector_address: Addr, - pub open_edition_minter_code_id: u64, - pub admin: Addr, -} - -pub const PARAMS: Item = Item::new("params"); +pub const PARAMS: Item> = Item::new("params"); diff --git a/contracts/factories/open-edition-minter-factory/src/utils.rs b/contracts/factories/open-edition-minter-factory/src/utils.rs deleted file mode 100644 index 833f705..0000000 --- a/contracts/factories/open-edition-minter-factory/src/utils.rs +++ /dev/null @@ -1,114 +0,0 @@ -use cosmwasm_std::Coin; - -use crate::error::ContractError; - -pub fn check_payment(sent_funds: &[Coin], expected_funds: &[Coin]) -> Result<(), ContractError> { - // Check length - if sent_funds.len() > expected_funds.len() { - return Err(ContractError::IncorrectFunds { - expected: expected_funds.to_vec(), - actual: sent_funds.to_vec(), - }); - } - - let mut mut_sent_funds = sent_funds.to_vec(); // Create a mutable copy - - for expected in expected_funds { - if let Some(sent_index) = mut_sent_funds - .iter() - .position(|sent| expected.denom == sent.denom) - { - let sent = &mut mut_sent_funds[sent_index]; - if expected.amount > sent.amount { - return Err(ContractError::IncorrectFunds { - expected: expected_funds.to_vec(), - actual: sent_funds.to_vec(), - }); - } else { - sent.amount = sent.amount.checked_sub(expected.amount).unwrap(); - } - } else { - return Err(ContractError::IncorrectFunds { - expected: expected_funds.to_vec(), - actual: sent_funds.to_vec(), - }); - } - } - - Ok(()) -} - -// Test check_payment -#[cfg(test)] -mod tests { - use super::*; - use cosmwasm_std::coin; - - #[test] - fn test_check_payment() { - let sent_funds = vec![coin(100, "uluna"), coin(100, "uusd")]; - let expected_funds = vec![coin(100, "uluna"), coin(100, "uusd")]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_ok()); - - let sent_funds = vec![coin(100, "uluna"), coin(100, "uusd")]; - let expected_funds = vec![coin(100, "uluna")]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_err()); - - let sent_funds = vec![coin(100, "uluna")]; - let expected_funds = vec![coin(100, "uluna"), coin(100, "uusd")]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_err()); - - let sent_funds = vec![coin(100, "uluna"), coin(100, "uusd")]; - let expected_funds = vec![coin(100, "uluna"), coin(200, "uusd")]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_err()); - - let sent_funds = vec![coin(300, "uluna")]; - let expected_funds = vec![coin(100, "uluna"), coin(200, "uluna")]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_ok()); - - let sent_funds = vec![coin(300 - 1, "uluna")]; - let expected_funds = vec![coin(100, "uluna"), coin(200, "uluna")]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_err()); - - let sent_funds = vec![coin(300, "uluna"), coin(100, "uusd")]; - let expected_funds = vec![coin(300, "uluna"), coin(200, "uatom")]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_err()); - - let sent_funds = vec![coin(1100, "uluna")]; - let expected_funds = vec![ - coin(100, "uluna"), - coin(200, "uluna"), - coin(300, "uluna"), - coin(500, "uluna"), - ]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_ok()); - - let sent_funds = vec![coin(1100 + 1, "uluna")]; - let expected_funds = vec![ - coin(100, "uluna"), - coin(200, "uluna"), - coin(300, "uluna"), - coin(500, "uluna"), - ]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_ok()); - - let sent_funds = vec![coin(1100 - 1, "uluna")]; - let expected_funds = vec![ - coin(100, "uluna"), - coin(200, "uluna"), - coin(300, "uluna"), - coin(500, "uluna"), - ]; - let res = check_payment(&sent_funds, &expected_funds); - assert!(res.is_err()); - } -} diff --git a/contracts/factories/round-whitelist-factory/.cargo/config b/contracts/factories/round-whitelist-factory/.cargo/config new file mode 100644 index 0000000..5b8deaa --- /dev/null +++ b/contracts/factories/round-whitelist-factory/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run schema" diff --git a/contracts/factories/round-whitelist-factory/Cargo.toml b/contracts/factories/round-whitelist-factory/Cargo.toml index 9e75ed0..f52a775 100644 --- a/contracts/factories/round-whitelist-factory/Cargo.toml +++ b/contracts/factories/round-whitelist-factory/Cargo.toml @@ -45,4 +45,5 @@ cw2 = { workspace = true } cw-storage-plus = { workspace = true } cw-utils = { workspace = true } serde = { workspace = true } -whitelist-types={ workspace = true } \ No newline at end of file +whitelist-types={ workspace = true } +factory-types = { workspace = true } \ No newline at end of file diff --git a/contracts/factories/round-whitelist-factory/README.md b/contracts/factories/round-whitelist-factory/README.md deleted file mode 100644 index fe69790..0000000 --- a/contracts/factories/round-whitelist-factory/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Round Whitelist Factory -Simple factory contract. Stores params for whitelist creation and creates whitelists. - -### Parameters -- `whitelist_creation_fee`: The fee to create a whitelist -- `fee_collector_address`: The address to send the fee to -- `whitelist_code_id`: The code id of the whitelist contract -- `admin`: The admin address of the factory contract if not sent its the creator of the factory - diff --git a/contracts/factories/round-whitelist-factory/schema/omniflix-round-whitelist-factory.json b/contracts/factories/round-whitelist-factory/schema/omniflix-round-whitelist-factory.json index d2a623a..697309e 100644 --- a/contracts/factories/round-whitelist-factory/schema/omniflix-round-whitelist-factory.json +++ b/contracts/factories/round-whitelist-factory/schema/omniflix-round-whitelist-factory.json @@ -7,31 +7,19 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "fee_collector_address", - "whitelist_code_id", - "whitelist_creation_fee" + "params" ], "properties": { - "admin": { - "type": [ - "string", - "null" - ] - }, - "fee_collector_address": { - "type": "string" - }, - "whitelist_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "whitelist_creation_fee": { - "$ref": "#/definitions/Coin" + "params": { + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -47,6 +35,44 @@ } } }, + "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" + }, + "FactoryParams_for_Empty": { + "type": "object", + "required": [ + "admin", + "contract_id", + "creation_fee", + "fee_collector_address", + "init", + "product_label" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -188,14 +214,12 @@ "InstantiateMsg": { "type": "object", "required": [ + "admin", "rounds" ], "properties": { "admin": { - "type": [ - "string", - "null" - ] + "type": "string" }, "rounds": { "type": "array", @@ -288,7 +312,7 @@ ], "properties": { "params": { - "$ref": "#/definitions/Params" + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, @@ -312,28 +336,40 @@ } } }, - "Params": { + "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" + }, + "FactoryParams_for_Empty": { "type": "object", "required": [ "admin", + "contract_id", + "creation_fee", "fee_collector_address", - "whitelist_code_id", - "whitelist_creation_fee" + "init", + "product_label" ], "properties": { "admin": { "$ref": "#/definitions/Addr" }, - "fee_collector_address": { - "$ref": "#/definitions/Addr" - }, - "whitelist_code_id": { + "contract_id": { "type": "integer", "format": "uint64", "minimum": 0.0 }, - "whitelist_creation_fee": { + "creation_fee": { "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" } }, "additionalProperties": false diff --git a/contracts/factories/round-whitelist-factory/schema/raw/execute.json b/contracts/factories/round-whitelist-factory/schema/raw/execute.json index 2628712..7ce859a 100644 --- a/contracts/factories/round-whitelist-factory/schema/raw/execute.json +++ b/contracts/factories/round-whitelist-factory/schema/raw/execute.json @@ -133,14 +133,12 @@ "InstantiateMsg": { "type": "object", "required": [ + "admin", "rounds" ], "properties": { "admin": { - "type": [ - "string", - "null" - ] + "type": "string" }, "rounds": { "type": "array", diff --git a/contracts/factories/round-whitelist-factory/schema/raw/instantiate.json b/contracts/factories/round-whitelist-factory/schema/raw/instantiate.json index 9ddcac0..cfd786b 100644 --- a/contracts/factories/round-whitelist-factory/schema/raw/instantiate.json +++ b/contracts/factories/round-whitelist-factory/schema/raw/instantiate.json @@ -3,31 +3,19 @@ "title": "InstantiateMsg", "type": "object", "required": [ - "fee_collector_address", - "whitelist_code_id", - "whitelist_creation_fee" + "params" ], "properties": { - "admin": { - "type": [ - "string", - "null" - ] - }, - "fee_collector_address": { - "type": "string" - }, - "whitelist_code_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "whitelist_creation_fee": { - "$ref": "#/definitions/Coin" + "params": { + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -43,6 +31,44 @@ } } }, + "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" + }, + "FactoryParams_for_Empty": { + "type": "object", + "required": [ + "admin", + "contract_id", + "creation_fee", + "fee_collector_address", + "init", + "product_label" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "contract_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "creation_fee": { + "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/factories/round-whitelist-factory/schema/raw/response_to_params.json b/contracts/factories/round-whitelist-factory/schema/raw/response_to_params.json index 477c5be..a5901bc 100644 --- a/contracts/factories/round-whitelist-factory/schema/raw/response_to_params.json +++ b/contracts/factories/round-whitelist-factory/schema/raw/response_to_params.json @@ -7,7 +7,7 @@ ], "properties": { "params": { - "$ref": "#/definitions/Params" + "$ref": "#/definitions/FactoryParams_for_Empty" } }, "additionalProperties": false, @@ -31,28 +31,40 @@ } } }, - "Params": { + "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" + }, + "FactoryParams_for_Empty": { "type": "object", "required": [ "admin", + "contract_id", + "creation_fee", "fee_collector_address", - "whitelist_code_id", - "whitelist_creation_fee" + "init", + "product_label" ], "properties": { "admin": { "$ref": "#/definitions/Addr" }, - "fee_collector_address": { - "$ref": "#/definitions/Addr" - }, - "whitelist_code_id": { + "contract_id": { "type": "integer", "format": "uint64", "minimum": 0.0 }, - "whitelist_creation_fee": { + "creation_fee": { "$ref": "#/definitions/Coin" + }, + "fee_collector_address": { + "$ref": "#/definitions/Addr" + }, + "init": { + "$ref": "#/definitions/Empty" + }, + "product_label": { + "type": "string" } }, "additionalProperties": false diff --git a/contracts/factories/round-whitelist-factory/src/contract.rs b/contracts/factories/round-whitelist-factory/src/contract.rs index de87f30..e7b55f3 100644 --- a/contracts/factories/round-whitelist-factory/src/contract.rs +++ b/contracts/factories/round-whitelist-factory/src/contract.rs @@ -1,14 +1,13 @@ use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg, ParamsResponse, QueryMsg}; -use crate::state::{Params, PARAMS}; +use crate::state::PARAMS; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, BankMsg, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, StdResult, WasmMsg, }; -use cw_utils::maybe_addr; - +use cw_utils::may_pay; use whitelist_types::InstantiateMsg as WhitelistInstantiateMsg; #[cfg_attr(not(feature = "library"), entry_point)] @@ -18,13 +17,16 @@ pub fn instantiate( info: MessageInfo, msg: InstantiateMsg, ) -> Result { - let admin = maybe_addr(deps.api, msg.admin)?.unwrap_or(info.sender); - let params = Params { - admin: admin.clone(), - fee_collector_address: deps.api.addr_validate(&msg.fee_collector_address)?, - whitelist_code_id: msg.whitelist_code_id, - whitelist_creation_fee: msg.whitelist_creation_fee, - }; + let _admin = deps + .api + .addr_validate(&msg.params.clone().admin.into_string()) + .unwrap_or(info.sender.clone()); + let _fee_collector_address = deps + .api + .addr_validate(&msg.params.fee_collector_address.clone().into_string()) + .unwrap_or(info.sender.clone()); + + let params = msg.params; PARAMS.save(deps.storage, ¶ms)?; Ok(Response::default()) } @@ -58,24 +60,28 @@ pub fn create_whitelist( msg: WhitelistInstantiateMsg, ) -> Result { let params = PARAMS.load(deps.storage)?; - let creation_fee = params.whitelist_creation_fee; + let creation_fee = params.creation_fee; let fee_collector_address = params.fee_collector_address; - let whitelist_code_id = params.whitelist_code_id; + let whitelist_code_id = params.contract_id; let mut messages: Vec = vec![]; - if [creation_fee.clone()].to_vec() != info.funds { + let amount = may_pay(&info, &creation_fee.clone().denom)?; + + if amount != creation_fee.amount { return Err(ContractError::MissingCreationFee {}); } - messages.push(CosmosMsg::Bank(BankMsg::Send { - to_address: fee_collector_address.to_string(), - amount: vec![creation_fee], - })); + if !creation_fee.amount.is_zero() { + messages.push(CosmosMsg::Bank(BankMsg::Send { + to_address: fee_collector_address.to_string(), + amount: vec![creation_fee], + })); + } messages.push(CosmosMsg::Wasm(WasmMsg::Instantiate { - admin: None, + admin: Some(msg.admin.clone()), code_id: whitelist_code_id, msg: to_json_binary(&msg)?, funds: vec![], - label: "Whitelist".to_string(), + label: params.product_label, })); Ok(Response::new() .add_messages(messages) @@ -125,7 +131,7 @@ pub fn update_whitelist_creation_fee( if info.sender != params.admin { return Err(ContractError::Unauthorized {}); } - params.whitelist_creation_fee = whitelist_creation_fee; + params.creation_fee = whitelist_creation_fee; PARAMS.save(deps.storage, ¶ms)?; Ok(Response::new().add_attribute("action", "update_whitelist_creation_fee")) } @@ -140,7 +146,7 @@ pub fn update_whitelist_code_id( if info.sender != params.admin { return Err(ContractError::Unauthorized {}); } - params.whitelist_code_id = whitelist_code_id; + params.contract_id = whitelist_code_id; PARAMS.save(deps.storage, ¶ms)?; Ok(Response::new().add_attribute("action", "update_whitelist_code_id")) } diff --git a/contracts/factories/round-whitelist-factory/src/error.rs b/contracts/factories/round-whitelist-factory/src/error.rs index b83b8d5..9c9b6a2 100644 --- a/contracts/factories/round-whitelist-factory/src/error.rs +++ b/contracts/factories/round-whitelist-factory/src/error.rs @@ -1,6 +1,5 @@ -use cosmwasm_std::{ - Coin, StdError, -}; +use cosmwasm_std::{Coin, StdError}; +use cw_utils::PaymentError; use thiserror::Error; #[derive(Error, Debug, PartialEq)] @@ -8,6 +7,8 @@ use thiserror::Error; pub enum ContractError { #[error("{0}")] Std(#[from] StdError), + #[error("Payment error")] + PaymentError(#[from] PaymentError), #[error("Unauthorized")] Unauthorized {}, diff --git a/contracts/factories/round-whitelist-factory/src/msg.rs b/contracts/factories/round-whitelist-factory/src/msg.rs index 73844f8..d77514a 100644 --- a/contracts/factories/round-whitelist-factory/src/msg.rs +++ b/contracts/factories/round-whitelist-factory/src/msg.rs @@ -1,15 +1,11 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Coin}; +use cosmwasm_std::{Coin, Empty}; +use factory_types::FactoryParams; use whitelist_types::InstantiateMsg as WhitelistInstantiateMsg; -use crate::state::Params; - #[cw_serde] pub struct InstantiateMsg { - pub admin: Option, - pub fee_collector_address: String, - pub whitelist_code_id: u64, - pub whitelist_creation_fee: Coin, + pub params: FactoryParams, } #[cw_serde] @@ -23,7 +19,7 @@ pub enum ExecuteMsg { #[cw_serde] pub struct ParamsResponse { - pub params: Params, + pub params: FactoryParams, } #[cw_serde] diff --git a/contracts/factories/round-whitelist-factory/src/state.rs b/contracts/factories/round-whitelist-factory/src/state.rs index 57d9fc8..8e8d165 100644 --- a/contracts/factories/round-whitelist-factory/src/state.rs +++ b/contracts/factories/round-whitelist-factory/src/state.rs @@ -1,12 +1,5 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Coin}; -use cw_storage_plus::{Item}; +use cosmwasm_std::Empty; +use cw_storage_plus::Item; +use factory_types::FactoryParams; -#[cw_serde] -pub struct Params { - pub whitelist_creation_fee: Coin, - pub fee_collector_address: Addr, - pub whitelist_code_id: u64, - pub admin: Addr, -} -pub const PARAMS: Item = Item::new("params"); +pub const PARAMS: Item> = Item::new("params"); diff --git a/contracts/minters/minter/.cargo/config b/contracts/minters/minter/.cargo/config new file mode 100644 index 0000000..5b8deaa --- /dev/null +++ b/contracts/minters/minter/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run schema" diff --git a/contracts/minters/minter/schema/omniflix-minter.json b/contracts/minters/minter/schema/omniflix-minter.json index a3b89c2..337015e 100644 --- a/contracts/minters/minter/schema/omniflix-minter.json +++ b/contracts/minters/minter/schema/omniflix-minter.json @@ -8,7 +8,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -16,6 +17,9 @@ }, "init": { "$ref": "#/definitions/MinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false, @@ -38,45 +42,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -88,34 +81,39 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "MinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", "num_tokens", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -147,13 +145,13 @@ ] }, "per_address_limit": { - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "type": "string" - }, "start_time": { "$ref": "#/definitions/Timestamp" }, @@ -174,6 +172,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -415,13 +463,13 @@ "update_denom": { "type": "object", "properties": { - "description": { + "collection_name": { "type": [ "string", "null" ] }, - "name": { + "description": { "type": [ "string", "null" @@ -451,6 +499,48 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_admin" + ], + "properties": { + "set_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_payment_collector" + ], + "properties": { + "set_payment_collector": { + "type": "object", + "required": [ + "payment_collector" + ], + "properties": { + "payment_collector": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } ], "definitions": { @@ -510,10 +600,10 @@ { "type": "object", "required": [ - "config" + "token_details" ], "properties": { - "config": { + "token_details": { "type": "object", "additionalProperties": false } @@ -523,10 +613,23 @@ { "type": "object", "required": [ - "mintable_tokens" + "auth_details" ], "properties": { - "mintable_tokens": { + "auth_details": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { "type": "object", "additionalProperties": false } @@ -557,10 +660,10 @@ { "type": "object", "required": [ - "total_tokens" + "is_paused" ], "properties": { - "total_tokens": { + "is_paused": { "type": "object", "additionalProperties": false } @@ -570,10 +673,10 @@ { "type": "object", "required": [ - "is_paused" + "pausers" ], "properties": { - "is_paused": { + "pausers": { "type": "object", "additionalProperties": false } @@ -583,65 +686,122 @@ { "type": "object", "required": [ - "pausers" + "extension" ], "properties": { - "pausers": { + "extension": { + "$ref": "#/definitions/MinterExtensionQueryMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_minted_count" + ], + "properties": { + "total_minted_count": { "type": "object", "additionalProperties": false } }, "additionalProperties": false } - ] + ], + "definitions": { + "MinterExtensionQueryMsg": { + "oneOf": [ + { + "type": "object", + "required": [ + "mintable_tokens" + ], + "properties": { + "mintable_tokens": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_tokens_remaining" + ], + "properties": { + "total_tokens_remaining": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } }, "migrate": null, "sudo": null, "responses": { + "auth_details": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AuthDetails", + "type": "object", + "required": [ + "admin", + "payment_collector" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "payment_collector": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + }, "collection": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "CollectionDetails", "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -653,22 +813,25 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, @@ -695,17 +858,10 @@ "title": "Config", "type": "object", "required": [ - "admin", "mint_price", - "payment_collector", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { - "admin": { - "$ref": "#/definitions/Addr" - }, "end_time": { "anyOf": [ { @@ -719,21 +875,15 @@ "mint_price": { "$ref": "#/definitions/Coin" }, - "payment_collector": { - "$ref": "#/definitions/Addr" - }, - "per_address_limit": { - "type": "integer", + "num_tokens": { + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "$ref": "#/definitions/Decimal" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { + "per_address_limit": { "type": [ "integer", "null" @@ -741,6 +891,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "anyOf": [ { @@ -773,10 +926,6 @@ } } }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "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": [ @@ -795,33 +944,18 @@ } } }, + "extension": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, "is_paused": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Boolean", "type": "boolean" }, - "mintable_tokens": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Array_of_Token", - "type": "array", - "items": { - "$ref": "#/definitions/Token" - }, - "definitions": { - "Token": { - "type": "object", - "required": [ - "token_id" - ], - "properties": { - "token_id": { - "type": "string" - } - }, - "additionalProperties": false - } - } - }, "minted_tokens": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "UserDetails", @@ -879,7 +1013,65 @@ } } }, - "total_tokens": { + "token_details": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokenDetails", + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } + }, + "total_minted_count": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "uint32", "type": "integer", diff --git a/contracts/minters/minter/schema/raw/execute.json b/contracts/minters/minter/schema/raw/execute.json index 74d2680..fe0cf0d 100644 --- a/contracts/minters/minter/schema/raw/execute.json +++ b/contracts/minters/minter/schema/raw/execute.json @@ -214,13 +214,13 @@ "update_denom": { "type": "object", "properties": { - "description": { + "collection_name": { "type": [ "string", "null" ] }, - "name": { + "description": { "type": [ "string", "null" @@ -250,6 +250,48 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_admin" + ], + "properties": { + "set_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_payment_collector" + ], + "properties": { + "set_payment_collector": { + "type": "object", + "required": [ + "payment_collector" + ], + "properties": { + "payment_collector": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } ], "definitions": { diff --git a/contracts/minters/minter/schema/raw/instantiate.json b/contracts/minters/minter/schema/raw/instantiate.json index 5c3759e..716574e 100644 --- a/contracts/minters/minter/schema/raw/instantiate.json +++ b/contracts/minters/minter/schema/raw/instantiate.json @@ -4,7 +4,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -12,6 +13,9 @@ }, "init": { "$ref": "#/definitions/MinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false, @@ -34,45 +38,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -84,34 +77,39 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "MinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", "num_tokens", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -143,13 +141,13 @@ ] }, "per_address_limit": { - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "type": "string" - }, "start_time": { "$ref": "#/definitions/Timestamp" }, @@ -170,6 +168,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/minters/minter/schema/raw/query.json b/contracts/minters/minter/schema/raw/query.json index 1ccec1f..1f56dc9 100644 --- a/contracts/minters/minter/schema/raw/query.json +++ b/contracts/minters/minter/schema/raw/query.json @@ -18,10 +18,23 @@ { "type": "object", "required": [ - "config" + "token_details" ], "properties": { - "config": { + "token_details": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "auth_details" + ], + "properties": { + "auth_details": { "type": "object", "additionalProperties": false } @@ -31,10 +44,10 @@ { "type": "object", "required": [ - "mintable_tokens" + "config" ], "properties": { - "mintable_tokens": { + "config": { "type": "object", "additionalProperties": false } @@ -65,10 +78,10 @@ { "type": "object", "required": [ - "total_tokens" + "is_paused" ], "properties": { - "total_tokens": { + "is_paused": { "type": "object", "additionalProperties": false } @@ -78,10 +91,10 @@ { "type": "object", "required": [ - "is_paused" + "pausers" ], "properties": { - "is_paused": { + "pausers": { "type": "object", "additionalProperties": false } @@ -91,15 +104,59 @@ { "type": "object", "required": [ - "pausers" + "extension" ], "properties": { - "pausers": { + "extension": { + "$ref": "#/definitions/MinterExtensionQueryMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_minted_count" + ], + "properties": { + "total_minted_count": { "type": "object", "additionalProperties": false } }, "additionalProperties": false } - ] + ], + "definitions": { + "MinterExtensionQueryMsg": { + "oneOf": [ + { + "type": "object", + "required": [ + "mintable_tokens" + ], + "properties": { + "mintable_tokens": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_tokens_remaining" + ], + "properties": { + "total_tokens_remaining": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } } diff --git a/contracts/minters/minter/schema/raw/response_to_auth_details.json b/contracts/minters/minter/schema/raw/response_to_auth_details.json new file mode 100644 index 0000000..aad6fe8 --- /dev/null +++ b/contracts/minters/minter/schema/raw/response_to_auth_details.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AuthDetails", + "type": "object", + "required": [ + "admin", + "payment_collector" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "payment_collector": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/contracts/minters/minter/schema/raw/response_to_collection.json b/contracts/minters/minter/schema/raw/response_to_collection.json index d8a9fd7..8a9414c 100644 --- a/contracts/minters/minter/schema/raw/response_to_collection.json +++ b/contracts/minters/minter/schema/raw/response_to_collection.json @@ -3,45 +3,34 @@ "title": "CollectionDetails", "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -53,22 +42,25 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, diff --git a/contracts/minters/minter/schema/raw/response_to_config.json b/contracts/minters/minter/schema/raw/response_to_config.json index 73907a6..0a3efbd 100644 --- a/contracts/minters/minter/schema/raw/response_to_config.json +++ b/contracts/minters/minter/schema/raw/response_to_config.json @@ -3,17 +3,10 @@ "title": "Config", "type": "object", "required": [ - "admin", "mint_price", - "payment_collector", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { - "admin": { - "$ref": "#/definitions/Addr" - }, "end_time": { "anyOf": [ { @@ -27,21 +20,15 @@ "mint_price": { "$ref": "#/definitions/Coin" }, - "payment_collector": { - "$ref": "#/definitions/Addr" - }, - "per_address_limit": { - "type": "integer", + "num_tokens": { + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "$ref": "#/definitions/Decimal" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { + "per_address_limit": { "type": [ "integer", "null" @@ -49,6 +36,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "anyOf": [ { @@ -81,10 +71,6 @@ } } }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "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": [ diff --git a/contracts/minters/minter/schema/raw/response_to_extension.json b/contracts/minters/minter/schema/raw/response_to_extension.json new file mode 100644 index 0000000..de85c3e --- /dev/null +++ b/contracts/minters/minter/schema/raw/response_to_extension.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 +} diff --git a/contracts/minters/minter/schema/raw/response_to_token_details.json b/contracts/minters/minter/schema/raw/response_to_token_details.json new file mode 100644 index 0000000..516fcb4 --- /dev/null +++ b/contracts/minters/minter/schema/raw/response_to_token_details.json @@ -0,0 +1,58 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokenDetails", + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } +} diff --git a/contracts/minters/minter/schema/raw/response_to_total_minted_count.json b/contracts/minters/minter/schema/raw/response_to_total_minted_count.json new file mode 100644 index 0000000..de85c3e --- /dev/null +++ b/contracts/minters/minter/schema/raw/response_to_total_minted_count.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 +} diff --git a/contracts/minters/minter/src/bin/schema.rs b/contracts/minters/minter/src/bin/schema.rs index 904d587..7b1a2f4 100644 --- a/contracts/minters/minter/src/bin/schema.rs +++ b/contracts/minters/minter/src/bin/schema.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::write_api; -use omniflix_minter::msg::ExecuteMsg; +use omniflix_minter::msg::{ExecuteMsg, MinterExtensionQueryMsg}; use minter_types::QueryMsg; @@ -10,6 +10,6 @@ fn main() { write_api! { instantiate: CreateMinterMsg, execute: ExecuteMsg, - query: QueryMsg, + query: QueryMsg, } } diff --git a/contracts/minters/minter/src/contract.rs b/contracts/minters/minter/src/contract.rs index ab316a4..b6997da 100644 --- a/contracts/minters/minter/src/contract.rs +++ b/contracts/minters/minter/src/contract.rs @@ -1,7 +1,7 @@ use std::env; use std::str::FromStr; -use crate::msg::ExecuteMsg; +use crate::msg::{ExecuteMsg, MinterExtensionQueryMsg}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ @@ -9,7 +9,10 @@ use cosmwasm_std::{ Response, StdResult, Uint128, WasmMsg, }; use cw_utils::{may_pay, maybe_addr, must_pay, nonpayable}; -use minter_types::{generate_mint_message, CollectionDetails}; +use minter_types::{ + generate_create_denom_msg, generate_mint_message, AuthDetails, CollectionDetails, + QueryMsg as BaseMinterQueryMsg, TokenDetails, +}; use omniflix_minter_factory::msg::QueryMsg::Params as QueryFactoryParams; use omniflix_minter_factory::msg::{CreateMinterMsg, ParamsResponse}; use omniflix_round_whitelist::msg::ExecuteMsg::PrivateMint; @@ -18,16 +21,19 @@ use whitelist_types::{ }; use crate::error::ContractError; -use crate::state::{COLLECTION, CONFIG, MINTABLE_TOKENS, MINTED_TOKENS, TOTAL_TOKENS_REMAINING}; +use crate::state::{ + AUTH_DETAILS, COLLECTION, CONFIG, MINTABLE_TOKENS, MINTED_TOKENS, TOKEN_DETAILS, + TOTAL_TOKENS_REMAINING, +}; use crate::utils::{ collect_mintable_tokens, generate_tokens, randomize_token_list, return_random_token, }; -use minter_types::{Config, QueryMsg, Token, UserDetails}; -use pauser::PauseState; +use minter_types::{Config, Token, UserDetails}; +use pauser::{PauseState, PAUSED_KEY, PAUSERS_KEY}; use cw2::set_contract_version; use omniflix_std::types::omniflix::onft::v1beta1::{ - Collection, MsgCreateDenom, MsgPurgeDenom, MsgUpdateDenom, OnftQuerier, WeightedAddress, + MsgPurgeDenom, MsgUpdateDenom, OnftQuerier, WeightedAddress, }; // version info for migration info @@ -46,9 +52,6 @@ const CREATION_FEE: Uint128 = Uint128::new(100_000_000); #[cfg(test)] const CREATION_FEE_DENOM: &str = "uflix"; -const PAUSED_KEY: &str = "paused"; -const PAUSERS_KEY: &str = "pausers"; - #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, @@ -79,17 +82,24 @@ pub fn instantiate( } else { CREATION_FEE_DENOM.to_string() }; + let amount = must_pay(&info, &creation_fee_denom)?; // Exact amount must be paid if amount != creation_fee_amount { return Err(ContractError::InvalidCreationFee { - expected: amount, - sent: amount, + expected: [Coin { + denom: creation_fee_denom, + amount: creation_fee_amount, + }] + .to_vec(), + sent: info.funds, }); } // Check if per address limit is 0 - if msg.init.per_address_limit == 0 { - return Err(ContractError::PerAddressLimitZero {}); + if let Some(per_address_limit) = msg.init.per_address_limit { + if per_address_limit == 0 { + return Err(ContractError::PerAddressLimitZero {}); + } } // Check num_tokens if msg.init.num_tokens == 0 { @@ -107,7 +117,7 @@ pub fn instantiate( } // Check royalty ratio we expect decimal number - let royalty_ratio = Decimal::from_str(&msg.init.royalty_ratio)?; + let royalty_ratio = msg.token_details.royalty_ratio; if royalty_ratio < Decimal::zero() || royalty_ratio > Decimal::one() { return Err(ContractError::InvalidRoyaltyRatio {}); } @@ -126,43 +136,36 @@ pub fn instantiate( if msg.init.mint_price.amount == Uint128::new(0) { return Err(ContractError::InvalidMintPrice {}); } + let admin = deps.api.addr_validate(&msg.init.admin)?; let payment_collector = - maybe_addr(deps.api, msg.init.payment_collector.clone())?.unwrap_or(info.sender.clone()); + maybe_addr(deps.api, msg.init.payment_collector.clone())?.unwrap_or(admin.clone()); + let num_tokens = msg.init.num_tokens; let config = Config { per_address_limit: msg.init.per_address_limit, - payment_collector: payment_collector.clone(), start_time: msg.init.start_time, - royalty_ratio, - admin: admin.clone(), mint_price: msg.init.mint_price, whitelist_address: maybe_addr(deps.api, msg.init.whitelist_address.clone())?, end_time: msg.init.end_time, - token_limit: Some(num_tokens), + num_tokens: Some(num_tokens), }; CONFIG.save(deps.storage, &config)?; - let collection = CollectionDetails { - name: msg.collection_details.name, - description: msg.collection_details.description, - preview_uri: msg.collection_details.preview_uri, - schema: msg.collection_details.schema, - symbol: msg.collection_details.symbol, - id: msg.collection_details.id, - extensible: msg.collection_details.extensible, - nsfw: msg.collection_details.nsfw, - base_uri: msg.collection_details.base_uri, - uri: msg.collection_details.uri, - uri_hash: msg.collection_details.uri_hash, - data: msg.collection_details.data, - token_name: msg.collection_details.token_name, - transferable: msg.collection_details.transferable, - royalty_receivers: msg.collection_details.royalty_receivers, - }; - COLLECTION.save(deps.storage, &collection)?; + AUTH_DETAILS.save( + deps.storage, + &AuthDetails { + admin: admin.clone(), + payment_collector: payment_collector.clone(), + }, + )?; + + let collection_details = msg.collection_details; + let token_details = msg.token_details; + COLLECTION.save(deps.storage, &collection_details.clone())?; + TOKEN_DETAILS.save(deps.storage, &token_details)?; // Generate tokens let tokens = generate_tokens(num_tokens); @@ -175,39 +178,25 @@ pub fn instantiate( // Save total tokens TOTAL_TOKENS_REMAINING.save(deps.storage, &num_tokens)?; + // Initialize pause state and set admin as pauser let pause_state = PauseState::new(PAUSED_KEY, PAUSERS_KEY)?; pause_state.set_pausers(deps.storage, info.sender.clone(), [admin.clone()].to_vec())?; - let nft_creation_msg: CosmosMsg = MsgCreateDenom { - description: collection.description, - id: collection.id, - name: collection.name, - preview_uri: collection.preview_uri, - schema: collection.schema, - sender: env.contract.address.into_string(), - symbol: collection.symbol, - data: collection.data, - uri: collection.uri, - uri_hash: collection.uri_hash.unwrap_or("".to_string()), - creation_fee: Some( - Coin { - denom: creation_fee_denom, - amount: creation_fee_amount, - } - .into(), - ), - royalty_receivers: collection - .royalty_receivers - .unwrap_or(vec![WeightedAddress { - address: payment_collector.clone().into_string(), - weight: Decimal::one().to_string(), - }]), - } + let collection_creation_fee = Coin { + denom: creation_fee_denom, + amount: creation_fee_amount, + }; + let collection_creation_msg: CosmosMsg = generate_create_denom_msg( + &collection_details, + env.contract.address, + collection_creation_fee, + admin, + )? .into(); let res = Response::new() - .add_message(nft_creation_msg) + .add_message(collection_creation_msg) .add_attribute("action", "instantiate"); Ok(res) @@ -237,6 +226,10 @@ pub fn execute( ExecuteMsg::UpdateWhitelistAddress { address } => { execute_update_whitelist_address(deps, env, info, address) } + ExecuteMsg::SetAdmin { admin } => execute_set_admin(deps, env, info, admin), + ExecuteMsg::SetPaymentCollector { payment_collector } => { + execute_set_payment_collector(deps, env, info, payment_collector) + } ExecuteMsg::Pause {} => execute_pause(deps, env, info), ExecuteMsg::Unpause {} => execute_unpause(deps, env, info), ExecuteMsg::SetPausers { pausers } => execute_set_pausers(deps, env, info, pausers), @@ -244,10 +237,10 @@ pub fn execute( execute_update_royalty_receivers(deps, env, info, receivers) } ExecuteMsg::UpdateDenom { - name, + collection_name, description, preview_uri, - } => execute_update_denom(deps, env, info, name, description, preview_uri), + } => execute_update_denom(deps, env, info, collection_name, description, preview_uri), ExecuteMsg::PurgeDenom {} => execute_purge_denom(deps, env, info), } } @@ -258,6 +251,7 @@ pub fn execute_mint(deps: DepsMut, env: Env, info: MessageInfo) -> Result Result config.per_address_limit { - return Err(ContractError::AddressReachedMintLimit {}); + if let Some(per_address_limit) = config.per_address_limit { + if user_details.public_mint_count > per_address_limit { + return Err(ContractError::AddressReachedMintLimit {}); + } } } // Increment total minted count @@ -347,8 +343,9 @@ pub fn execute_mint(deps: DepsMut, env: Env, info: MessageInfo) -> Result Result Result { // Check if sender is admin - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // We technicaly cant burn tokens because they are not minted yet @@ -498,26 +495,23 @@ pub fn execute_burn_remaining_tokens( pub fn execute_update_royalty_ratio( deps: DepsMut, - env: Env, + _env: Env, info: MessageInfo, ratio: String, ) -> Result { // Check if sender is admin - let mut config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } - // Check if trading has started - if env.block.time > config.start_time { - return Err(ContractError::MintingAlreadyStarted {}); - } + let ratio = Decimal::from_str(&ratio)?; // Check if ratio is decimal number if ratio < Decimal::zero() || ratio > Decimal::one() { return Err(ContractError::InvalidRoyaltyRatio {}); } - config.royalty_ratio = ratio; - - CONFIG.save(deps.storage, &config)?; + let mut token_details = TOKEN_DETAILS.load(deps.storage)?; + token_details.royalty_ratio = ratio; + TOKEN_DETAILS.save(deps.storage, &token_details)?; let res = Response::new() .add_attribute("action", "update_royalty_ratio") @@ -525,6 +519,48 @@ pub fn execute_update_royalty_ratio( Ok(res) } +pub fn execute_set_admin( + deps: DepsMut, + _env: Env, + info: MessageInfo, + admin: String, +) -> Result { + // Check if sender is admin + let mut auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { + return Err(ContractError::Unauthorized {}); + } + let new_admin = deps.api.addr_validate(&admin)?; + auth_details.admin = new_admin.clone(); + AUTH_DETAILS.save(deps.storage, &auth_details)?; + + let res = Response::new() + .add_attribute("action", "set_admin") + .add_attribute("admin", admin.to_string()); + Ok(res) +} + +pub fn execute_set_payment_collector( + deps: DepsMut, + _env: Env, + info: MessageInfo, + payment_collector: String, +) -> Result { + // Check if sender is admin + let mut auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { + return Err(ContractError::Unauthorized {}); + } + let new_payment_collector = deps.api.addr_validate(&payment_collector)?; + auth_details.payment_collector = new_payment_collector.clone(); + AUTH_DETAILS.save(deps.storage, &auth_details)?; + + let res = Response::new() + .add_attribute("action", "set_payment_collector") + .add_attribute("payment_collector", payment_collector.to_string()); + Ok(res) +} + pub fn execute_update_mint_price( deps: DepsMut, _env: Env, @@ -533,7 +569,8 @@ pub fn execute_update_mint_price( ) -> Result { // Check if sender is admin let mut config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // Check if mint price is valid @@ -557,9 +594,9 @@ pub fn execute_randomize_list( info: MessageInfo, ) -> Result { // Check if sender is admin - let config = CONFIG.load(deps.storage)?; + let auth_details = AUTH_DETAILS.load(deps.storage)?; // This should be available for everyone but then this could be abused - if info.sender != config.admin { + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // Collect mintable tokens @@ -589,7 +626,8 @@ pub fn execute_update_whitelist_address( ) -> Result { // Check if sender is admin let mut config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } let whitelist_address = config.whitelist_address.clone(); @@ -671,8 +709,8 @@ pub fn execute_update_royalty_receivers( ) -> Result { // Check if sender is admin let mut collection = COLLECTION.load(deps.storage)?; - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } collection.royalty_receivers = Some(receivers.clone()); @@ -683,9 +721,9 @@ pub fn execute_update_royalty_receivers( sender: env.contract.address.into_string(), royalty_receivers: receivers, id: collection.id, - description: collection.description, - name: collection.name, - preview_uri: collection.preview_uri, + description: "[do-not-modify]".to_string(), + name: "[do-not-modify]".to_string(), + preview_uri: "[do-not-modify]".to_string(), } .into(); @@ -699,44 +737,31 @@ pub fn execute_update_denom( deps: DepsMut, env: Env, info: MessageInfo, - name: Option, + collection_name: Option, description: Option, preview_uri: Option, ) -> Result { // Check if sender is admin let mut collection = COLLECTION.load(deps.storage)?; - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } - let onft_querier = OnftQuerier::new(&deps.querier); - let minted_nfties_res = onft_querier.collection(collection.clone().id, None)?; - let minted_nfties = minted_nfties_res - .collection - .unwrap_or(Collection::default()) - .onfts; - if !minted_nfties.is_empty() { - // If there is any nft minted for the collection update denoms should not work - return Err(ContractError::MintingAlreadyStarted {}); - } - collection.name = name.clone().unwrap_or(collection.name); - collection.description = description.clone().unwrap_or(collection.description); - collection.preview_uri = preview_uri.clone().unwrap_or(collection.preview_uri); + collection.collection_name = collection_name + .clone() + .unwrap_or(collection.collection_name); + collection.description = description.clone(); + collection.preview_uri = preview_uri.clone(); COLLECTION.save(deps.storage, &collection)?; let update_msg: CosmosMsg = MsgUpdateDenom { sender: env.contract.address.into_string(), id: collection.id, - description: description.unwrap_or(collection.description), - name: name.unwrap_or(collection.name), - preview_uri: preview_uri.unwrap_or(collection.preview_uri), - royalty_receivers: collection - .royalty_receivers - .unwrap_or(vec![WeightedAddress { - address: config.payment_collector.into_string(), - weight: Decimal::one().to_string(), - }]), + description: description.unwrap_or("[do-not-modify]".to_string()), + name: collection_name.unwrap_or("[do-not-modify]".to_string()), + preview_uri: preview_uri.unwrap_or("[do-not-modify]".to_string()), + royalty_receivers: [].to_vec(), } .into(); @@ -752,20 +777,10 @@ fn execute_purge_denom( ) -> Result { // Check if sender is admin let collection = COLLECTION.load(deps.storage)?; - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } - let onft_querier = OnftQuerier::new(&deps.querier); - let minted_nfties_res = onft_querier.collection(collection.clone().id, None)?; - let minted_nfties = minted_nfties_res - .collection - .unwrap_or(Collection::default()) - .onfts; - if !minted_nfties.is_empty() { - // If there is any nft minted for the collection update denoms should not work - return Err(ContractError::MintingAlreadyStarted {}); - } let purge_msg: CosmosMsg = MsgPurgeDenom { sender: env.contract.address.into_string(), id: collection.id, @@ -780,17 +795,32 @@ fn execute_purge_denom( // Implement Queries #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query( + deps: Deps, + env: Env, + msg: BaseMinterQueryMsg, +) -> StdResult { match msg { - QueryMsg::Collection {} => to_json_binary(&query_collection(deps, env)?), - QueryMsg::Config {} => to_json_binary(&query_config(deps, env)?), - QueryMsg::MintableTokens {} => to_json_binary(&query_mintable_tokens(deps, env)?), - QueryMsg::MintedTokens { address } => { + BaseMinterQueryMsg::Collection {} => to_json_binary(&query_collection(deps, env)?), + BaseMinterQueryMsg::Config {} => to_json_binary(&query_config(deps, env)?), + BaseMinterQueryMsg::MintedTokens { address } => { to_json_binary(&query_minted_tokens(deps, env, address)?) } - QueryMsg::TotalTokens {} => to_json_binary(&query_total_tokens(deps, env)?), - QueryMsg::IsPaused {} => to_json_binary(&query_is_paused(deps, env)?), - QueryMsg::Pausers {} => to_json_binary(&query_pausers(deps, env)?), + BaseMinterQueryMsg::AuthDetails {} => to_json_binary(&query_auth_details(deps, env)?), + BaseMinterQueryMsg::IsPaused {} => to_json_binary(&query_is_paused(deps, env)?), + BaseMinterQueryMsg::Pausers {} => to_json_binary(&query_pausers(deps, env)?), + BaseMinterQueryMsg::TotalMintedCount {} => { + to_json_binary(&query_total_minted_count(deps, env)?) + } + BaseMinterQueryMsg::TokenDetails {} => to_json_binary(&query_token_details(deps, env)?), + BaseMinterQueryMsg::Extension(ext) => match ext { + MinterExtensionQueryMsg::MintableTokens {} => { + to_json_binary(&query_mintable_tokens(deps, env)?) + } + MinterExtensionQueryMsg::TotalTokensRemaining {} => { + to_json_binary(&query_total_tokens(deps, env)?) + } + }, } } @@ -798,6 +828,10 @@ fn query_collection(deps: Deps, _env: Env) -> Result Result { + let token_details = TOKEN_DETAILS.load(deps.storage)?; + Ok(token_details) +} fn query_config(deps: Deps, _env: Env) -> Result { let config = CONFIG.load(deps.storage)?; @@ -841,3 +875,12 @@ fn query_pausers(deps: Deps, _env: Env) -> Result, ContractError> { let pausers = pause_state.pausers.load(deps.storage).unwrap_or(vec![]); Ok(pausers) } +fn query_total_minted_count(deps: Deps, _env: Env) -> Result { + let config = CONFIG.load(deps.storage)?; + let total_tokens = config.num_tokens.unwrap_or(0); + Ok(total_tokens - TOTAL_TOKENS_REMAINING.load(deps.storage)?) +} +fn query_auth_details(deps: Deps, _env: Env) -> Result { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + Ok(auth_details) +} diff --git a/contracts/minters/minter/src/error.rs b/contracts/minters/minter/src/error.rs index 4a96c3b..dd80ec8 100644 --- a/contracts/minters/minter/src/error.rs +++ b/contracts/minters/minter/src/error.rs @@ -1,6 +1,8 @@ use std::convert::Infallible; -use cosmwasm_std::{CheckedFromRatioError, ConversionOverflowError, StdError, Timestamp, Uint128}; +use cosmwasm_std::{ + CheckedFromRatioError, Coin, ConversionOverflowError, StdError, Timestamp, Uint128, +}; use cw_utils::PaymentError; use pauser::PauseError; use thiserror::Error; @@ -26,7 +28,10 @@ pub enum ContractError { DivideByZero {}, #[error("Invalid creation fee")] - InvalidCreationFee { expected: Uint128, sent: Uint128 }, + InvalidCreationFee { + expected: Vec, + sent: Vec, + }, #[error("Minting has not started yet")] MintingNotStarted { diff --git a/contracts/minters/minter/src/msg.rs b/contracts/minters/minter/src/msg.rs index 6288ab8..b5d4326 100644 --- a/contracts/minters/minter/src/msg.rs +++ b/contracts/minters/minter/src/msg.rs @@ -1,5 +1,6 @@ -use cosmwasm_schema::cw_serde; +use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Coin; +use minter_types::Token; use omniflix_std::types::omniflix::onft::v1beta1::WeightedAddress; #[cw_serde] @@ -31,9 +32,23 @@ pub enum ExecuteMsg { receivers: Vec, }, UpdateDenom { - name: Option, + collection_name: Option, description: Option, preview_uri: Option, }, PurgeDenom {}, + SetAdmin { + admin: String, + }, + SetPaymentCollector { + payment_collector: String, + }, +} +#[cw_serde] +#[derive(QueryResponses)] +pub enum MinterExtensionQueryMsg { + #[returns(Vec)] + MintableTokens {}, + #[returns(u32)] + TotalTokensRemaining {}, } diff --git a/contracts/minters/minter/src/state.rs b/contracts/minters/minter/src/state.rs index a66a464..916cf10 100644 --- a/contracts/minters/minter/src/state.rs +++ b/contracts/minters/minter/src/state.rs @@ -3,13 +3,15 @@ use std::u32; use cosmwasm_std::Addr; use cw_storage_plus::{Item, Map}; -use minter_types::{CollectionDetails, Config, Token, UserDetails}; +use minter_types::{AuthDetails, CollectionDetails, Config, Token, TokenDetails, UserDetails}; pub const CONFIG: Item = Item::new("config"); pub const COLLECTION: Item = Item::new("collection"); +pub const TOKEN_DETAILS: Item = Item::new("token_details"); // Index of mintable tokens and denom ids pub const MINTABLE_TOKENS: Map = Map::new("mintable_tokens"); // Total number of tokens pub const TOTAL_TOKENS_REMAINING: Item = Item::new("total_tokens_remaining"); // Address and number of tokens minted pub const MINTED_TOKENS: Map = Map::new("minted_tokens"); +pub const AUTH_DETAILS: Item = Item::new("auth_details"); diff --git a/contracts/minters/minter/ts/OmniflixMinter.client.ts b/contracts/minters/minter/ts/OmniflixMinter.client.ts deleted file mode 100644 index 1c38836..0000000 --- a/contracts/minters/minter/ts/OmniflixMinter.client.ts +++ /dev/null @@ -1,161 +0,0 @@ -/** -* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ - -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; -import { StdFee } from "@cosmjs/amino"; -import { Uint128, Timestamp, Uint64, InstantiateMsg, CollectionDetails, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Coin, ArrayOfToken, Token, UserDetails, Uint32 } from "./OmniflixMinter.types"; -export interface OmniflixMinterReadOnlyInterface { - contractAddress: string; - collection: () => Promise; - config: () => Promise; - mintableTokens: () => Promise; - mintedTokens: ({ - address - }: { - address: string; - }) => Promise; - totalTokens: () => Promise; -} -export class OmniflixMinterQueryClient implements OmniflixMinterReadOnlyInterface { - client: CosmWasmClient; - contractAddress: string; - - constructor(client: CosmWasmClient, contractAddress: string) { - this.client = client; - this.contractAddress = contractAddress; - this.collection = this.collection.bind(this); - this.config = this.config.bind(this); - this.mintableTokens = this.mintableTokens.bind(this); - this.mintedTokens = this.mintedTokens.bind(this); - this.totalTokens = this.totalTokens.bind(this); - } - - collection = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - collection: {} - }); - }; - config = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - config: {} - }); - }; - mintableTokens = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - mintable_tokens: {} - }); - }; - mintedTokens = async ({ - address - }: { - address: string; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - minted_tokens: { - address - } - }); - }; - totalTokens = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - total_tokens: {} - }); - }; -} -export interface OmniflixMinterInterface extends OmniflixMinterReadOnlyInterface { - contractAddress: string; - sender: string; - mint: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - mintAdmin: ({ - denomId, - recipient - }: { - denomId?: string; - recipient: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - burnRemainingTokens: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateRoyaltyRatio: ({ - ratio - }: { - ratio: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateMintPrice: ({ - mintPrice - }: { - mintPrice: Uint128; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - randomizeList: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; -} -export class OmniflixMinterClient extends OmniflixMinterQueryClient implements OmniflixMinterInterface { - client: SigningCosmWasmClient; - sender: string; - contractAddress: string; - - constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { - super(client, contractAddress); - this.client = client; - this.sender = sender; - this.contractAddress = contractAddress; - this.mint = this.mint.bind(this); - this.mintAdmin = this.mintAdmin.bind(this); - this.burnRemainingTokens = this.burnRemainingTokens.bind(this); - this.updateRoyaltyRatio = this.updateRoyaltyRatio.bind(this); - this.updateMintPrice = this.updateMintPrice.bind(this); - this.randomizeList = this.randomizeList.bind(this); - } - - mint = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - mint: {} - }, fee, memo, _funds); - }; - mintAdmin = async ({ - denomId, - recipient - }: { - denomId?: string; - recipient: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - mint_admin: { - denom_id: denomId, - recipient - } - }, fee, memo, _funds); - }; - burnRemainingTokens = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - burn_remaining_tokens: {} - }, fee, memo, _funds); - }; - updateRoyaltyRatio = async ({ - ratio - }: { - ratio: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_royalty_ratio: { - ratio - } - }, fee, memo, _funds); - }; - updateMintPrice = async ({ - mintPrice - }: { - mintPrice: Uint128; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_mint_price: { - mint_price: mintPrice - } - }, fee, memo, _funds); - }; - randomizeList = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - randomize_list: {} - }, fee, memo, _funds); - }; -} \ No newline at end of file diff --git a/contracts/minters/minter/ts/OmniflixMinter.types.ts b/contracts/minters/minter/ts/OmniflixMinter.types.ts deleted file mode 100644 index 1375cd8..0000000 --- a/contracts/minters/minter/ts/OmniflixMinter.types.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** -* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ - -export type Uint128 = string; -export type Timestamp = Uint64; -export type Uint64 = string; -export interface InstantiateMsg { - admin?: string | null; - collection_details: CollectionDetails; - mint_denom: string; - mint_price: Uint128; - payment_collector?: string | null; - per_address_limit: number; - royalty_ratio: string; - start_time: Timestamp; - end_time?: Timestamp | null; - whitelist_address?: string | null; -} -export interface CollectionDetails { - base_uri: string; - data: string; - description: string; - extensible: boolean; - id: string; - name: string; - nsfw: boolean; - num_tokens: number; - preview_uri: string; - schema: string; - symbol: string; - uri: string; - uri_hash: string; -} -export type ExecuteMsg = { - mint: {}; -} | { - mint_admin: { - denom_id?: string | null; - recipient: string; - }; -} | { - burn_remaining_tokens: {}; -} | { - update_royalty_ratio: { - ratio: string; - }; -} | { - update_mint_price: { - mint_price: Uint128; - }; -} | { - randomize_list: {}; -}; -export type QueryMsg = { - collection: {}; -} | { - config: {}; -} | { - mintable_tokens: {}; -} | { - minted_tokens: { - address: string; - }; -} | { - total_tokens: {}; -}; -export type Addr = string; -export type Decimal = string; -export interface Config { - admin: Addr; - mint_price: Coin; - payment_collector: Addr; - per_address_limit: number; - royalty_ratio: Decimal; - start_time: Timestamp; - whitelist_address?: Addr | null; -} -export interface Coin { - amount: Uint128; - denom: string; - [k: string]: unknown; -} -export type ArrayOfToken = Token[]; -export interface Token { - token_id: string; -} -export interface UserDetails { - minted_tokens: Token[]; - total_minted_count: number; -} -export type Uint32 = number; \ No newline at end of file diff --git a/contracts/minters/multi-mint-oem/.cargo/config b/contracts/minters/multi-mint-oem/.cargo/config new file mode 100644 index 0000000..5b8deaa --- /dev/null +++ b/contracts/minters/multi-mint-oem/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run schema" diff --git a/contracts/minters/multi-mint-oem/Cargo.toml b/contracts/minters/multi-mint-oem/Cargo.toml index 738f621..91a42a6 100644 --- a/contracts/minters/multi-mint-oem/Cargo.toml +++ b/contracts/minters/multi-mint-oem/Cargo.toml @@ -54,7 +54,6 @@ serde = { workspace = true } minter-types={ workspace = true } sha2 = { version = "0.10.2", default-features = false } whitelist-types ={ workspace = true } -multi-mint-open-edition-minter-types = {workspace=true} omniflix-open-edition-minter-factory = {path = "../../factories/open-edition-minter-factory"} omniflix-round-whitelist = {path="../../whitelists/round-whitelist"} pauser = { workspace = true } diff --git a/contracts/minters/multi-mint-oem/README.md b/contracts/minters/multi-mint-oem/README.md new file mode 100644 index 0000000..f62b454 --- /dev/null +++ b/contracts/minters/multi-mint-oem/README.md @@ -0,0 +1,37 @@ +## Multi-Minter + +Multi minter contract is a Open edition minter contract with configurable token parameters called "drop". + +#### Drop + +Drop is a configuration for a set of tokens. It includes the following parameters: + +- `token_details`: Token details such as name, symbol, description, and preview_uri. +- `price`: The price of the token. +- `start_time`: The start time of the trading. +- `end_time`: The end time of the trading. +- `num_tokens`: The maximum supply of the token. +- `per_address_limit` : The maximum number of tokens that can be minted by a single address. + +#### Instantiate + +Similar with the Minter contract, the creator should send Collection details along with trading information such as price, denomination, and trading start time. Factory contract will create a new MultiMinter contract and initialize it with the given parameters. Upon creation, First drop will be created with the given parameters. + +### NewDrop + +- This function allows the creator to create a new drop with the given parameters. The creator can create multiple drops with different parameters. Active drop will be changed to the new drop. But the previous drop will be still active for minting. + - `token_details`: Token details such as name, symbol, description, and preview_uri. + - `price`: The price of the token. + - `start_time`: The start time of the trading. + - `end_time`: The end time of the trading. + - `num_tokens`: The maximum supply of the token. + - `per_address_limit` : The maximum number of tokens that can be minted by a single address. + +### Mint + +- There are two types of minting: `Mint{}` and `AdminMint{}` +- `Mint{}`: This option is for users who want to own the NFT, and they need to pay the active price at that time. + - `drop_id`: The id of the drop to mint. OPTIONAL. If not provided, it will mint the active drop. +- `AdminMint{}`: As the name suggests, this option is specifically for admin to mint a token. Admins have the ability to determine the recipient. Admins are not subject to address limits or private mint checks, and this action does not require a payment. + - `drop_id`: The id of the drop to mint. OPTIONAL. If not provided, it will mint the active drop. + - `recipient`: The address of the recipient. \ No newline at end of file diff --git a/contracts/minters/multi-mint-oem/schema/omniflix-multi-mint-open-edition-minter.json b/contracts/minters/multi-mint-oem/schema/omniflix-multi-mint-open-edition-minter.json index 90773b9..c617d57 100644 --- a/contracts/minters/multi-mint-oem/schema/omniflix-multi-mint-open-edition-minter.json +++ b/contracts/minters/multi-mint-oem/schema/omniflix-multi-mint-open-edition-minter.json @@ -8,7 +8,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -16,6 +17,9 @@ }, "init": { "$ref": "#/definitions/OpenEditionMinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false, @@ -38,45 +42,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -88,33 +81,38 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "OpenEditionMinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -134,6 +132,14 @@ "mint_price": { "$ref": "#/definitions/Coin" }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, "payment_collector": { "type": [ "string", @@ -141,17 +147,6 @@ ] }, "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "royalty_ratio": { - "type": "string" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { "type": [ "integer", "null" @@ -159,6 +154,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "type": [ "string", @@ -176,6 +174,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -403,103 +451,15 @@ "new_drop": { "type": "object", "required": [ - "mint_price", - "per_address_limit", - "start_time", - "token_name" + "new_config", + "new_token_details" ], "properties": { - "base_uri": { - "type": [ - "string", - "null" - ] - }, - "data": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "end_time": { - "anyOf": [ - { - "$ref": "#/definitions/Timestamp" - }, - { - "type": "null" - } - ] - }, - "extensible": { - "type": [ - "boolean", - "null" - ] - }, - "mint_price": { - "$ref": "#/definitions/Coin" - }, - "nsfw": { - "type": [ - "boolean", - "null" - ] - }, - "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "preview_uri": { - "type": [ - "string", - "null" - ] - }, - "royalty_ratio": { - "type": [ - "string", - "null" - ] - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": [ - "boolean", - "null" - ] - }, - "uri_hash": { - "type": [ - "string", - "null" - ] + "new_config": { + "$ref": "#/definitions/Config" }, - "whitelist_address": { - "type": [ - "string", - "null" - ] + "new_token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false @@ -576,9 +536,55 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_admin" + ], + "properties": { + "set_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_payment_collector" + ], + "properties": { + "set_payment_collector": { + "type": "object", + "required": [ + "payment_collector" + ], + "properties": { + "payment_collector": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } ], "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -594,37 +600,143 @@ } } }, - "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" - } - ] - }, - "Uint128": { - "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", - "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" - }, - "WeightedAddress": { + "Config": { "type": "object", "required": [ - "address", - "weight" + "mint_price", + "start_time" ], "properties": { - "address": { - "type": "string" + "end_time": { + "anyOf": [ + { + "$ref": "#/definitions/Timestamp" + }, + { + "type": "null" + } + ] }, - "weight": { - "type": "string" - } - } - } + "mint_price": { + "$ref": "#/definitions/Coin" + }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "per_address_limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, + "whitelist_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "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" + } + ] + }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "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" + }, + "WeightedAddress": { + "type": "object", + "required": [ + "address", + "weight" + ], + "properties": { + "address": { + "type": "string" + }, + "weight": { + "type": "string" + } + } + } } }, "query": { @@ -639,16 +751,6 @@ "properties": { "collection": { "type": "object", - "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -657,21 +759,11 @@ { "type": "object", "required": [ - "config" + "token_details" ], "properties": { - "config": { + "token_details": { "type": "object", - "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -680,27 +772,11 @@ { "type": "object", "required": [ - "minted_tokens" + "auth_details" ], "properties": { - "minted_tokens": { + "auth_details": { "type": "object", - "required": [ - "address" - ], - "properties": { - "address": { - "type": "string" - }, - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -709,21 +785,11 @@ { "type": "object", "required": [ - "total_minted_count" + "config" ], "properties": { - "total_minted_count": { + "config": { "type": "object", - "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -732,19 +798,17 @@ { "type": "object", "required": [ - "tokens_remaining" + "minted_tokens" ], "properties": { - "tokens_remaining": { + "minted_tokens": { "type": "object", + "required": [ + "address" + ], "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 + "address": { + "type": "string" } }, "additionalProperties": false @@ -781,65 +845,243 @@ { "type": "object", "required": [ - "current_drop_number" + "extension" ], "properties": { - "current_drop_number": { + "extension": { + "$ref": "#/definitions/QueryMsgExtension" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_minted_count" + ], + "properties": { + "total_minted_count": { "type": "object", "additionalProperties": false } }, "additionalProperties": false } - ] + ], + "definitions": { + "QueryMsgExtension": { + "oneOf": [ + { + "type": "object", + "required": [ + "collection" + ], + "properties": { + "collection": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "token_details" + ], + "properties": { + "token_details": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minted_tokens" + ], + "properties": { + "minted_tokens": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + }, + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "tokens_remaining" + ], + "properties": { + "tokens_remaining": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "current_drop_number" + ], + "properties": { + "current_drop_number": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_drops" + ], + "properties": { + "all_drops": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } }, "migrate": null, "sudo": null, "responses": { + "auth_details": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AuthDetails", + "type": "object", + "required": [ + "admin", + "payment_collector" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "payment_collector": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + }, "collection": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "CollectionDetails", "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -851,22 +1093,25 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, @@ -893,17 +1138,10 @@ "title": "Config", "type": "object", "required": [ - "admin", "mint_price", - "payment_collector", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { - "admin": { - "$ref": "#/definitions/Addr" - }, "end_time": { "anyOf": [ { @@ -917,21 +1155,15 @@ "mint_price": { "$ref": "#/definitions/Coin" }, - "payment_collector": { - "$ref": "#/definitions/Addr" - }, - "per_address_limit": { - "type": "integer", + "num_tokens": { + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "$ref": "#/definitions/Decimal" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { + "per_address_limit": { "type": [ "integer", "null" @@ -939,6 +1171,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "anyOf": [ { @@ -971,10 +1206,6 @@ } } }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "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": [ @@ -993,7 +1224,7 @@ } } }, - "current_drop_number": { + "extension": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "uint32", "type": "integer", @@ -1062,12 +1293,63 @@ } } }, - "tokens_remaining": { + "token_details": { "$schema": "http://json-schema.org/draft-07/schema#", - "title": "uint32", - "type": "integer", - "format": "uint32", - "minimum": 0.0 + "title": "TokenDetails", + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } }, "total_minted_count": { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/contracts/minters/multi-mint-oem/schema/raw/execute.json b/contracts/minters/multi-mint-oem/schema/raw/execute.json index 44bc2e8..7a50bc1 100644 --- a/contracts/minters/multi-mint-oem/schema/raw/execute.json +++ b/contracts/minters/multi-mint-oem/schema/raw/execute.json @@ -200,103 +200,15 @@ "new_drop": { "type": "object", "required": [ - "mint_price", - "per_address_limit", - "start_time", - "token_name" + "new_config", + "new_token_details" ], "properties": { - "base_uri": { - "type": [ - "string", - "null" - ] - }, - "data": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "end_time": { - "anyOf": [ - { - "$ref": "#/definitions/Timestamp" - }, - { - "type": "null" - } - ] - }, - "extensible": { - "type": [ - "boolean", - "null" - ] - }, - "mint_price": { - "$ref": "#/definitions/Coin" - }, - "nsfw": { - "type": [ - "boolean", - "null" - ] + "new_config": { + "$ref": "#/definitions/Config" }, - "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "preview_uri": { - "type": [ - "string", - "null" - ] - }, - "royalty_ratio": { - "type": [ - "string", - "null" - ] - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": [ - "boolean", - "null" - ] - }, - "uri_hash": { - "type": [ - "string", - "null" - ] - }, - "whitelist_address": { - "type": [ - "string", - "null" - ] + "new_token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false @@ -373,9 +285,55 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_admin" + ], + "properties": { + "set_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_payment_collector" + ], + "properties": { + "set_payment_collector": { + "type": "object", + "required": [ + "payment_collector" + ], + "properties": { + "payment_collector": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } ], "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, "Coin": { "type": "object", "required": [ @@ -391,6 +349,62 @@ } } }, + "Config": { + "type": "object", + "required": [ + "mint_price", + "start_time" + ], + "properties": { + "end_time": { + "anyOf": [ + { + "$ref": "#/definitions/Timestamp" + }, + { + "type": "null" + } + ] + }, + "mint_price": { + "$ref": "#/definitions/Coin" + }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "per_address_limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, + "whitelist_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "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": [ @@ -399,6 +413,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/minters/multi-mint-oem/schema/raw/instantiate.json b/contracts/minters/multi-mint-oem/schema/raw/instantiate.json index 1c48236..7d6ce3f 100644 --- a/contracts/minters/multi-mint-oem/schema/raw/instantiate.json +++ b/contracts/minters/multi-mint-oem/schema/raw/instantiate.json @@ -4,7 +4,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -12,6 +13,9 @@ }, "init": { "$ref": "#/definitions/OpenEditionMinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false, @@ -34,45 +38,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -84,33 +77,38 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "OpenEditionMinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -130,6 +128,14 @@ "mint_price": { "$ref": "#/definitions/Coin" }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, "payment_collector": { "type": [ "string", @@ -137,17 +143,6 @@ ] }, "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "royalty_ratio": { - "type": "string" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { "type": [ "integer", "null" @@ -155,6 +150,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "type": [ "string", @@ -172,6 +170,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/minters/multi-mint-oem/schema/raw/query.json b/contracts/minters/multi-mint-oem/schema/raw/query.json index 4fc8833..b0b882c 100644 --- a/contracts/minters/multi-mint-oem/schema/raw/query.json +++ b/contracts/minters/multi-mint-oem/schema/raw/query.json @@ -10,16 +10,6 @@ "properties": { "collection": { "type": "object", - "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -28,21 +18,11 @@ { "type": "object", "required": [ - "config" + "token_details" ], "properties": { - "config": { + "token_details": { "type": "object", - "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -51,27 +31,11 @@ { "type": "object", "required": [ - "minted_tokens" + "auth_details" ], "properties": { - "minted_tokens": { + "auth_details": { "type": "object", - "required": [ - "address" - ], - "properties": { - "address": { - "type": "string" - }, - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -80,21 +44,11 @@ { "type": "object", "required": [ - "total_minted_count" + "config" ], "properties": { - "total_minted_count": { + "config": { "type": "object", - "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 - } - }, "additionalProperties": false } }, @@ -103,19 +57,17 @@ { "type": "object", "required": [ - "tokens_remaining" + "minted_tokens" ], "properties": { - "tokens_remaining": { + "minted_tokens": { "type": "object", + "required": [ + "address" + ], "properties": { - "drop_id": { - "type": [ - "integer", - "null" - ], - "format": "uint32", - "minimum": 0.0 + "address": { + "type": "string" } }, "additionalProperties": false @@ -152,15 +104,180 @@ { "type": "object", "required": [ - "current_drop_number" + "extension" ], "properties": { - "current_drop_number": { + "extension": { + "$ref": "#/definitions/QueryMsgExtension" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_minted_count" + ], + "properties": { + "total_minted_count": { "type": "object", "additionalProperties": false } }, "additionalProperties": false } - ] + ], + "definitions": { + "QueryMsgExtension": { + "oneOf": [ + { + "type": "object", + "required": [ + "collection" + ], + "properties": { + "collection": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "token_details" + ], + "properties": { + "token_details": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minted_tokens" + ], + "properties": { + "minted_tokens": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + }, + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "tokens_remaining" + ], + "properties": { + "tokens_remaining": { + "type": "object", + "properties": { + "drop_id": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "current_drop_number" + ], + "properties": { + "current_drop_number": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_drops" + ], + "properties": { + "all_drops": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } } diff --git a/contracts/minters/multi-mint-oem/schema/raw/response_to_auth_details.json b/contracts/minters/multi-mint-oem/schema/raw/response_to_auth_details.json new file mode 100644 index 0000000..aad6fe8 --- /dev/null +++ b/contracts/minters/multi-mint-oem/schema/raw/response_to_auth_details.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AuthDetails", + "type": "object", + "required": [ + "admin", + "payment_collector" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "payment_collector": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/contracts/minters/multi-mint-oem/schema/raw/response_to_collection.json b/contracts/minters/multi-mint-oem/schema/raw/response_to_collection.json index d8a9fd7..8a9414c 100644 --- a/contracts/minters/multi-mint-oem/schema/raw/response_to_collection.json +++ b/contracts/minters/multi-mint-oem/schema/raw/response_to_collection.json @@ -3,45 +3,34 @@ "title": "CollectionDetails", "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -53,22 +42,25 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, diff --git a/contracts/minters/multi-mint-oem/schema/raw/response_to_config.json b/contracts/minters/multi-mint-oem/schema/raw/response_to_config.json index 73907a6..0a3efbd 100644 --- a/contracts/minters/multi-mint-oem/schema/raw/response_to_config.json +++ b/contracts/minters/multi-mint-oem/schema/raw/response_to_config.json @@ -3,17 +3,10 @@ "title": "Config", "type": "object", "required": [ - "admin", "mint_price", - "payment_collector", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { - "admin": { - "$ref": "#/definitions/Addr" - }, "end_time": { "anyOf": [ { @@ -27,21 +20,15 @@ "mint_price": { "$ref": "#/definitions/Coin" }, - "payment_collector": { - "$ref": "#/definitions/Addr" - }, - "per_address_limit": { - "type": "integer", + "num_tokens": { + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "$ref": "#/definitions/Decimal" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { + "per_address_limit": { "type": [ "integer", "null" @@ -49,6 +36,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "anyOf": [ { @@ -81,10 +71,6 @@ } } }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "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": [ diff --git a/contracts/minters/multi-mint-oem/schema/raw/response_to_extension.json b/contracts/minters/multi-mint-oem/schema/raw/response_to_extension.json new file mode 100644 index 0000000..de85c3e --- /dev/null +++ b/contracts/minters/multi-mint-oem/schema/raw/response_to_extension.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 +} diff --git a/contracts/minters/multi-mint-oem/schema/raw/response_to_token_details.json b/contracts/minters/multi-mint-oem/schema/raw/response_to_token_details.json new file mode 100644 index 0000000..516fcb4 --- /dev/null +++ b/contracts/minters/multi-mint-oem/schema/raw/response_to_token_details.json @@ -0,0 +1,58 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokenDetails", + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } +} diff --git a/contracts/minters/multi-mint-oem/src/bin/schema.rs b/contracts/minters/multi-mint-oem/src/bin/schema.rs index 43ccdf6..c9a122b 100644 --- a/contracts/minters/multi-mint-oem/src/bin/schema.rs +++ b/contracts/minters/multi-mint-oem/src/bin/schema.rs @@ -1,8 +1,8 @@ use cosmwasm_schema::write_api; -use multi_mint_open_edition_minter_types::QueryMsg; +use minter_types::QueryMsg; -use omniflix_multi_mint_open_edition_minter::msg::ExecuteMsg; +use omniflix_multi_mint_open_edition_minter::msg::{ExecuteMsg, QueryMsgExtension}; use omniflix_open_edition_minter_factory::msg::OpenEditionMinterCreateMsg; @@ -10,6 +10,6 @@ fn main() { write_api! { instantiate: OpenEditionMinterCreateMsg, execute: ExecuteMsg, - query: QueryMsg, + query: QueryMsg, } } diff --git a/contracts/minters/multi-mint-oem/src/contract.rs b/contracts/minters/multi-mint-oem/src/contract.rs index 9ec13ae..fd52a67 100644 --- a/contracts/minters/multi-mint-oem/src/contract.rs +++ b/contracts/minters/multi-mint-oem/src/contract.rs @@ -1,30 +1,31 @@ -use std::str::FromStr; - -//use crate::msg::ExecuteMsg; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ to_json_binary, Addr, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, MessageInfo, - Response, StdResult, Timestamp, Uint128, WasmMsg, + Response, StdResult, Uint128, WasmMsg, }; use cw_utils::{may_pay, maybe_addr, must_pay, nonpayable}; -use minter_types::{generate_mint_message, CollectionDetails, Config, Token, UserDetails}; -use multi_mint_open_edition_minter_types::QueryMsg; -use pauser::PauseState; +use minter_types::{ + generate_create_denom_msg, generate_mint_message, AuthDetails, CollectionDetails, Config, + QueryMsg as MinterQueryMsg, Token, TokenDetails, UserDetails, +}; +use pauser::{PauseState, PAUSED_KEY, PAUSERS_KEY}; +use std::str::FromStr; use crate::error::ContractError; -use crate::msg::ExecuteMsg; +use crate::msg::{ExecuteMsg, QueryMsgExtension}; use crate::state::{ - DropParams, MintedTokens, CURRENT_DROP_ID, DROPS, LAST_MINTED_TOKEN_ID, MINTED_COUNT, - MINTED_TOKENS_KEY, + DropParams, UserMintedTokens, AUTH_DETAILS, CURRENT_DROP_ID, DROPS, DROP_MINTED_COUNT, + LAST_MINTED_TOKEN_ID, USER_MINTED_TOKENS_KEY, }; + use cw2::set_contract_version; use omniflix_open_edition_minter_factory::msg::{ OpenEditionMinterCreateMsg, ParamsResponse, QueryMsg as OpenEditionMinterFactoryQueryMsg, }; use omniflix_round_whitelist::msg::ExecuteMsg as RoundWhitelistExecuteMsg; use omniflix_std::types::omniflix::onft::v1beta1::{ - Collection, MsgCreateDenom, MsgPurgeDenom, MsgUpdateDenom, OnftQuerier, WeightedAddress, + MsgPurgeDenom, MsgUpdateDenom, OnftQuerier, WeightedAddress, }; use whitelist_types::{ check_if_address_is_member, check_if_whitelist_is_active, check_whitelist_price, @@ -46,9 +47,6 @@ const CREATION_FEE: Uint128 = Uint128::new(100_000_000); #[cfg(test)] const CREATION_FEE_DENOM: &str = "uflix"; -const PAUSED_KEY: &str = "paused"; -const PAUSERS_KEY: &str = "pausers"; - #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, @@ -81,21 +79,27 @@ pub fn instantiate( CREATION_FEE_DENOM.to_string() }; - let amount = must_pay(&info, &creation_fee_denom)?; + let amount = must_pay(&info.clone(), &creation_fee_denom)?; // Exact amount must be paid if amount != creation_fee_amount { return Err(ContractError::InvalidCreationFee { - expected: amount, - sent: amount, + expected: [Coin { + denom: creation_fee_denom, + amount: creation_fee_amount, + }] + .to_vec(), + sent: info.funds.clone(), }); } // Check if per address limit is 0 - if msg.init.per_address_limit == 0 { - return Err(ContractError::PerAddressLimitZero {}); + if let Some(per_address_limit) = msg.init.per_address_limit { + if per_address_limit == 0 { + return Err(ContractError::PerAddressLimitZero {}); + } } // Check if token limit is 0 - if let Some(token_limit) = msg.init.token_limit { - if token_limit == 0 { + if let Some(num_tokens) = msg.init.num_tokens { + if num_tokens == 0 { return Err(ContractError::InvalidNumTokens {}); } } @@ -112,7 +116,8 @@ pub fn instantiate( } // Check royalty ratio we expect decimal number - let royalty_ratio = Decimal::from_str(&msg.init.royalty_ratio)?; + let royalty_ratio = msg.token_details.royalty_ratio; + if royalty_ratio < Decimal::zero() || royalty_ratio > Decimal::one() { return Err(ContractError::InvalidRoyaltyRatio {}); } @@ -130,77 +135,49 @@ pub fn instantiate( let admin = deps.api.addr_validate(&msg.init.admin)?; let payment_collector = - maybe_addr(deps.api, msg.init.payment_collector.clone())?.unwrap_or(info.sender.clone()); + maybe_addr(deps.api, msg.init.payment_collector.clone())?.unwrap_or(admin.clone()); let config = Config { per_address_limit: msg.init.per_address_limit, - payment_collector, start_time: msg.init.start_time, - royalty_ratio, - admin: admin.clone(), mint_price: msg.init.mint_price, whitelist_address: maybe_addr(deps.api, msg.init.whitelist_address.clone())?, end_time: msg.init.end_time, - token_limit: msg.init.token_limit, + num_tokens: msg.init.num_tokens, }; // Set the pause state let pause_state = PauseState::new(PAUSED_KEY, PAUSERS_KEY)?; pause_state.set_pausers(deps.storage, info.sender.clone(), vec![admin.clone()])?; - let collection = CollectionDetails { - name: msg.collection_details.name, - description: msg.collection_details.description, - preview_uri: msg.collection_details.preview_uri, - schema: msg.collection_details.schema, - symbol: msg.collection_details.symbol, - id: msg.collection_details.id, - extensible: msg.collection_details.extensible, - nsfw: msg.collection_details.nsfw, - base_uri: msg.collection_details.base_uri, - uri: msg.collection_details.uri, - uri_hash: msg.collection_details.uri_hash, - data: msg.collection_details.data, - token_name: msg.collection_details.token_name, - transferable: msg.collection_details.transferable, - royalty_receivers: msg.collection_details.royalty_receivers, + let collection_details = msg.collection_details.clone(); + let token_details = msg.token_details.clone(); + let auth_details = AuthDetails { + admin: admin.clone(), + payment_collector: payment_collector.clone(), }; // Save the collection as drop 1 let drop_params = DropParams { config: config.clone(), - collection: collection.clone(), + collection_details: collection_details.clone(), + token_details, }; DROPS.save(deps.storage, 1, &drop_params)?; CURRENT_DROP_ID.save(deps.storage, &1)?; - MINTED_COUNT.save(deps.storage, 1, &0)?; + DROP_MINTED_COUNT.save(deps.storage, 1, &0)?; LAST_MINTED_TOKEN_ID.save(deps.storage, &0)?; - - let nft_creation_msg: CosmosMsg = MsgCreateDenom { - description: collection.description, - id: collection.id, - name: collection.name, - preview_uri: collection.preview_uri, - schema: collection.schema, - sender: env.contract.address.into_string(), - symbol: collection.symbol, - data: collection.data, - uri: collection.uri, - uri_hash: collection.uri_hash.unwrap_or("".to_string()), - creation_fee: Some( - Coin { - denom: creation_fee_denom, - amount: creation_fee_amount, - } - .into(), - ), - royalty_receivers: collection - .royalty_receivers - .unwrap_or(vec![WeightedAddress { - address: admin.clone().into_string(), - weight: Decimal::one().to_string(), - }]), - } + AUTH_DETAILS.save(deps.storage, &auth_details)?; + let nft_creation_fee = Coin { + denom: creation_fee_denom, + amount: creation_fee_amount, + }; + let nft_creation_msg: CosmosMsg = generate_create_denom_msg( + &collection_details, + env.contract.address, + nft_creation_fee, + admin, + )? .into(); let res = Response::new() @@ -235,47 +212,18 @@ pub fn execute( ExecuteMsg::UpdateWhitelistAddress { address, drop_id } => { execute_update_whitelist_address(deps, env, info, address, drop_id) } + ExecuteMsg::SetAdmin { admin } => execute_set_admin(deps, env, info, admin), + ExecuteMsg::SetPaymentCollector { payment_collector } => { + execute_set_payment_collector(deps, env, info, payment_collector) + } ExecuteMsg::Pause {} => execute_pause(deps, env, info), ExecuteMsg::Unpause {} => execute_unpause(deps, env, info), ExecuteMsg::SetPausers { pausers } => execute_set_pausers(deps, env, info, pausers), ExecuteMsg::NewDrop { - whitelist_address, - token_limit, - start_time, - end_time, - mint_price, - royalty_ratio, - token_name, - description, - base_uri, - preview_uri, - uri_hash, - transferable, - extensible, - nsfw, - data, - per_address_limit, - } => execute_new_drop( - deps, - env, - info, - whitelist_address, - token_limit, - start_time, - end_time, - mint_price, - per_address_limit, - royalty_ratio, - token_name, - description, - base_uri, - preview_uri, - uri_hash, - transferable, - extensible, - nsfw, - data, - ), + new_config, + new_token_details, + } => execute_new_drop(deps, env, info, new_config, new_token_details), + ExecuteMsg::UpdateRoyaltyReceivers { receivers } => { execute_update_royalty_receivers(deps, env, info, receivers) } @@ -302,10 +250,12 @@ pub fn execute_mint( let drop_params = DROPS.load(deps.storage, drop_id)?; let config = drop_params.config; - let collection = drop_params.collection; + let collection_details = drop_params.collection_details; + let token_details = drop_params.token_details; + let auth_details = AUTH_DETAILS.load(deps.storage)?; // Check if any token limit set and if it is reached - if let Some(token_limit) = config.token_limit { - if MINTED_COUNT.load(deps.storage, drop_id).unwrap_or(0) >= token_limit { + if let Some(num_tokens) = config.num_tokens { + if DROP_MINTED_COUNT.load(deps.storage, drop_id).unwrap_or(0) >= num_tokens { return Err(ContractError::NoTokensLeftToMint {}); } } @@ -316,9 +266,9 @@ pub fn execute_mint( return Err(ContractError::PublicMintingEnded {}); } }; - let minted_tokens = MintedTokens::new(MINTED_TOKENS_KEY); + let user_minted_tokens = UserMintedTokens::new(USER_MINTED_TOKENS_KEY); - let mut user_details = minted_tokens + let mut user_details = user_minted_tokens .load(deps.storage, drop_id, info.sender.clone()) .unwrap_or_default(); // Load and increment the minted count @@ -367,9 +317,11 @@ pub fn execute_mint( }; } else { user_details.public_mint_count += 1; - // Check if address has reached the public mint limit - if user_details.public_mint_count > config.per_address_limit { - return Err(ContractError::AddressReachedMintLimit {}); + // Check if per address limit is set and if it is reached + if let Some(per_address_limit) = config.per_address_limit { + if user_details.public_mint_count > per_address_limit { + return Err(ContractError::AddressReachedMintLimit {}); + } } } // Increment total minted count @@ -379,7 +331,7 @@ pub fn execute_mint( token_id: token_id.to_string(), }); // Save the user details - minted_tokens.save(deps.storage, drop_id, info.sender.clone(), &user_details); + user_minted_tokens.save(deps.storage, drop_id, info.sender.clone(), &user_details); // Check the payment // Can be set to zero so use may_pay @@ -392,20 +344,20 @@ pub fn execute_mint( }); } // Get the payment collector address - let payment_collector = config.payment_collector; + let payment_collector = auth_details.payment_collector; - let mut minted_count = MINTED_COUNT.load(deps.storage, drop_id)?; - minted_count += 1; - MINTED_COUNT.save(deps.storage, drop_id, &minted_count)?; + let mut drop_minted_count = DROP_MINTED_COUNT.load(deps.storage, drop_id)?; + drop_minted_count += 1; + DROP_MINTED_COUNT.save(deps.storage, drop_id, &drop_minted_count)?; let mint_msg: CosmosMsg = generate_mint_message( - &collection, - config.royalty_ratio, - &info.sender, - &env.contract.address, - true, + &collection_details, + &token_details, token_id.to_string(), - Some(minted_count.to_string()), + env.contract.address, + info.sender, + Some((drop_minted_count).to_string()), + true, ) .into(); @@ -426,7 +378,8 @@ pub fn execute_mint( .add_messages(messages) .add_attribute("action", "mint") .add_attribute("token_id", token_id.to_string()) - .add_attribute("collection_id", collection.id) + .add_attribute("drop_token_id", drop_minted_count.to_string()) + .add_attribute("collection_id", collection_details.id) .add_attribute("drop_id", drop_id.to_string()); Ok(res) @@ -445,15 +398,16 @@ pub fn execute_mint_admin( let drop_params = DROPS.load(deps.storage, drop_id)?; let config = drop_params.config; - let collection = drop_params.collection; - - // Check if sender is admin - if info.sender != config.admin { + let collection_details = drop_params.collection_details; + let token_details = drop_params.token_details; + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // Check if any token left for current drop - if let Some(token_limit) = config.token_limit { - if MINTED_COUNT.load(deps.storage, drop_id).unwrap_or(0) >= token_limit { + if let Some(num_tokens) = config.num_tokens { + if DROP_MINTED_COUNT.load(deps.storage, drop_id).unwrap_or(0) >= num_tokens { return Err(ContractError::NoTokensLeftToMint {}); } } @@ -466,37 +420,38 @@ pub fn execute_mint_admin( let pause_state = PauseState::new(PAUSED_KEY, PAUSERS_KEY)?; pause_state.error_if_paused(deps.storage)?; - let recipient = deps.api.addr_validate(&recipient)?; + let recipient = deps.api.addr_validate(&recipient)?; let last_token_id = LAST_MINTED_TOKEN_ID.load(deps.storage)?; let token_id = last_token_id + 1; - let minted_tokens = MintedTokens::new(MINTED_TOKENS_KEY); + let user_minted_tokens = UserMintedTokens::new(USER_MINTED_TOKENS_KEY); - let mut user_details = minted_tokens + let mut user_details = user_minted_tokens .load(deps.storage, drop_id, recipient.clone()) .unwrap_or_default(); - + // We are only updating these params but not checking the mint limit user_details.total_minted_count += 1; user_details.minted_tokens.push(Token { token_id: token_id.to_string(), }); // Save the user details - minted_tokens.save(deps.storage, drop_id, recipient.clone(), &user_details); + user_minted_tokens.save(deps.storage, drop_id, recipient.clone(), &user_details); // Load current drops minted count and increment it - let minted_count = MINTED_COUNT.load(deps.storage, drop_id)?; - MINTED_COUNT.save(deps.storage, drop_id, &(minted_count.clone() + 1))?; + let mut drop_minted_count = DROP_MINTED_COUNT.load(deps.storage, drop_id)?; + drop_minted_count += 1; + DROP_MINTED_COUNT.save(deps.storage, drop_id, &drop_minted_count)?; let mint_msg: CosmosMsg = generate_mint_message( - &collection, - config.royalty_ratio, - &recipient, - &env.contract.address, - true, + &collection_details, + &token_details, token_id.to_string(), - Some((minted_count + 1).to_string()), + env.contract.address, + recipient.clone(), + Some((drop_minted_count).to_string()), + true, ) .into(); @@ -504,7 +459,8 @@ pub fn execute_mint_admin( .add_message(mint_msg) .add_attribute("action", "mint") .add_attribute("token_id", token_id.to_string()) - .add_attribute("denom_id", collection.id) + .add_attribute("denom_id", collection_details.id) + .add_attribute("drop_token_id", drop_minted_count.to_string()) .add_attribute("drop_id", drop_id.to_string()); Ok(res) } @@ -518,11 +474,12 @@ pub fn execute_update_royalty_ratio( ) -> Result { let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); let mut drop_params = DROPS.load(deps.storage, drop_id)?; - + let auth_details = AUTH_DETAILS.load(deps.storage)?; // Check if sender is admin - if info.sender != drop_params.config.admin { + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } + // Check if ratio is decimal number let ratio = Decimal::from_str(&ratio)?; @@ -530,7 +487,7 @@ pub fn execute_update_royalty_ratio( return Err(ContractError::InvalidRoyaltyRatio {}); } - drop_params.config.royalty_ratio = ratio; + drop_params.token_details.royalty_ratio = ratio; DROPS.save(deps.storage, drop_id, &drop_params)?; @@ -550,9 +507,10 @@ pub fn execute_update_mint_price( ) -> Result { let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); let mut drop_params = DROPS.load(deps.storage, drop_id)?; + let auth_details = AUTH_DETAILS.load(deps.storage)?; // Check if sender is admin - if info.sender != drop_params.config.admin { + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } drop_params.config.mint_price = mint_price.clone(); @@ -567,6 +525,48 @@ pub fn execute_update_mint_price( Ok(res) } +pub fn execute_set_admin( + deps: DepsMut, + _env: Env, + info: MessageInfo, + admin: String, +) -> Result { + let mut auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if sender is admin + if info.sender != auth_details.admin { + return Err(ContractError::Unauthorized {}); + } + let new_admin = deps.api.addr_validate(&admin)?; + auth_details.admin = new_admin.clone(); + AUTH_DETAILS.save(deps.storage, &auth_details)?; + + let res = Response::new() + .add_attribute("action", "set_admin") + .add_attribute("admin", admin.to_string()); + Ok(res) +} + +pub fn execute_set_payment_collector( + deps: DepsMut, + _env: Env, + info: MessageInfo, + payment_collector: String, +) -> Result { + let mut auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if sender is admin + if info.sender != auth_details.admin { + return Err(ContractError::Unauthorized {}); + } + let new_payment_collector = deps.api.addr_validate(&payment_collector)?; + auth_details.payment_collector = new_payment_collector.clone(); + AUTH_DETAILS.save(deps.storage, &auth_details)?; + + let res = Response::new() + .add_attribute("action", "set_payment_collector") + .add_attribute("payment_collector", payment_collector.to_string()); + Ok(res) +} + pub fn execute_update_whitelist_address( deps: DepsMut, _env: Env, @@ -577,10 +577,12 @@ pub fn execute_update_whitelist_address( // Check if sender is admin let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); let mut drop_params = DROPS.load(deps.storage, drop_id)?; - - if info.sender != drop_params.config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if sender is admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } + let whitelist_address = drop_params.config.whitelist_address.clone(); // Check if whitelist already active @@ -656,50 +658,43 @@ pub fn execute_new_drop( deps: DepsMut, env: Env, info: MessageInfo, - whitelist_address: Option, - token_limit: Option, - start_time: Timestamp, - end_time: Option, - mint_price: Coin, - per_address_limit: u32, - royalty_ratio: Option, - token_name: String, - description: Option, - base_uri: Option, - preview_uri: Option, - uri_hash: Option, - transferable: Option, - extensible: Option, - nsfw: Option, - data: Option, + config: Config, + token_details: TokenDetails, ) -> Result { // Check if sender is admin let current_drop_id = CURRENT_DROP_ID.load(deps.storage)?; let current_drop_params = DROPS.load(deps.storage, current_drop_id)?; + let auth_details = AUTH_DETAILS.load(deps.storage)?; - if info.sender != current_drop_params.config.admin { + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // Check if token limit is 0 - if let Some(token_limit) = token_limit { - if token_limit == 0 { + if let Some(num_tokens) = config.num_tokens { + if num_tokens == 0 { return Err(ContractError::InvalidNumTokens {}); } } + // Check if per address limit is 0 + if let Some(per_address_limit) = config.per_address_limit { + if per_address_limit == 0 { + return Err(ContractError::PerAddressLimitZero {}); + } + } // Check start time - if start_time < env.block.time { + if config.start_time < env.block.time { return Err(ContractError::InvalidStartTime {}); } // Check end time - if let Some(end_time) = end_time { - if end_time < start_time { + if let Some(end_time) = config.end_time { + if end_time < config.start_time { return Err(ContractError::InvalidEndTime {}); } } // Check if any whitelist is present - if let Some(whitelist_address) = whitelist_address.clone() { + if let Some(whitelist_address) = config.whitelist_address.clone() { let is_active: bool = check_if_whitelist_is_active( - &deps.api.addr_validate(&whitelist_address)?, + &deps.api.addr_validate(&whitelist_address.into_string())?, deps.as_ref(), )?; if is_active { @@ -707,43 +702,21 @@ pub fn execute_new_drop( } } // Check royalty ratio we expect decimal number - let royalty_ratio = Decimal::from_str( - &royalty_ratio.unwrap_or(current_drop_params.config.royalty_ratio.to_string()), - )?; + let royalty_ratio = token_details.royalty_ratio; - let config = Config { - per_address_limit: per_address_limit, - payment_collector: current_drop_params.config.payment_collector, - start_time, - royalty_ratio, - admin: current_drop_params.config.admin, - mint_price, - whitelist_address: maybe_addr(deps.api, whitelist_address)?, - end_time, - token_limit, - }; - let collection = CollectionDetails { - name: current_drop_params.collection.name, - description: description.unwrap_or(current_drop_params.collection.description), - preview_uri: preview_uri.unwrap_or(current_drop_params.collection.preview_uri), - schema: current_drop_params.collection.schema, - symbol: current_drop_params.collection.symbol, - id: current_drop_params.collection.id, - extensible: extensible.unwrap_or(current_drop_params.collection.extensible), - nsfw: nsfw.unwrap_or(current_drop_params.collection.nsfw), - base_uri: base_uri.unwrap_or(current_drop_params.collection.base_uri), - uri: current_drop_params.collection.uri, - uri_hash: uri_hash, - data: data.unwrap_or(current_drop_params.collection.data), - token_name, - transferable: transferable.unwrap_or(current_drop_params.collection.transferable), - royalty_receivers: current_drop_params.collection.royalty_receivers, + if royalty_ratio < Decimal::zero() || royalty_ratio > Decimal::one() { + return Err(ContractError::InvalidRoyaltyRatio {}); + } + + let new_drop_params = DropParams { + config: config.clone(), + collection_details: current_drop_params.collection_details, + token_details, }; - let drop_params = DropParams { config, collection }; let new_drop_id = current_drop_id + 1; - DROPS.save(deps.storage, new_drop_id, &drop_params)?; + DROPS.save(deps.storage, new_drop_id, &new_drop_params)?; CURRENT_DROP_ID.save(deps.storage, &new_drop_id)?; - MINTED_COUNT.save(deps.storage, new_drop_id, &0)?; + DROP_MINTED_COUNT.save(deps.storage, new_drop_id, &0)?; let res = Response::new() .add_attribute("action", "new_drop") @@ -760,17 +733,19 @@ pub fn execute_update_royalty_receivers( // Check if sender is admin let current_drop_id = CURRENT_DROP_ID.load(deps.storage)?; let drop_params = DROPS.load(deps.storage, current_drop_id)?; + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if sender is admin + if info.sender != auth_details.admin { + return Err(ContractError::Unauthorized {}); + } - // TODO: - // This update does not happening inside drops - // Consider updating the collection in all drops let update_msg: CosmosMsg = MsgUpdateDenom { sender: env.contract.address.into_string(), - royalty_receivers: receivers, - id: drop_params.collection.id, + id: drop_params.collection_details.id, description: "[do-not-modify]".to_string(), name: "[do-not-modify]".to_string(), preview_uri: "[do-not-modify]".to_string(), + royalty_receivers: receivers, } .into(); @@ -789,41 +764,32 @@ pub fn execute_update_denom( preview_uri: Option, ) -> Result { let current_drop_id = CURRENT_DROP_ID.load(deps.storage)?; + let current_drop_params = DROPS.load(deps.storage, current_drop_id)?; + let auth_details = AUTH_DETAILS.load(deps.storage)?; + let admin = auth_details.admin; + // Current drops admin can update the denom + if info.sender != admin { + return Err(ContractError::Unauthorized {}); + } // We would have to update name and description in the collection of all drops for edition_number in 1..=current_drop_id { - let edition_params = DROPS.load(deps.storage, edition_number)?; - let mut collection = edition_params.collection; - let config = edition_params.config; + let mut edition_params = DROPS.load(deps.storage, edition_number)?; + edition_params.collection_details.collection_name = name + .clone() + .unwrap_or(edition_params.collection_details.collection_name); + edition_params.collection_details.description = description.clone(); + edition_params.collection_details.preview_uri = preview_uri.clone(); - if info.sender != config.admin { - return Err(ContractError::Unauthorized {}); - } - collection.name = name.clone().unwrap_or(collection.name); - collection.description = description.clone().unwrap_or(collection.description); - collection.preview_uri = preview_uri.clone().unwrap_or(collection.preview_uri); - DROPS.save( - deps.storage, - edition_number, - &DropParams { - config: config, - collection: collection, - }, - )?; + DROPS.save(deps.storage, edition_number, &edition_params)?; } - let current_drop_params = DROPS.load(deps.storage, current_drop_id)?; + let update_msg: CosmosMsg = MsgUpdateDenom { sender: env.contract.address.into_string(), - id: current_drop_params.collection.id, + id: current_drop_params.collection_details.id, description: description.unwrap_or("[do-not-modify]".to_string()), name: name.unwrap_or("[do-not-modify]".to_string()), preview_uri: preview_uri.unwrap_or("[do-not-modify]".to_string()), - royalty_receivers: current_drop_params - .collection - .royalty_receivers - .unwrap_or(vec![WeightedAddress { - address: current_drop_params.config.payment_collector.into_string(), - weight: Decimal::one().to_string(), - }]), + royalty_receivers: vec![], } .into(); @@ -834,30 +800,20 @@ pub fn execute_update_denom( } fn execute_purge_denom( deps: DepsMut, - _env: Env, + env: Env, info: MessageInfo, ) -> Result { let current_drop_id = CURRENT_DROP_ID.load(deps.storage)?; let current_drop_params = DROPS.load(deps.storage, current_drop_id)?; - if current_drop_params.config.admin != info.sender { - return Err(ContractError::Unauthorized {}); - } - let onft_querier = OnftQuerier::new(&deps.querier); - let minted_nfties_res = - onft_querier.collection(current_drop_params.collection.clone().id, None)?; - let minted_nfties = minted_nfties_res - .collection - .unwrap_or(Collection::default()) - .onfts; + let auth_details = AUTH_DETAILS.load(deps.storage)?; - if !minted_nfties.is_empty() { - // If there is any nft minted for the collection purge denoms should not work - return Err(ContractError::MintingAlreadyStarted {}); + if auth_details.admin != info.sender { + return Err(ContractError::Unauthorized {}); } let purge_msg: CosmosMsg = MsgPurgeDenom { - id: current_drop_params.collection.id, - sender: info.sender.into_string(), + id: current_drop_params.collection_details.id, + sender: env.contract.address.into_string(), } .into(); @@ -866,25 +822,42 @@ fn execute_purge_denom( .add_message(purge_msg)) } -// Implement Queries #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, env: Env, msg: MinterQueryMsg) -> StdResult { match msg { - QueryMsg::Collection { drop_id } => to_json_binary(&query_collection(deps, env, drop_id)?), - QueryMsg::Config { drop_id } => to_json_binary(&query_config(deps, env, drop_id)?), - QueryMsg::MintedTokens { address, drop_id } => { - to_json_binary(&query_minted_tokens(deps, env, address, drop_id)?) - } - QueryMsg::TotalMintedCount { drop_id } => { - to_json_binary(&query_total_tokens_minted(deps, env, drop_id)?) + MinterQueryMsg::Collection {} => to_json_binary(&query_collection(deps, env, None)?), + MinterQueryMsg::TokenDetails {} => to_json_binary(&query_token_details(deps, env, None)?), + MinterQueryMsg::Config {} => to_json_binary(&query_config(deps, env, None)?), + MinterQueryMsg::MintedTokens { address } => { + to_json_binary(&query_minted_tokens(deps, env, address, None)?) } - QueryMsg::TokensRemaining { drop_id } => { - to_json_binary(&query_tokens_remaining(deps, env, drop_id)?) + MinterQueryMsg::TotalMintedCount {} => { + to_json_binary(&query_total_tokens_minted(deps, env)?) } - QueryMsg::IsPaused {} => to_json_binary(&query_is_paused(deps, env)?), - QueryMsg::Pausers {} => to_json_binary(&query_pausers(deps, env)?), - QueryMsg::CurrentDropNumber {} => to_json_binary(&query_current_drop_number(deps, env)?), - QueryMsg::AllDrops {} => to_json_binary(&query_all_drops(deps, env)?), + MinterQueryMsg::AuthDetails {} => to_json_binary(&query_auth_details(deps, env)?), + MinterQueryMsg::IsPaused {} => to_json_binary(&query_is_paused(deps, env)?), + MinterQueryMsg::Pausers {} => to_json_binary(&query_pausers(deps, env)?), + MinterQueryMsg::Extension(ext) => match ext { + QueryMsgExtension::CurrentDropNumber {} => { + to_json_binary(&query_current_drop_number(deps, env)?) + } + QueryMsgExtension::AllDrops {} => to_json_binary(&query_all_drops(deps, env)?), + QueryMsgExtension::Collection { drop_id } => { + to_json_binary(&query_collection(deps, env, drop_id)?) + } + QueryMsgExtension::Config { drop_id } => { + to_json_binary(&query_config(deps, env, drop_id)?) + } + QueryMsgExtension::MintedTokens { address, drop_id } => { + to_json_binary(&query_minted_tokens(deps, env, address, drop_id)?) + } + QueryMsgExtension::TokensRemaining { drop_id } => { + to_json_binary(&query_tokens_remaining(deps, env, drop_id)?) + } + QueryMsgExtension::TokenDetails { drop_id } => { + to_json_binary(&query_token_details(deps, env, drop_id)?) + } + }, } } @@ -894,9 +867,18 @@ fn query_collection( drop_id: Option, ) -> Result { let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); - let collection = DROPS.load(deps.storage, drop_id)?.collection; + let collection = DROPS.load(deps.storage, drop_id)?.collection_details; Ok(collection) } +fn query_token_details( + deps: Deps, + _env: Env, + drop_id: Option, +) -> Result { + let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); + let token_details = DROPS.load(deps.storage, drop_id)?.token_details; + Ok(token_details) +} fn query_config(deps: Deps, _env: Env, drop_id: Option) -> Result { let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); @@ -913,19 +895,14 @@ fn query_minted_tokens( ) -> Result { let address = deps.api.addr_validate(&address)?; let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); - let minted_tokens = MintedTokens::new(MINTED_TOKENS_KEY); + let minted_tokens = UserMintedTokens::new(USER_MINTED_TOKENS_KEY); let user_details = minted_tokens.load(deps.storage, drop_id, address)?; Ok(user_details) } -fn query_total_tokens_minted( - deps: Deps, - _env: Env, - drop_id: Option, -) -> Result { - let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); - let minted_count = MINTED_COUNT.load(deps.storage, drop_id).unwrap_or(0); - Ok(minted_count) +fn query_total_tokens_minted(deps: Deps, _env: Env) -> Result { + let total_minted_count = LAST_MINTED_TOKEN_ID.load(deps.storage)?; + Ok(total_minted_count) } fn query_tokens_remaining( @@ -936,11 +913,13 @@ fn query_tokens_remaining( let drop_id = drop_id.unwrap_or(CURRENT_DROP_ID.load(deps.storage)?); let drop_params = DROPS.load(deps.storage, drop_id)?; let config = drop_params.config; - let minted_count = MINTED_COUNT.load(deps.storage, drop_id).unwrap_or(0); - // TODO : This is not the correct way to calculate the remaining tokens - // If the token limit is not set then we should return error - let tokens_remaining = config.token_limit.unwrap_or(u32::MAX) - minted_count; - Ok(tokens_remaining) + let drop_minted_count = DROP_MINTED_COUNT.load(deps.storage, drop_id).unwrap_or(0); + if let Some(num_tokens) = config.num_tokens { + let tokens_remaining = num_tokens - drop_minted_count; + Ok(tokens_remaining) + } else { + Err(ContractError::TokenLimitNotSet {}) + } } fn query_is_paused(deps: Deps, _env: Env) -> Result { @@ -969,3 +948,8 @@ fn query_all_drops(deps: Deps, _env: Env) -> Result, Cont } Ok(drops) } + +fn query_auth_details(deps: Deps, _env: Env) -> Result { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + Ok(auth_details) +} diff --git a/contracts/minters/multi-mint-oem/src/error.rs b/contracts/minters/multi-mint-oem/src/error.rs index faaf3f4..b13cf55 100644 --- a/contracts/minters/multi-mint-oem/src/error.rs +++ b/contracts/minters/multi-mint-oem/src/error.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{StdError, Timestamp, Uint128}; +use cosmwasm_std::{Coin, StdError, Timestamp, Uint128}; use cw_utils::PaymentError; use pauser::PauseError; use thiserror::Error; @@ -24,7 +24,10 @@ pub enum ContractError { DivideByZero {}, #[error("Invalid creation fee")] - InvalidCreationFee { expected: Uint128, sent: Uint128 }, + InvalidCreationFee { + expected: Vec, + sent: Vec, + }, #[error("Minting has not started yet")] MintingNotStarted { diff --git a/contracts/minters/multi-mint-oem/src/msg.rs b/contracts/minters/multi-mint-oem/src/msg.rs index 5f7d39c..62b5a1c 100644 --- a/contracts/minters/multi-mint-oem/src/msg.rs +++ b/contracts/minters/multi-mint-oem/src/msg.rs @@ -1,5 +1,7 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Coin, Timestamp}; +use crate::state::DropParams; +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Coin; +use minter_types::{CollectionDetails, Config, TokenDetails, UserDetails}; use omniflix_std::types::omniflix::onft::v1beta1::WeightedAddress; #[cw_serde] @@ -29,22 +31,8 @@ pub enum ExecuteMsg { pausers: Vec, }, NewDrop { - start_time: Timestamp, - mint_price: Coin, - token_name: String, - per_address_limit: u32, - token_limit: Option, - whitelist_address: Option, - end_time: Option, - royalty_ratio: Option, - description: Option, - base_uri: Option, - preview_uri: Option, - uri_hash: Option, - transferable: Option, - extensible: Option, - nsfw: Option, - data: Option, + new_token_details: TokenDetails, + new_config: Config, }, UpdateRoyaltyReceivers { receivers: Vec, @@ -55,4 +43,32 @@ pub enum ExecuteMsg { preview_uri: Option, }, PurgeDenom {}, + SetAdmin { + admin: String, + }, + SetPaymentCollector { + payment_collector: String, + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsgExtension { + #[returns(CollectionDetails)] + Collection { drop_id: Option }, + #[returns(TokenDetails)] + TokenDetails { drop_id: Option }, + #[returns(Config)] + Config { drop_id: Option }, + #[returns(UserDetails)] + MintedTokens { + address: String, + drop_id: Option, + }, + #[returns(u32)] + TokensRemaining { drop_id: Option }, + #[returns(u32)] + CurrentDropNumber {}, + #[returns(Vec<(u32,DropParams)>)] + AllDrops {}, } diff --git a/contracts/minters/multi-mint-oem/src/state.rs b/contracts/minters/multi-mint-oem/src/state.rs index 33f2b22..afce36c 100644 --- a/contracts/minters/multi-mint-oem/src/state.rs +++ b/contracts/minters/multi-mint-oem/src/state.rs @@ -3,26 +3,28 @@ use cosmwasm_std::{Addr, StdError, Storage}; use cw_storage_plus::{Item, Map}; use std::u32; -use minter_types::{CollectionDetails, Config, UserDetails}; +use minter_types::{AuthDetails, CollectionDetails, Config, TokenDetails, UserDetails}; -pub const MINTED_COUNT: Map = Map::new("minted_count"); +pub const DROP_MINTED_COUNT: Map = Map::new("drop_minted_count"); pub const CURRENT_DROP_ID: Item = Item::new("current_edition"); -pub const MINTED_TOKENS_KEY: &str = "minted_tokens"; pub const LAST_MINTED_TOKEN_ID: Item = Item::new("last_minted_token_id"); +pub const AUTH_DETAILS: Item = Item::new("auth_details"); pub type DropID = u32; #[cw_serde] pub struct DropParams { pub config: Config, - pub collection: CollectionDetails, + pub collection_details: CollectionDetails, + pub token_details: TokenDetails, } pub const DROPS: Map = Map::new("editions"); -pub struct MintedTokens<'a>(Map<'a, (DropID, Addr), UserDetails>); +pub const USER_MINTED_TOKENS_KEY: &str = "user_minted_tokens"; +pub struct UserMintedTokens<'a>(Map<'a, (DropID, Addr), UserDetails>); -impl<'a> MintedTokens<'a> { +impl<'a> UserMintedTokens<'a> { pub const fn new(storage_key: &'a str) -> Self { - MintedTokens(Map::new(storage_key)) + UserMintedTokens(Map::new(storage_key)) } pub fn load( diff --git a/contracts/minters/open-edition-minter/.cargo/config b/contracts/minters/open-edition-minter/.cargo/config new file mode 100644 index 0000000..5b8deaa --- /dev/null +++ b/contracts/minters/open-edition-minter/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run schema" diff --git a/contracts/minters/open-edition-minter/Cargo.toml b/contracts/minters/open-edition-minter/Cargo.toml index 20b7ca6..6e1f67a 100644 --- a/contracts/minters/open-edition-minter/Cargo.toml +++ b/contracts/minters/open-edition-minter/Cargo.toml @@ -54,7 +54,6 @@ serde = { workspace = true } minter-types={ workspace = true } sha2 = { version = "0.10.2", default-features = false } whitelist-types ={ workspace = true } -open-edition-minter-types = {workspace=true} omniflix-open-edition-minter-factory = {path = "../../factories/open-edition-minter-factory"} omniflix-round-whitelist = {path="../../whitelists/round-whitelist"} pauser = { workspace = true } diff --git a/contracts/minters/open-edition-minter/README.md b/contracts/minters/open-edition-minter/README.md new file mode 100644 index 0000000..059a2e7 --- /dev/null +++ b/contracts/minters/open-edition-minter/README.md @@ -0,0 +1,14 @@ +## Open Edition Minter + +Open edition minter contract is a minter contract which mints one NFT with predefined metadata. + +#### Instantiate + +Similar with the Minter contract, the creator should send Collection details along with trading information such as price, denomination, and trading start time. Factory contract will create a new OEM contract and initialize it with the given parameters. + +### Mint + +- There are two types of minting: `Mint{}` and `AdminMint{}` +- `Mint{}`: This option is for users who want to own the NFT, and they need to pay the active price at that time. +- `AdminMint{}`: As the name suggests, this option is specifically for admin to mint a token. Admins have the ability to determine the recipient. Admins are not subject to address limits or private mint checks, and this action does not require a payment. + - `recipient`: The address of the recipient. \ No newline at end of file diff --git a/contracts/minters/open-edition-minter/schema/omniflix-open-edition-minter.json b/contracts/minters/open-edition-minter/schema/omniflix-open-edition-minter.json index fb50121..c8ff265 100644 --- a/contracts/minters/open-edition-minter/schema/omniflix-open-edition-minter.json +++ b/contracts/minters/open-edition-minter/schema/omniflix-open-edition-minter.json @@ -8,7 +8,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -16,6 +17,9 @@ }, "init": { "$ref": "#/definitions/OpenEditionMinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false, @@ -38,45 +42,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -88,33 +81,38 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "OpenEditionMinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -134,6 +132,14 @@ "mint_price": { "$ref": "#/definitions/Coin" }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, "payment_collector": { "type": [ "string", @@ -141,17 +147,6 @@ ] }, "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "royalty_ratio": { - "type": "string" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { "type": [ "integer", "null" @@ -159,6 +154,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "type": [ "string", @@ -176,6 +174,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" @@ -385,13 +433,13 @@ "update_denom": { "type": "object", "properties": { - "description": { + "collection_name": { "type": [ "string", "null" ] }, - "name": { + "description": { "type": [ "string", "null" @@ -421,6 +469,48 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_admin" + ], + "properties": { + "set_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_payment_collector" + ], + "properties": { + "set_payment_collector": { + "type": "object", + "required": [ + "payment_collector" + ], + "properties": { + "payment_collector": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } ], "definitions": { @@ -477,6 +567,32 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "token_details" + ], + "properties": { + "token_details": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "auth_details" + ], + "properties": { + "auth_details": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ @@ -514,10 +630,10 @@ { "type": "object", "required": [ - "total_minted_count" + "is_paused" ], "properties": { - "total_minted_count": { + "is_paused": { "type": "object", "additionalProperties": false } @@ -527,10 +643,10 @@ { "type": "object", "required": [ - "tokens_remaining" + "pausers" ], "properties": { - "tokens_remaining": { + "pausers": { "type": "object", "additionalProperties": false } @@ -540,12 +656,11 @@ { "type": "object", "required": [ - "is_paused" + "extension" ], "properties": { - "is_paused": { - "type": "object", - "additionalProperties": false + "extension": { + "$ref": "#/definitions/OEMQueryExtension" } }, "additionalProperties": false @@ -553,65 +668,97 @@ { "type": "object", "required": [ - "pausers" + "total_minted_count" ], "properties": { - "pausers": { + "total_minted_count": { "type": "object", "additionalProperties": false } }, "additionalProperties": false } - ] + ], + "definitions": { + "OEMQueryExtension": { + "oneOf": [ + { + "type": "object", + "required": [ + "tokens_remaining" + ], + "properties": { + "tokens_remaining": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } }, "migrate": null, "sudo": null, "responses": { + "auth_details": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AuthDetails", + "type": "object", + "required": [ + "admin", + "payment_collector" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "payment_collector": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + }, "collection": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "CollectionDetails", "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -623,22 +770,25 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, @@ -665,17 +815,10 @@ "title": "Config", "type": "object", "required": [ - "admin", "mint_price", - "payment_collector", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { - "admin": { - "$ref": "#/definitions/Addr" - }, "end_time": { "anyOf": [ { @@ -689,21 +832,15 @@ "mint_price": { "$ref": "#/definitions/Coin" }, - "payment_collector": { - "$ref": "#/definitions/Addr" - }, - "per_address_limit": { - "type": "integer", + "num_tokens": { + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "$ref": "#/definitions/Decimal" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { + "per_address_limit": { "type": [ "integer", "null" @@ -711,6 +848,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "anyOf": [ { @@ -743,10 +883,6 @@ } } }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "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": [ @@ -765,6 +901,13 @@ } } }, + "extension": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, "is_paused": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Boolean", @@ -827,12 +970,63 @@ } } }, - "tokens_remaining": { + "token_details": { "$schema": "http://json-schema.org/draft-07/schema#", - "title": "uint32", - "type": "integer", - "format": "uint32", - "minimum": 0.0 + "title": "TokenDetails", + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } }, "total_minted_count": { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/contracts/minters/open-edition-minter/schema/raw/execute.json b/contracts/minters/open-edition-minter/schema/raw/execute.json index 39b8262..7659165 100644 --- a/contracts/minters/open-edition-minter/schema/raw/execute.json +++ b/contracts/minters/open-edition-minter/schema/raw/execute.json @@ -182,13 +182,13 @@ "update_denom": { "type": "object", "properties": { - "description": { + "collection_name": { "type": [ "string", "null" ] }, - "name": { + "description": { "type": [ "string", "null" @@ -218,6 +218,48 @@ } }, "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_admin" + ], + "properties": { + "set_admin": { + "type": "object", + "required": [ + "admin" + ], + "properties": { + "admin": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "set_payment_collector" + ], + "properties": { + "set_payment_collector": { + "type": "object", + "required": [ + "payment_collector" + ], + "properties": { + "payment_collector": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } ], "definitions": { diff --git a/contracts/minters/open-edition-minter/schema/raw/instantiate.json b/contracts/minters/open-edition-minter/schema/raw/instantiate.json index 1c48236..7d6ce3f 100644 --- a/contracts/minters/open-edition-minter/schema/raw/instantiate.json +++ b/contracts/minters/open-edition-minter/schema/raw/instantiate.json @@ -4,7 +4,8 @@ "type": "object", "required": [ "collection_details", - "init" + "init", + "token_details" ], "properties": { "collection_details": { @@ -12,6 +13,9 @@ }, "init": { "$ref": "#/definitions/OpenEditionMinterInitExtention" + }, + "token_details": { + "$ref": "#/definitions/TokenDetails" } }, "additionalProperties": false, @@ -34,45 +38,34 @@ "CollectionDetails": { "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -84,33 +77,38 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, "OpenEditionMinterInitExtention": { "type": "object", "required": [ "admin", "mint_price", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { @@ -130,6 +128,14 @@ "mint_price": { "$ref": "#/definitions/Coin" }, + "num_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, "payment_collector": { "type": [ "string", @@ -137,17 +143,6 @@ ] }, "per_address_limit": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "royalty_ratio": { - "type": "string" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { "type": [ "integer", "null" @@ -155,6 +150,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "type": [ "string", @@ -172,6 +170,56 @@ } ] }, + "TokenDetails": { + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "Uint128": { "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 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 `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", "type": "string" diff --git a/contracts/minters/open-edition-minter/schema/raw/query.json b/contracts/minters/open-edition-minter/schema/raw/query.json index d9e43d2..499a786 100644 --- a/contracts/minters/open-edition-minter/schema/raw/query.json +++ b/contracts/minters/open-edition-minter/schema/raw/query.json @@ -15,6 +15,32 @@ }, "additionalProperties": false }, + { + "type": "object", + "required": [ + "token_details" + ], + "properties": { + "token_details": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "auth_details" + ], + "properties": { + "auth_details": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, { "type": "object", "required": [ @@ -52,10 +78,10 @@ { "type": "object", "required": [ - "total_minted_count" + "is_paused" ], "properties": { - "total_minted_count": { + "is_paused": { "type": "object", "additionalProperties": false } @@ -65,10 +91,10 @@ { "type": "object", "required": [ - "tokens_remaining" + "pausers" ], "properties": { - "tokens_remaining": { + "pausers": { "type": "object", "additionalProperties": false } @@ -78,12 +104,11 @@ { "type": "object", "required": [ - "is_paused" + "extension" ], "properties": { - "is_paused": { - "type": "object", - "additionalProperties": false + "extension": { + "$ref": "#/definitions/OEMQueryExtension" } }, "additionalProperties": false @@ -91,15 +116,34 @@ { "type": "object", "required": [ - "pausers" + "total_minted_count" ], "properties": { - "pausers": { + "total_minted_count": { "type": "object", "additionalProperties": false } }, "additionalProperties": false } - ] + ], + "definitions": { + "OEMQueryExtension": { + "oneOf": [ + { + "type": "object", + "required": [ + "tokens_remaining" + ], + "properties": { + "tokens_remaining": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } } diff --git a/contracts/minters/open-edition-minter/schema/raw/response_to_auth_details.json b/contracts/minters/open-edition-minter/schema/raw/response_to_auth_details.json new file mode 100644 index 0000000..aad6fe8 --- /dev/null +++ b/contracts/minters/open-edition-minter/schema/raw/response_to_auth_details.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AuthDetails", + "type": "object", + "required": [ + "admin", + "payment_collector" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "payment_collector": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/contracts/minters/open-edition-minter/schema/raw/response_to_collection.json b/contracts/minters/open-edition-minter/schema/raw/response_to_collection.json index d8a9fd7..8a9414c 100644 --- a/contracts/minters/open-edition-minter/schema/raw/response_to_collection.json +++ b/contracts/minters/open-edition-minter/schema/raw/response_to_collection.json @@ -3,45 +3,34 @@ "title": "CollectionDetails", "type": "object", "required": [ - "base_uri", - "data", - "description", - "extensible", + "collection_name", "id", - "name", - "nsfw", - "preview_uri", - "schema", - "symbol", - "token_name", - "transferable", - "uri", - "uri_hash" + "symbol" ], "properties": { - "base_uri": { + "collection_name": { "type": "string" }, "data": { - "type": "string" + "type": [ + "string", + "null" + ] }, "description": { - "type": "string" - }, - "extensible": { - "type": "boolean" + "type": [ + "string", + "null" + ] }, "id": { "type": "string" }, - "name": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, "preview_uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "royalty_receivers": { "type": [ @@ -53,22 +42,25 @@ } }, "schema": { - "type": "string" + "type": [ + "string", + "null" + ] }, "symbol": { "type": "string" }, - "token_name": { - "type": "string" - }, - "transferable": { - "type": "boolean" - }, "uri": { - "type": "string" + "type": [ + "string", + "null" + ] }, "uri_hash": { - "type": "string" + "type": [ + "string", + "null" + ] } }, "additionalProperties": false, diff --git a/contracts/minters/open-edition-minter/schema/raw/response_to_config.json b/contracts/minters/open-edition-minter/schema/raw/response_to_config.json index 73907a6..0a3efbd 100644 --- a/contracts/minters/open-edition-minter/schema/raw/response_to_config.json +++ b/contracts/minters/open-edition-minter/schema/raw/response_to_config.json @@ -3,17 +3,10 @@ "title": "Config", "type": "object", "required": [ - "admin", "mint_price", - "payment_collector", - "per_address_limit", - "royalty_ratio", "start_time" ], "properties": { - "admin": { - "$ref": "#/definitions/Addr" - }, "end_time": { "anyOf": [ { @@ -27,21 +20,15 @@ "mint_price": { "$ref": "#/definitions/Coin" }, - "payment_collector": { - "$ref": "#/definitions/Addr" - }, - "per_address_limit": { - "type": "integer", + "num_tokens": { + "type": [ + "integer", + "null" + ], "format": "uint32", "minimum": 0.0 }, - "royalty_ratio": { - "$ref": "#/definitions/Decimal" - }, - "start_time": { - "$ref": "#/definitions/Timestamp" - }, - "token_limit": { + "per_address_limit": { "type": [ "integer", "null" @@ -49,6 +36,9 @@ "format": "uint32", "minimum": 0.0 }, + "start_time": { + "$ref": "#/definitions/Timestamp" + }, "whitelist_address": { "anyOf": [ { @@ -81,10 +71,6 @@ } } }, - "Decimal": { - "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", - "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": [ diff --git a/contracts/minters/open-edition-minter/schema/raw/response_to_extension.json b/contracts/minters/open-edition-minter/schema/raw/response_to_extension.json new file mode 100644 index 0000000..de85c3e --- /dev/null +++ b/contracts/minters/open-edition-minter/schema/raw/response_to_extension.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 +} diff --git a/contracts/minters/open-edition-minter/schema/raw/response_to_token_details.json b/contracts/minters/open-edition-minter/schema/raw/response_to_token_details.json new file mode 100644 index 0000000..516fcb4 --- /dev/null +++ b/contracts/minters/open-edition-minter/schema/raw/response_to_token_details.json @@ -0,0 +1,58 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokenDetails", + "type": "object", + "required": [ + "base_token_uri", + "extensible", + "nsfw", + "royalty_ratio", + "token_name", + "transferable" + ], + "properties": { + "base_token_uri": { + "type": "string" + }, + "data": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "extensible": { + "type": "boolean" + }, + "nsfw": { + "type": "boolean" + }, + "preview_uri": { + "type": [ + "string", + "null" + ] + }, + "royalty_ratio": { + "$ref": "#/definitions/Decimal" + }, + "token_name": { + "type": "string" + }, + "transferable": { + "type": "boolean" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } +} diff --git a/contracts/minters/open-edition-minter/src/bin/schema.rs b/contracts/minters/open-edition-minter/src/bin/schema.rs index 7535117..73679f7 100644 --- a/contracts/minters/open-edition-minter/src/bin/schema.rs +++ b/contracts/minters/open-edition-minter/src/bin/schema.rs @@ -1,8 +1,8 @@ use cosmwasm_schema::write_api; -use open_edition_minter_types::QueryMsg; +use omniflix_open_edition_minter::msg::{ExecuteMsg, OEMQueryExtension}; -use omniflix_open_edition_minter::msg::ExecuteMsg; +use minter_types::QueryMsg; use omniflix_open_edition_minter_factory::msg::OpenEditionMinterCreateMsg; @@ -10,6 +10,6 @@ fn main() { write_api! { instantiate: OpenEditionMinterCreateMsg, execute: ExecuteMsg, - query: QueryMsg, + query: QueryMsg, } } diff --git a/contracts/minters/open-edition-minter/src/contract.rs b/contracts/minters/open-edition-minter/src/contract.rs index 69d135b..9865e0e 100644 --- a/contracts/minters/open-edition-minter/src/contract.rs +++ b/contracts/minters/open-edition-minter/src/contract.rs @@ -1,7 +1,3 @@ -use std::ptr::null; -use std::str::FromStr; - -//use crate::msg::ExecuteMsg; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ @@ -9,25 +5,28 @@ use cosmwasm_std::{ Response, StdResult, Uint128, WasmMsg, }; use cw_utils::{may_pay, maybe_addr, must_pay, nonpayable}; -use minter_types::{generate_mint_message, CollectionDetails, Config, Token, UserDetails}; -use open_edition_minter_types::QueryMsg; -use pauser::PauseState; +use minter_types::{ + generate_create_denom_msg, generate_mint_message, AuthDetails, CollectionDetails, Config, + QueryMsg, Token, TokenDetails, UserDetails, +}; +use std::str::FromStr; use crate::error::ContractError; -use crate::msg::ExecuteMsg; -use crate::state::{last_token_id, COLLECTION, CONFIG, MINTED_COUNT, MINTED_TOKENS}; +use crate::msg::{ExecuteMsg, OEMQueryExtension}; +use crate::state::{ + last_token_id, AUTH_DETAILS, COLLECTION, CONFIG, MINTED_COUNT, MINTED_TOKENS, TOKEN_DETAILS, +}; use cw2::set_contract_version; use omniflix_open_edition_minter_factory::msg::{ OpenEditionMinterCreateMsg, ParamsResponse, QueryMsg as OpenEditionMinterFactoryQueryMsg, }; use omniflix_round_whitelist::msg::ExecuteMsg as RoundWhitelistExecuteMsg; use omniflix_std::types::omniflix::onft::v1beta1::{ - Collection, Metadata, MsgCreateDenom, MsgMintOnft, MsgPurgeDenom, MsgUpdateDenom, OnftQuerier, - WeightedAddress, + MsgPurgeDenom, MsgUpdateDenom, OnftQuerier, WeightedAddress, }; +use pauser::{PauseState, PAUSED_KEY, PAUSERS_KEY}; use whitelist_types::{ check_if_address_is_member, check_if_whitelist_is_active, check_whitelist_price, - IsActiveResponse, IsMemberResponse, MintPriceResponse, RoundWhitelistQueryMsgs, }; // version info for migration info @@ -46,9 +45,6 @@ const CREATION_FEE: Uint128 = Uint128::new(100_000_000); #[cfg(test)] const CREATION_FEE_DENOM: &str = "uflix"; -const PAUSED_KEY: &str = "paused"; -const PAUSERS_KEY: &str = "pausers"; - #[cfg_attr(not(feature = "library"), entry_point)] pub fn instantiate( deps: DepsMut, @@ -85,17 +81,23 @@ pub fn instantiate( // Exact amount must be paid if amount != creation_fee_amount { return Err(ContractError::InvalidCreationFee { - expected: amount, - sent: amount, + expected: [Coin { + denom: creation_fee_denom, + amount: creation_fee_amount, + }] + .to_vec(), + sent: info.funds, }); } // Check if per address limit is 0 - if msg.init.per_address_limit == 0 { - return Err(ContractError::PerAddressLimitZero {}); + if let Some(per_address_limit) = msg.init.per_address_limit { + if per_address_limit == 0 { + return Err(ContractError::PerAddressLimitZero {}); + } } - // Check if token limit is 0 - if let Some(token_limit) = msg.init.token_limit { - if token_limit == 0 { + // Check if num tokens is 0 + if let Some(num_tokens) = msg.init.num_tokens { + if num_tokens == 0 { return Err(ContractError::InvalidNumTokens {}); } } @@ -112,7 +114,7 @@ pub fn instantiate( } // Check royalty ratio we expect decimal number - let royalty_ratio = Decimal::from_str(&msg.init.royalty_ratio)?; + let royalty_ratio = msg.token_details.royalty_ratio; if royalty_ratio < Decimal::zero() || royalty_ratio > Decimal::one() { return Err(ContractError::InvalidRoyaltyRatio {}); } @@ -134,71 +136,45 @@ pub fn instantiate( let config = Config { per_address_limit: msg.init.per_address_limit, - payment_collector, start_time: msg.init.start_time, - royalty_ratio, - admin: admin.clone(), mint_price: msg.init.mint_price, whitelist_address: maybe_addr(deps.api, msg.init.whitelist_address.clone())?, end_time: msg.init.end_time, - token_limit: msg.init.token_limit, + num_tokens: msg.init.num_tokens, + }; + let auth_details = AuthDetails { + admin: admin.clone(), + payment_collector: payment_collector.clone(), }; CONFIG.save(deps.storage, &config)?; MINTED_COUNT.save(deps.storage, &0)?; + AUTH_DETAILS.save(deps.storage, &auth_details)?; let pause_state = PauseState::new(PAUSED_KEY, PAUSERS_KEY)?; pause_state.set_pausers(deps.storage, info.sender.clone(), vec![admin.clone()])?; - let collection = CollectionDetails { - name: msg.collection_details.name, - description: msg.collection_details.description, - preview_uri: msg.collection_details.preview_uri, - schema: msg.collection_details.schema, - symbol: msg.collection_details.symbol, - id: msg.collection_details.id, - extensible: msg.collection_details.extensible, - nsfw: msg.collection_details.nsfw, - base_uri: msg.collection_details.base_uri, - uri: msg.collection_details.uri, - uri_hash: msg.collection_details.uri_hash, - data: msg.collection_details.data, - token_name: msg.collection_details.token_name, - transferable: msg.collection_details.transferable, - royalty_receivers: msg.collection_details.royalty_receivers, - }; + let collection_details = msg.collection_details; + let token_details = msg.token_details; - COLLECTION.save(deps.storage, &collection)?; + COLLECTION.save(deps.storage, &collection_details)?; + TOKEN_DETAILS.save(deps.storage, &token_details)?; - let nft_creation_msg: CosmosMsg = MsgCreateDenom { - description: collection.description, - id: collection.id, - name: collection.name, - preview_uri: collection.preview_uri, - schema: collection.schema, - sender: env.contract.address.into_string(), - symbol: collection.symbol, - data: collection.data, - uri: collection.uri, - uri_hash: collection.uri_hash.unwrap_or("".to_string()), - creation_fee: Some( - Coin { - denom: creation_fee_denom, - amount: creation_fee_amount, - } - .into(), - ), - royalty_receivers: collection - .royalty_receivers - .unwrap_or(vec![WeightedAddress { - address: admin.into_string(), - weight: Decimal::one().to_string(), - }]), - } + let creation_fee = Coin { + denom: creation_fee_denom, + amount: creation_fee_amount, + }; + + let collection_creation_msg: CosmosMsg = generate_create_denom_msg( + &collection_details, + env.contract.address.clone(), + creation_fee, + admin, + )? .into(); let res = Response::new() - .add_message(nft_creation_msg) + .add_message(collection_creation_msg) .add_attribute("action", "instantiate"); Ok(res) @@ -223,6 +199,10 @@ pub fn execute( ExecuteMsg::UpdateWhitelistAddress { address } => { execute_update_whitelist_address(deps, env, info, address) } + ExecuteMsg::SetAdmin { admin } => execute_set_admin(deps, env, info, admin), + ExecuteMsg::SetPaymentCollector { payment_collector } => { + execute_set_payment_collector(deps, env, info, payment_collector) + } ExecuteMsg::Pause {} => execute_pause(deps, env, info), ExecuteMsg::Unpause {} => execute_unpause(deps, env, info), ExecuteMsg::SetPausers { pausers } => execute_set_pausers(deps, env, info, pausers), @@ -230,10 +210,10 @@ pub fn execute( execute_update_royalty_receivers(deps, env, info, receivers) } ExecuteMsg::UpdateDenom { - name, + collection_name, description, preview_uri, - } => execute_update_denom(deps, env, info, name, description, preview_uri), + } => execute_update_denom(deps, env, info, collection_name, description, preview_uri), ExecuteMsg::PurgeDenom {} => execute_purge_denom(deps, env, info), } } @@ -243,9 +223,10 @@ pub fn execute_mint(deps: DepsMut, env: Env, info: MessageInfo) -> Result= token_limit { + if let Some(num_tokens) = config.num_tokens { + if MINTED_COUNT.load(deps.storage)? >= num_tokens { return Err(ContractError::NoTokensLeftToMint {}); } } @@ -262,9 +243,11 @@ pub fn execute_mint(deps: DepsMut, env: Env, info: MessageInfo) -> Result config.per_address_limit { - return Err(ContractError::AddressReachedMintLimit {}); + // Check if mint limit is set and if it is reached + if let Some(per_address_limit) = config.per_address_limit { + if user_details.total_minted_count > per_address_limit { + return Err(ContractError::AddressReachedMintLimit {}); + } } let token_id = last_token_id(deps.storage) + 1; @@ -325,8 +308,9 @@ pub fn execute_mint(deps: DepsMut, env: Env, info: MessageInfo) -> Result StdResult<_> { total_tokens += 1; @@ -339,12 +323,12 @@ pub fn execute_mint(deps: DepsMut, env: Env, info: MessageInfo) -> Result= token_limit { + if let Some(num_tokens) = config.num_tokens { + if MINTED_COUNT.load(deps.storage)? >= num_tokens { return Err(ContractError::NoTokensLeftToMint {}); } } @@ -419,12 +405,12 @@ pub fn execute_mint_admin( let mint_msg: CosmosMsg = generate_mint_message( &collection, - config.royalty_ratio, - &recipient, - &env.contract.address, - true, + &token_details, token_id.to_string(), + env.contract.address, + recipient, None, + true, ) .into(); @@ -441,14 +427,15 @@ pub fn execute_burn_remaining_tokens( info: MessageInfo, ) -> Result { // Check if sender is admin - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // We cannot burn open edition minter but we can set token limit to 0 let mut config = CONFIG.load(deps.storage)?; - config.token_limit = Some(0); + config.num_tokens = Some(0); CONFIG.save(deps.storage, &config)?; let res = Response::new().add_attribute("action", "burn_remaining_tokens"); @@ -462,8 +449,10 @@ pub fn execute_update_royalty_ratio( ratio: String, ) -> Result { // Check if sender is admin - let mut config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let config = CONFIG.load(deps.storage)?; + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // Check if ratio is decimal number @@ -472,8 +461,9 @@ pub fn execute_update_royalty_ratio( if ratio < Decimal::zero() || ratio > Decimal::one() { return Err(ContractError::InvalidRoyaltyRatio {}); } - config.royalty_ratio = ratio; - + let mut token_details = TOKEN_DETAILS.load(deps.storage)?; + token_details.royalty_ratio = ratio; + TOKEN_DETAILS.save(deps.storage, &token_details)?; CONFIG.save(deps.storage, &config)?; let res = Response::new() @@ -484,19 +474,17 @@ pub fn execute_update_royalty_ratio( pub fn execute_update_mint_price( deps: DepsMut, - env: Env, + _env: Env, info: MessageInfo, mint_price: Coin, ) -> Result { // Check if sender is admin let mut config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } - // Check if trading has started - if env.block.time > config.start_time { - return Err(ContractError::MintingAlreadyStarted {}); - } config.mint_price = mint_price.clone(); CONFIG.save(deps.storage, &config)?; @@ -516,7 +504,9 @@ pub fn execute_update_whitelist_address( ) -> Result { // Check if sender is admin let mut config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } // Current whitelist can not be active if we are updating it @@ -585,6 +575,49 @@ pub fn execute_set_pausers( Ok(res) } +pub fn execute_set_admin( + deps: DepsMut, + _env: Env, + info: MessageInfo, + admin: String, +) -> Result { + // Check if sender is admin + let mut auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { + return Err(ContractError::Unauthorized {}); + } + let new_admin = deps.api.addr_validate(&admin)?; + auth_details.admin = new_admin.clone(); + AUTH_DETAILS.save(deps.storage, &auth_details)?; + + let res = Response::new() + .add_attribute("action", "set_admin") + .add_attribute("admin", admin.to_string()); + Ok(res) +} + +pub fn execute_set_payment_collector( + deps: DepsMut, + _env: Env, + info: MessageInfo, + payment_collector: String, +) -> Result { + // Check if sender is admin + let mut auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { + return Err(ContractError::Unauthorized {}); + } + let new_payment_collector = deps.api.addr_validate(&payment_collector)?; + auth_details.payment_collector = new_payment_collector.clone(); + AUTH_DETAILS.save(deps.storage, &auth_details)?; + + let res = Response::new() + .add_attribute("action", "set_payment_collector") + .add_attribute("payment_collector", new_payment_collector.to_string()); + Ok(res) +} pub fn execute_update_royalty_receivers( deps: DepsMut, env: Env, @@ -593,8 +626,9 @@ pub fn execute_update_royalty_receivers( ) -> Result { // Check if sender is admin let mut collection = COLLECTION.load(deps.storage)?; - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } collection.royalty_receivers = Some(receivers.clone()); @@ -605,9 +639,9 @@ pub fn execute_update_royalty_receivers( sender: env.contract.address.into_string(), royalty_receivers: receivers, id: collection.id, - description: collection.description, - name: collection.name, - preview_uri: collection.preview_uri, + description: "[do-not-modify]".to_string(), + name: "[do-not-modify]".to_string(), + preview_uri: "[do-not-modify]".to_string(), } .into(); @@ -621,26 +655,29 @@ pub fn execute_update_denom( deps: DepsMut, env: Env, info: MessageInfo, - name: Option, + collection_name: Option, description: Option, preview_uri: Option, ) -> Result { // Check if sender is admin let mut collection = COLLECTION.load(deps.storage)?; - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } - collection.name = name.clone().unwrap_or(collection.name); - collection.description = description.clone().unwrap_or(collection.description); - collection.preview_uri = preview_uri.clone().unwrap_or(collection.preview_uri); + collection.collection_name = collection_name + .clone() + .unwrap_or(collection.collection_name); + collection.description = description.clone(); + collection.preview_uri = preview_uri.clone(); COLLECTION.save(deps.storage, &collection)?; let update_msg: CosmosMsg = MsgUpdateDenom { sender: env.contract.address.into_string(), id: collection.id, description: description.unwrap_or("[do-not-modify]".to_string()), - name: name.unwrap_or("[do-not-modify]".to_string()), + name: collection_name.unwrap_or("[do-not-modify]".to_string()), preview_uri: preview_uri.unwrap_or("[do-not-modify]".to_string()), royalty_receivers: collection.royalty_receivers.unwrap_or(vec![]), } @@ -658,8 +695,9 @@ fn execute_purge_denom( ) -> Result { // Check if sender is admin let collection = COLLECTION.load(deps.storage)?; - let config = CONFIG.load(deps.storage)?; - if info.sender != config.admin { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + // Check if admin + if info.sender != auth_details.admin { return Err(ContractError::Unauthorized {}); } let purge_msg: CosmosMsg = MsgPurgeDenom { @@ -676,17 +714,23 @@ fn execute_purge_denom( // Implement Queries #[cfg_attr(not(feature = "library"), entry_point)] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { match msg { QueryMsg::Collection {} => to_json_binary(&query_collection(deps, env)?), + QueryMsg::TokenDetails {} => to_json_binary(&query_token_details(deps, env)?), QueryMsg::Config {} => to_json_binary(&query_config(deps, env)?), QueryMsg::MintedTokens { address } => { to_json_binary(&query_minted_tokens(deps, env, address)?) } QueryMsg::TotalMintedCount {} => to_json_binary(&query_total_tokens_minted(deps, env)?), - QueryMsg::TokensRemaining {} => to_json_binary(&query_tokens_remaining(deps, env)?), QueryMsg::IsPaused {} => to_json_binary(&query_is_paused(deps, env)?), QueryMsg::Pausers {} => to_json_binary(&query_pausers(deps, env)?), + QueryMsg::AuthDetails {} => to_json_binary(&query_auth_details(deps, env)?), + QueryMsg::Extension(ext) => match ext { + OEMQueryExtension::TokensRemaining {} => { + to_json_binary(&query_tokens_remaining(deps, env)?) + } + }, } } @@ -695,6 +739,11 @@ fn query_collection(deps: Deps, _env: Env) -> Result Result { + let token_details = TOKEN_DETAILS.load(deps.storage)?; + Ok(token_details) +} + fn query_config(deps: Deps, _env: Env) -> Result { let config = CONFIG.load(deps.storage)?; Ok(config) @@ -717,9 +766,9 @@ fn query_total_tokens_minted(deps: Deps, _env: Env) -> Result Result { let config = CONFIG.load(deps.storage)?; - if let Some(token_limit) = config.token_limit { + if let Some(num_tokens) = config.num_tokens { let total_tokens = MINTED_COUNT.load(deps.storage).unwrap_or(0); - Ok(token_limit - total_tokens) + Ok(num_tokens - total_tokens) } else { Err(ContractError::TokenLimitNotSet {}) } @@ -736,3 +785,7 @@ fn query_pausers(deps: Deps, _env: Env) -> Result, ContractError> { let pausers = pause_state.pausers.load(deps.storage).unwrap_or(vec![]); Ok(pausers) } +fn query_auth_details(deps: Deps, _env: Env) -> Result { + let auth_details = AUTH_DETAILS.load(deps.storage)?; + Ok(auth_details) +} diff --git a/contracts/minters/open-edition-minter/src/error.rs b/contracts/minters/open-edition-minter/src/error.rs index faaf3f4..b13cf55 100644 --- a/contracts/minters/open-edition-minter/src/error.rs +++ b/contracts/minters/open-edition-minter/src/error.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{StdError, Timestamp, Uint128}; +use cosmwasm_std::{Coin, StdError, Timestamp, Uint128}; use cw_utils::PaymentError; use pauser::PauseError; use thiserror::Error; @@ -24,7 +24,10 @@ pub enum ContractError { DivideByZero {}, #[error("Invalid creation fee")] - InvalidCreationFee { expected: Uint128, sent: Uint128 }, + InvalidCreationFee { + expected: Vec, + sent: Vec, + }, #[error("Minting has not started yet")] MintingNotStarted { diff --git a/contracts/minters/open-edition-minter/src/msg.rs b/contracts/minters/open-edition-minter/src/msg.rs index 07a54ae..29b3482 100644 --- a/contracts/minters/open-edition-minter/src/msg.rs +++ b/contracts/minters/open-edition-minter/src/msg.rs @@ -1,4 +1,4 @@ -use cosmwasm_schema::cw_serde; +use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Coin, Uint128}; use omniflix_std::types::omniflix::onft::v1beta1::WeightedAddress; @@ -26,9 +26,22 @@ pub enum ExecuteMsg { receivers: Vec, }, UpdateDenom { - name: Option, + collection_name: Option, description: Option, preview_uri: Option, }, PurgeDenom {}, + SetAdmin { + admin: String, + }, + SetPaymentCollector { + payment_collector: String, + }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum OEMQueryExtension { + #[returns(Uint128)] + TokensRemaining {}, } diff --git a/contracts/minters/open-edition-minter/src/state.rs b/contracts/minters/open-edition-minter/src/state.rs index 43e301d..94dd006 100644 --- a/contracts/minters/open-edition-minter/src/state.rs +++ b/contracts/minters/open-edition-minter/src/state.rs @@ -3,15 +3,17 @@ use std::u32; use cosmwasm_std::{Addr, Storage}; use cw_storage_plus::{Item, Map}; -use minter_types::{CollectionDetails, Config, UserDetails}; +use minter_types::{AuthDetails, CollectionDetails, Config, TokenDetails, UserDetails}; pub const CONFIG: Item = Item::new("config"); pub const COLLECTION: Item = Item::new("collection"); +pub const TOKEN_DETAILS: Item = Item::new("token_details"); pub const MINTED_COUNT: Item = Item::new("minted_count"); // Address and number of tokens minted pub const MINTED_TOKENS: Map = Map::new("minted_tokens"); +pub const AUTH_DETAILS: Item = Item::new("auth_details"); pub fn last_token_id(store: &mut dyn Storage) -> u32 { - let minted_count = MINTED_COUNT.load(store).unwrap_or_default(); - minted_count + + MINTED_COUNT.load(store).unwrap_or_default() } diff --git a/contracts/whitelists/round-whitelist/.cargo/config b/contracts/whitelists/round-whitelist/.cargo/config new file mode 100644 index 0000000..5b8deaa --- /dev/null +++ b/contracts/whitelists/round-whitelist/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run schema" diff --git a/contracts/whitelists/round-whitelist/schema/omniflix-round-whitelist.json b/contracts/whitelists/round-whitelist/schema/omniflix-round-whitelist.json index 838ab4e..8c44b0d 100644 --- a/contracts/whitelists/round-whitelist/schema/omniflix-round-whitelist.json +++ b/contracts/whitelists/round-whitelist/schema/omniflix-round-whitelist.json @@ -7,14 +7,12 @@ "title": "InstantiateMsg", "type": "object", "required": [ + "admin", "rounds" ], "properties": { "admin": { - "type": [ - "string", - "null" - ] + "type": "string" }, "rounds": { "type": "array", diff --git a/contracts/whitelists/round-whitelist/schema/raw/instantiate.json b/contracts/whitelists/round-whitelist/schema/raw/instantiate.json index d9713fa..2addcfc 100644 --- a/contracts/whitelists/round-whitelist/schema/raw/instantiate.json +++ b/contracts/whitelists/round-whitelist/schema/raw/instantiate.json @@ -3,14 +3,12 @@ "title": "InstantiateMsg", "type": "object", "required": [ + "admin", "rounds" ], "properties": { "admin": { - "type": [ - "string", - "null" - ] + "type": "string" }, "rounds": { "type": "array", diff --git a/contracts/whitelists/round-whitelist/src/contract.rs b/contracts/whitelists/round-whitelist/src/contract.rs index 317eb86..e38f452 100644 --- a/contracts/whitelists/round-whitelist/src/contract.rs +++ b/contracts/whitelists/round-whitelist/src/contract.rs @@ -3,7 +3,6 @@ use cosmwasm_std::entry_point; use cosmwasm_std::Coin; use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; use cw2::set_contract_version; -use cw_utils::maybe_addr; use omniflix_round_whitelist_factory::msg::ParamsResponse; use omniflix_round_whitelist_factory::msg::QueryMsg as QueryFactoryParams; @@ -30,7 +29,7 @@ pub fn instantiate( &QueryFactoryParams::Params {}, )?; - let admin = maybe_addr(deps.api, msg.admin)?.unwrap_or(info.sender); + let admin = deps.api.addr_validate(&msg.admin)?; let rounds = msg.rounds; // Check if rounds are valid @@ -39,7 +38,7 @@ pub fn instantiate( } let rounds_state = Rounds::new(ROUNDS_KEY); rounds_state.check_round_overlaps(deps.storage, Some(rounds.clone()))?; - // Save the rounds + // Save the rounds rounds.clone().into_iter().for_each(|round| { let _ = rounds_state.save(deps.storage, &round); }); diff --git a/contracts/whitelists/round-whitelist/src/state.rs b/contracts/whitelists/round-whitelist/src/state.rs index 1eed2d0..61ff37b 100644 --- a/contracts/whitelists/round-whitelist/src/state.rs +++ b/contracts/whitelists/round-whitelist/src/state.rs @@ -111,7 +111,7 @@ impl<'a> Rounds<'a> { pub fn load(&self, store: &dyn Storage, id: u32) -> Result { self.0 .may_load(store, id)? - .ok_or_else(|| ContractError::RoundNotFound {}) + .ok_or(ContractError::RoundNotFound {}) } pub fn remove(&self, store: &mut dyn Storage, id: u32) -> StdResult<()> { self.0.remove(store, id); @@ -124,7 +124,7 @@ impl<'a> Rounds<'a> { ) -> Option<(u32, Round)> { self.0 .range(store, None, None, Order::Ascending) - .filter_map(|result| result.ok().map(|(id, round)| (id, round))) + .filter_map(|result| result.ok()) .find(|(_, round)| round.is_active(current_time)) } diff --git a/contracts/whitelists/round-whitelist/ts/OmniflixWhitelist.client.ts b/contracts/whitelists/round-whitelist/ts/OmniflixWhitelist.client.ts deleted file mode 100644 index 164e669..0000000 --- a/contracts/whitelists/round-whitelist/ts/OmniflixWhitelist.client.ts +++ /dev/null @@ -1,184 +0,0 @@ -/** -* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ - -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; -import { StdFee } from "@cosmjs/amino"; -import { Addr, Timestamp, Uint64, Uint128, InstantiateMsg, Round, Coin, ExecuteMsg, QueryMsg, IsActiveResponse, IsMemberResponse, MembersResponse, MintPriceResponse, ArrayOfRound } from "./OmniflixWhitelist.types"; -export interface OmniflixWhitelistReadOnlyInterface { - contractAddress: string; - rounds: () => Promise; - round: ({ - roundIndex - }: { - roundIndex: number; - }) => Promise; - isActive: () => Promise; - activeRound: () => Promise; - members: ({ - limit, - roundIndex, - startAfter - }: { - limit?: number; - roundIndex: number; - startAfter?: string; - }) => Promise; - price: () => Promise; - isMember: ({ - address - }: { - address: string; - }) => Promise; -} -export class OmniflixWhitelistQueryClient implements OmniflixWhitelistReadOnlyInterface { - client: CosmWasmClient; - contractAddress: string; - - constructor(client: CosmWasmClient, contractAddress: string) { - this.client = client; - this.contractAddress = contractAddress; - this.rounds = this.rounds.bind(this); - this.round = this.round.bind(this); - this.isActive = this.isActive.bind(this); - this.activeRound = this.activeRound.bind(this); - this.members = this.members.bind(this); - this.price = this.price.bind(this); - this.isMember = this.isMember.bind(this); - } - - rounds = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - rounds: {} - }); - }; - round = async ({ - roundIndex - }: { - roundIndex: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - round: { - round_index: roundIndex - } - }); - }; - isActive = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - is_active: {} - }); - }; - activeRound = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - active_round: {} - }); - }; - members = async ({ - limit, - roundIndex, - startAfter - }: { - limit?: number; - roundIndex: number; - startAfter?: string; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - members: { - limit, - round_index: roundIndex, - start_after: startAfter - } - }); - }; - price = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - price: {} - }); - }; - isMember = async ({ - address - }: { - address: string; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - is_member: { - address - } - }); - }; -} -export interface OmniflixWhitelistInterface extends OmniflixWhitelistReadOnlyInterface { - contractAddress: string; - sender: string; - removeRound: ({ - roundIndex - }: { - roundIndex: number; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - addRound: ({ - round - }: { - round: Round; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - privateMint: ({ - admin, - minter - }: { - admin: string; - minter: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; -} -export class OmniflixWhitelistClient extends OmniflixWhitelistQueryClient implements OmniflixWhitelistInterface { - client: SigningCosmWasmClient; - sender: string; - contractAddress: string; - - constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { - super(client, contractAddress); - this.client = client; - this.sender = sender; - this.contractAddress = contractAddress; - this.removeRound = this.removeRound.bind(this); - this.addRound = this.addRound.bind(this); - this.privateMint = this.privateMint.bind(this); - } - - removeRound = async ({ - roundIndex - }: { - roundIndex: number; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - remove_round: { - round_index: roundIndex - } - }, fee, memo, _funds); - }; - addRound = async ({ - round - }: { - round: Round; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - add_round: { - round - } - }, fee, memo, _funds); - }; - privateMint = async ({ - admin, - minter - }: { - admin: string; - minter: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - private_mint: { - admin, - minter - } - }, fee, memo, _funds); - }; -} \ No newline at end of file diff --git a/contracts/whitelists/round-whitelist/ts/OmniflixWhitelist.types.ts b/contracts/whitelists/round-whitelist/ts/OmniflixWhitelist.types.ts deleted file mode 100644 index ab4dd92..0000000 --- a/contracts/whitelists/round-whitelist/ts/OmniflixWhitelist.types.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** -* This file was automatically generated by @cosmwasm/ts-codegen@0.35.3. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ - -export type Addr = string; -export type Timestamp = Uint64; -export type Uint64 = string; -export type Uint128 = string; -export interface InstantiateMsg { - admin?: string | null; - rounds: Round[]; -} -export interface Round { - addresses: Addr[]; - end_time: Timestamp; - mint_price: Coin; - round_per_address_limit: number; - start_time: Timestamp; -} -export interface Coin { - amount: Uint128; - denom: string; - [k: string]: unknown; -} -export type ExecuteMsg = { - remove_round: { - round_index: number; - }; -} | { - add_round: { - round: Round; - }; -} | { - private_mint: { - admin: string; - minter: string; - }; -}; -export type QueryMsg = { - rounds: {}; -} | { - round: { - round_index: number; - }; -} | { - is_active: {}; -} | { - active_round: {}; -} | { - members: { - limit?: number | null; - round_index: number; - start_after?: string | null; - }; -} | { - price: {}; -} | { - is_member: { - address: string; - }; -}; -export interface IsActiveResponse { - is_active: boolean; -} -export interface IsMemberResponse { - is_member: boolean; -} -export interface MembersResponse { - members: string[]; -} -export interface MintPriceResponse { - mint_price: Coin; -} -export type ArrayOfRound = Round[]; \ No newline at end of file diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 7502acb..972fb6a 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -27,7 +27,6 @@ schemars = "0.8.16" cw-multi-test = "0.20.0" minter-types={ workspace = true } whitelist-types ={ workspace = true } -open-edition-minter-types = { workspace = true } omniflix-minter-factory = {path = "../contracts/factories/minter-factory"} omniflix-open-edition-minter-factory = {path = "../contracts/factories/open-edition-minter-factory"} omniflix-minter = {path = "../contracts/minters/minter"} @@ -43,6 +42,7 @@ itertools = "0.12.0" serde = "1.0.195" thiserror = "1.0.56" pauser = { workspace = true } +factory-types = { workspace = true } diff --git a/integration-tests/src/scenarios.rs b/integration-tests/src/scenarios.rs index a9abbbb..ce65e6d 100644 --- a/integration-tests/src/scenarios.rs +++ b/integration-tests/src/scenarios.rs @@ -1,32 +1,20 @@ #[cfg(test)] mod scenarios { - - use std::ops::Add; - - use cosmwasm_std::{ - coin, coins, to_json_binary, Addr, BlockInfo, QueryRequest, Timestamp, Uint128, WasmQuery, - }; - use cw_multi_test::{BankSudo, Executor, SudoMsg}; + use cosmwasm_std::Decimal; + use cosmwasm_std::{coin, coins, Addr, BlockInfo, Timestamp, Uint128}; + use cw_multi_test::Executor; use minter_types::CollectionDetails; - use minter_types::Token; - use minter_types::UserDetails; - - use minter_types::QueryMsg; + use minter_types::TokenDetails; use omniflix_minter::msg::ExecuteMsg as MinterExecuteMsg; use omniflix_minter_factory::msg::CreateMinterMsg; + use omniflix_minter_factory::msg::ExecuteMsg as FactoryExecuteMsg; use omniflix_minter_factory::msg::MinterInitExtention; - use omniflix_minter_factory::msg::{ - ExecuteMsg as FactoryExecuteMsg, InstantiateMsg as FactoryInstantiateMsg, - }; - use omniflix_open_edition_minter::error; use omniflix_round_whitelist::msg::ExecuteMsg as RoundWhitelistExecuteMsg; - use omniflix_round_whitelist::round; use whitelist_types::Round; use whitelist_types::RoundWhitelistQueryMsgs; use crate::utils::{ - get_contract_address_from_res, mint_to_address, return_minter_instantiate_msg, - return_rounds, + get_contract_address_from_res, mint_to_address, return_factory_inst_message, }; use crate::{setup::setup, utils::query_onft_collection}; @@ -121,12 +109,7 @@ mod scenarios { let creator = test_addresses.creator; let _collector = test_addresses.collector; - let factory_inst_msg = FactoryInstantiateMsg { - admin: Some(admin.to_string()), - minter_creation_fee: coin(1000000, "uflix"), - minter_code_id, - fee_collector_address: admin.clone().into_string(), - }; + let factory_inst_msg = return_factory_inst_message(minter_code_id); let minter_factory_addr = app .instantiate_contract( minter_factory_code_id, @@ -137,13 +120,7 @@ mod scenarios { None, ) .unwrap(); - let round_whitelist_factory_inst_msg = - omniflix_round_whitelist_factory::msg::InstantiateMsg { - admin: Some(admin.to_string()), - fee_collector_address: admin.clone().into_string(), - whitelist_code_id: round_whitelist_code_id, - whitelist_creation_fee: coin(1000000, "uflix"), - }; + let round_whitelist_factory_inst_msg = return_factory_inst_message(round_whitelist_code_id); let round_whitelist_factory_addr = app .instantiate_contract( round_whitelist_factory_code_id, @@ -187,7 +164,7 @@ mod scenarios { .to_vec(); let round_whitelist_inst_msg = whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }; let create_round_whitelist_msg = @@ -206,29 +183,34 @@ mod scenarios { let minter_1_inst_message = CreateMinterMsg { collection_details: CollectionDetails { - name: "Test_collection_1".to_string(), - description: "description".to_string(), - preview_uri: "preview_uri".to_string(), - schema: "schema".to_string(), + collection_name: "Test_collection_1".to_string(), + description: Some("description".to_string()), + preview_uri: Some("preview_uri".to_string()), + schema: Some("schema".to_string()), symbol: "symbol".to_string(), id: "test1".to_string(), - extensible: true, - nsfw: false, - base_uri: "base_uri".to_string(), - uri: "uri".to_string(), + uri: Some("uri".to_string()), uri_hash: Some("uri_hash".to_string()), - data: "data".to_string(), - token_name: "token_name".to_string(), - transferable: true, + data: Some("data".to_string()), royalty_receivers: None, }, + token_details: TokenDetails { + transferable: true, + token_name: "token_name".to_string(), + description: Some("description".to_string()), + base_token_uri: "base_token_uri".to_string(), + preview_uri: Some("preview_uri".to_string()), + extensible: true, + nsfw: false, + royalty_ratio: Decimal::percent(10), + data: None, + }, init: MinterInitExtention { admin: creator.to_string(), mint_price: coin(5_000_000, "uflix"), start_time: Timestamp::from_nanos(1_000_000_000), end_time: Some(Timestamp::from_nanos(2_000_000_000)), - per_address_limit: 1, - royalty_ratio: "0.1".to_string(), + per_address_limit: Some(1), payment_collector: Some(creator.to_string()), whitelist_address: Some(round_whitelist_addr.clone()), num_tokens: 100, @@ -238,10 +220,10 @@ mod scenarios { minter_2_inst_msg.init.mint_price = coin(10_000_000, "uflix"); minter_2_inst_msg.init.start_time = Timestamp::from_nanos(2_000_000_000); minter_2_inst_msg.init.end_time = Some(Timestamp::from_nanos(3_000_000_000)); - minter_2_inst_msg.init.per_address_limit = 100; + minter_2_inst_msg.init.per_address_limit = Some(100); minter_2_inst_msg.init.num_tokens = 100; minter_2_inst_msg.collection_details.id = "test2".to_string(); - minter_2_inst_msg.collection_details.name = "Test_collection_2".to_string(); + minter_2_inst_msg.collection_details.collection_name = "Test_collection_2".to_string(); // Instantiate minter_1 let res = app @@ -283,7 +265,7 @@ mod scenarios { height: 1_000, time: Timestamp::from_nanos(1_000_000 + 1), }); - let res = app + let _res = app .execute_contract( collector_1.clone(), Addr::unchecked(minter_1_addr.clone()), @@ -294,7 +276,7 @@ mod scenarios { // Collector_1 buys 1 NFT from Minter_2 during round 1 // Price is round 1 price and its 1_000_000 uflix - let res = app + let _res = app .execute_contract( collector_1.clone(), Addr::unchecked(minter_2_addr.clone()), @@ -348,7 +330,7 @@ mod scenarios { collector_1.to_string(), coins(2000000, "ibc_atom"), ); - let res = app + let _res = app .execute_contract( collector_1.clone(), Addr::unchecked(minter_1_addr.clone()), @@ -412,7 +394,7 @@ mod scenarios { .0; // Add collector_1 to round 3 whitelist addresses - let res = app + let _res = app .execute_contract( admin.clone(), Addr::unchecked(round_whitelist_addr.clone()), @@ -448,7 +430,7 @@ mod scenarios { .collect::>(), mint_price: coin(200_000, "uflix"), }; - let res = app + let _res = app .execute_contract( admin.clone(), Addr::unchecked(round_whitelist_addr.clone()), @@ -500,7 +482,7 @@ mod scenarios { mint_to_address(&mut app, collector_1.to_string(), coins(5000000, "uflix")); // Creator buys 1 NFT from Minter_1 - let res = app + let _res = app .execute_contract( creator.clone(), Addr::unchecked(minter_1_addr.clone()), diff --git a/integration-tests/src/setup.rs b/integration-tests/src/setup.rs index 3c215d4..ed3c5e2 100644 --- a/integration-tests/src/setup.rs +++ b/integration-tests/src/setup.rs @@ -1,5 +1,5 @@ -use cosmwasm_std::{coins, Addr, BlockInfo, Coin, Timestamp}; -use cw_multi_test::{BankSudo, ContractWrapper, SudoMsg}; +use cosmwasm_std::{coins, Addr, BlockInfo, Timestamp}; +use cw_multi_test::ContractWrapper; use omniflix_minter::contract::{ execute as minter_execute, instantiate as minter_instantiate, query as minter_query, }; diff --git a/integration-tests/src/test_minter_creation.rs b/integration-tests/src/test_minter_creation.rs index 5a84fa3..518cf3c 100644 --- a/integration-tests/src/test_minter_creation.rs +++ b/integration-tests/src/test_minter_creation.rs @@ -1,20 +1,22 @@ #[cfg(test)] mod test_minter_creation { + use cosmwasm_std::Empty; use cosmwasm_std::{ - coin, to_json_binary, Addr, Decimal, QueryRequest, Timestamp, Uint128, WasmQuery, + coin, to_json_binary, Decimal, QueryRequest, Timestamp, Uint128, WasmQuery, }; use cw_multi_test::Executor; - use minter_types::Token; + use factory_types::CustomPaymentError; + use minter_types::{Token, TokenDetails}; use minter_types::Config as MinterConfig; use minter_types::QueryMsg; - use omniflix_minter_factory::msg::{ - ExecuteMsg as FactoryExecuteMsg, InstantiateMsg as FactoryInstantiateMsg, - }; + use omniflix_minter_factory::msg::ExecuteMsg as FactoryExecuteMsg; - use crate::utils::{get_contract_address_from_res, return_minter_instantiate_msg}; + use crate::utils::{ + get_contract_address_from_res, return_factory_inst_message, return_minter_instantiate_msg, + }; use crate::{setup::setup, utils::query_onft_collection}; use omniflix_minter::error::ContractError as MinterContractError; @@ -36,12 +38,7 @@ mod test_minter_creation { let creator = test_addresses.creator; let _collector = test_addresses.collector; - let factory_inst_msg = FactoryInstantiateMsg { - admin: Some(admin.to_string()), - minter_creation_fee: coin(1000000, "uflix"), - minter_code_id, - fee_collector_address: admin.clone().into_string(), - }; + let factory_inst_msg = return_factory_inst_message(minter_code_id); let factory_addr = app .instantiate_contract( minter_factory_code_id, @@ -71,10 +68,10 @@ mod test_minter_creation { let error = res.downcast_ref::().unwrap(); assert_eq!( error, - &MinterFactoryError::IncorrectFunds { + &MinterFactoryError::PaymentError(CustomPaymentError::InsufficientFunds { expected: [coin(1000000, "uflix"), coin(1000000, "uflix")].to_vec(), actual: [].to_vec() - } + }) ); // Send incorrect denom let error = app @@ -90,10 +87,10 @@ mod test_minter_creation { let error = res.downcast_ref::().unwrap(); assert_eq!( error, - &MinterFactoryError::IncorrectFunds { + &MinterFactoryError::PaymentError(CustomPaymentError::InsufficientFunds { expected: [coin(1000000, "uflix"), coin(1000000, "uflix")].to_vec(), actual: [coin(1000000, "diffirent_denom")].to_vec() - } + }) ); // Send correct denom incorrect amount let error = app @@ -109,10 +106,10 @@ mod test_minter_creation { let error = res.downcast_ref::().unwrap(); assert_eq!( error, - &MinterFactoryError::IncorrectFunds { + &MinterFactoryError::PaymentError(CustomPaymentError::InsufficientFunds { expected: [coin(1000000, "uflix"), coin(1000000, "uflix")].to_vec(), actual: [coin(1000000, "uflix")].to_vec() - } + }) ); // Send 0 num tokens @@ -135,7 +132,7 @@ mod test_minter_creation { // Send royalty ratio more than 100% let mut minter_inst_msg = return_minter_instantiate_msg(); - minter_inst_msg.init.royalty_ratio = "1.1".to_string(); + minter_inst_msg.token_details.royalty_ratio = Decimal::percent(101); let create_minter_msg = FactoryExecuteMsg::CreateMinter { msg: minter_inst_msg, }; @@ -244,26 +241,32 @@ mod test_minter_creation { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::Config {}).unwrap(), + msg: to_json_binary(&QueryMsg::::Config {}).unwrap(), })) .unwrap(); - assert_eq!(config_data.per_address_limit, 1); + assert_eq!(config_data.per_address_limit, Some(1)); assert_eq!(config_data.mint_price.denom, "uflix".to_string()); assert_eq!(config_data.start_time, Timestamp::from_nanos(1000000000)); assert_eq!(config_data.mint_price.amount, Uint128::from(1000000u128)); - assert_eq!( - config_data.royalty_ratio, - Decimal::from_ratio(1u128, 10u128) - ); - assert_eq!(config_data.admin, Addr::unchecked("creator")); - assert_eq!(config_data.payment_collector, Addr::unchecked("creator")); + + let token_details: TokenDetails = app + .wrap() + .query(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: minter_address.clone(), + msg: to_json_binary(&QueryMsg::::TokenDetails {}).unwrap(), + })) + .unwrap(); + assert_eq!(token_details.royalty_ratio, Decimal::percent(10)); // Query mintable tokens let mintable_tokens_data: Vec = app .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintableTokens {}).unwrap(), + msg: to_json_binary(&QueryMsg::Extension( + omniflix_minter::msg::MinterExtensionQueryMsg::MintableTokens {}, + )) + .unwrap(), })) .unwrap(); assert_eq!(mintable_tokens_data.len(), 1000); @@ -275,7 +278,10 @@ mod test_minter_creation { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::TotalTokens {}).unwrap(), + msg: to_json_binary(&QueryMsg::Extension( + omniflix_minter::msg::MinterExtensionQueryMsg::TotalTokensRemaining {}, + )) + .unwrap(), })) .unwrap(); assert_eq!(total_tokens_remaining_data, 1000); diff --git a/integration-tests/src/test_minting.rs b/integration-tests/src/test_minting.rs index 31831d2..7bcf2b6 100644 --- a/integration-tests/src/test_minting.rs +++ b/integration-tests/src/test_minting.rs @@ -2,20 +2,19 @@ mod test_minting { use cosmwasm_std::{ - coin, coins, to_json_binary, Addr, BlockInfo, QueryRequest, Timestamp, Uint128, WasmQuery, + coin, coins, to_json_binary, Addr, BlockInfo, Empty, QueryRequest, Timestamp, Uint128, + WasmQuery, }; use cw_multi_test::{BankSudo, Executor, SudoMsg}; - use minter_types::Token; use minter_types::UserDetails; + use minter_types::{QueryMsg as MinterQueryMsg, Token}; - use minter_types::QueryMsg; - use omniflix_minter::msg::ExecuteMsg as MinterExecuteMsg; - use omniflix_minter_factory::msg::{ - ExecuteMsg as FactoryExecuteMsg, InstantiateMsg as FactoryInstantiateMsg, - }; + use omniflix_minter::msg::{ExecuteMsg as MinterExecuteMsg, MinterExtensionQueryMsg}; + use omniflix_minter_factory::msg::ExecuteMsg as FactoryExecuteMsg; use crate::utils::{ - get_contract_address_from_res, return_minter_instantiate_msg, return_rounds, + get_contract_address_from_res, return_factory_inst_message, return_minter_instantiate_msg, + return_rounds, }; use crate::{setup::setup, utils::query_onft_collection}; @@ -39,12 +38,7 @@ mod test_minting { let creator = test_addresses.creator; let collector = test_addresses.collector; - let factory_inst_msg = FactoryInstantiateMsg { - admin: Some(admin.to_string()), - minter_creation_fee: coin(1000000, "uflix"), - minter_code_id, - fee_collector_address: admin.clone().into_string(), - }; + let factory_inst_msg = return_factory_inst_message(minter_code_id); let factory_addr = app .instantiate_contract( minter_factory_code_id, @@ -107,8 +101,8 @@ mod test_minting { let error = res.downcast_ref::().unwrap(); assert_eq!( error, - &MinterContractError::PaymentError(cw_utils::PaymentError::MissingDenom( - "uflix".to_string() + &MinterContractError::PaymentError(cw_utils::PaymentError::ExtraDenom( + "incorrect_denom".to_string() )) ); @@ -199,9 +193,11 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintedTokens { - address: collector.clone().into_string(), - }) + msg: to_json_binary::>( + &MinterQueryMsg::MintedTokens { + address: collector.clone().into_string(), + }, + ) .unwrap(), })) .unwrap(); @@ -212,7 +208,10 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintableTokens {}).unwrap(), + msg: to_json_binary(&MinterQueryMsg::Extension( + omniflix_minter::msg::MinterExtensionQueryMsg::MintableTokens {}, + )) + .unwrap(), })) .unwrap(); assert_eq!(total_tokens_remaining_data.len(), 999); @@ -257,7 +256,10 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintableTokens {}).unwrap(), + msg: to_json_binary(&MinterQueryMsg::Extension( + omniflix_minter::msg::MinterExtensionQueryMsg::MintableTokens {}, + )) + .unwrap(), })) .unwrap(); assert_eq!(mintable_tokens_data.len(), 0); @@ -267,7 +269,10 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::TotalTokens {}).unwrap(), + msg: to_json_binary(&MinterQueryMsg::Extension( + omniflix_minter::msg::MinterExtensionQueryMsg::TotalTokensRemaining {}, + )) + .unwrap(), })) .unwrap(); assert_eq!(total_tokens_remaining_data, 0); @@ -281,9 +286,11 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintedTokens { - address: Addr::unchecked(format!("{}{}", collector, i)).into_string(), - }) + msg: to_json_binary::>( + &MinterQueryMsg::MintedTokens { + address: Addr::unchecked(format!("{}{}", collector, i)).to_string(), + }, + ) .unwrap(), })) .unwrap(); @@ -331,12 +338,7 @@ mod test_minting { let creator = test_addresses.creator; let collector = test_addresses.collector; - let factory_inst_msg = FactoryInstantiateMsg { - admin: Some(admin.to_string()), - minter_creation_fee: coin(1000000, "uflix"), - minter_code_id, - fee_collector_address: admin.clone().into_string(), - }; + let factory_inst_msg = return_factory_inst_message(minter_code_id); let factory_addr = app .instantiate_contract( minter_factory_code_id, @@ -446,7 +448,7 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintedTokens { + msg: to_json_binary(&MinterQueryMsg::::MintedTokens { address: "gift_recipient".to_string(), }) .unwrap(), @@ -459,7 +461,10 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintableTokens {}).unwrap(), + msg: to_json_binary(&MinterQueryMsg::Extension( + MinterExtensionQueryMsg::MintableTokens {}, + )) + .unwrap(), })) .unwrap(); assert_eq!(total_tokens_remaining_data.len(), 999); @@ -502,7 +507,7 @@ mod test_minting { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::MintedTokens { + msg: to_json_binary(&MinterQueryMsg::::MintedTokens { address: "gift_recipient".to_string(), }) .unwrap(), @@ -527,12 +532,7 @@ mod test_minting { let creator = test_addresses.creator; let collector = test_addresses.collector; - let factory_inst_msg = FactoryInstantiateMsg { - admin: Some(admin.to_string()), - minter_creation_fee: coin(1000000, "uflix"), - minter_code_id, - fee_collector_address: admin.clone().into_string(), - }; + let factory_inst_msg = return_factory_inst_message(minter_code_id); let minter_factory_addr = app .instantiate_contract( minter_factory_code_id, @@ -543,13 +543,7 @@ mod test_minting { None, ) .unwrap(); - let round_whitelist_factory_inst_msg = - omniflix_round_whitelist_factory::msg::InstantiateMsg { - admin: Some(admin.to_string()), - fee_collector_address: admin.clone().into_string(), - whitelist_code_id: round_whitelist_code_id, - whitelist_creation_fee: coin(1000000, "uflix"), - }; + let round_whitelist_factory_inst_msg = return_factory_inst_message(round_whitelist_code_id); let round_whitelist_factory_addr = app .instantiate_contract( round_whitelist_factory_code_id, @@ -569,7 +563,7 @@ mod test_minting { // Try instantiating minter with already active whitelist let round_whitelist_inst_msg = whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }; let create_round_whitelist_msg = @@ -593,7 +587,7 @@ mod test_minting { let mut minter_inst_msg = return_minter_instantiate_msg(); minter_inst_msg.init.whitelist_address = Some(round_whitelist_address.clone()); - minter_inst_msg.init.per_address_limit = 2; + minter_inst_msg.init.per_address_limit = Some(2); let create_minter_msg = FactoryExecuteMsg::CreateMinter { msg: minter_inst_msg, @@ -672,8 +666,8 @@ mod test_minting { let error = res.downcast_ref::().unwrap(); assert_eq!( error, - &MinterContractError::PaymentError(cw_utils::PaymentError::MissingDenom( - "diffirent_denom".to_string() + &MinterContractError::PaymentError(cw_utils::PaymentError::ExtraDenom( + "uflix".to_string() )) ); // Try minting round one with wrong amount diff --git a/integration-tests/src/test_open_edition_minter.rs b/integration-tests/src/test_open_edition_minter.rs index 7fdb403..4298db0 100644 --- a/integration-tests/src/test_open_edition_minter.rs +++ b/integration-tests/src/test_open_edition_minter.rs @@ -1,20 +1,22 @@ #[cfg(test)] mod test_open_edition_minter_creation { - use cosmwasm_std::{coin, Addr, Coin, Decimal, Timestamp, Uint128}; + use cosmwasm_std::{coin, Coin, Decimal, Timestamp, Uint128}; use cw_multi_test::Executor; + use factory_types::CustomPaymentError; use minter_types::{CollectionDetails, Config}; - use omniflix_open_edition_minter_factory::msg::{ - ExecuteMsg as OpenEditionMinterFactoryExecuteMsg, - InstantiateMsg as OpenEditionMinterFactoryInstantiateMsg, - }; + use omniflix_open_edition_minter_factory::msg::ExecuteMsg as OpenEditionMinterFactoryExecuteMsg; - use crate::utils::{get_contract_address_from_res, return_open_edition_minter_inst_msg}; + use crate::utils::{ + get_contract_address_from_res, return_factory_inst_message, + return_open_edition_minter_inst_msg, + }; use crate::{setup::setup, utils::query_onft_collection}; - use open_edition_minter_types::QueryMsg as OpenEditionMinterQueryMsg; + use minter_types::QueryMsg as OpenEditionMinterQueryMsg; + use omniflix_open_edition_minter::msg::OEMQueryExtension; use omniflix_open_edition_minter::error::ContractError as OpenEditionMinterError; @@ -37,12 +39,8 @@ mod test_open_edition_minter_creation { let _collector = test_addresses.collector; // Instantiate the minter factory - let open_edition_minter_factory_instantiate_msg = OpenEditionMinterFactoryInstantiateMsg { - admin: Some(admin.to_string()), - open_edition_minter_code_id, - fee_collector_address: admin.to_string(), - minter_creation_fee: coin(1000000, "uflix"), - }; + let open_edition_minter_factory_instantiate_msg = + return_factory_inst_message(open_edition_minter_code_id); let open_edition_minter_factory_address = app .instantiate_contract( @@ -72,7 +70,7 @@ mod test_open_edition_minter_creation { let err = res.source().unwrap(); let error = err.downcast_ref::().unwrap(); assert_eq!( - OpenEditionMinterFactoryError::IncorrectFunds { + OpenEditionMinterFactoryError::PaymentError(CustomPaymentError::InsufficientFunds { expected: [ Coin { denom: "uflix".to_string(), @@ -85,7 +83,7 @@ mod test_open_edition_minter_creation { ] .to_vec(), actual: vec![] - }, + }), *error ); @@ -101,7 +99,8 @@ mod test_open_edition_minter_creation { let err = res.source().unwrap(); let error = err.downcast_ref::().unwrap(); assert_eq!( - OpenEditionMinterFactoryError::IncorrectFunds { + *error, + OpenEditionMinterFactoryError::PaymentError(CustomPaymentError::InsufficientFunds { expected: [ Coin { denom: "uflix".to_string(), @@ -113,9 +112,8 @@ mod test_open_edition_minter_creation { } ] .to_vec(), - actual: vec![coin(1000000, "incorrect_denom")] - }, - *error + actual: vec![coin(1000000, "incorrect_denom"),] + }), ); // Send incorrect amount @@ -130,7 +128,8 @@ mod test_open_edition_minter_creation { let err = res.source().unwrap(); let error = err.downcast_ref::().unwrap(); assert_eq!( - OpenEditionMinterFactoryError::IncorrectFunds { + *error, + OpenEditionMinterFactoryError::PaymentError(CustomPaymentError::InsufficientFunds { expected: [ Coin { denom: "uflix".to_string(), @@ -142,14 +141,13 @@ mod test_open_edition_minter_creation { } ] .to_vec(), - actual: vec![coin(1000000, "uflix")] - }, - *error + actual: vec![coin(1000000, "uflix"),] + }), ); // Send zero token limit let mut open_edition_minter_instantiate_msg = return_open_edition_minter_inst_msg(); - open_edition_minter_instantiate_msg.init.token_limit = Some(0); + open_edition_minter_instantiate_msg.init.num_tokens = Some(0); let create_minter_msg = OpenEditionMinterFactoryExecuteMsg::CreateMinter { msg: open_edition_minter_instantiate_msg, }; @@ -169,7 +167,7 @@ mod test_open_edition_minter_creation { // Send zero per address limit let mut open_edition_minter_instantiate_msg = return_open_edition_minter_inst_msg(); - open_edition_minter_instantiate_msg.init.per_address_limit = 0; + open_edition_minter_instantiate_msg.init.per_address_limit = Some(0); let create_minter_msg = OpenEditionMinterFactoryExecuteMsg::CreateMinter { msg: open_edition_minter_instantiate_msg, }; @@ -189,7 +187,9 @@ mod test_open_edition_minter_creation { // Send incorrect royalty ratio let mut open_edition_minter_instantiate_msg = return_open_edition_minter_inst_msg(); - open_edition_minter_instantiate_msg.init.royalty_ratio = "1.1".to_string(); + open_edition_minter_instantiate_msg + .token_details + .royalty_ratio = Decimal::percent(101); let create_minter_msg = OpenEditionMinterFactoryExecuteMsg::CreateMinter { msg: open_edition_minter_instantiate_msg, }; @@ -273,33 +273,30 @@ mod test_open_edition_minter_creation { // We are collecting fee as expected assert_eq!(uflix_after - uflix_before, Uint128::from(1000000u128)); - // Query the minter - let query_msg = OpenEditionMinterQueryMsg::Config {}; - let config_res: Config = app .wrap() - .query_wasm_smart(open_edition_minter_address.clone(), &query_msg) + .query_wasm_smart( + open_edition_minter_address.clone(), + &OpenEditionMinterQueryMsg::::Config {}, + ) .unwrap(); assert_eq!( config_res, Config { - admin: Addr::unchecked(creator.clone()), - payment_collector: Addr::unchecked(creator.clone()), end_time: Some(Timestamp::from_nanos(2_000_000_000)), start_time: Timestamp::from_nanos(1_000_000_000), mint_price: Coin { denom: "uflix".to_string(), amount: Uint128::from(1000000u128) }, - per_address_limit: 1, - royalty_ratio: Decimal::percent(10), + per_address_limit: Some(1), whitelist_address: None, - token_limit: Some(1000), + num_tokens: Some(1000) } ); // Query the minter - let query_msg = OpenEditionMinterQueryMsg::TokensRemaining {}; + let query_msg = OpenEditionMinterQueryMsg::Extension(OEMQueryExtension::TokensRemaining {}); let tokens_remaining_res: u32 = app .wrap() @@ -309,7 +306,7 @@ mod test_open_edition_minter_creation { assert_eq!(tokens_remaining_res, 1000); // Query the minter - let query_msg = OpenEditionMinterQueryMsg::TotalMintedCount {}; + let query_msg = OpenEditionMinterQueryMsg::::TotalMintedCount {}; let total_minted_count_res: u32 = app .wrap() @@ -319,30 +316,24 @@ mod test_open_edition_minter_creation { assert_eq!(total_minted_count_res, 0); // Query the minter - let query_msg = OpenEditionMinterQueryMsg::Collection {}; + let query_msg = OpenEditionMinterQueryMsg::::Collection {}; let collection_res: CollectionDetails = app .wrap() .query_wasm_smart(open_edition_minter_address.clone(), &query_msg) .unwrap(); - assert_eq!( collection_res, CollectionDetails { - name: "name".to_string(), - description: "description".to_string(), - preview_uri: "preview_uri".to_string(), - schema: "schema".to_string(), + collection_name: "name".to_string(), + description: Some("description".to_string()), + preview_uri: Some("preview_uri".to_string()), + schema: Some("schema".to_string()), symbol: "symbol".to_string(), id: "id".to_string(), - extensible: true, - nsfw: false, - base_uri: "base_uri".to_string(), - uri: "uri".to_string(), + uri: Some("uri".to_string()), uri_hash: Some("uri_hash".to_string()), - data: "data".to_string(), - token_name: "token_name".to_string(), - transferable: true, + data: Some("data".to_string()), royalty_receivers: None } ); diff --git a/integration-tests/src/test_open_edition_minting.rs b/integration-tests/src/test_open_edition_minting.rs index ac0990c..b10c780 100644 --- a/integration-tests/src/test_open_edition_minting.rs +++ b/integration-tests/src/test_open_edition_minting.rs @@ -4,22 +4,20 @@ mod test_open_edition_minter_minting { use cosmwasm_std::{coin, coins, Addr, BlockInfo, Coin, Timestamp, Uint128}; use cw_multi_test::{BankSudo, Executor, SudoMsg}; - use minter_types::{CollectionDetails, UserDetails}; - use omniflix_open_edition_minter_factory::msg::{ - ExecuteMsg as OpenEditionMinterFactoryExecuteMsg, - InstantiateMsg as OpenEditionMinterFactoryInstantiateMsg, OpenEditionMinterCreateMsg, - OpenEditionMinterInitExtention, - }; + use minter_types::{QueryMsg, UserDetails}; + use omniflix_open_edition_minter_factory::msg::ExecuteMsg as OpenEditionMinterFactoryExecuteMsg; use crate::utils::{ - get_contract_address_from_res, return_open_edition_minter_inst_msg, return_rounds, + get_contract_address_from_res, return_factory_inst_message, + return_open_edition_minter_inst_msg, return_rounds, }; use crate::{setup::setup, utils::query_onft_collection}; - use omniflix_open_edition_minter::msg::ExecuteMsg as OpenEditionMinterExecuteMsg; - - use open_edition_minter_types::QueryMsg as OpenEditionMinterQueryMsg; + use omniflix_open_edition_minter::msg::{ + ExecuteMsg as OpenEditionMinterExecuteMsg, OEMQueryExtension, + }; + type OpenEditionMinterQueryMsg = QueryMsg; use omniflix_open_edition_minter::error::ContractError as OpenEditionMinterError; @@ -40,12 +38,8 @@ mod test_open_edition_minter_minting { let collector = test_addresses.collector; // Instantiate the minter factory - let open_edition_minter_factory_instantiate_msg = OpenEditionMinterFactoryInstantiateMsg { - admin: Some(admin.to_string()), - open_edition_minter_code_id, - fee_collector_address: admin.to_string(), - minter_creation_fee: coin(1000000, "uflix"), - }; + let open_edition_minter_factory_instantiate_msg = + return_factory_inst_message(open_edition_minter_code_id); let open_edition_minter_factory_address = app .instantiate_contract( @@ -113,8 +107,8 @@ mod test_open_edition_minter_minting { let error = err.downcast_ref::().unwrap(); assert_eq!( error, - &OpenEditionMinterError::PaymentError(cw_utils::PaymentError::MissingDenom( - "uflix".to_string() + &OpenEditionMinterError::PaymentError(cw_utils::PaymentError::ExtraDenom( + "incorrect_denom".to_string() )) ); @@ -211,7 +205,7 @@ mod test_open_edition_minter_minting { "token_name # 1".to_string() ); // Query minter - let query_msg = OpenEditionMinterQueryMsg::TokensRemaining {}; + let query_msg = OpenEditionMinterQueryMsg::Extension(OEMQueryExtension::TokensRemaining {}); let res: u32 = app .wrap() .query_wasm_smart(Addr::unchecked(minter_address.clone()), &query_msg) @@ -258,7 +252,7 @@ mod test_open_edition_minter_minting { } // Query minter - let query_msg = OpenEditionMinterQueryMsg::TokensRemaining {}; + let query_msg = OpenEditionMinterQueryMsg::Extension(OEMQueryExtension::TokensRemaining {}); let res: u32 = app .wrap() .query_wasm_smart(Addr::unchecked(minter_address.clone()), &query_msg) @@ -305,12 +299,8 @@ mod test_open_edition_minter_minting { let collector = test_addresses.collector; // Instantiate the minter factory - let open_edition_minter_factory_instantiate_msg = OpenEditionMinterFactoryInstantiateMsg { - admin: Some(admin.to_string()), - open_edition_minter_code_id, - fee_collector_address: admin.to_string(), - minter_creation_fee: coin(1000000, "uflix"), - }; + let open_edition_minter_factory_instantiate_msg = + return_factory_inst_message(open_edition_minter_code_id); let open_edition_minter_factory_address = app .instantiate_contract( open_edition_minter_factory_code_id, @@ -322,13 +312,7 @@ mod test_open_edition_minter_minting { ) .unwrap(); - let round_whitelist_factory_inst_msg = - omniflix_round_whitelist_factory::msg::InstantiateMsg { - admin: Some(admin.to_string()), - fee_collector_address: admin.clone().into_string(), - whitelist_code_id: round_whitelist_code_id, - whitelist_creation_fee: coin(1000000, "uflix"), - }; + let round_whitelist_factory_inst_msg = return_factory_inst_message(round_whitelist_code_id); let round_whitelist_factory_addr = app .instantiate_contract( round_whitelist_factory_code_id, @@ -343,7 +327,7 @@ mod test_open_edition_minter_minting { let rounds = return_rounds(); let round_whitelist_inst_msg = whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }; let create_round_whitelist_msg = diff --git a/integration-tests/src/test_pause.rs b/integration-tests/src/test_pause.rs index 4661e13..0809e0d 100644 --- a/integration-tests/src/test_pause.rs +++ b/integration-tests/src/test_pause.rs @@ -2,17 +2,19 @@ mod test_pause { - use cosmwasm_std::{coin, to_json_binary, Addr, BlockInfo, QueryRequest, Timestamp, WasmQuery}; + use cosmwasm_std::{ + coin, to_json_binary, Addr, BlockInfo, Empty, QueryRequest, Timestamp, WasmQuery, + }; use cw_multi_test::Executor; use pauser::PauseError; use minter_types::QueryMsg; use omniflix_minter::msg::ExecuteMsg as MinterExecuteMsg; - use omniflix_minter_factory::msg::{ - ExecuteMsg as FactoryExecuteMsg, InstantiateMsg as FactoryInstantiateMsg, - }; + use omniflix_minter_factory::msg::ExecuteMsg as FactoryExecuteMsg; - use crate::utils::{get_contract_address_from_res, return_minter_instantiate_msg}; + use crate::utils::{ + get_contract_address_from_res, return_factory_inst_message, return_minter_instantiate_msg, + }; use crate::setup::setup; use omniflix_minter::error::ContractError as MinterContractError; @@ -33,12 +35,7 @@ mod test_pause { let creator = test_addresses.creator; let collector = test_addresses.collector; - let factory_inst_msg = FactoryInstantiateMsg { - admin: Some(admin.to_string()), - minter_creation_fee: coin(1000000, "uflix"), - minter_code_id, - fee_collector_address: admin.clone().into_string(), - }; + let factory_inst_msg = return_factory_inst_message(minter_code_id); let factory_addr = app .instantiate_contract( minter_factory_code_id, @@ -69,17 +66,17 @@ mod test_pause { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::IsPaused {}).unwrap(), + msg: to_json_binary(&QueryMsg::::IsPaused {}).unwrap(), })) .unwrap(); - assert_eq!(is_paused, false); + assert!(!is_paused); // Query pausers let pausers: Vec = app .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::Pausers {}).unwrap(), + msg: to_json_binary(&QueryMsg::::Pausers {}).unwrap(), })) .unwrap(); assert_eq!(pausers.len(), 1); @@ -120,10 +117,10 @@ mod test_pause { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::IsPaused {}).unwrap(), + msg: to_json_binary(&QueryMsg::::IsPaused {}).unwrap(), })) .unwrap(); - assert_eq!(is_paused, true); + assert!(is_paused); // Try pausing again let pause_msg = MinterExecuteMsg::Pause {}; @@ -193,10 +190,10 @@ mod test_pause { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::IsPaused {}).unwrap(), + msg: to_json_binary(&QueryMsg::::IsPaused {}).unwrap(), })) .unwrap(); - assert_eq!(is_paused, false); + assert!(!is_paused); // Try minting let mint_msg = MinterExecuteMsg::Mint {}; @@ -227,7 +224,7 @@ mod test_pause { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::Pausers {}).unwrap(), + msg: to_json_binary(&QueryMsg::::Pausers {}).unwrap(), })) .unwrap(); assert_eq!(pausers.len(), 1); @@ -268,9 +265,9 @@ mod test_pause { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: minter_address.clone(), - msg: to_json_binary(&QueryMsg::IsPaused {}).unwrap(), + msg: to_json_binary(&QueryMsg::::IsPaused {}).unwrap(), })) .unwrap(); - assert_eq!(is_paused, true); + assert!(is_paused); } } diff --git a/integration-tests/src/test_round_whitelist_creation.rs b/integration-tests/src/test_round_whitelist_creation.rs index cded4fc..95ca2a2 100644 --- a/integration-tests/src/test_round_whitelist_creation.rs +++ b/integration-tests/src/test_round_whitelist_creation.rs @@ -9,7 +9,7 @@ mod test_round_whitelist_creation { use whitelist_types::{Round, RoundWhitelistQueryMsgs}; - use crate::utils::{get_contract_address_from_res, return_rounds}; + use crate::utils::{get_contract_address_from_res, return_factory_inst_message, return_rounds}; use crate::setup::setup; @@ -32,13 +32,7 @@ mod test_round_whitelist_creation { let creator = test_addresses.creator; let _collector = test_addresses.collector; - let round_whitelist_factory_inst_msg = - omniflix_round_whitelist_factory::msg::InstantiateMsg { - admin: Some(admin.to_string()), - fee_collector_address: admin.clone().into_string(), - whitelist_code_id: round_whitelist_code_id, - whitelist_creation_fee: coin(1000000, "uflix"), - }; + let round_whitelist_factory_inst_msg = return_factory_inst_message(round_whitelist_code_id); let round_whitelist_factory_addr = app .instantiate_contract( round_whitelist_factory_code_id, @@ -57,7 +51,7 @@ mod test_round_whitelist_creation { round_whitelist_factory_addr.clone(), &omniflix_round_whitelist_factory::msg::ExecuteMsg::CreateWhitelist { msg: whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, }, @@ -70,7 +64,9 @@ mod test_round_whitelist_creation { .unwrap(); assert_eq!( error, - &RoundWhitelistFactoryContractError::MissingCreationFee {} + &RoundWhitelistFactoryContractError::PaymentError(cw_utils::PaymentError::ExtraDenom( + "diffirent_denom".to_string() + )) ); // Send more than fee amount @@ -80,7 +76,7 @@ mod test_round_whitelist_creation { round_whitelist_factory_addr.clone(), &omniflix_round_whitelist_factory::msg::ExecuteMsg::CreateWhitelist { msg: whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, }, @@ -104,7 +100,7 @@ mod test_round_whitelist_creation { round_whitelist_factory_addr.clone(), &omniflix_round_whitelist_factory::msg::ExecuteMsg::CreateWhitelist { msg: whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, }, @@ -125,7 +121,7 @@ mod test_round_whitelist_creation { round_whitelist_factory_addr.clone(), &omniflix_round_whitelist_factory::msg::ExecuteMsg::CreateWhitelist { msg: whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, }, @@ -148,7 +144,7 @@ mod test_round_whitelist_creation { round_whitelist_factory_addr.clone(), &omniflix_round_whitelist_factory::msg::ExecuteMsg::CreateWhitelist { msg: whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, }, @@ -168,7 +164,7 @@ mod test_round_whitelist_creation { round_whitelist_factory_addr.clone(), &omniflix_round_whitelist_factory::msg::ExecuteMsg::CreateWhitelist { msg: whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, }, @@ -191,7 +187,7 @@ mod test_round_whitelist_creation { round_whitelist_code_id, admin.clone(), &whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, &[], @@ -215,7 +211,7 @@ mod test_round_whitelist_creation { round_whitelist_factory_addr.clone(), &omniflix_round_whitelist_factory::msg::ExecuteMsg::CreateWhitelist { msg: whitelist_types::InstantiateMsg { - admin: Some(admin.to_string()), + admin: admin.to_string(), rounds: rounds.clone(), }, }, diff --git a/integration-tests/src/utils.rs b/integration-tests/src/utils.rs index d931299..54a5136 100644 --- a/integration-tests/src/utils.rs +++ b/integration-tests/src/utils.rs @@ -1,13 +1,13 @@ -use cosmwasm_std::{from_json, Addr, Coin, MemoryStorage, Storage, Timestamp}; +use cosmwasm_std::{from_json, Addr, Coin, Decimal, Empty, MemoryStorage, Storage, Timestamp}; use cw_multi_test::{AppResponse, BankSudo, SudoMsg}; -use minter_types::CollectionDetails; +use minter_types::{CollectionDetails, TokenDetails}; +use omniflix_minter_factory::msg::InstantiateMsg; use omniflix_minter_factory::msg::{CreateMinterMsg, MinterInitExtention}; use omniflix_open_edition_minter_factory::msg::{ OpenEditionMinterCreateMsg, OpenEditionMinterInitExtention, }; use omniflix_std::types::omniflix::onft::v1beta1::Collection; use omniflix_testing::app::OmniflixApp; - pub fn get_contract_address_from_res(res: AppResponse) -> String { res.events .iter() @@ -30,55 +30,56 @@ pub fn query_onft_collection(storage: &MemoryStorage, minter_address: String) -> pub fn return_minter_instantiate_msg() -> CreateMinterMsg { let collection_details = CollectionDetails { - name: "name".to_string(), - description: "description".to_string(), - preview_uri: "preview_uri".to_string(), - schema: "schema".to_string(), + collection_name: "name".to_string(), + description: Some("description".to_string()), + preview_uri: Some("preview_uri".to_string()), + schema: Some("schema".to_string()), symbol: "symbol".to_string(), id: "id".to_string(), - extensible: true, - nsfw: false, - base_uri: "base_uri".to_string(), - uri: "uri".to_string(), uri_hash: Some("uri_hash".to_string()), - data: "data".to_string(), + data: Some("data".to_string()), + royalty_receivers: None, + uri: Some("uri".to_string()), + }; + let token_details = TokenDetails { token_name: "token_name".to_string(), + description: Some("description".to_string()), + preview_uri: Some("preview_uri".to_string()), + base_token_uri: "base_token_uri".to_string(), transferable: true, - royalty_receivers: None, + royalty_ratio: Decimal::percent(10), + extensible: true, + nsfw: false, + data: None, }; - let init = CreateMinterMsg { - collection_details: collection_details, + + CreateMinterMsg { + collection_details, + token_details, init: MinterInitExtention { admin: "creator".to_string(), mint_price: Coin::new(1000000, "uflix"), start_time: Timestamp::from_nanos(1_000_000_000), end_time: Some(Timestamp::from_nanos(2_000_000_000)), - per_address_limit: 1, - royalty_ratio: "0.1".to_string(), + per_address_limit: Some(1), payment_collector: Some("creator".to_string()), whitelist_address: None, num_tokens: 1000, }, - }; - init + } } pub fn return_open_edition_minter_inst_msg() -> OpenEditionMinterCreateMsg { let collection_details = CollectionDetails { - name: "name".to_string(), - description: "description".to_string(), - preview_uri: "preview_uri".to_string(), - schema: "schema".to_string(), + collection_name: "name".to_string(), + description: Some("description".to_string()), + preview_uri: Some("preview_uri".to_string()), + schema: Some("schema".to_string()), symbol: "symbol".to_string(), id: "id".to_string(), - extensible: true, - nsfw: false, - base_uri: "base_uri".to_string(), - uri: "uri".to_string(), + uri: Some("uri".to_string()), uri_hash: Some("uri_hash".to_string()), - data: "data".to_string(), - token_name: "token_name".to_string(), - transferable: true, + data: Some("data".to_string()), royalty_receivers: None, }; let init = OpenEditionMinterInitExtention { @@ -86,17 +87,28 @@ pub fn return_open_edition_minter_inst_msg() -> OpenEditionMinterCreateMsg { mint_price: Coin::new(1000000, "uflix"), start_time: Timestamp::from_nanos(1_000_000_000), end_time: Some(Timestamp::from_nanos(2_000_000_000)), - per_address_limit: 1, - royalty_ratio: "0.1".to_string(), + per_address_limit: Some(1), payment_collector: Some("creator".to_string()), whitelist_address: None, - token_limit: Some(1000), + num_tokens: Some(1000), }; - let open_edition_minter_inst_msg = OpenEditionMinterCreateMsg { - collection_details: collection_details, - init: init, + let token_details = TokenDetails { + token_name: "token_name".to_string(), + description: Some("description".to_string()), + preview_uri: Some("preview_uri".to_string()), + base_token_uri: "base_token_uri".to_string(), + transferable: true, + royalty_ratio: Decimal::percent(10), + extensible: true, + nsfw: false, + data: None, }; - open_edition_minter_inst_msg + + OpenEditionMinterCreateMsg { + collection_details, + init, + token_details, + } } pub fn return_rounds() -> Vec { @@ -123,3 +135,15 @@ pub fn mint_to_address(app: &mut OmniflixApp, to_address: String, amount: Vec InstantiateMsg { + let params = factory_types::FactoryParams { + admin: Addr::unchecked("admin".to_string()), + creation_fee: Coin::new(1000000, "uflix"), + contract_id: code_id, + fee_collector_address: Addr::unchecked("admin".to_string()), + product_label: "label".to_string(), + init: Empty {}, + }; + + InstantiateMsg { params } +} diff --git a/packages/open-edition-minter-types/Cargo.toml b/packages/factory-types/Cargo.toml similarity index 86% rename from packages/open-edition-minter-types/Cargo.toml rename to packages/factory-types/Cargo.toml index 41a5b35..7744bec 100644 --- a/packages/open-edition-minter-types/Cargo.toml +++ b/packages/factory-types/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "open-edition-minter-types" +name = "factory-types" authors = ["Adnan Deniz Corlu "] -description = "Common types used by minter contracts" +description = "Common types used by factory contracts" version = { workspace = true } edition = { workspace = true } homepage = { workspace = true } @@ -32,4 +32,5 @@ cw721-base = { workspace = true, features = ["library"] } cw-utils = { workspace = true } thiserror = { workspace = true } serde = { workspace = true } -minter-types = { workspace = true } \ No newline at end of file +cw-storage-plus = { workspace = true } +omniflix-std = { workspace = true } diff --git a/contracts/factories/minter-factory/src/utils.rs b/packages/factory-types/src/lib.rs similarity index 72% rename from contracts/factories/minter-factory/src/utils.rs rename to packages/factory-types/src/lib.rs index 833f705..d095716 100644 --- a/contracts/factories/minter-factory/src/utils.rs +++ b/packages/factory-types/src/lib.rs @@ -1,11 +1,32 @@ -use cosmwasm_std::Coin; - -use crate::error::ContractError; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, StdError}; +use cosmwasm_std::{Coin, Uint128}; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum CustomPaymentError { + #[error(transparent)] + Std(#[from] StdError), + #[error("Insufficient funds sent")] + InsufficientFunds { + expected: Vec, + actual: Vec, + }, +} +pub fn check_payment( + sent_funds: &[Coin], + expected_funds: &[Coin], +) -> Result<(), CustomPaymentError> { + // Remove 0 amounts + let expected_funds = expected_funds + .iter() + .filter(|coin| coin.amount > Uint128::zero()) + .cloned() // Clone the elements + .collect::>(); -pub fn check_payment(sent_funds: &[Coin], expected_funds: &[Coin]) -> Result<(), ContractError> { // Check length if sent_funds.len() > expected_funds.len() { - return Err(ContractError::IncorrectFunds { + return Err(CustomPaymentError::InsufficientFunds { expected: expected_funds.to_vec(), actual: sent_funds.to_vec(), }); @@ -13,14 +34,14 @@ pub fn check_payment(sent_funds: &[Coin], expected_funds: &[Coin]) -> Result<(), let mut mut_sent_funds = sent_funds.to_vec(); // Create a mutable copy - for expected in expected_funds { + for expected in expected_funds.clone() { if let Some(sent_index) = mut_sent_funds .iter() .position(|sent| expected.denom == sent.denom) { let sent = &mut mut_sent_funds[sent_index]; if expected.amount > sent.amount { - return Err(ContractError::IncorrectFunds { + return Err(CustomPaymentError::InsufficientFunds { expected: expected_funds.to_vec(), actual: sent_funds.to_vec(), }); @@ -28,7 +49,7 @@ pub fn check_payment(sent_funds: &[Coin], expected_funds: &[Coin]) -> Result<(), sent.amount = sent.amount.checked_sub(expected.amount).unwrap(); } } else { - return Err(ContractError::IncorrectFunds { + return Err(CustomPaymentError::InsufficientFunds { expected: expected_funds.to_vec(), actual: sent_funds.to_vec(), }); @@ -37,6 +58,15 @@ pub fn check_payment(sent_funds: &[Coin], expected_funds: &[Coin]) -> Result<(), Ok(()) } +#[cw_serde] +pub struct FactoryParams { + pub admin: Addr, + pub creation_fee: Coin, + pub fee_collector_address: Addr, + pub contract_id: u64, + pub product_label: String, + pub init: T, +} // Test check_payment #[cfg(test)] @@ -110,5 +140,10 @@ mod tests { ]; let res = check_payment(&sent_funds, &expected_funds); assert!(res.is_err()); + + let sent_funds = vec![coin(1100, "uluna")]; + let expected_funds = vec![coin(0, "something"), coin(1100, "uluna")]; + let res = check_payment(&sent_funds, &expected_funds); + assert!(res.is_ok()); } } diff --git a/packages/minter-types/src/lib.rs b/packages/minter-types/src/lib.rs index 3b172ea..7d7356e 100644 --- a/packages/minter-types/src/lib.rs +++ b/packages/minter-types/src/lib.rs @@ -1,53 +1,70 @@ -use std::{fmt::format, ptr::NonNull}; - use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, Coin, Decimal, StdError, Storage, Timestamp}; -use cw_storage_plus::Item; -use omniflix_std::types::omniflix::onft::v1beta1::{Metadata, MsgMintOnft, WeightedAddress}; -use thiserror::Error; +use cosmwasm_std::{Addr, Coin, Decimal, StdError, Timestamp}; +use omniflix_std::types::omniflix::onft::v1beta1::{ + Metadata, MsgCreateDenom, MsgMintOnft, WeightedAddress, +}; #[cw_serde] pub struct CollectionDetails { - pub name: String, - pub description: String, - pub preview_uri: String, - pub schema: String, + pub description: Option, + pub preview_uri: Option, + pub schema: Option, + pub uri: Option, + pub uri_hash: Option, + pub collection_name: String, + pub data: Option, pub symbol: String, pub id: String, - pub extensible: bool, - pub nsfw: bool, - pub base_uri: String, - pub uri: String, - pub uri_hash: Option, - pub data: String, - pub transferable: bool, // FE: Collection:"Badkids" each token name "BadKid" #token_id - pub token_name: String, pub royalty_receivers: Option>, } +#[cw_serde] +pub struct TokenDetails { + // FE: Collection:"Badkids" description: "Collection of Badkids", token{ description: "Badkid from badkids collection", name: "Badkid", symbol: "BKID", uri: "https://badkids.com/1", uri_hash: "QmZG9Z3Y9Z3Y} + pub data: Option, + pub description: Option, + pub preview_uri: Option, + pub token_name: String, + pub transferable: bool, + pub extensible: bool, + pub nsfw: bool, + pub royalty_ratio: Decimal, + // This preview_uri is used for the preview of the token. If provided, it will be used as the preview_uri+token_id + // This is the base token uri. If provided, it will be used as the base_token_uri+token_id should be pointing at a json file. + pub base_token_uri: String, +} +#[cw_serde] +pub struct Config { + pub per_address_limit: Option, + pub start_time: Timestamp, + pub end_time: Option, + pub whitelist_address: Option, + pub num_tokens: Option, + pub mint_price: Coin, +} + +#[cw_serde] +pub struct AuthDetails { + pub admin: Addr, + pub payment_collector: Addr, +} #[cw_serde] pub struct MinterInstantiateMsg { pub collection_details: CollectionDetails, + pub token_details: TokenDetails, pub init: T, } #[cw_serde] +#[derive(Default)] pub struct UserDetails { pub minted_tokens: Vec, pub total_minted_count: u32, pub public_mint_count: u32, } -impl Default for UserDetails { - fn default() -> Self { - UserDetails { - minted_tokens: Vec::new(), - total_minted_count: 0, - public_mint_count: 0, - } - } -} + #[cw_serde] pub struct Token { @@ -56,94 +73,123 @@ pub struct Token { #[cw_serde] #[derive(QueryResponses)] -pub enum QueryMsg { +pub enum QueryMsg { #[returns(CollectionDetails)] Collection {}, + #[returns(TokenDetails)] + TokenDetails {}, + #[returns(AuthDetails)] + AuthDetails {}, #[returns(Config)] Config {}, - #[returns(Vec)] - MintableTokens {}, #[returns(UserDetails)] MintedTokens { address: String }, - #[returns(u32)] - TotalTokens {}, #[returns(bool)] IsPaused {}, #[returns(Vec)] Pausers {}, -} - -#[cw_serde] -pub struct Config { - pub per_address_limit: u32, - pub payment_collector: Addr, - pub start_time: Timestamp, - pub end_time: Option, - pub mint_price: Coin, - pub royalty_ratio: Decimal, - pub admin: Addr, - pub whitelist_address: Option, - pub token_limit: Option, + #[returns(u32)] + Extension(T), + #[returns(u32)] + TotalMintedCount {}, } pub fn generate_mint_message( collection: &CollectionDetails, - royalty_ratio: Decimal, - recipient: &Addr, - contract_address: &Addr, - is_edition: bool, + token_details: &TokenDetails, token_id: String, - // Purpose of token_number is to handle the case when the token is an drop + minter_address: Addr, + recipient: Addr, + // Purpose of drop_token_number is to handle the case when the token is an drop drop_token_number: Option, + is_edition: bool, ) -> MsgMintOnft { match is_edition { false => { let metadata = Metadata { - name: format!("{} # {}", collection.token_name.clone(), token_id), - description: collection.description.clone(), - media_uri: format!("{}/{}", collection.base_uri, token_id), - preview_uri: collection.preview_uri.clone(), + name: format!("{} # {}", token_details.token_name.clone(), token_id), + description: token_details.description.clone().unwrap_or("".to_string()), + media_uri: format!("{}/{}", token_details.base_token_uri.clone(), token_id), + preview_uri: format!( + "{}/{}", + token_details + .preview_uri + .clone() + .unwrap_or(token_details.base_token_uri.clone()), + token_id, + ), uri_hash: collection.uri_hash.clone().unwrap_or("".to_string()), }; MsgMintOnft { - data: collection.data.clone(), + data: token_details.data.clone().unwrap_or("".to_string()), id: token_id, metadata: Some(metadata), denom_id: collection.id.clone(), - transferable: collection.transferable, - sender: contract_address.clone().into_string(), - extensible: collection.extensible, - nsfw: collection.nsfw, + transferable: token_details.transferable, + sender: minter_address.into_string(), + extensible: token_details.extensible, + nsfw: token_details.nsfw, recipient: recipient.clone().into_string(), - royalty_share: royalty_ratio.atomics().to_string(), + royalty_share: token_details.royalty_ratio.atomics().to_string(), } } true => { let metadata = Metadata { name: format!( "{} # {}", - collection.token_name.clone(), + token_details.token_name.clone(), drop_token_number.unwrap_or(token_id.clone()) ), - description: collection.description.clone(), - media_uri: collection.base_uri.clone(), - preview_uri: collection.preview_uri.clone(), + description: token_details.description.clone().unwrap_or("".to_string()), + media_uri: token_details.base_token_uri.clone(), + preview_uri: token_details + .preview_uri + .clone() + .unwrap_or(token_details.base_token_uri.clone()), uri_hash: "".to_string(), }; MsgMintOnft { - data: collection.data.clone(), + data: token_details.data.clone().unwrap_or("".to_string()), id: token_id, metadata: Some(metadata), denom_id: collection.id.clone(), - transferable: collection.transferable, - sender: contract_address.clone().into_string(), - extensible: collection.extensible, - nsfw: collection.nsfw, + transferable: token_details.transferable, + sender: minter_address.into_string(), + extensible: token_details.extensible, + nsfw: token_details.nsfw, recipient: recipient.clone().into_string(), - royalty_share: royalty_ratio.atomics().to_string(), + royalty_share: token_details.royalty_ratio.atomics().to_string(), } } } } +pub fn generate_create_denom_msg( + collection: &CollectionDetails, + minter_address: Addr, + creation_fee: Coin, + admin: Addr, +) -> Result { + let create_denom_msg = MsgCreateDenom { + creation_fee: Some(creation_fee.into()), + id: collection.id.clone(), + symbol: collection.symbol.clone(), + name: collection.collection_name.clone(), + description: collection.description.clone().unwrap_or("".to_string()), + preview_uri: collection.preview_uri.clone().unwrap_or("".to_string()), + schema: collection.schema.clone().unwrap_or("".to_string()), + sender: minter_address.into_string(), + uri: collection.uri.clone().unwrap_or("".to_string()), + uri_hash: collection.uri_hash.clone().unwrap_or("".to_string()), + data: collection.data.clone().unwrap_or("".to_string()), + royalty_receivers: collection.royalty_receivers.clone().unwrap_or( + [WeightedAddress { + address: admin.into_string(), + weight: Decimal::one().to_string(), + }] + .to_vec(), + ), + }; + Ok(create_denom_msg) +} diff --git a/packages/multi-mint-oem-types/Cargo.toml b/packages/multi-mint-oem-types/Cargo.toml deleted file mode 100644 index 9ceaa87..0000000 --- a/packages/multi-mint-oem-types/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = "multi-mint-open-edition-minter-types" -authors = ["Adnan Deniz Corlu "] -description = "Common types used by minter contracts" -version = { workspace = true } -edition = { workspace = true } -homepage = { workspace = true } -repository = { workspace = true } -license = { workspace = true } - -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. - "contract.wasm", - "hash.txt", -] - -# 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] -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw721-base = { workspace = true, features = ["library"] } -cw-utils = { workspace = true } -thiserror = { workspace = true } -serde = { workspace = true } -minter-types = { workspace = true } \ No newline at end of file diff --git a/packages/multi-mint-oem-types/src/lib.rs b/packages/multi-mint-oem-types/src/lib.rs deleted file mode 100644 index 07ec9d7..0000000 --- a/packages/multi-mint-oem-types/src/lib.rs +++ /dev/null @@ -1,35 +0,0 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::Addr; -use minter_types::{CollectionDetails, Config, UserDetails}; - -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - #[returns(CollectionDetails)] - Collection { drop_id: Option }, - #[returns(Config)] - Config { drop_id: Option }, - #[returns(UserDetails)] - MintedTokens { - address: String, - drop_id: Option, - }, - #[returns(u32)] - TotalMintedCount { drop_id: Option }, - #[returns(u32)] - TokensRemaining { drop_id: Option }, - #[returns(bool)] - IsPaused {}, - #[returns(Vec)] - Pausers {}, - #[returns(u32)] - CurrentDropNumber {}, - #[returns(Vec<(u32,DropParams)>)] - AllDrops {}, -} - -#[cw_serde] -pub struct DropParams { - pub config: Config, - pub collection: CollectionDetails, -} diff --git a/packages/open-edition-minter-types/src/lib.rs b/packages/open-edition-minter-types/src/lib.rs deleted file mode 100644 index 3f08f91..0000000 --- a/packages/open-edition-minter-types/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::Addr; -use minter_types::{CollectionDetails, Config, UserDetails}; - -#[cw_serde] -#[derive(QueryResponses)] -pub enum QueryMsg { - #[returns(CollectionDetails)] - Collection {}, - #[returns(Config)] - Config {}, - #[returns(UserDetails)] - MintedTokens { address: String }, - #[returns(u32)] - TotalMintedCount {}, - #[returns(u32)] - TokensRemaining {}, - #[returns(bool)] - IsPaused {}, - #[returns(Vec)] - Pausers {}, -} diff --git a/packages/pauser/src/READ.md b/packages/pauser/src/READ.md new file mode 100644 index 0000000..3340997 --- /dev/null +++ b/packages/pauser/src/READ.md @@ -0,0 +1 @@ +This rust package is a simple swich that can be used to pause and unpause the contract. \ No newline at end of file diff --git a/packages/pauser/src/lib.rs b/packages/pauser/src/lib.rs index 579d5a2..41ac822 100644 --- a/packages/pauser/src/lib.rs +++ b/packages/pauser/src/lib.rs @@ -1,9 +1,10 @@ -use std::fmt::format; - -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, Coin, Decimal, StdError, Storage, Timestamp}; +use cosmwasm_std::{Addr, StdError, Storage}; use cw_storage_plus::Item; use thiserror::Error; + +pub const PAUSED_KEY: &str = "paused"; +pub const PAUSERS_KEY: &str = "pausers"; + #[derive(Error, Debug, PartialEq)] pub enum PauseError { #[error(transparent)] @@ -40,7 +41,7 @@ impl<'a> PauseState<'a> { sender: Addr, pausers: Vec, ) -> Result<(), PauseError> { - let mut current_pausers = self.pausers.load(storage).unwrap_or(vec![]); + let mut current_pausers = self.pausers.load(storage).unwrap_or_default(); if current_pausers.is_empty() { current_pausers = pausers; } else { diff --git a/packages/testing/Cargo.toml b/packages/testing/Cargo.toml index 9f5381b..fec6d1b 100644 --- a/packages/testing/Cargo.toml +++ b/packages/testing/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "omniflix-testing" authors = ["Adnan Deniz Corlu "] -description = "Common types used by round whitelist contract" +description = "A unique testing package designed to execute and query Stargate in multi-test environment." version = { workspace = true } edition = { workspace = true } homepage = { workspace = true } diff --git a/packages/testing/src/app.rs b/packages/testing/src/app.rs index 2fdfc14..73e3de8 100644 --- a/packages/testing/src/app.rs +++ b/packages/testing/src/app.rs @@ -45,6 +45,12 @@ impl DerefMut for OmniflixApp { &mut self.0 } } +impl Default for OmniflixApp { + fn default() -> Self { + Self::new() + } +} + impl OmniflixApp { pub fn new() -> Self { let app_builder = AppBuilder::default(); diff --git a/packages/whitelist-types/src/lib.rs b/packages/whitelist-types/src/lib.rs index 356cf47..ff7a4f5 100644 --- a/packages/whitelist-types/src/lib.rs +++ b/packages/whitelist-types/src/lib.rs @@ -1,12 +1,12 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::StdError; -use cosmwasm_std::{Addr, Coin, Deps, Storage, Timestamp}; +use cosmwasm_std::{Addr, Coin, Deps, Timestamp}; +use cosmwasm_std::{Empty, StdError}; use minter_types::Config as MinterConfig; use minter_types::QueryMsg as MinterQueryMsg; #[cw_serde] pub struct InstantiateMsg { - pub admin: Option, + pub admin: String, pub rounds: Vec, } @@ -74,7 +74,7 @@ pub fn check_if_minter(address: &Addr, deps: Deps) -> Result<(), StdError> { // Check if sender is a minter contract let _minter_config: MinterConfig = deps .querier - .query_wasm_smart(address, &MinterQueryMsg::Config {})?; + .query_wasm_smart(address, &MinterQueryMsg::<&Empty>::Config {})?; Ok(()) } diff --git a/ts/package.json b/ts/package.json index 10587e4..261fbb9 100644 --- a/ts/package.json +++ b/ts/package.json @@ -6,7 +6,7 @@ "main": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "generate_ts": "ts-node codegen_script.ts" + "generate-ts": "ts-node codegen_script.ts" }, "dependencies": { "@cosmjs/amino": "0.29.5", @@ -21,4 +21,4 @@ "ts-node": "10.9.1", "typescript": "4.9.5" } -} +} \ No newline at end of file diff --git a/ts/types/OmniflixMinter.client.ts b/ts/types/OmniflixMinter.client.ts index 298e690..b19e0db 100644 --- a/ts/types/OmniflixMinter.client.ts +++ b/ts/types/OmniflixMinter.client.ts @@ -6,20 +6,22 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, MinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Boolean, ArrayOfToken, Token, UserDetails, ArrayOfAddr, Uint32 } from "./OmniflixMinter.types"; +import { Timestamp, Uint64, Uint128, Decimal, InstantiateMsg, CollectionDetails, WeightedAddress, MinterInitExtention, Coin, TokenDetails, ExecuteMsg, QueryMsg, MinterExtensionQueryMsg, Addr, AuthDetails, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixMinter.types"; export interface OmniflixMinterReadOnlyInterface { contractAddress: string; collection: () => Promise; + tokenDetails: () => Promise; + authDetails: () => Promise; config: () => Promise; - mintableTokens: () => Promise; mintedTokens: ({ address }: { address: string; }) => Promise; - totalTokens: () => Promise; isPaused: () => Promise; pausers: () => Promise; + extension: (minterExtensionQueryMsg: MinterExtensionQueryMsg) => Promise; + totalMintedCount: () => Promise; } export class OmniflixMinterQueryClient implements OmniflixMinterReadOnlyInterface { client: CosmWasmClient; @@ -29,12 +31,14 @@ export class OmniflixMinterQueryClient implements OmniflixMinterReadOnlyInterfac this.client = client; this.contractAddress = contractAddress; this.collection = this.collection.bind(this); + this.tokenDetails = this.tokenDetails.bind(this); + this.authDetails = this.authDetails.bind(this); this.config = this.config.bind(this); - this.mintableTokens = this.mintableTokens.bind(this); this.mintedTokens = this.mintedTokens.bind(this); - this.totalTokens = this.totalTokens.bind(this); this.isPaused = this.isPaused.bind(this); this.pausers = this.pausers.bind(this); + this.extension = this.extension.bind(this); + this.totalMintedCount = this.totalMintedCount.bind(this); } collection = async (): Promise => { @@ -42,14 +46,19 @@ export class OmniflixMinterQueryClient implements OmniflixMinterReadOnlyInterfac collection: {} }); }; - config = async (): Promise => { + tokenDetails = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - config: {} + token_details: {} + }); + }; + authDetails = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + auth_details: {} }); }; - mintableTokens = async (): Promise => { + config = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - mintable_tokens: {} + config: {} }); }; mintedTokens = async ({ @@ -63,11 +72,6 @@ export class OmniflixMinterQueryClient implements OmniflixMinterReadOnlyInterfac } }); }; - totalTokens = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - total_tokens: {} - }); - }; isPaused = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { is_paused: {} @@ -78,6 +82,16 @@ export class OmniflixMinterQueryClient implements OmniflixMinterReadOnlyInterfac pausers: {} }); }; + extension = async (minterExtensionQueryMsg: MinterExtensionQueryMsg): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + extension: minterExtensionQueryMsg + }); + }; + totalMintedCount = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + total_minted_count: {} + }); + }; } export interface OmniflixMinterInterface extends OmniflixMinterReadOnlyInterface { contractAddress: string; @@ -120,15 +134,25 @@ export interface OmniflixMinterInterface extends OmniflixMinterReadOnlyInterface receivers: WeightedAddress[]; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; updateDenom: ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; purgeDenom: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setAdmin: ({ + admin + }: { + admin: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setPaymentCollector: ({ + paymentCollector + }: { + paymentCollector: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; } export class OmniflixMinterClient extends OmniflixMinterQueryClient implements OmniflixMinterInterface { client: SigningCosmWasmClient; @@ -153,6 +177,8 @@ export class OmniflixMinterClient extends OmniflixMinterQueryClient implements O this.updateRoyaltyReceivers = this.updateRoyaltyReceivers.bind(this); this.updateDenom = this.updateDenom.bind(this); this.purgeDenom = this.purgeDenom.bind(this); + this.setAdmin = this.setAdmin.bind(this); + this.setPaymentCollector = this.setPaymentCollector.bind(this); } mint = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { @@ -250,18 +276,18 @@ export class OmniflixMinterClient extends OmniflixMinterQueryClient implements O }, fee, memo, _funds); }; updateDenom = async ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { return await this.client.execute(this.sender, this.contractAddress, { update_denom: { + collection_name: collectionName, description, - name, preview_uri: previewUri } }, fee, memo, _funds); @@ -271,4 +297,26 @@ export class OmniflixMinterClient extends OmniflixMinterQueryClient implements O purge_denom: {} }, fee, memo, _funds); }; + setAdmin = async ({ + admin + }: { + admin: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + set_admin: { + admin + } + }, fee, memo, _funds); + }; + setPaymentCollector = async ({ + paymentCollector + }: { + paymentCollector: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + set_payment_collector: { + payment_collector: paymentCollector + } + }, fee, memo, _funds); + }; } \ No newline at end of file diff --git a/ts/types/OmniflixMinter.message-composer.ts b/ts/types/OmniflixMinter.message-composer.ts index 7c7590f..8323c96 100644 --- a/ts/types/OmniflixMinter.message-composer.ts +++ b/ts/types/OmniflixMinter.message-composer.ts @@ -7,7 +7,7 @@ import { MsgExecuteContractEncodeObject } from "@cosmjs/cosmwasm-stargate"; import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; import { toUtf8 } from "@cosmjs/encoding"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, MinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Boolean, ArrayOfToken, Token, UserDetails, ArrayOfAddr, Uint32 } from "./OmniflixMinter.types"; +import { Timestamp, Uint64, Uint128, Decimal, InstantiateMsg, CollectionDetails, WeightedAddress, MinterInitExtention, Coin, TokenDetails, ExecuteMsg, QueryMsg, MinterExtensionQueryMsg, Addr, AuthDetails, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixMinter.types"; export interface OmniflixMinterMsg { contractAddress: string; sender: string; @@ -49,15 +49,25 @@ export interface OmniflixMinterMsg { receivers: WeightedAddress[]; }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; updateDenom: ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; purgeDenom: (_funds?: Coin[]) => MsgExecuteContractEncodeObject; + setAdmin: ({ + admin + }: { + admin: string; + }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; + setPaymentCollector: ({ + paymentCollector + }: { + paymentCollector: string; + }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; } export class OmniflixMinterMsgComposer implements OmniflixMinterMsg { sender: string; @@ -79,6 +89,8 @@ export class OmniflixMinterMsgComposer implements OmniflixMinterMsg { this.updateRoyaltyReceivers = this.updateRoyaltyReceivers.bind(this); this.updateDenom = this.updateDenom.bind(this); this.purgeDenom = this.purgeDenom.bind(this); + this.setAdmin = this.setAdmin.bind(this); + this.setPaymentCollector = this.setPaymentCollector.bind(this); } mint = (_funds?: Coin[]): MsgExecuteContractEncodeObject => { @@ -264,12 +276,12 @@ export class OmniflixMinterMsgComposer implements OmniflixMinterMsg { }; }; updateDenom = ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { return { @@ -279,8 +291,8 @@ export class OmniflixMinterMsgComposer implements OmniflixMinterMsg { contract: this.contractAddress, msg: toUtf8(JSON.stringify({ update_denom: { + collection_name: collectionName, description, - name, preview_uri: previewUri } })), @@ -301,4 +313,42 @@ export class OmniflixMinterMsgComposer implements OmniflixMinterMsg { }) }; }; + setAdmin = ({ + admin + }: { + admin: string; + }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { + return { + typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", + value: MsgExecuteContract.fromPartial({ + sender: this.sender, + contract: this.contractAddress, + msg: toUtf8(JSON.stringify({ + set_admin: { + admin + } + })), + funds: _funds + }) + }; + }; + setPaymentCollector = ({ + paymentCollector + }: { + paymentCollector: string; + }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { + return { + typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", + value: MsgExecuteContract.fromPartial({ + sender: this.sender, + contract: this.contractAddress, + msg: toUtf8(JSON.stringify({ + set_payment_collector: { + payment_collector: paymentCollector + } + })), + funds: _funds + }) + }; + }; } \ No newline at end of file diff --git a/ts/types/OmniflixMinter.types.ts b/ts/types/OmniflixMinter.types.ts index 02de493..2f4ee20 100644 --- a/ts/types/OmniflixMinter.types.ts +++ b/ts/types/OmniflixMinter.types.ts @@ -7,26 +7,23 @@ export type Timestamp = Uint64; export type Uint64 = string; export type Uint128 = string; +export type Decimal = string; export interface InstantiateMsg { collection_details: CollectionDetails; init: MinterInitExtention; + token_details: TokenDetails; } export interface CollectionDetails { - base_uri: string; - data: string; - description: string; - extensible: boolean; + collection_name: string; + data?: string | null; + description?: string | null; id: string; - name: string; - nsfw: boolean; - preview_uri: string; + preview_uri?: string | null; royalty_receivers?: WeightedAddress[] | null; - schema: string; + schema?: string | null; symbol: string; - token_name: string; - transferable: boolean; - uri: string; - uri_hash: string; + uri?: string | null; + uri_hash?: string | null; } export interface WeightedAddress { address: string; @@ -39,8 +36,7 @@ export interface MinterInitExtention { mint_price: Coin; num_tokens: number; payment_collector?: string | null; - per_address_limit: number; - royalty_ratio: string; + per_address_limit?: number | null; start_time: Timestamp; whitelist_address?: string | null; } @@ -49,6 +45,17 @@ export interface Coin { denom: string; [k: string]: unknown; } +export interface TokenDetails { + base_token_uri: string; + data?: string | null; + description?: string | null; + extensible: boolean; + nsfw: boolean; + preview_uri?: string | null; + royalty_ratio: Decimal; + token_name: string; + transferable: boolean; +} export type ExecuteMsg = { mint: {}; } | { @@ -86,52 +93,68 @@ export type ExecuteMsg = { }; } | { update_denom: { + collection_name?: string | null; description?: string | null; - name?: string | null; preview_uri?: string | null; }; } | { purge_denom: {}; +} | { + set_admin: { + admin: string; + }; +} | { + set_payment_collector: { + payment_collector: string; + }; }; export type QueryMsg = { collection: {}; } | { - config: {}; + token_details: {}; } | { - mintable_tokens: {}; + auth_details: {}; +} | { + config: {}; } | { minted_tokens: { address: string; }; -} | { - total_tokens: {}; } | { is_paused: {}; } | { pausers: {}; +} | { + extension: MinterExtensionQueryMsg; +} | { + total_minted_count: {}; +}; +export type MinterExtensionQueryMsg = { + mintable_tokens: {}; +} | { + total_tokens_remaining: {}; }; export type Addr = string; -export type Decimal = string; -export interface Config { +export interface AuthDetails { admin: Addr; + payment_collector: Addr; +} +export interface Config { end_time?: Timestamp | null; mint_price: Coin; - payment_collector: Addr; - per_address_limit: number; - royalty_ratio: Decimal; + num_tokens?: number | null; + per_address_limit?: number | null; start_time: Timestamp; - token_limit?: number | null; whitelist_address?: Addr | null; } +export type Uint32 = number; export type Boolean = boolean; -export type ArrayOfToken = Token[]; -export interface Token { - token_id: string; -} export interface UserDetails { minted_tokens: Token[]; public_mint_count: number; total_minted_count: number; } -export type ArrayOfAddr = Addr[]; -export type Uint32 = number; \ No newline at end of file +export interface Token { + token_id: string; +} +export type ArrayOfAddr = Addr[]; \ No newline at end of file diff --git a/ts/types/OmniflixMinterFactory.client.ts b/ts/types/OmniflixMinterFactory.client.ts index 38b4b08..6a011c6 100644 --- a/ts/types/OmniflixMinterFactory.client.ts +++ b/ts/types/OmniflixMinterFactory.client.ts @@ -6,7 +6,7 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Timestamp, Uint64, MinterInstantiateMsgForMinterInitExtention, CollectionDetails, WeightedAddress, MinterInitExtention, QueryMsg, Addr, ParamsResponse, Params } from "./OmniflixMinterFactory.types"; +import { Addr, Uint128, InstantiateMsg, FactoryParamsForEmpty, Coin, Empty, ExecuteMsg, Timestamp, Uint64, Decimal, MinterInstantiateMsgForMinterInitExtention, CollectionDetails, WeightedAddress, MinterInitExtention, TokenDetails, QueryMsg, ParamsResponse } from "./OmniflixMinterFactory.types"; export interface OmniflixMinterFactoryReadOnlyInterface { contractAddress: string; params: () => Promise; diff --git a/ts/types/OmniflixMinterFactory.message-composer.ts b/ts/types/OmniflixMinterFactory.message-composer.ts index f779ad1..66ac628 100644 --- a/ts/types/OmniflixMinterFactory.message-composer.ts +++ b/ts/types/OmniflixMinterFactory.message-composer.ts @@ -7,7 +7,7 @@ import { MsgExecuteContractEncodeObject } from "@cosmjs/cosmwasm-stargate"; import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; import { toUtf8 } from "@cosmjs/encoding"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Timestamp, Uint64, MinterInstantiateMsgForMinterInitExtention, CollectionDetails, WeightedAddress, MinterInitExtention, QueryMsg, Addr, ParamsResponse, Params } from "./OmniflixMinterFactory.types"; +import { Addr, Uint128, InstantiateMsg, FactoryParamsForEmpty, Coin, Empty, ExecuteMsg, Timestamp, Uint64, Decimal, MinterInstantiateMsgForMinterInitExtention, CollectionDetails, WeightedAddress, MinterInitExtention, TokenDetails, QueryMsg, ParamsResponse } from "./OmniflixMinterFactory.types"; export interface OmniflixMinterFactoryMsg { contractAddress: string; sender: string; diff --git a/ts/types/OmniflixMinterFactory.types.ts b/ts/types/OmniflixMinterFactory.types.ts index 3a2bf8f..37bd5ad 100644 --- a/ts/types/OmniflixMinterFactory.types.ts +++ b/ts/types/OmniflixMinterFactory.types.ts @@ -4,18 +4,27 @@ * and run the @cosmwasm/ts-codegen generate command to regenerate this file. */ +export type Addr = string; export type Uint128 = string; export interface InstantiateMsg { - admin?: string | null; - fee_collector_address: string; - minter_code_id: number; - minter_creation_fee: Coin; + params: FactoryParamsForEmpty; +} +export interface FactoryParamsForEmpty { + admin: Addr; + contract_id: number; + creation_fee: Coin; + fee_collector_address: Addr; + init: Empty; + product_label: string; } export interface Coin { amount: Uint128; denom: string; [k: string]: unknown; } +export interface Empty { + [k: string]: unknown; +} export type ExecuteMsg = { create_minter: { msg: MinterInstantiateMsgForMinterInitExtention; @@ -39,26 +48,23 @@ export type ExecuteMsg = { }; export type Timestamp = Uint64; export type Uint64 = string; +export type Decimal = string; export interface MinterInstantiateMsgForMinterInitExtention { collection_details: CollectionDetails; init: MinterInitExtention; + token_details: TokenDetails; } export interface CollectionDetails { - base_uri: string; - data: string; - description: string; - extensible: boolean; + collection_name: string; + data?: string | null; + description?: string | null; id: string; - name: string; - nsfw: boolean; - preview_uri: string; + preview_uri?: string | null; royalty_receivers?: WeightedAddress[] | null; - schema: string; + schema?: string | null; symbol: string; - token_name: string; - transferable: boolean; - uri: string; - uri_hash: string; + uri?: string | null; + uri_hash?: string | null; } export interface WeightedAddress { address: string; @@ -71,21 +77,24 @@ export interface MinterInitExtention { mint_price: Coin; num_tokens: number; payment_collector?: string | null; - per_address_limit: number; - royalty_ratio: string; + per_address_limit?: number | null; start_time: Timestamp; whitelist_address?: string | null; } +export interface TokenDetails { + base_token_uri: string; + data?: string | null; + description?: string | null; + extensible: boolean; + nsfw: boolean; + preview_uri?: string | null; + royalty_ratio: Decimal; + token_name: string; + transferable: boolean; +} export type QueryMsg = { params: {}; }; -export type Addr = string; export interface ParamsResponse { - params: Params; -} -export interface Params { - admin: Addr; - fee_collector_address: Addr; - minter_code_id: number; - minter_creation_fee: Coin; + params: FactoryParamsForEmpty; } \ No newline at end of file diff --git a/ts/types/OmniflixMultiMintOpenEditionMinter.client.ts b/ts/types/OmniflixMultiMintOpenEditionMinter.client.ts index 21d0671..4568011 100644 --- a/ts/types/OmniflixMultiMintOpenEditionMinter.client.ts +++ b/ts/types/OmniflixMultiMintOpenEditionMinter.client.ts @@ -6,39 +6,22 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixMultiMintOpenEditionMinter.types"; +import { Timestamp, Uint64, Uint128, Decimal, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, TokenDetails, ExecuteMsg, Addr, Config, QueryMsg, QueryMsgExtension, AuthDetails, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixMultiMintOpenEditionMinter.types"; export interface OmniflixMultiMintOpenEditionMinterReadOnlyInterface { contractAddress: string; - collection: ({ - dropId - }: { - dropId?: number; - }) => Promise; - config: ({ - dropId - }: { - dropId?: number; - }) => Promise; + collection: () => Promise; + tokenDetails: () => Promise; + authDetails: () => Promise; + config: () => Promise; mintedTokens: ({ - address, - dropId + address }: { address: string; - dropId?: number; }) => Promise; - totalMintedCount: ({ - dropId - }: { - dropId?: number; - }) => Promise; - tokensRemaining: ({ - dropId - }: { - dropId?: number; - }) => Promise; isPaused: () => Promise; pausers: () => Promise; - currentDropNumber: () => Promise; + extension: (queryMsgExtension: QueryMsgExtension) => Promise; + totalMintedCount: () => Promise; } export class OmniflixMultiMintOpenEditionMinterQueryClient implements OmniflixMultiMintOpenEditionMinterReadOnlyInterface { client: CosmWasmClient; @@ -48,70 +31,44 @@ export class OmniflixMultiMintOpenEditionMinterQueryClient implements OmniflixMu this.client = client; this.contractAddress = contractAddress; this.collection = this.collection.bind(this); + this.tokenDetails = this.tokenDetails.bind(this); + this.authDetails = this.authDetails.bind(this); this.config = this.config.bind(this); this.mintedTokens = this.mintedTokens.bind(this); - this.totalMintedCount = this.totalMintedCount.bind(this); - this.tokensRemaining = this.tokensRemaining.bind(this); this.isPaused = this.isPaused.bind(this); this.pausers = this.pausers.bind(this); - this.currentDropNumber = this.currentDropNumber.bind(this); + this.extension = this.extension.bind(this); + this.totalMintedCount = this.totalMintedCount.bind(this); } - collection = async ({ - dropId - }: { - dropId?: number; - }): Promise => { + collection = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - collection: { - drop_id: dropId - } + collection: {} }); }; - config = async ({ - dropId - }: { - dropId?: number; - }): Promise => { + tokenDetails = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - config: { - drop_id: dropId - } + token_details: {} }); }; - mintedTokens = async ({ - address, - dropId - }: { - address: string; - dropId?: number; - }): Promise => { + authDetails = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - minted_tokens: { - address, - drop_id: dropId - } + auth_details: {} }); }; - totalMintedCount = async ({ - dropId - }: { - dropId?: number; - }): Promise => { + config = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - total_minted_count: { - drop_id: dropId - } + config: {} }); }; - tokensRemaining = async ({ - dropId + mintedTokens = async ({ + address }: { - dropId?: number; - }): Promise => { + address: string; + }): Promise => { return this.client.queryContractSmart(this.contractAddress, { - tokens_remaining: { - drop_id: dropId + minted_tokens: { + address } }); }; @@ -125,9 +82,14 @@ export class OmniflixMultiMintOpenEditionMinterQueryClient implements OmniflixMu pausers: {} }); }; - currentDropNumber = async (): Promise => { + extension = async (queryMsgExtension: QueryMsgExtension): Promise => { return this.client.queryContractSmart(this.contractAddress, { - current_drop_number: {} + extension: queryMsgExtension + }); + }; + totalMintedCount = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + total_minted_count: {} }); }; } @@ -175,39 +137,11 @@ export interface OmniflixMultiMintOpenEditionMinterInterface extends OmniflixMul pausers: string[]; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; newDrop: ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - perAddressLimit, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress + newConfig, + newTokenDetails }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - perAddressLimit: number; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; + newConfig: Config; + newTokenDetails: TokenDetails; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; updateRoyaltyReceivers: ({ receivers @@ -224,6 +158,16 @@ export interface OmniflixMultiMintOpenEditionMinterInterface extends OmniflixMul previewUri?: string; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; purgeDenom: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setAdmin: ({ + admin + }: { + admin: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setPaymentCollector: ({ + paymentCollector + }: { + paymentCollector: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; } export class OmniflixMultiMintOpenEditionMinterClient extends OmniflixMultiMintOpenEditionMinterQueryClient implements OmniflixMultiMintOpenEditionMinterInterface { client: SigningCosmWasmClient; @@ -247,6 +191,8 @@ export class OmniflixMultiMintOpenEditionMinterClient extends OmniflixMultiMintO this.updateRoyaltyReceivers = this.updateRoyaltyReceivers.bind(this); this.updateDenom = this.updateDenom.bind(this); this.purgeDenom = this.purgeDenom.bind(this); + this.setAdmin = this.setAdmin.bind(this); + this.setPaymentCollector = this.setPaymentCollector.bind(this); } mint = async ({ @@ -338,58 +284,16 @@ export class OmniflixMultiMintOpenEditionMinterClient extends OmniflixMultiMintO }, fee, memo, _funds); }; newDrop = async ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - perAddressLimit, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress + newConfig, + newTokenDetails }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - perAddressLimit: number; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; + newConfig: Config; + newTokenDetails: TokenDetails; }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { return await this.client.execute(this.sender, this.contractAddress, { new_drop: { - base_uri: baseUri, - data, - description, - end_time: endTime, - extensible, - mint_price: mintPrice, - nsfw, - per_address_limit: perAddressLimit, - preview_uri: previewUri, - royalty_ratio: royaltyRatio, - start_time: startTime, - token_limit: tokenLimit, - token_name: tokenName, - transferable, - uri_hash: uriHash, - whitelist_address: whitelistAddress + new_config: newConfig, + new_token_details: newTokenDetails } }, fee, memo, _funds); }; @@ -426,4 +330,26 @@ export class OmniflixMultiMintOpenEditionMinterClient extends OmniflixMultiMintO purge_denom: {} }, fee, memo, _funds); }; + setAdmin = async ({ + admin + }: { + admin: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + set_admin: { + admin + } + }, fee, memo, _funds); + }; + setPaymentCollector = async ({ + paymentCollector + }: { + paymentCollector: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + set_payment_collector: { + payment_collector: paymentCollector + } + }, fee, memo, _funds); + }; } \ No newline at end of file diff --git a/ts/types/OmniflixMultiMintOpenEditionMinter.message-composer.ts b/ts/types/OmniflixMultiMintOpenEditionMinter.message-composer.ts index aac1c02..9628b6f 100644 --- a/ts/types/OmniflixMultiMintOpenEditionMinter.message-composer.ts +++ b/ts/types/OmniflixMultiMintOpenEditionMinter.message-composer.ts @@ -7,7 +7,7 @@ import { MsgExecuteContractEncodeObject } from "@cosmjs/cosmwasm-stargate"; import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; import { toUtf8 } from "@cosmjs/encoding"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixMultiMintOpenEditionMinter.types"; +import { Timestamp, Uint64, Uint128, Decimal, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, TokenDetails, ExecuteMsg, Addr, Config, QueryMsg, QueryMsgExtension, AuthDetails, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixMultiMintOpenEditionMinter.types"; export interface OmniflixMultiMintOpenEditionMinterMsg { contractAddress: string; sender: string; @@ -52,39 +52,11 @@ export interface OmniflixMultiMintOpenEditionMinterMsg { pausers: string[]; }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; newDrop: ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - perAddressLimit, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress + newConfig, + newTokenDetails }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - perAddressLimit: number; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; + newConfig: Config; + newTokenDetails: TokenDetails; }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; updateRoyaltyReceivers: ({ receivers @@ -101,6 +73,16 @@ export interface OmniflixMultiMintOpenEditionMinterMsg { previewUri?: string; }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; purgeDenom: (_funds?: Coin[]) => MsgExecuteContractEncodeObject; + setAdmin: ({ + admin + }: { + admin: string; + }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; + setPaymentCollector: ({ + paymentCollector + }: { + paymentCollector: string; + }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; } export class OmniflixMultiMintOpenEditionMinterMsgComposer implements OmniflixMultiMintOpenEditionMinterMsg { sender: string; @@ -121,6 +103,8 @@ export class OmniflixMultiMintOpenEditionMinterMsgComposer implements OmniflixMu this.updateRoyaltyReceivers = this.updateRoyaltyReceivers.bind(this); this.updateDenom = this.updateDenom.bind(this); this.purgeDenom = this.purgeDenom.bind(this); + this.setAdmin = this.setAdmin.bind(this); + this.setPaymentCollector = this.setPaymentCollector.bind(this); } mint = ({ @@ -276,39 +260,11 @@ export class OmniflixMultiMintOpenEditionMinterMsgComposer implements OmniflixMu }; }; newDrop = ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - perAddressLimit, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress + newConfig, + newTokenDetails }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - perAddressLimit: number; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; + newConfig: Config; + newTokenDetails: TokenDetails; }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { return { typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", @@ -317,22 +273,8 @@ export class OmniflixMultiMintOpenEditionMinterMsgComposer implements OmniflixMu contract: this.contractAddress, msg: toUtf8(JSON.stringify({ new_drop: { - base_uri: baseUri, - data, - description, - end_time: endTime, - extensible, - mint_price: mintPrice, - nsfw, - per_address_limit: perAddressLimit, - preview_uri: previewUri, - royalty_ratio: royaltyRatio, - start_time: startTime, - token_limit: tokenLimit, - token_name: tokenName, - transferable, - uri_hash: uriHash, - whitelist_address: whitelistAddress + new_config: newConfig, + new_token_details: newTokenDetails } })), funds: _funds @@ -396,4 +338,42 @@ export class OmniflixMultiMintOpenEditionMinterMsgComposer implements OmniflixMu }) }; }; + setAdmin = ({ + admin + }: { + admin: string; + }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { + return { + typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", + value: MsgExecuteContract.fromPartial({ + sender: this.sender, + contract: this.contractAddress, + msg: toUtf8(JSON.stringify({ + set_admin: { + admin + } + })), + funds: _funds + }) + }; + }; + setPaymentCollector = ({ + paymentCollector + }: { + paymentCollector: string; + }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { + return { + typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", + value: MsgExecuteContract.fromPartial({ + sender: this.sender, + contract: this.contractAddress, + msg: toUtf8(JSON.stringify({ + set_payment_collector: { + payment_collector: paymentCollector + } + })), + funds: _funds + }) + }; + }; } \ No newline at end of file diff --git a/ts/types/OmniflixMultiMintOpenEditionMinter.types.ts b/ts/types/OmniflixMultiMintOpenEditionMinter.types.ts index 9c28539..0d5363e 100644 --- a/ts/types/OmniflixMultiMintOpenEditionMinter.types.ts +++ b/ts/types/OmniflixMultiMintOpenEditionMinter.types.ts @@ -7,26 +7,23 @@ export type Timestamp = Uint64; export type Uint64 = string; export type Uint128 = string; +export type Decimal = string; export interface InstantiateMsg { collection_details: CollectionDetails; init: OpenEditionMinterInitExtention; + token_details: TokenDetails; } export interface CollectionDetails { - base_uri: string; - data: string; - description: string; - extensible: boolean; + collection_name: string; + data?: string | null; + description?: string | null; id: string; - name: string; - nsfw: boolean; - preview_uri: string; + preview_uri?: string | null; royalty_receivers?: WeightedAddress[] | null; - schema: string; + schema?: string | null; symbol: string; - token_name: string; - transferable: boolean; - uri: string; - uri_hash: string; + uri?: string | null; + uri_hash?: string | null; } export interface WeightedAddress { address: string; @@ -37,11 +34,10 @@ export interface OpenEditionMinterInitExtention { admin: string; end_time?: Timestamp | null; mint_price: Coin; + num_tokens?: number | null; payment_collector?: string | null; - per_address_limit: number; - royalty_ratio: string; + per_address_limit?: number | null; start_time: Timestamp; - token_limit?: number | null; whitelist_address?: string | null; } export interface Coin { @@ -49,6 +45,17 @@ export interface Coin { denom: string; [k: string]: unknown; } +export interface TokenDetails { + base_token_uri: string; + data?: string | null; + description?: string | null; + extensible: boolean; + nsfw: boolean; + preview_uri?: string | null; + royalty_ratio: Decimal; + token_name: string; + transferable: boolean; +} export type ExecuteMsg = { mint: { drop_id?: number | null; @@ -83,22 +90,8 @@ export type ExecuteMsg = { }; } | { new_drop: { - base_uri?: string | null; - data?: string | null; - description?: string | null; - end_time?: Timestamp | null; - extensible?: boolean | null; - mint_price: Coin; - nsfw?: boolean | null; - per_address_limit: number; - preview_uri?: string | null; - royalty_ratio?: string | null; - start_time: Timestamp; - token_limit?: number | null; - token_name: string; - transferable?: boolean | null; - uri_hash?: string | null; - whitelist_address?: string | null; + new_config: Config; + new_token_details: TokenDetails; }; } | { update_royalty_receivers: { @@ -112,47 +105,74 @@ export type ExecuteMsg = { }; } | { purge_denom: {}; +} | { + set_admin: { + admin: string; + }; +} | { + set_payment_collector: { + payment_collector: string; + }; }; +export type Addr = string; +export interface Config { + end_time?: Timestamp | null; + mint_price: Coin; + num_tokens?: number | null; + per_address_limit?: number | null; + start_time: Timestamp; + whitelist_address?: Addr | null; +} export type QueryMsg = { + collection: {}; +} | { + token_details: {}; +} | { + auth_details: {}; +} | { + config: {}; +} | { + minted_tokens: { + address: string; + }; +} | { + is_paused: {}; +} | { + pausers: {}; +} | { + extension: QueryMsgExtension; +} | { + total_minted_count: {}; +}; +export type QueryMsgExtension = { collection: { drop_id?: number | null; }; } | { - config: { + token_details: { drop_id?: number | null; }; } | { - minted_tokens: { - address: string; + config: { drop_id?: number | null; }; } | { - total_minted_count: { + minted_tokens: { + address: string; drop_id?: number | null; }; } | { tokens_remaining: { drop_id?: number | null; }; -} | { - is_paused: {}; -} | { - pausers: {}; } | { current_drop_number: {}; +} | { + all_drops: {}; }; -export type Addr = string; -export type Decimal = string; -export interface Config { +export interface AuthDetails { admin: Addr; - end_time?: Timestamp | null; - mint_price: Coin; payment_collector: Addr; - per_address_limit: number; - royalty_ratio: Decimal; - start_time: Timestamp; - token_limit?: number | null; - whitelist_address?: Addr | null; } export type Uint32 = number; export type Boolean = boolean; diff --git a/ts/types/OmniflixOpenEditionMinter.client.ts b/ts/types/OmniflixOpenEditionMinter.client.ts index 8c4c327..9538e85 100644 --- a/ts/types/OmniflixOpenEditionMinter.client.ts +++ b/ts/types/OmniflixOpenEditionMinter.client.ts @@ -6,20 +6,22 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Boolean, UserDetails, Token, ArrayOfAddr, Uint32 } from "./OmniflixOpenEditionMinter.types"; +import { Timestamp, Uint64, Uint128, Decimal, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, TokenDetails, ExecuteMsg, QueryMsg, OEMQueryExtension, Addr, AuthDetails, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixOpenEditionMinter.types"; export interface OmniflixOpenEditionMinterReadOnlyInterface { contractAddress: string; collection: () => Promise; + tokenDetails: () => Promise; + authDetails: () => Promise; config: () => Promise; mintedTokens: ({ address }: { address: string; }) => Promise; - totalMintedCount: () => Promise; - tokensRemaining: () => Promise; isPaused: () => Promise; pausers: () => Promise; + extension: (oEMQueryExtension: OEMQueryExtension) => Promise; + totalMintedCount: () => Promise; } export class OmniflixOpenEditionMinterQueryClient implements OmniflixOpenEditionMinterReadOnlyInterface { client: CosmWasmClient; @@ -29,12 +31,14 @@ export class OmniflixOpenEditionMinterQueryClient implements OmniflixOpenEdition this.client = client; this.contractAddress = contractAddress; this.collection = this.collection.bind(this); + this.tokenDetails = this.tokenDetails.bind(this); + this.authDetails = this.authDetails.bind(this); this.config = this.config.bind(this); this.mintedTokens = this.mintedTokens.bind(this); - this.totalMintedCount = this.totalMintedCount.bind(this); - this.tokensRemaining = this.tokensRemaining.bind(this); this.isPaused = this.isPaused.bind(this); this.pausers = this.pausers.bind(this); + this.extension = this.extension.bind(this); + this.totalMintedCount = this.totalMintedCount.bind(this); } collection = async (): Promise => { @@ -42,6 +46,16 @@ export class OmniflixOpenEditionMinterQueryClient implements OmniflixOpenEdition collection: {} }); }; + tokenDetails = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + token_details: {} + }); + }; + authDetails = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + auth_details: {} + }); + }; config = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { config: {} @@ -58,24 +72,24 @@ export class OmniflixOpenEditionMinterQueryClient implements OmniflixOpenEdition } }); }; - totalMintedCount = async (): Promise => { + isPaused = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - total_minted_count: {} + is_paused: {} }); }; - tokensRemaining = async (): Promise => { + pausers = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - tokens_remaining: {} + pausers: {} }); }; - isPaused = async (): Promise => { + extension = async (oEMQueryExtension: OEMQueryExtension): Promise => { return this.client.queryContractSmart(this.contractAddress, { - is_paused: {} + extension: oEMQueryExtension }); }; - pausers = async (): Promise => { + totalMintedCount = async (): Promise => { return this.client.queryContractSmart(this.contractAddress, { - pausers: {} + total_minted_count: {} }); }; } @@ -116,15 +130,25 @@ export interface OmniflixOpenEditionMinterInterface extends OmniflixOpenEditionM receivers: WeightedAddress[]; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; updateDenom: ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; purgeDenom: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setAdmin: ({ + admin + }: { + admin: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + setPaymentCollector: ({ + paymentCollector + }: { + paymentCollector: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; } export class OmniflixOpenEditionMinterClient extends OmniflixOpenEditionMinterQueryClient implements OmniflixOpenEditionMinterInterface { client: SigningCosmWasmClient; @@ -147,6 +171,8 @@ export class OmniflixOpenEditionMinterClient extends OmniflixOpenEditionMinterQu this.updateRoyaltyReceivers = this.updateRoyaltyReceivers.bind(this); this.updateDenom = this.updateDenom.bind(this); this.purgeDenom = this.purgeDenom.bind(this); + this.setAdmin = this.setAdmin.bind(this); + this.setPaymentCollector = this.setPaymentCollector.bind(this); } mint = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { @@ -231,18 +257,18 @@ export class OmniflixOpenEditionMinterClient extends OmniflixOpenEditionMinterQu }, fee, memo, _funds); }; updateDenom = async ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { return await this.client.execute(this.sender, this.contractAddress, { update_denom: { + collection_name: collectionName, description, - name, preview_uri: previewUri } }, fee, memo, _funds); @@ -252,4 +278,26 @@ export class OmniflixOpenEditionMinterClient extends OmniflixOpenEditionMinterQu purge_denom: {} }, fee, memo, _funds); }; + setAdmin = async ({ + admin + }: { + admin: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + set_admin: { + admin + } + }, fee, memo, _funds); + }; + setPaymentCollector = async ({ + paymentCollector + }: { + paymentCollector: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + set_payment_collector: { + payment_collector: paymentCollector + } + }, fee, memo, _funds); + }; } \ No newline at end of file diff --git a/ts/types/OmniflixOpenEditionMinter.message-composer.ts b/ts/types/OmniflixOpenEditionMinter.message-composer.ts index 034678c..976e086 100644 --- a/ts/types/OmniflixOpenEditionMinter.message-composer.ts +++ b/ts/types/OmniflixOpenEditionMinter.message-composer.ts @@ -7,7 +7,7 @@ import { MsgExecuteContractEncodeObject } from "@cosmjs/cosmwasm-stargate"; import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; import { toUtf8 } from "@cosmjs/encoding"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Boolean, UserDetails, Token, ArrayOfAddr, Uint32 } from "./OmniflixOpenEditionMinter.types"; +import { Timestamp, Uint64, Uint128, Decimal, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, TokenDetails, ExecuteMsg, QueryMsg, OEMQueryExtension, Addr, AuthDetails, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixOpenEditionMinter.types"; export interface OmniflixOpenEditionMinterMsg { contractAddress: string; sender: string; @@ -45,15 +45,25 @@ export interface OmniflixOpenEditionMinterMsg { receivers: WeightedAddress[]; }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; updateDenom: ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; purgeDenom: (_funds?: Coin[]) => MsgExecuteContractEncodeObject; + setAdmin: ({ + admin + }: { + admin: string; + }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; + setPaymentCollector: ({ + paymentCollector + }: { + paymentCollector: string; + }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; } export class OmniflixOpenEditionMinterMsgComposer implements OmniflixOpenEditionMinterMsg { sender: string; @@ -73,6 +83,8 @@ export class OmniflixOpenEditionMinterMsgComposer implements OmniflixOpenEdition this.updateRoyaltyReceivers = this.updateRoyaltyReceivers.bind(this); this.updateDenom = this.updateDenom.bind(this); this.purgeDenom = this.purgeDenom.bind(this); + this.setAdmin = this.setAdmin.bind(this); + this.setPaymentCollector = this.setPaymentCollector.bind(this); } mint = (_funds?: Coin[]): MsgExecuteContractEncodeObject => { @@ -229,12 +241,12 @@ export class OmniflixOpenEditionMinterMsgComposer implements OmniflixOpenEdition }; }; updateDenom = ({ + collectionName, description, - name, previewUri }: { + collectionName?: string; description?: string; - name?: string; previewUri?: string; }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { return { @@ -244,8 +256,8 @@ export class OmniflixOpenEditionMinterMsgComposer implements OmniflixOpenEdition contract: this.contractAddress, msg: toUtf8(JSON.stringify({ update_denom: { + collection_name: collectionName, description, - name, preview_uri: previewUri } })), @@ -266,4 +278,42 @@ export class OmniflixOpenEditionMinterMsgComposer implements OmniflixOpenEdition }) }; }; + setAdmin = ({ + admin + }: { + admin: string; + }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { + return { + typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", + value: MsgExecuteContract.fromPartial({ + sender: this.sender, + contract: this.contractAddress, + msg: toUtf8(JSON.stringify({ + set_admin: { + admin + } + })), + funds: _funds + }) + }; + }; + setPaymentCollector = ({ + paymentCollector + }: { + paymentCollector: string; + }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { + return { + typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", + value: MsgExecuteContract.fromPartial({ + sender: this.sender, + contract: this.contractAddress, + msg: toUtf8(JSON.stringify({ + set_payment_collector: { + payment_collector: paymentCollector + } + })), + funds: _funds + }) + }; + }; } \ No newline at end of file diff --git a/ts/types/OmniflixOpenEditionMinter.types.ts b/ts/types/OmniflixOpenEditionMinter.types.ts index 0b5dd02..8819510 100644 --- a/ts/types/OmniflixOpenEditionMinter.types.ts +++ b/ts/types/OmniflixOpenEditionMinter.types.ts @@ -7,26 +7,23 @@ export type Timestamp = Uint64; export type Uint64 = string; export type Uint128 = string; +export type Decimal = string; export interface InstantiateMsg { collection_details: CollectionDetails; init: OpenEditionMinterInitExtention; + token_details: TokenDetails; } export interface CollectionDetails { - base_uri: string; - data: string; - description: string; - extensible: boolean; + collection_name: string; + data?: string | null; + description?: string | null; id: string; - name: string; - nsfw: boolean; - preview_uri: string; + preview_uri?: string | null; royalty_receivers?: WeightedAddress[] | null; - schema: string; + schema?: string | null; symbol: string; - token_name: string; - transferable: boolean; - uri: string; - uri_hash: string; + uri?: string | null; + uri_hash?: string | null; } export interface WeightedAddress { address: string; @@ -37,11 +34,10 @@ export interface OpenEditionMinterInitExtention { admin: string; end_time?: Timestamp | null; mint_price: Coin; + num_tokens?: number | null; payment_collector?: string | null; - per_address_limit: number; - royalty_ratio: string; + per_address_limit?: number | null; start_time: Timestamp; - token_limit?: number | null; whitelist_address?: string | null; } export interface Coin { @@ -49,6 +45,17 @@ export interface Coin { denom: string; [k: string]: unknown; } +export interface TokenDetails { + base_token_uri: string; + data?: string | null; + description?: string | null; + extensible: boolean; + nsfw: boolean; + preview_uri?: string | null; + royalty_ratio: Decimal; + token_name: string; + transferable: boolean; +} export type ExecuteMsg = { mint: {}; } | { @@ -81,43 +88,59 @@ export type ExecuteMsg = { }; } | { update_denom: { + collection_name?: string | null; description?: string | null; - name?: string | null; preview_uri?: string | null; }; } | { purge_denom: {}; +} | { + set_admin: { + admin: string; + }; +} | { + set_payment_collector: { + payment_collector: string; + }; }; export type QueryMsg = { collection: {}; +} | { + token_details: {}; +} | { + auth_details: {}; } | { config: {}; } | { minted_tokens: { address: string; }; -} | { - total_minted_count: {}; -} | { - tokens_remaining: {}; } | { is_paused: {}; } | { pausers: {}; +} | { + extension: OEMQueryExtension; +} | { + total_minted_count: {}; +}; +export type OEMQueryExtension = { + tokens_remaining: {}; }; export type Addr = string; -export type Decimal = string; -export interface Config { +export interface AuthDetails { admin: Addr; + payment_collector: Addr; +} +export interface Config { end_time?: Timestamp | null; mint_price: Coin; - payment_collector: Addr; - per_address_limit: number; - royalty_ratio: Decimal; + num_tokens?: number | null; + per_address_limit?: number | null; start_time: Timestamp; - token_limit?: number | null; whitelist_address?: Addr | null; } +export type Uint32 = number; export type Boolean = boolean; export interface UserDetails { minted_tokens: Token[]; @@ -127,5 +150,4 @@ export interface UserDetails { export interface Token { token_id: string; } -export type ArrayOfAddr = Addr[]; -export type Uint32 = number; \ No newline at end of file +export type ArrayOfAddr = Addr[]; \ No newline at end of file diff --git a/ts/types/OmniflixOpenEditionMinterCopy.client.ts b/ts/types/OmniflixOpenEditionMinterCopy.client.ts deleted file mode 100644 index 8973671..0000000 --- a/ts/types/OmniflixOpenEditionMinterCopy.client.ts +++ /dev/null @@ -1,358 +0,0 @@ -/** -* This file was automatically generated by @cosmwasm/ts-codegen@0.35.7. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ - -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; -import { StdFee } from "@cosmjs/amino"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixOpenEditionMinterCopy.types"; -export interface OmniflixOpenEditionMinterCopyReadOnlyInterface { - contractAddress: string; - collection: ({ - edition - }: { - edition?: number; - }) => Promise; - config: ({ - edition - }: { - edition?: number; - }) => Promise; - mintedTokens: ({ - address, - edition - }: { - address: string; - edition?: number; - }) => Promise; - totalMintedCount: ({ - edition - }: { - edition?: number; - }) => Promise; - tokensRemaining: ({ - edition - }: { - edition?: number; - }) => Promise; - isPaused: () => Promise; - pausers: () => Promise; - currentEditionNumber: () => Promise; -} -export class OmniflixOpenEditionMinterCopyQueryClient implements OmniflixOpenEditionMinterCopyReadOnlyInterface { - client: CosmWasmClient; - contractAddress: string; - - constructor(client: CosmWasmClient, contractAddress: string) { - this.client = client; - this.contractAddress = contractAddress; - this.collection = this.collection.bind(this); - this.config = this.config.bind(this); - this.mintedTokens = this.mintedTokens.bind(this); - this.totalMintedCount = this.totalMintedCount.bind(this); - this.tokensRemaining = this.tokensRemaining.bind(this); - this.isPaused = this.isPaused.bind(this); - this.pausers = this.pausers.bind(this); - this.currentEditionNumber = this.currentEditionNumber.bind(this); - } - - collection = async ({ - edition - }: { - edition?: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - collection: { - edition - } - }); - }; - config = async ({ - edition - }: { - edition?: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - config: { - edition - } - }); - }; - mintedTokens = async ({ - address, - edition - }: { - address: string; - edition?: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - minted_tokens: { - address, - edition - } - }); - }; - totalMintedCount = async ({ - edition - }: { - edition?: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - total_minted_count: { - edition - } - }); - }; - tokensRemaining = async ({ - edition - }: { - edition?: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - tokens_remaining: { - edition - } - }); - }; - isPaused = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - is_paused: {} - }); - }; - pausers = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - pausers: {} - }); - }; - currentEditionNumber = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - current_edition_number: {} - }); - }; -} -export interface OmniflixOpenEditionMinterCopyInterface extends OmniflixOpenEditionMinterCopyReadOnlyInterface { - contractAddress: string; - sender: string; - mint: ({ - edition - }: { - edition?: number; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - mintAdmin: ({ - edition, - recipient - }: { - edition?: number; - recipient: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateRoyaltyRatio: ({ - ratio - }: { - ratio: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateMintPrice: ({ - mintPrice - }: { - mintPrice: Coin; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - updateWhitelistAddress: ({ - address - }: { - address: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - pause: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - unpause: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - setPausers: ({ - pausers - }: { - pausers: string[]; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; - newEdition: ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress - }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; - }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; -} -export class OmniflixOpenEditionMinterCopyClient extends OmniflixOpenEditionMinterCopyQueryClient implements OmniflixOpenEditionMinterCopyInterface { - client: SigningCosmWasmClient; - sender: string; - contractAddress: string; - - constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { - super(client, contractAddress); - this.client = client; - this.sender = sender; - this.contractAddress = contractAddress; - this.mint = this.mint.bind(this); - this.mintAdmin = this.mintAdmin.bind(this); - this.updateRoyaltyRatio = this.updateRoyaltyRatio.bind(this); - this.updateMintPrice = this.updateMintPrice.bind(this); - this.updateWhitelistAddress = this.updateWhitelistAddress.bind(this); - this.pause = this.pause.bind(this); - this.unpause = this.unpause.bind(this); - this.setPausers = this.setPausers.bind(this); - this.newEdition = this.newEdition.bind(this); - } - - mint = async ({ - edition - }: { - edition?: number; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - mint: { - edition - } - }, fee, memo, _funds); - }; - mintAdmin = async ({ - edition, - recipient - }: { - edition?: number; - recipient: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - mint_admin: { - edition, - recipient - } - }, fee, memo, _funds); - }; - updateRoyaltyRatio = async ({ - ratio - }: { - ratio: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_royalty_ratio: { - ratio - } - }, fee, memo, _funds); - }; - updateMintPrice = async ({ - mintPrice - }: { - mintPrice: Coin; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_mint_price: { - mint_price: mintPrice - } - }, fee, memo, _funds); - }; - updateWhitelistAddress = async ({ - address - }: { - address: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_whitelist_address: { - address - } - }, fee, memo, _funds); - }; - pause = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - pause: {} - }, fee, memo, _funds); - }; - unpause = async (fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - unpause: {} - }, fee, memo, _funds); - }; - setPausers = async ({ - pausers - }: { - pausers: string[]; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - set_pausers: { - pausers - } - }, fee, memo, _funds); - }; - newEdition = async ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress - }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; - }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - new_edition: { - base_uri: baseUri, - data, - description, - end_time: endTime, - extensible, - mint_price: mintPrice, - nsfw, - preview_uri: previewUri, - royalty_ratio: royaltyRatio, - start_time: startTime, - token_limit: tokenLimit, - token_name: tokenName, - transferable, - uri_hash: uriHash, - whitelist_address: whitelistAddress - } - }, fee, memo, _funds); - }; -} \ No newline at end of file diff --git a/ts/types/OmniflixOpenEditionMinterCopy.message-composer.ts b/ts/types/OmniflixOpenEditionMinterCopy.message-composer.ts deleted file mode 100644 index 7bc6e21..0000000 --- a/ts/types/OmniflixOpenEditionMinterCopy.message-composer.ts +++ /dev/null @@ -1,304 +0,0 @@ -/** -* This file was automatically generated by @cosmwasm/ts-codegen@0.35.7. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ - -import { MsgExecuteContractEncodeObject } from "@cosmjs/cosmwasm-stargate"; -import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; -import { toUtf8 } from "@cosmjs/encoding"; -import { Timestamp, Uint64, Uint128, InstantiateMsg, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, Coin, ExecuteMsg, QueryMsg, Addr, Decimal, Config, Uint32, Boolean, UserDetails, Token, ArrayOfAddr } from "./OmniflixOpenEditionMinterCopy.types"; -export interface OmniflixOpenEditionMinterCopyMsg { - contractAddress: string; - sender: string; - mint: ({ - edition - }: { - edition?: number; - }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; - mintAdmin: ({ - edition, - recipient - }: { - edition?: number; - recipient: string; - }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; - updateRoyaltyRatio: ({ - ratio - }: { - ratio: string; - }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; - updateMintPrice: ({ - mintPrice - }: { - mintPrice: Coin; - }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; - updateWhitelistAddress: ({ - address - }: { - address: string; - }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; - pause: (_funds?: Coin[]) => MsgExecuteContractEncodeObject; - unpause: (_funds?: Coin[]) => MsgExecuteContractEncodeObject; - setPausers: ({ - pausers - }: { - pausers: string[]; - }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; - newEdition: ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress - }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; - }, _funds?: Coin[]) => MsgExecuteContractEncodeObject; -} -export class OmniflixOpenEditionMinterCopyMsgComposer implements OmniflixOpenEditionMinterCopyMsg { - sender: string; - contractAddress: string; - - constructor(sender: string, contractAddress: string) { - this.sender = sender; - this.contractAddress = contractAddress; - this.mint = this.mint.bind(this); - this.mintAdmin = this.mintAdmin.bind(this); - this.updateRoyaltyRatio = this.updateRoyaltyRatio.bind(this); - this.updateMintPrice = this.updateMintPrice.bind(this); - this.updateWhitelistAddress = this.updateWhitelistAddress.bind(this); - this.pause = this.pause.bind(this); - this.unpause = this.unpause.bind(this); - this.setPausers = this.setPausers.bind(this); - this.newEdition = this.newEdition.bind(this); - } - - mint = ({ - edition - }: { - edition?: number; - }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - mint: { - edition - } - })), - funds: _funds - }) - }; - }; - mintAdmin = ({ - edition, - recipient - }: { - edition?: number; - recipient: string; - }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - mint_admin: { - edition, - recipient - } - })), - funds: _funds - }) - }; - }; - updateRoyaltyRatio = ({ - ratio - }: { - ratio: string; - }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - update_royalty_ratio: { - ratio - } - })), - funds: _funds - }) - }; - }; - updateMintPrice = ({ - mintPrice - }: { - mintPrice: Coin; - }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - update_mint_price: { - mint_price: mintPrice - } - })), - funds: _funds - }) - }; - }; - updateWhitelistAddress = ({ - address - }: { - address: string; - }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - update_whitelist_address: { - address - } - })), - funds: _funds - }) - }; - }; - pause = (_funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - pause: {} - })), - funds: _funds - }) - }; - }; - unpause = (_funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - unpause: {} - })), - funds: _funds - }) - }; - }; - setPausers = ({ - pausers - }: { - pausers: string[]; - }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - set_pausers: { - pausers - } - })), - funds: _funds - }) - }; - }; - newEdition = ({ - baseUri, - data, - description, - endTime, - extensible, - mintPrice, - nsfw, - previewUri, - royaltyRatio, - startTime, - tokenLimit, - tokenName, - transferable, - uriHash, - whitelistAddress - }: { - baseUri?: string; - data?: string; - description?: string; - endTime?: Timestamp; - extensible?: boolean; - mintPrice: Coin; - nsfw?: boolean; - previewUri?: string; - royaltyRatio?: string; - startTime: Timestamp; - tokenLimit?: number; - tokenName: string; - transferable?: boolean; - uriHash?: string; - whitelistAddress?: string; - }, _funds?: Coin[]): MsgExecuteContractEncodeObject => { - return { - typeUrl: "/cosmwasm.wasm.v1.MsgExecuteContract", - value: MsgExecuteContract.fromPartial({ - sender: this.sender, - contract: this.contractAddress, - msg: toUtf8(JSON.stringify({ - new_edition: { - base_uri: baseUri, - data, - description, - end_time: endTime, - extensible, - mint_price: mintPrice, - nsfw, - preview_uri: previewUri, - royalty_ratio: royaltyRatio, - start_time: startTime, - token_limit: tokenLimit, - token_name: tokenName, - transferable, - uri_hash: uriHash, - whitelist_address: whitelistAddress - } - })), - funds: _funds - }) - }; - }; -} \ No newline at end of file diff --git a/ts/types/OmniflixOpenEditionMinterCopy.types.ts b/ts/types/OmniflixOpenEditionMinterCopy.types.ts deleted file mode 100644 index a512bc2..0000000 --- a/ts/types/OmniflixOpenEditionMinterCopy.types.ts +++ /dev/null @@ -1,151 +0,0 @@ -/** -* This file was automatically generated by @cosmwasm/ts-codegen@0.35.7. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @cosmwasm/ts-codegen generate command to regenerate this file. -*/ - -export type Timestamp = Uint64; -export type Uint64 = string; -export type Uint128 = string; -export interface InstantiateMsg { - collection_details: CollectionDetails; - init: OpenEditionMinterInitExtention; -} -export interface CollectionDetails { - base_uri: string; - data: string; - description: string; - extensible: boolean; - id: string; - name: string; - nsfw: boolean; - preview_uri: string; - royalty_receivers?: WeightedAddress[] | null; - schema: string; - symbol: string; - token_name: string; - transferable: boolean; - uri: string; - uri_hash: string; -} -export interface WeightedAddress { - address: string; - weight: string; - [k: string]: unknown; -} -export interface OpenEditionMinterInitExtention { - admin: string; - end_time?: Timestamp | null; - mint_price: Coin; - payment_collector?: string | null; - per_address_limit: number; - royalty_ratio: string; - start_time: Timestamp; - token_limit?: number | null; - whitelist_address?: string | null; -} -export interface Coin { - amount: Uint128; - denom: string; - [k: string]: unknown; -} -export type ExecuteMsg = { - mint: { - edition?: number | null; - }; -} | { - mint_admin: { - edition?: number | null; - recipient: string; - }; -} | { - update_royalty_ratio: { - ratio: string; - }; -} | { - update_mint_price: { - mint_price: Coin; - }; -} | { - update_whitelist_address: { - address: string; - }; -} | { - pause: {}; -} | { - unpause: {}; -} | { - set_pausers: { - pausers: string[]; - }; -} | { - new_edition: { - base_uri?: string | null; - data?: string | null; - description?: string | null; - end_time?: Timestamp | null; - extensible?: boolean | null; - mint_price: Coin; - nsfw?: boolean | null; - preview_uri?: string | null; - royalty_ratio?: string | null; - start_time: Timestamp; - token_limit?: number | null; - token_name: string; - transferable?: boolean | null; - uri_hash?: string | null; - whitelist_address?: string | null; - }; -}; -export type QueryMsg = { - collection: { - edition?: number | null; - }; -} | { - config: { - edition?: number | null; - }; -} | { - minted_tokens: { - address: string; - edition?: number | null; - }; -} | { - total_minted_count: { - edition?: number | null; - }; -} | { - tokens_remaining: { - edition?: number | null; - }; -} | { - is_paused: {}; -} | { - pausers: {}; -} | { - current_edition_number: {}; -}; -export type Addr = string; -export type Decimal = string; -export interface Config { - admin: Addr; - end_time?: Timestamp | null; - mint_price: Coin; - payment_collector: Addr; - per_address_limit: number; - royalty_ratio: Decimal; - start_time: Timestamp; - token_limit?: number | null; - whitelist_address?: Addr | null; -} -export type Uint32 = number; -export type Boolean = boolean; -export interface UserDetails { - minted_tokens: Token[]; - public_mint_count: number; - total_minted_count: number; -} -export interface Token { - token_id: string; -} -export type ArrayOfAddr = Addr[]; \ No newline at end of file diff --git a/ts/types/OmniflixOpenEditionMinterFactory.client.ts b/ts/types/OmniflixOpenEditionMinterFactory.client.ts index 15a87e0..65d9873 100644 --- a/ts/types/OmniflixOpenEditionMinterFactory.client.ts +++ b/ts/types/OmniflixOpenEditionMinterFactory.client.ts @@ -6,7 +6,7 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Timestamp, Uint64, MinterInstantiateMsgForOpenEditionMinterInitExtention, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, QueryMsg, Addr, ParamsResponse, Params } from "./OmniflixOpenEditionMinterFactory.types"; +import { Addr, Uint128, InstantiateMsg, FactoryParamsForEmpty, Coin, Empty, ExecuteMsg, Timestamp, Uint64, Decimal, MinterInstantiateMsgForOpenEditionMinterInitExtention, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, TokenDetails, QueryMsg, ParamsResponse } from "./OmniflixOpenEditionMinterFactory.types"; export interface OmniflixOpenEditionMinterFactoryReadOnlyInterface { contractAddress: string; params: () => Promise; diff --git a/ts/types/OmniflixOpenEditionMinterFactory.message-composer.ts b/ts/types/OmniflixOpenEditionMinterFactory.message-composer.ts index 8c4fd9a..4574ade 100644 --- a/ts/types/OmniflixOpenEditionMinterFactory.message-composer.ts +++ b/ts/types/OmniflixOpenEditionMinterFactory.message-composer.ts @@ -7,7 +7,7 @@ import { MsgExecuteContractEncodeObject } from "@cosmjs/cosmwasm-stargate"; import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; import { toUtf8 } from "@cosmjs/encoding"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Timestamp, Uint64, MinterInstantiateMsgForOpenEditionMinterInitExtention, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, QueryMsg, Addr, ParamsResponse, Params } from "./OmniflixOpenEditionMinterFactory.types"; +import { Addr, Uint128, InstantiateMsg, FactoryParamsForEmpty, Coin, Empty, ExecuteMsg, Timestamp, Uint64, Decimal, MinterInstantiateMsgForOpenEditionMinterInitExtention, CollectionDetails, WeightedAddress, OpenEditionMinterInitExtention, TokenDetails, QueryMsg, ParamsResponse } from "./OmniflixOpenEditionMinterFactory.types"; export interface OmniflixOpenEditionMinterFactoryMsg { contractAddress: string; sender: string; diff --git a/ts/types/OmniflixOpenEditionMinterFactory.types.ts b/ts/types/OmniflixOpenEditionMinterFactory.types.ts index e168623..b51355e 100644 --- a/ts/types/OmniflixOpenEditionMinterFactory.types.ts +++ b/ts/types/OmniflixOpenEditionMinterFactory.types.ts @@ -4,18 +4,27 @@ * and run the @cosmwasm/ts-codegen generate command to regenerate this file. */ +export type Addr = string; export type Uint128 = string; export interface InstantiateMsg { - admin?: string | null; - fee_collector_address: string; - minter_creation_fee: Coin; - open_edition_minter_code_id: number; + params: FactoryParamsForEmpty; +} +export interface FactoryParamsForEmpty { + admin: Addr; + contract_id: number; + creation_fee: Coin; + fee_collector_address: Addr; + init: Empty; + product_label: string; } export interface Coin { amount: Uint128; denom: string; [k: string]: unknown; } +export interface Empty { + [k: string]: unknown; +} export type ExecuteMsg = { create_minter: { msg: MinterInstantiateMsgForOpenEditionMinterInitExtention; @@ -39,26 +48,23 @@ export type ExecuteMsg = { }; export type Timestamp = Uint64; export type Uint64 = string; +export type Decimal = string; export interface MinterInstantiateMsgForOpenEditionMinterInitExtention { collection_details: CollectionDetails; init: OpenEditionMinterInitExtention; + token_details: TokenDetails; } export interface CollectionDetails { - base_uri: string; - data: string; - description: string; - extensible: boolean; + collection_name: string; + data?: string | null; + description?: string | null; id: string; - name: string; - nsfw: boolean; - preview_uri: string; + preview_uri?: string | null; royalty_receivers?: WeightedAddress[] | null; - schema: string; + schema?: string | null; symbol: string; - token_name: string; - transferable: boolean; - uri: string; - uri_hash: string; + uri?: string | null; + uri_hash?: string | null; } export interface WeightedAddress { address: string; @@ -69,23 +75,26 @@ export interface OpenEditionMinterInitExtention { admin: string; end_time?: Timestamp | null; mint_price: Coin; + num_tokens?: number | null; payment_collector?: string | null; - per_address_limit: number; - royalty_ratio: string; + per_address_limit?: number | null; start_time: Timestamp; - token_limit?: number | null; whitelist_address?: string | null; } +export interface TokenDetails { + base_token_uri: string; + data?: string | null; + description?: string | null; + extensible: boolean; + nsfw: boolean; + preview_uri?: string | null; + royalty_ratio: Decimal; + token_name: string; + transferable: boolean; +} export type QueryMsg = { params: {}; }; -export type Addr = string; export interface ParamsResponse { - params: Params; -} -export interface Params { - admin: Addr; - fee_collector_address: Addr; - minter_creation_fee: Coin; - open_edition_minter_code_id: number; + params: FactoryParamsForEmpty; } \ No newline at end of file diff --git a/ts/types/OmniflixRoundWhitelist.types.ts b/ts/types/OmniflixRoundWhitelist.types.ts index 08779d8..feceac0 100644 --- a/ts/types/OmniflixRoundWhitelist.types.ts +++ b/ts/types/OmniflixRoundWhitelist.types.ts @@ -9,7 +9,7 @@ export type Timestamp = Uint64; export type Uint64 = string; export type Uint128 = string; export interface InstantiateMsg { - admin?: string | null; + admin: string; rounds: Round[]; } export interface Round { diff --git a/ts/types/OmniflixRoundWhitelistFactory.client.ts b/ts/types/OmniflixRoundWhitelistFactory.client.ts index 0eb4d34..f72072d 100644 --- a/ts/types/OmniflixRoundWhitelistFactory.client.ts +++ b/ts/types/OmniflixRoundWhitelistFactory.client.ts @@ -6,7 +6,7 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Addr, Timestamp, Uint64, Round, QueryMsg, ParamsResponse, Params } from "./OmniflixRoundWhitelistFactory.types"; +import { Addr, Uint128, InstantiateMsg, FactoryParamsForEmpty, Coin, Empty, ExecuteMsg, Timestamp, Uint64, Round, QueryMsg, ParamsResponse } from "./OmniflixRoundWhitelistFactory.types"; export interface OmniflixRoundWhitelistFactoryReadOnlyInterface { contractAddress: string; params: () => Promise; diff --git a/ts/types/OmniflixRoundWhitelistFactory.message-composer.ts b/ts/types/OmniflixRoundWhitelistFactory.message-composer.ts index aa5b45b..0252821 100644 --- a/ts/types/OmniflixRoundWhitelistFactory.message-composer.ts +++ b/ts/types/OmniflixRoundWhitelistFactory.message-composer.ts @@ -7,7 +7,7 @@ import { MsgExecuteContractEncodeObject } from "@cosmjs/cosmwasm-stargate"; import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx"; import { toUtf8 } from "@cosmjs/encoding"; -import { Uint128, InstantiateMsg, Coin, ExecuteMsg, Addr, Timestamp, Uint64, Round, QueryMsg, ParamsResponse, Params } from "./OmniflixRoundWhitelistFactory.types"; +import { Addr, Uint128, InstantiateMsg, FactoryParamsForEmpty, Coin, Empty, ExecuteMsg, Timestamp, Uint64, Round, QueryMsg, ParamsResponse } from "./OmniflixRoundWhitelistFactory.types"; export interface OmniflixRoundWhitelistFactoryMsg { contractAddress: string; sender: string; diff --git a/ts/types/OmniflixRoundWhitelistFactory.types.ts b/ts/types/OmniflixRoundWhitelistFactory.types.ts index 042f04b..bc7d498 100644 --- a/ts/types/OmniflixRoundWhitelistFactory.types.ts +++ b/ts/types/OmniflixRoundWhitelistFactory.types.ts @@ -4,16 +4,28 @@ * and run the @cosmwasm/ts-codegen generate command to regenerate this file. */ +export type Addr = string; export type Uint128 = string; export interface InstantiateMsg { - admin?: string | null; + admin: string; rounds: Round[]; } +export interface FactoryParamsForEmpty { + admin: Addr; + contract_id: number; + creation_fee: Coin; + fee_collector_address: Addr; + init: Empty; + product_label: string; +} export interface Coin { amount: Uint128; denom: string; [k: string]: unknown; } +export interface Empty { + [k: string]: unknown; +} export type ExecuteMsg = { create_whitelist: { msg: InstantiateMsg; @@ -35,7 +47,6 @@ export type ExecuteMsg = { whitelist_code_id: number; }; }; -export type Addr = string; export type Timestamp = Uint64; export type Uint64 = string; export interface Round { @@ -49,11 +60,5 @@ export type QueryMsg = { params: {}; }; export interface ParamsResponse { - params: Params; -} -export interface Params { - admin: Addr; - fee_collector_address: Addr; - whitelist_code_id: number; - whitelist_creation_fee: Coin; + params: FactoryParamsForEmpty; } \ No newline at end of file