From 8f6362ba912e82b362536522ea490fee7d4842fb Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 18 Oct 2024 14:06:26 -0400 Subject: [PATCH 01/33] feat: add nft-launchpad contract and deps --- .gitignore | 6 +- rust/apipb/Cargo.toml | 9 + rust/apipb/src/dao.v1.rs | 56 + rust/apipb/src/feed.v1.rs | 134 + rust/apipb/src/launchpad.v1.rs | 278 ++ rust/apipb/src/lib.rs | 3 + rust/apipb/src/marketplace.v1.rs | 604 +++ rust/apipb/src/multisig.v1.rs | 398 ++ rust/apipb/src/p2e.v1.rs | 132 + rust/apipb/src/prices.v1.rs | 26 + .../nft-launchpad/.cargo/config.toml | 6 + rust/cw-contracts/nft-launchpad/.gitignore | 2 + rust/cw-contracts/nft-launchpad/Cargo.lock | 814 ++++ rust/cw-contracts/nft-launchpad/Cargo.toml | 26 + rust/cw-contracts/nft-launchpad/Makefile | 55 + .../nft-launchpad/config-mainnet.json | 9 + rust/cw-contracts/nft-launchpad/config.json | 9 + rust/cw-contracts/nft-launchpad/deploy.ts | 25 + .../nft-launchpad/schema/nft-launchpad.json | 839 +++++ .../nft-launchpad/schema/raw/execute.json | 409 ++ .../nft-launchpad/schema/raw/instantiate.json | 56 + .../nft-launchpad/schema/raw/query.json | 38 + .../raw/response_to_get_collection_by_id.json | 282 ++ .../schema/raw/response_to_get_config.json | 45 + .../nft-launchpad/src/bin/schema.rs | 10 + .../nft-launchpad/src/contract.rs | 377 ++ rust/cw-contracts/nft-launchpad/src/error.rs | 54 + rust/cw-contracts/nft-launchpad/src/lib.rs | 6 + .../nft-launchpad/src/multitest.rs | 363 ++ .../nft-launchpad/src/responses.rs | 26 + .../cw-contracts/nft-tr721/.cargo/config.toml | 6 + rust/cw-contracts/nft-tr721/Cargo.lock | 814 ++++ rust/cw-contracts/nft-tr721/Cargo.toml | 35 + rust/cw-contracts/nft-tr721/Makefile | 22 + rust/cw-contracts/nft-tr721/deploy.ts | 9 + .../nft-tr721/schema/nft-tr721.json | 3301 +++++++++++++++++ .../nft-tr721/schema/raw/execute.json | 635 ++++ .../nft-tr721/schema/raw/instantiate.json | 181 + .../nft-tr721/schema/raw/query.json | 496 +++ .../schema/raw/response_to_all_nft_info.json | 257 ++ .../schema/raw/response_to_all_operators.json | 100 + .../schema/raw/response_to_all_tokens.json | 18 + .../schema/raw/response_to_approval.json | 97 + .../schema/raw/response_to_approvals.json | 100 + .../raw/response_to_check_royalties.json | 15 + .../schema/raw/response_to_contract_info.json | 18 + .../raw/response_to_contract_version.json | 18 + .../schema/raw/response_to_extension.json | 659 ++++ .../schema/raw/response_to_merkle_root.json | 5 + .../schema/raw/response_to_mint_info.json | 44 + .../schema/raw/response_to_mint_periods.json | 109 + .../response_to_minted_count_by_period.json | 7 + .../raw/response_to_minted_count_by_user.json | 7 + .../schema/raw/response_to_minter.json | 15 + .../schema/raw/response_to_nft_info.json | 129 + .../schema/raw/response_to_num_tokens.json | 16 + .../schema/raw/response_to_operator.json | 97 + .../schema/raw/response_to_owner_of.json | 106 + .../schema/raw/response_to_ownership.json | 107 + .../schema/raw/response_to_royalty_info.json | 24 + .../schema/raw/response_to_tokens.json | 18 + .../schema/raw/response_to_total_minted.json | 7 + ...esponse_to_total_minted_count_by_user.json | 7 + rust/cw-contracts/nft-tr721/src/bin/schema.rs | 10 + rust/cw-contracts/nft-tr721/src/contract.rs | 817 ++++ rust/cw-contracts/nft-tr721/src/error.rs | 62 + rust/cw-contracts/nft-tr721/src/hasher.rs | 16 + rust/cw-contracts/nft-tr721/src/lib.rs | 9 + rust/cw-contracts/nft-tr721/src/multitest.rs | 685 ++++ .../nft-tr721/src/test_helpers.rs | 138 + rust/cw-contracts/nft-tr721/src/utils.rs | 32 + rust/utils/scripts.ts | 56 + 72 files changed, 14400 insertions(+), 1 deletion(-) create mode 100644 rust/apipb/Cargo.toml create mode 100644 rust/apipb/src/dao.v1.rs create mode 100644 rust/apipb/src/feed.v1.rs create mode 100644 rust/apipb/src/launchpad.v1.rs create mode 100644 rust/apipb/src/lib.rs create mode 100644 rust/apipb/src/marketplace.v1.rs create mode 100644 rust/apipb/src/multisig.v1.rs create mode 100644 rust/apipb/src/p2e.v1.rs create mode 100644 rust/apipb/src/prices.v1.rs create mode 100644 rust/cw-contracts/nft-launchpad/.cargo/config.toml create mode 100644 rust/cw-contracts/nft-launchpad/.gitignore create mode 100644 rust/cw-contracts/nft-launchpad/Cargo.lock create mode 100644 rust/cw-contracts/nft-launchpad/Cargo.toml create mode 100644 rust/cw-contracts/nft-launchpad/Makefile create mode 100644 rust/cw-contracts/nft-launchpad/config-mainnet.json create mode 100644 rust/cw-contracts/nft-launchpad/config.json create mode 100644 rust/cw-contracts/nft-launchpad/deploy.ts create mode 100644 rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json create mode 100644 rust/cw-contracts/nft-launchpad/schema/raw/execute.json create mode 100644 rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json create mode 100644 rust/cw-contracts/nft-launchpad/schema/raw/query.json create mode 100644 rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json create mode 100644 rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json create mode 100644 rust/cw-contracts/nft-launchpad/src/bin/schema.rs create mode 100644 rust/cw-contracts/nft-launchpad/src/contract.rs create mode 100644 rust/cw-contracts/nft-launchpad/src/error.rs create mode 100644 rust/cw-contracts/nft-launchpad/src/lib.rs create mode 100644 rust/cw-contracts/nft-launchpad/src/multitest.rs create mode 100644 rust/cw-contracts/nft-launchpad/src/responses.rs create mode 100644 rust/cw-contracts/nft-tr721/.cargo/config.toml create mode 100644 rust/cw-contracts/nft-tr721/Cargo.lock create mode 100644 rust/cw-contracts/nft-tr721/Cargo.toml create mode 100644 rust/cw-contracts/nft-tr721/Makefile create mode 100644 rust/cw-contracts/nft-tr721/deploy.ts create mode 100644 rust/cw-contracts/nft-tr721/schema/nft-tr721.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/execute.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/instantiate.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/query.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_all_nft_info.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_all_operators.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_all_tokens.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_approval.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_approvals.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_check_royalties.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_info.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_version.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_extension.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_merkle_root.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_info.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_periods.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_period.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_user.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_minter.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_nft_info.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_num_tokens.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_operator.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_owner_of.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_ownership.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_royalty_info.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_tokens.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted.json create mode 100644 rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted_count_by_user.json create mode 100644 rust/cw-contracts/nft-tr721/src/bin/schema.rs create mode 100644 rust/cw-contracts/nft-tr721/src/contract.rs create mode 100644 rust/cw-contracts/nft-tr721/src/error.rs create mode 100644 rust/cw-contracts/nft-tr721/src/hasher.rs create mode 100644 rust/cw-contracts/nft-tr721/src/lib.rs create mode 100644 rust/cw-contracts/nft-tr721/src/multitest.rs create mode 100644 rust/cw-contracts/nft-tr721/src/test_helpers.rs create mode 100644 rust/cw-contracts/nft-tr721/src/utils.rs create mode 100644 rust/utils/scripts.ts diff --git a/.gitignore b/.gitignore index d6e7b05ea6..1d5fca3586 100644 --- a/.gitignore +++ b/.gitignore @@ -104,6 +104,10 @@ temp/ # rust /target/ artifacts +rust/cw-contracts/*/target # cypress -cypress/screenshots \ No newline at end of file +cypress/screenshots + +# secret files +rust/utils/mnemonic.ts \ No newline at end of file diff --git a/rust/apipb/Cargo.toml b/rust/apipb/Cargo.toml new file mode 100644 index 0000000000..bee18a7788 --- /dev/null +++ b/rust/apipb/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "apipb" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +prost = { workspace = true } diff --git a/rust/apipb/src/dao.v1.rs b/rust/apipb/src/dao.v1.rs new file mode 100644 index 0000000000..ef346abae1 --- /dev/null +++ b/rust/apipb/src/dao.v1.rs @@ -0,0 +1,56 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DaOsRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub member_address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DaOsResponse { + #[prost(message, repeated, tag="1")] + pub daos: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IsUserDaoMemberRequest { + #[prost(string, tag="1")] + pub user_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub dao_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IsUserDaoMemberResponse { + #[prost(bool, tag="1")] + pub is_member: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Dao { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub admin: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub contract_address: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag="5")] + pub description: ::prost::alloc::string::String, + #[prost(string, tag="6")] + pub image_url: ::prost::alloc::string::String, + #[prost(string, tag="7")] + pub quorum: ::prost::alloc::string::String, + #[prost(string, tag="8")] + pub threshold: ::prost::alloc::string::String, + #[prost(string, tag="9")] + pub token_name: ::prost::alloc::string::String, + #[prost(string, tag="10")] + pub token_symbol: ::prost::alloc::string::String, + #[prost(uint64, tag="11")] + pub unstaking_duration: u64, +} +// @@protoc_insertion_point(module) diff --git a/rust/apipb/src/feed.v1.rs b/rust/apipb/src/feed.v1.rs new file mode 100644 index 0000000000..b7496def8b --- /dev/null +++ b/rust/apipb/src/feed.v1.rs @@ -0,0 +1,134 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IpfsKeyRequest { + #[prost(string, tag="1")] + pub user_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IpfsKeyResponse { + #[prost(string, tag="1")] + pub jwt: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Reaction { + #[prost(string, tag="1")] + pub icon: ::prost::alloc::string::String, + #[prost(uint32, tag="2")] + pub count: u32, + #[prost(bool, tag="3")] + pub own_state: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Post { + #[prost(uint32, tag="1")] + pub category: u32, + #[prost(bool, tag="2")] + pub is_deleted: bool, + /// use local_identifier + #[deprecated] + #[prost(string, tag="3")] + pub identifier: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub metadata: ::prost::alloc::string::String, + #[prost(string, tag="5")] + pub parent_post_identifier: ::prost::alloc::string::String, + #[prost(uint32, tag="6")] + pub sub_post_length: u32, + #[prost(string, tag="7")] + pub author_id: ::prost::alloc::string::String, + #[prost(int64, tag="8")] + pub created_at: i64, + #[prost(message, repeated, tag="9")] + pub reactions: ::prost::alloc::vec::Vec, + #[prost(int64, tag="10")] + pub tip_amount: i64, + #[prost(uint32, tag="11")] + pub premium_level: u32, + #[prost(string, tag="12")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="13")] + pub local_identifier: ::prost::alloc::string::String, + #[prost(string, tag="14")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PostFilter { + #[prost(string, tag="1")] + pub user: ::prost::alloc::string::String, + #[prost(string, repeated, tag="2")] + pub mentions: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint32, repeated, tag="3")] + pub categories: ::prost::alloc::vec::Vec, + #[prost(string, repeated, tag="4")] + pub hashtags: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// inclusive + #[prost(int32, tag="5")] + pub premium_level_min: i32, + /// inclusive, -1 means infinity + #[prost(int32, tag="6")] + pub premium_level_max: i32, + #[prost(string, tag="7")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PostsRequest { + #[prost(message, optional, tag="1")] + pub filter: ::core::option::Option, + #[prost(uint32, tag="2")] + pub limit: u32, + #[prost(uint32, tag="3")] + pub offset: u32, + #[prost(string, tag="4")] + pub query_user_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PostsWithLocationRequest { + #[prost(float, tag="1")] + pub north: f32, + #[prost(float, tag="2")] + pub south: f32, + #[prost(float, tag="3")] + pub west: f32, + #[prost(float, tag="4")] + pub east: f32, + #[prost(string, repeated, tag="5")] + pub hashtags: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint32, tag="6")] + pub limit: u32, + #[prost(string, tag="7")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AggregatedPost { + #[prost(float, tag="1")] + pub lat: f32, + #[prost(float, tag="2")] + pub long: f32, + #[prost(int64, tag="3")] + pub total_points: i64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PostsResponse { + #[prost(message, repeated, tag="1")] + pub posts: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PostsWithLocationResponse { + #[prost(message, repeated, tag="1")] + pub posts: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag="2")] + pub aggregated_posts: ::prost::alloc::vec::Vec, + #[prost(bool, tag="3")] + pub is_aggregated: bool, +} +// @@protoc_insertion_point(module) diff --git a/rust/apipb/src/launchpad.v1.rs b/rust/apipb/src/launchpad.v1.rs new file mode 100644 index 0000000000..bce910d3e1 --- /dev/null +++ b/rust/apipb/src/launchpad.v1.rs @@ -0,0 +1,278 @@ +// @generated +// ------------------------------- + +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectsByCreatorRequest { + #[prost(string, tag="1")] + pub creator_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub network_id: ::prost::alloc::string::String, + #[prost(int32, tag="3")] + pub limit: i32, + #[prost(int32, tag="4")] + pub offset: i32, + #[prost(enumeration="Sort", tag="5")] + pub sort: i32, + #[prost(enumeration="SortDirection", tag="6")] + pub sort_direction: i32, + #[prost(enumeration="Status", optional, tag="7")] + pub status: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectsByCreatorResponse { + #[prost(message, repeated, tag="1")] + pub projects: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectsRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, + #[prost(int32, tag="2")] + pub limit: i32, + #[prost(int32, tag="3")] + pub offset: i32, + #[prost(enumeration="Sort", tag="4")] + pub sort: i32, + #[prost(enumeration="SortDirection", tag="5")] + pub sort_direction: i32, + #[prost(enumeration="Status", optional, tag="6")] + pub status: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectsResponse { + #[prost(message, repeated, tag="1")] + pub projects: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectByIdRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub project_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectByIdResponse { + #[prost(message, optional, tag="1")] + pub project: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UploadMetadatasRequest { + #[prost(string, tag="1")] + pub sender: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub project_id: ::prost::alloc::string::String, + #[prost(message, repeated, tag="4")] + pub metadatas: ::prost::alloc::vec::Vec, + #[prost(string, optional, tag="5")] + pub pinata_jwt: ::core::option::Option<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UploadMetadatasResponse { + #[prost(string, tag="1")] + pub merkle_root: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CalculateCollectionMerkleRootRequest { + #[prost(string, tag="1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, repeated, tag="2")] + pub metadatas: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CalculateCollectionMerkleRootResponse { + #[prost(string, tag="1")] + pub merkle_root: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TokenMetadataRequest { + #[prost(string, tag="1")] + pub sender: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub project_id: ::prost::alloc::string::String, + #[prost(uint32, tag="4")] + pub token_id: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TokenMetadataResponse { + #[prost(string, tag="1")] + pub merkle_root: ::prost::alloc::string::String, + #[prost(message, optional, tag="2")] + pub metadata: ::core::option::Option, + #[prost(string, repeated, tag="3")] + pub merkle_proof: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectsCountRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, + #[prost(enumeration="Status", optional, tag="2")] + pub status: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProjectsCountResponse { + #[prost(uint32, tag="1")] + pub count: u32, +} +// ------------------------------- + +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LaunchpadProject { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub creator_id: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub collection_data: ::prost::alloc::string::String, + #[prost(string, optional, tag="5")] + pub merkle_root: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="6")] + pub deployed_address: ::core::option::Option<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Metadata { + #[prost(string, optional, tag="1")] + pub image: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="2")] + pub image_data: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="3")] + pub external_url: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="4")] + pub description: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="5")] + pub name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, repeated, tag="6")] + pub attributes: ::prost::alloc::vec::Vec, + #[prost(string, optional, tag="7")] + pub background_color: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="8")] + pub animation_url: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag="9")] + pub youtube_url: ::core::option::Option<::prost::alloc::string::String>, + #[prost(uint64, optional, tag="10")] + pub royalty_percentage: ::core::option::Option, + #[prost(string, optional, tag="11")] + pub royalty_payment_address: ::core::option::Option<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Trait { + #[prost(string, optional, tag="1")] + pub display_type: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, tag="2")] + pub trait_type: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub value: ::prost::alloc::string::String, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Sort { + Unspecified = 0, + CollectionName = 1, +} +impl Sort { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Sort::Unspecified => "SORT_UNSPECIFIED", + Sort::CollectionName => "SORT_COLLECTION_NAME", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SORT_UNSPECIFIED" => Some(Self::Unspecified), + "SORT_COLLECTION_NAME" => Some(Self::CollectionName), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum SortDirection { + Unspecified = 0, + Ascending = 1, + Descending = 2, +} +impl SortDirection { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + SortDirection::Unspecified => "SORT_DIRECTION_UNSPECIFIED", + SortDirection::Ascending => "SORT_DIRECTION_ASCENDING", + SortDirection::Descending => "SORT_DIRECTION_DESCENDING", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SORT_DIRECTION_UNSPECIFIED" => Some(Self::Unspecified), + "SORT_DIRECTION_ASCENDING" => Some(Self::Ascending), + "SORT_DIRECTION_DESCENDING" => Some(Self::Descending), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Status { + Unspecified = 0, + Incomplete = 1, + Complete = 2, + Confirmed = 3, + Deployed = 4, +} +impl Status { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Status::Unspecified => "STATUS_UNSPECIFIED", + Status::Incomplete => "STATUS_INCOMPLETE", + Status::Complete => "STATUS_COMPLETE", + Status::Confirmed => "STATUS_CONFIRMED", + Status::Deployed => "STATUS_DEPLOYED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "STATUS_UNSPECIFIED" => Some(Self::Unspecified), + "STATUS_INCOMPLETE" => Some(Self::Incomplete), + "STATUS_COMPLETE" => Some(Self::Complete), + "STATUS_CONFIRMED" => Some(Self::Confirmed), + "STATUS_DEPLOYED" => Some(Self::Deployed), + _ => None, + } + } +} +// @@protoc_insertion_point(module) diff --git a/rust/apipb/src/lib.rs b/rust/apipb/src/lib.rs new file mode 100644 index 0000000000..93abc33d87 --- /dev/null +++ b/rust/apipb/src/lib.rs @@ -0,0 +1,3 @@ +#[path = "launchpad.v1.rs"] +#[allow(dead_code)] +pub mod launchpadpb; diff --git a/rust/apipb/src/marketplace.v1.rs b/rust/apipb/src/marketplace.v1.rs new file mode 100644 index 0000000000..31ab5b22d6 --- /dev/null +++ b/rust/apipb/src/marketplace.v1.rs @@ -0,0 +1,604 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Attribute { + #[prost(string, tag="1")] + pub trait_type: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub value: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PriceRange { + #[prost(string, tag="1")] + pub min: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub max: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Nft { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="14")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub image_uri: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag="5")] + pub mint_address: ::prost::alloc::string::String, + #[prost(string, tag="6")] + pub price: ::prost::alloc::string::String, + #[prost(string, tag="7")] + pub denom: ::prost::alloc::string::String, + #[prost(bool, tag="8")] + pub is_listed: bool, + #[prost(string, tag="9")] + pub text_insert: ::prost::alloc::string::String, + #[prost(string, tag="10")] + pub collection_name: ::prost::alloc::string::String, + #[prost(string, tag="13")] + pub owner_id: ::prost::alloc::string::String, + #[prost(string, tag="15")] + pub nft_contract_address: ::prost::alloc::string::String, + #[prost(string, tag="16")] + pub locked_on: ::prost::alloc::string::String, + #[prost(message, repeated, tag="17")] + pub attributes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Amount { + #[prost(string, tag="1")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub quantity: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Collection { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub image_uri: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub collection_name: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub creator_name: ::prost::alloc::string::String, + #[prost(bool, tag="5")] + pub verified: bool, + #[prost(string, tag="6")] + pub mint_address: ::prost::alloc::string::String, + #[prost(string, tag="11")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="8")] + pub volume: ::prost::alloc::string::String, + #[prost(string, tag="9")] + pub volume_denom: ::prost::alloc::string::String, + #[prost(string, tag="10")] + pub creator_id: ::prost::alloc::string::String, + #[prost(bool, tag="12")] + pub secondary_during_mint: bool, + #[prost(string, tag="13")] + pub website_url: ::prost::alloc::string::String, + #[prost(string, tag="14")] + pub twitter_url: ::prost::alloc::string::String, + #[prost(string, tag="15")] + pub floor_price: ::prost::alloc::string::String, + #[prost(int64, tag="16")] + pub max_supply: i64, + #[prost(string, tag="17")] + pub mint_price: ::prost::alloc::string::String, + #[prost(string, tag="18")] + pub total_volume: ::prost::alloc::string::String, + #[prost(int64, tag="19")] + pub num_trades: i64, + #[prost(int32, tag="20")] + pub num_owners: i32, + #[prost(string, tag="21")] + pub denom: ::prost::alloc::string::String, + #[prost(float, tag="22")] + pub volume_compare: f32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CollectionStats { + #[prost(message, repeated, tag="1")] + pub floor_price: ::prost::alloc::vec::Vec, + #[prost(string, tag="2")] + pub total_volume: ::prost::alloc::string::String, + #[prost(int32, tag="3")] + pub owners: i32, + #[prost(int32, tag="4")] + pub listed: i32, + #[prost(int64, tag="5")] + pub total_supply: i64, + #[prost(int32, tag="6")] + pub owned: i32, + #[prost(float, tag="7")] + pub avg_price_period: f32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AttributeRarityFloor { + #[prost(string, tag="1")] + pub trait_type: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub value: ::prost::alloc::string::String, + #[prost(int32, tag="3")] + pub counta: i32, + #[prost(float, tag="4")] + pub floor: f32, + #[prost(string, tag="5")] + pub collection_id: ::prost::alloc::string::String, + #[prost(float, tag="6")] + pub rare_ratio: f32, + #[prost(int32, tag="7")] + pub collection_size: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NftCollectionAttributesResponse { + #[prost(message, optional, tag="1")] + pub attributes: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Activity { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub transaction_kind: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub target_name: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub target_image_uri: ::prost::alloc::string::String, + #[prost(string, tag="5")] + pub contract_name: ::prost::alloc::string::String, + #[prost(string, tag="6")] + pub time: ::prost::alloc::string::String, + #[prost(string, tag="7")] + pub amount: ::prost::alloc::string::String, + #[prost(string, tag="8")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag="9")] + pub transaction_id: ::prost::alloc::string::String, + #[prost(string, tag="10")] + pub buyer_id: ::prost::alloc::string::String, + #[prost(string, tag="11")] + pub seller_id: ::prost::alloc::string::String, + #[prost(double, tag="12")] + pub usd_price: f64, + #[prost(string, tag="13")] + pub target_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Quest { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub title: ::prost::alloc::string::String, + #[prost(bool, tag="3")] + pub completed: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PriceDatum { + #[prost(string, tag="3")] + pub price: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub time: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CollectionsRequest { + #[prost(int32, tag="2")] + pub limit: i32, + #[prost(int32, tag="3")] + pub offset: i32, + #[prost(enumeration="Sort", tag="4")] + pub sort: i32, + #[prost(enumeration="SortDirection", tag="5")] + pub sort_direction: i32, + #[prost(bool, tag="6")] + pub upcoming: bool, + #[prost(string, tag="7")] + pub network_id: ::prost::alloc::string::String, + #[prost(enumeration="MintState", tag="8")] + pub mint_state: i32, + #[prost(int32, optional, tag="9")] + pub period_in_minutes: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CollectionStatsRequest { + #[prost(string, tag="1")] + pub collection_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub owner_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NftCollectionAttributesRequest { + #[prost(string, tag="1")] + pub collection_id: ::prost::alloc::string::String, + #[prost(message, repeated, tag="2")] + pub where_attributes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CollectionStatsResponse { + #[prost(message, optional, tag="1")] + pub stats: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CollectionsResponse { + #[prost(message, optional, tag="1")] + pub collection: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NfTsRequest { + #[prost(int32, tag="1")] + pub limit: i32, + #[prost(int32, tag="2")] + pub offset: i32, + #[prost(string, tag="3")] + pub collection_id: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub owner_id: ::prost::alloc::string::String, + #[prost(enumeration="Sort", tag="5")] + pub sort: i32, + #[prost(enumeration="SortDirection", tag="6")] + pub sort_direction: i32, + #[prost(message, repeated, tag="7")] + pub attributes: ::prost::alloc::vec::Vec, + #[prost(bool, tag="8")] + pub is_listed: bool, + #[prost(message, optional, tag="9")] + pub price_range: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NfTsResponse { + #[prost(message, optional, tag="1")] + pub nft: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QuestsRequest { + #[prost(int32, tag="1")] + pub limit: i32, + #[prost(int32, tag="2")] + pub offset: i32, + #[prost(string, tag="3")] + pub user_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QuestsResponse { + #[prost(message, optional, tag="1")] + pub quest: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ActivityRequest { + #[prost(string, tag="1")] + pub collection_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub nft_id: ::prost::alloc::string::String, + #[prost(int32, tag="3")] + pub limit: i32, + #[prost(int32, tag="4")] + pub offset: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ActivityResponse { + #[prost(message, optional, tag="1")] + pub activity: ::core::option::Option, + #[prost(int64, tag="2")] + pub total: i64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NftPriceHistoryRequest { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NftPriceHistoryResponse { + #[prost(message, repeated, tag="1")] + pub data: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Action { + #[prost(string, tag="1")] + pub label: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub url: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct News { + #[prost(string, tag="1")] + pub title: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub subtitle: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub text: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub image: ::prost::alloc::string::String, + #[prost(message, repeated, tag="5")] + pub actions: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Banner { + #[prost(string, tag="1")] + pub image: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub url: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BannersRequest { + #[prost(bool, tag="1")] + pub testnet: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BannersResponse { + #[prost(message, repeated, tag="1")] + pub banners: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NewsRequest { + #[prost(bool, tag="1")] + pub testnet: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NewsResponse { + #[prost(message, repeated, tag="1")] + pub news: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DAppsRequest { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DAppsGroupsRequest { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchNamesRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub input: ::prost::alloc::string::String, + #[prost(int32, tag="3")] + pub limit: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchNamesResponse { + #[prost(string, repeated, tag="1")] + pub names: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchCollectionsRequest { + #[prost(string, tag="1")] + pub input: ::prost::alloc::string::String, + #[prost(int32, tag="2")] + pub limit: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SearchCollectionsResponse { + #[prost(message, repeated, tag="1")] + pub collections: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LeaderboardEntry { + #[prost(uint32, tag="1")] + pub rank: u32, + #[prost(string, tag="2")] + pub user_id: ::prost::alloc::string::String, + #[prost(double, tag="3")] + pub total_xp: f64, + #[prost(double, tag="4")] + pub mint_xp: f64, + #[prost(double, tag="5")] + pub buy_xp: f64, + #[prost(double, tag="6")] + pub sell_xp: f64, + #[prost(double, tag="7")] + pub boost: f64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LeaderboardRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, + #[prost(uint32, tag="2")] + pub period_hours: u32, + #[prost(uint32, tag="3")] + pub limit: u32, + #[prost(uint32, tag="4")] + pub offset: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LeaderboardResponse { + #[prost(message, optional, tag="1")] + pub entry: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Coin { + #[prost(string, tag="1")] + pub amount: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub denom: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PopularCollection { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub image_uri: ::prost::alloc::string::String, + #[prost(message, repeated, tag="4")] + pub floor_prices: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag="5")] + pub trade_volumes_by_denom: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag="15")] + pub mint_volumes_by_denom: ::prost::alloc::vec::Vec, + #[prost(double, tag="6")] + pub trade_usd_volume: f64, + #[prost(double, tag="7")] + pub trade_usd_volume_prev: f64, + #[prost(double, tag="8")] + pub mint_usd_volume: f64, + #[prost(double, tag="9")] + pub mint_usd_volume_prev: f64, + #[prost(uint64, tag="10")] + pub trades_count: u64, + #[prost(uint64, tag="16")] + pub mints_count: u64, + #[prost(uint64, tag="11")] + pub owners_count: u64, + #[prost(uint32, tag="12")] + pub rank: u32, + #[prost(int64, tag="13")] + pub max_supply: i64, + #[prost(uint64, tag="14")] + pub current_supply: u64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PopularCollectionsRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, + #[prost(uint32, tag="2")] + pub period_hours: u32, + #[prost(uint32, tag="3")] + pub limit: u32, + #[prost(uint32, tag="4")] + pub offset: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PopularCollectionsResponse { + #[prost(message, optional, tag="1")] + pub collection: ::core::option::Option, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Sort { + Unspecified = 0, + Price = 1, + Volume = 2, + MarketCap = 3, + CreatedAt = 4, + VolumeUsd = 5, +} +impl Sort { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Sort::Unspecified => "SORT_UNSPECIFIED", + Sort::Price => "SORT_PRICE", + Sort::Volume => "SORT_VOLUME", + Sort::MarketCap => "SORT_MARKET_CAP", + Sort::CreatedAt => "SORT_CREATED_AT", + Sort::VolumeUsd => "SORT_VOLUME_USD", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SORT_UNSPECIFIED" => Some(Self::Unspecified), + "SORT_PRICE" => Some(Self::Price), + "SORT_VOLUME" => Some(Self::Volume), + "SORT_MARKET_CAP" => Some(Self::MarketCap), + "SORT_CREATED_AT" => Some(Self::CreatedAt), + "SORT_VOLUME_USD" => Some(Self::VolumeUsd), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum SortDirection { + Unspecified = 0, + Ascending = 1, + Descending = 2, +} +impl SortDirection { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + SortDirection::Unspecified => "SORT_DIRECTION_UNSPECIFIED", + SortDirection::Ascending => "SORT_DIRECTION_ASCENDING", + SortDirection::Descending => "SORT_DIRECTION_DESCENDING", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SORT_DIRECTION_UNSPECIFIED" => Some(Self::Unspecified), + "SORT_DIRECTION_ASCENDING" => Some(Self::Ascending), + "SORT_DIRECTION_DESCENDING" => Some(Self::Descending), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum MintState { + Unspecified = 0, + Running = 1, + Ended = 2, +} +impl MintState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + MintState::Unspecified => "MINT_STATE_UNSPECIFIED", + MintState::Running => "MINT_STATE_RUNNING", + MintState::Ended => "MINT_STATE_ENDED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "MINT_STATE_UNSPECIFIED" => Some(Self::Unspecified), + "MINT_STATE_RUNNING" => Some(Self::Running), + "MINT_STATE_ENDED" => Some(Self::Ended), + _ => None, + } + } +} +// @@protoc_insertion_point(module) diff --git a/rust/apipb/src/multisig.v1.rs b/rust/apipb/src/multisig.v1.rs new file mode 100644 index 0000000000..04d016c502 --- /dev/null +++ b/rust/apipb/src/multisig.v1.rs @@ -0,0 +1,398 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Multisig { + #[prost(string, tag="1")] + pub created_at: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub chain_id: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub address: ::prost::alloc::string::String, + #[prost(bool, tag="5")] + pub joined: bool, + #[prost(string, tag="6")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag="7")] + pub pubkey_json: ::prost::alloc::string::String, + #[prost(string, repeated, tag="8")] + pub users_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(uint32, tag="9")] + pub threshold: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Signature { + #[prost(string, tag="1")] + pub value: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub user_address: ::prost::alloc::string::String, + #[prost(bytes="vec", tag="3")] + pub body_bytes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Transaction { + #[prost(string, tag="1")] + pub created_at: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub final_hash: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub multisig_address: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub chain_id: ::prost::alloc::string::String, + #[prost(message, repeated, tag="5")] + pub msgs: ::prost::alloc::vec::Vec<::prost_types::Any>, + #[prost(string, tag="6")] + pub fee_json: ::prost::alloc::string::String, + #[prost(uint32, tag="7")] + pub account_number: u32, + #[prost(uint32, tag="8")] + pub sequence: u32, + #[prost(string, tag="9")] + pub creator_address: ::prost::alloc::string::String, + #[prost(uint32, tag="10")] + pub threshold: u32, + #[prost(uint32, tag="11")] + pub members_count: u32, + #[prost(string, tag="12")] + pub memo: ::prost::alloc::string::String, + #[prost(message, repeated, tag="13")] + pub signatures: ::prost::alloc::vec::Vec, + #[prost(string, tag="14")] + pub multisig_pubkey_json: ::prost::alloc::string::String, + #[prost(uint32, tag="15")] + pub id: u32, +} +/// we use string here because browser storage poorly supports bytes +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Token { + /// base64 + #[prost(string, tag="1")] + pub nonce: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub expiration: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub user_address: ::prost::alloc::string::String, + /// base64 signature by server of protobuf encoding of Token with server_signature field zeroed out + #[prost(string, tag="5")] + pub server_signature: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Challenge { + #[prost(bytes="vec", tag="1")] + pub nonce: ::prost::alloc::vec::Vec, + #[prost(string, tag="2")] + pub expiration: ::prost::alloc::string::String, + /// signature by server of protobuf encoding of Challenge with server_signature field zeroed out + #[prost(bytes="vec", tag="3")] + pub server_signature: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigsRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + #[prost(uint32, tag="2")] + pub limit: u32, + #[prost(string, tag="3")] + pub start_after: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub chain_id: ::prost::alloc::string::String, + #[prost(enumeration="JoinState", tag="5")] + pub join_state: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigsResponse { + #[prost(message, repeated, tag="1")] + pub multisigs: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigInfoRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + #[prost(string, tag="2")] + pub multisig_address: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub chain_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultisigInfoResponse { + #[prost(message, optional, tag="1")] + pub multisig: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionsRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + #[prost(uint32, tag="2")] + pub limit: u32, + #[prost(string, tag="3")] + pub start_after: ::prost::alloc::string::String, + /// if unspecified, return transactions for all multisigs of this user + #[prost(string, tag="4")] + pub multisig_address: ::prost::alloc::string::String, + #[prost(string, tag="5")] + pub chain_id: ::prost::alloc::string::String, + #[prost(string, repeated, tag="6")] + pub types: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(enumeration="ExecutionState", tag="7")] + pub execution_state: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionsResponse { + #[prost(message, repeated, tag="1")] + pub transactions: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateOrJoinMultisigRequest { + #[prost(string, tag="1")] + pub chain_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub multisig_pubkey_json: ::prost::alloc::string::String, + #[prost(message, optional, tag="3")] + pub auth_token: ::core::option::Option, + #[prost(string, tag="4")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag="5")] + pub bech32_prefix: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateOrJoinMultisigResponse { + #[prost(bool, tag="1")] + pub created: bool, + #[prost(bool, tag="2")] + pub joined: bool, + #[prost(string, tag="3")] + pub multisig_address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LeaveMultisigRequest { + #[prost(string, tag="1")] + pub multisig_address: ::prost::alloc::string::String, + #[prost(message, optional, tag="2")] + pub auth_token: ::core::option::Option, + #[prost(string, tag="3")] + pub chain_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LeaveMultisigResponse { + #[prost(bool, tag="1")] + pub left: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateTransactionRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + #[prost(string, tag="3")] + pub multisig_address: ::prost::alloc::string::String, + #[prost(uint32, tag="4")] + pub account_number: u32, + #[prost(uint32, tag="5")] + pub sequence: u32, + #[prost(message, repeated, tag="6")] + pub msgs: ::prost::alloc::vec::Vec<::prost_types::Any>, + #[prost(string, tag="7")] + pub fee_json: ::prost::alloc::string::String, + #[prost(string, tag="8")] + pub chain_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateTransactionResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SignTransactionRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + #[prost(string, tag="2")] + pub signature: ::prost::alloc::string::String, + #[prost(uint32, tag="3")] + pub transaction_id: u32, + #[prost(bytes="vec", tag="4")] + pub body_bytes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SignTransactionResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CompleteTransactionRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + #[prost(uint32, tag="2")] + pub transaction_id: u32, + #[prost(string, tag="3")] + pub final_hash: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CompleteTransactionResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClearSignaturesRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + #[prost(string, tag="2")] + pub multisig_chain_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub multisig_address: ::prost::alloc::string::String, + #[prost(uint32, tag="4")] + pub sequence: u32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ClearSignaturesResponse { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetChallengeRequest { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetChallengeResponse { + #[prost(message, optional, tag="1")] + pub challenge: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TokenRequestInfo { + #[prost(string, tag="1")] + pub kind: ::prost::alloc::string::String, + #[prost(message, optional, tag="2")] + pub challenge: ::core::option::Option, + #[prost(string, tag="3")] + pub user_bech32_prefix: ::prost::alloc::string::String, + #[prost(string, tag="4")] + pub user_pubkey_json: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTokenRequest { + /// protojson encoding of TokenRequestInfo + #[prost(string, tag="1")] + pub info_json: ::prost::alloc::string::String, + /// signature by client of info_json + #[prost(string, tag="2")] + pub user_signature: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTokenResponse { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionsCountsRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, + /// if unspecified, return transactions for all multisigs of this user + #[prost(string, tag="2")] + pub multisig_address: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub chain_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionsCount { + #[prost(uint32, tag="1")] + pub total: u32, + #[prost(uint32, tag="2")] + pub pending: u32, + #[prost(uint32, tag="3")] + pub executed: u32, + #[prost(string, tag="4")] + pub r#type: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionsCountsResponse { + #[prost(message, optional, tag="1")] + pub all: ::core::option::Option, + #[prost(message, repeated, tag="2")] + pub by_type: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidateTokenRequest { + #[prost(message, optional, tag="1")] + pub auth_token: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidateTokenResponse { +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum JoinState { + Unspecified = 0, + In = 1, + Out = 2, +} +impl JoinState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + JoinState::Unspecified => "JOIN_STATE_UNSPECIFIED", + JoinState::In => "JOIN_STATE_IN", + JoinState::Out => "JOIN_STATE_OUT", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "JOIN_STATE_UNSPECIFIED" => Some(Self::Unspecified), + "JOIN_STATE_IN" => Some(Self::In), + "JOIN_STATE_OUT" => Some(Self::Out), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ExecutionState { + Unspecified = 0, + Pending = 1, + Executed = 2, +} +impl ExecutionState { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ExecutionState::Unspecified => "EXECUTION_STATE_UNSPECIFIED", + ExecutionState::Pending => "EXECUTION_STATE_PENDING", + ExecutionState::Executed => "EXECUTION_STATE_EXECUTED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "EXECUTION_STATE_UNSPECIFIED" => Some(Self::Unspecified), + "EXECUTION_STATE_PENDING" => Some(Self::Pending), + "EXECUTION_STATE_EXECUTED" => Some(Self::Executed), + _ => None, + } + } +} +// @@protoc_insertion_point(module) diff --git a/rust/apipb/src/p2e.v1.rs b/rust/apipb/src/p2e.v1.rs new file mode 100644 index 0000000000..d845c6af8a --- /dev/null +++ b/rust/apipb/src/p2e.v1.rs @@ -0,0 +1,132 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MerkleDataRequest { + #[prost(string, tag="1")] + pub user_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub token: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UserReward { + #[prost(string, tag="1")] + pub to: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub token: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub amount: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MerkleDataResponse { + #[prost(string, repeated, tag="1")] + pub proof: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(message, optional, tag="2")] + pub user_reward: ::core::option::Option, + #[prost(string, tag="3")] + pub claimable_amount: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AllSeasonsRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SeasonWithoutPrize { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub boss_name: ::prost::alloc::string::String, + #[prost(int32, tag="3")] + pub boss_hp: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AllSeasonsResponse { + #[prost(message, repeated, tag="1")] + pub seasons: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CurrentSeasonRequest { + #[prost(string, tag="1")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CurrentSeasonResponse { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub denom: ::prost::alloc::string::String, + #[prost(int32, tag="3")] + pub total_prize: i32, + #[prost(string, tag="4")] + pub boss_name: ::prost::alloc::string::String, + #[prost(int32, tag="5")] + pub boss_hp: i32, + #[prost(float, tag="6")] + pub remaining_hp: f32, + #[prost(string, tag="7")] + pub boss_image: ::prost::alloc::string::String, + #[prost(bool, tag="8")] + pub is_pre: bool, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UserRankRequest { + #[prost(string, tag="1")] + pub season_id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub user_id: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UserRankResponse { + #[prost(message, optional, tag="1")] + pub user_score: ::core::option::Option, + #[prost(int32, tag="2")] + pub total_users: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LeaderboardRequest { + #[prost(string, tag="1")] + pub season_id: ::prost::alloc::string::String, + #[prost(int32, tag="2")] + pub limit: i32, + #[prost(int32, tag="3")] + pub offset: i32, + #[prost(string, tag="4")] + pub network_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UserScore { + #[prost(int32, tag="1")] + pub rank: i32, + #[prost(int32, tag="2")] + pub snapshot_rank: i32, + #[prost(string, tag="3")] + pub user_id: ::prost::alloc::string::String, + #[prost(int64, tag="4")] + pub in_progress_score: i64, + #[prost(int64, tag="5")] + pub snapshot_score: i64, + #[prost(string, tag="6")] + pub season_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LeaderboardResponse { + #[prost(message, optional, tag="1")] + pub user_score: ::core::option::Option, +} +// @@protoc_insertion_point(module) diff --git a/rust/apipb/src/prices.v1.rs b/rust/apipb/src/prices.v1.rs new file mode 100644 index 0000000000..fd45167017 --- /dev/null +++ b/rust/apipb/src/prices.v1.rs @@ -0,0 +1,26 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PricesRequest { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub time: ::prost::alloc::string::String, + #[prost(string, repeated, tag="3")] + pub vs_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Price { + #[prost(string, tag="1")] + pub id: ::prost::alloc::string::String, + #[prost(double, tag="2")] + pub value: f64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PricesResponse { + #[prost(message, repeated, tag="1")] + pub prices: ::prost::alloc::vec::Vec, +} +// @@protoc_insertion_point(module) diff --git a/rust/cw-contracts/nft-launchpad/.cargo/config.toml b/rust/cw-contracts/nft-launchpad/.cargo/config.toml new file mode 100644 index 0000000000..cd32d4f0b1 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/.cargo/config.toml @@ -0,0 +1,6 @@ +[alias] +wasm = "build --target wasm32-unknown-unknown --release --lib" +wasm-debug = "build --target wasm32-unknown-unknown --lib" +unit-test = "test --lib" +integration-test = "test --test integration" +schema = "run --bin schema" \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/.gitignore b/rust/cw-contracts/nft-launchpad/.gitignore new file mode 100644 index 0000000000..42dafca836 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/.gitignore @@ -0,0 +1,2 @@ +/target +/artifacts \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/Cargo.lock b/rust/cw-contracts/nft-launchpad/Cargo.lock new file mode 100644 index 0000000000..38518151c4 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/Cargo.lock @@ -0,0 +1,814 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bnum" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cosmwasm-crypto" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9934c79e58d9676edfd592557dee765d2a6ef54c09d5aa2edb06156b00148966" +dependencies = [ + "digest 0.10.7", + "ecdsa", + "ed25519-zebra", + "k256", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5e72e330bd3bdab11c52b5ecbdeb6a8697a004c57964caeb5d876f0b088b3c" +dependencies = [ + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-schema" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e3a2136e2a60e8b6582f5dffca5d1a683ed77bf38537d330bc1dfccd69010" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d803bea6bd9ed61bd1ee0b4a2eb09ee20dbb539cc6e0b8795614d20952ebb1" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-std" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8666e572a3a2519010dde88c04d16e9339ae751b56b2bb35081fe3f7d6be74" +dependencies = [ + "base64", + "bech32", + "bnum", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm", + "sha2 0.10.8", + "static_assertions", + "thiserror", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cw-multi-test" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fff029689ae89127cf6d7655809a68d712f3edbdb9686c70b018ba438b26ca" +dependencies = [ + "anyhow", + "bech32", + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "derivative", + "itertools 0.12.1", + "prost", + "schemars", + "serde", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "cw-storage-plus" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek", + "hashbrown", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.8", + "signature", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "nft-launchpad" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "cw-storage-plus", + "schemars", + "thiserror", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/rust/cw-contracts/nft-launchpad/Cargo.toml b/rust/cw-contracts/nft-launchpad/Cargo.toml new file mode 100644 index 0000000000..20a870ba73 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "nft-launchpad" +version = "0.2.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +cosmwasm-schema = "1.5.3" +cosmwasm-std = { version = "1.5.3", features = ["cosmwasm_1_2"] } +cw-storage-plus = "1.2.0" +cw-utils = "1.0.3" +cw2981-royalties = { version = "0.18.0", features = ["library"] } +cw721 = "0.18.0" +cw721-base = { version = "0.18.0", features = ["library"] } +schemars = "0.8.16" +serde = { version = "1.0.197", features = ["derive"] } +sylvia = "0.9.3" +thiserror = "1.0.57" +nft-tr721 = { workspace = true, features = ["library"] } + +[dev-dependencies] +sylvia = { version = "0.9.3", features = ["mt"] } diff --git a/rust/cw-contracts/nft-launchpad/Makefile b/rust/cw-contracts/nft-launchpad/Makefile new file mode 100644 index 0000000000..1b5911d4ac --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/Makefile @@ -0,0 +1,55 @@ +ADMIN_TESTNET=testnet-adm +ADMIN_ADDR_TESTNET=$(shell teritorid keys show $(ADMIN_TESTNET) --keyring-backend test --output json | jq -r .address) +NODE_FLAG_TESTNET=--node https://rpc.testnet.teritori.com:443 +TX_FLAGS_TESTNET=--from $(ADMIN_TESTNET) --chain-id teritori-test-7 $(NODE_FLAG_TESTNET) --gas auto --gas-adjustment 1.3 -y -b sync --output json --keyring-backend test -o json +QUERY_FLAGS_TESTNET=$(NODE_FLAG_TESTNET) -o json +CODE_ID_TESTNET=61 +CONFIG_TESTNET=$(shell cat config.json | jq -r '.owner="$(ADMIN_ADDR_TESTNET)" | tojson | @sh') + +ADMIN_MAINNET=mainnet-adm +ADMIN_ADDR_MAINNET=$(shell teritorid keys show $(ADMIN_MAINNET) --output json | jq -r .address) +NODE_FLAG_MAINNET=--node https://rpc.mainnet.teritori.com:443 +# --keyring-backend os by default +TX_FLAGS_MAINNET=--from $(ADMIN_MAINNET) --chain-id teritori-1 $(NODE_FLAG_MAINNET) --gas auto --gas-adjustment 1.3 -y -b sync --output json -o json +QUERY_FLAGS_MAINNET=$(NODE_FLAG_MAINNET) -o json +CODE_ID_MAINNET= +CONFIG_MAINNET=$(shell cat config-mainnet.json | jq -r '.owner="$(ADMIN_ADDR_MAINNET)" | tojson | @sh') + +WORKSPACE_PATH := $(shell realpath $(shell dirname $(shell pwd))/../..) + +# only informative +# CONTRACT_ADDRESS_TESTNET=tori1dqy2areatyu6372d67a25t494x63n046qd83dyzrwl73yrnuky4qg8fqsh +# CONTRACT_ADDRESS_MAINNET= + +.PHONY: artifacts/nft_launchpad.wasm +artifacts/nft_launchpad.wasm: + docker run --rm -v "$(WORKSPACE_PATH):/code" \ + --platform linux/amd64 \ + --mount type=volume,source=nft_launchpad_cache,target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/rust-optimizer:0.14.0 + +.PHONY: deploy.testnet +deploy.testnet: artifacts/nft_launchpad.wasm + set -o pipefail; \ + TXHASH=$$(teritorid tx wasm store $(WORKSPACE_PATH)/artifacts/nft_launchpad.wasm $(TX_FLAGS_TESTNET) | jq -r .txhash); \ + while ! teritorid query tx $$TXHASH $(QUERY_FLAGS_TESTNET) 2>/dev/null | jq -r '.logs[0].events[] | select(.type=="store_code").attributes[] | select(.key=="code_id").value'; do sleep 1; done + +.PHONY: instantiate.testnet +instantiate.testnet: config.json + set -o pipefail; \ + TXHASH=$$(teritorid tx wasm instantiate $(CODE_ID_TESTNET) $(CONFIG_TESTNET) --label NftLaunchpad --admin $(ADMIN_ADDR_TESTNET) $(TX_FLAGS_TESTNET) | jq -r .txhash); \ + while ! teritorid query tx $$TXHASH $(QUERY_FLAGS_TESTNET) 2>/dev/null | jq -r '.logs[0].events[] | select(.type=="instantiate").attributes[] | select(.key=="_contract_address").value'; do sleep 1; done + +.PHONY: deploy.mainnet +deploy.mainnet: artifacts/nft_launchpad.wasm + set -o pipefail; \ + TXHASH=$$(teritorid tx wasm store $(WORKSPACE_PATH)/artifacts/nft_launchpad.wasm $(TX_FLAGS_MAINNET) | jq -r .txhash); \ + while ! teritorid query tx $$TXHASH $(QUERY_FLAGS_MAINNET) 2>/dev/null | jq -r '.logs[0].events[] | select(.type=="store_code").attributes[] | select(.key=="code_id").value'; do sleep 1; done + +.PHONY: instantiate.mainnet +instantiate.mainnet: config-mainnet.json + set -o pipefail; \ + TXHASH=$$(teritorid tx wasm instantiate $(CODE_ID_MAINNET) $(CONFIG_MAINNET) --label NftsBurner --admin $(ADMIN_ADDR_MAINNET) $(TX_FLAGS_MAINNET) | jq -r .txhash); \ + while ! teritorid query tx $$TXHASH $(QUERY_FLAGS_MAINNET) 2>/dev/null | jq -r '.logs[0].events[] | select(.type=="instantiate").attributes[] | select(.key=="_contract_address").value'; do sleep 1; done + diff --git a/rust/cw-contracts/nft-launchpad/config-mainnet.json b/rust/cw-contracts/nft-launchpad/config-mainnet.json new file mode 100644 index 0000000000..0e2505c3d8 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/config-mainnet.json @@ -0,0 +1,9 @@ +{ + "config": { + "name": "NFT Launchpad", + "supported_networks": ["teritori"], + "owner": "", + "deployer": "", + "nft_code_id": 0 + } +} diff --git a/rust/cw-contracts/nft-launchpad/config.json b/rust/cw-contracts/nft-launchpad/config.json new file mode 100644 index 0000000000..9d3e5e2c8a --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/config.json @@ -0,0 +1,9 @@ +{ + "config": { + "name": "NFT Launchpad", + "supported_networks": ["teritori-testnet"], + "owner": "tori1llmym9upcpwnz7qte856ghlp5437ezz2gg7z0q", + "deployer": "tori1kjvyqf4mttwrhfuq5gfj9xgxx9jdt92xnxzf770x853567ymx8cscrnw05", + "nft_code_id": 60 + } +} diff --git a/rust/cw-contracts/nft-launchpad/deploy.ts b/rust/cw-contracts/nft-launchpad/deploy.ts new file mode 100644 index 0000000000..e5f469e3d1 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/deploy.ts @@ -0,0 +1,25 @@ +import { deploy, instantiate } from "../../utils/scripts"; + +const WASM_FILE = "nft_launchpad-aarch64.wasm"; +const DEPLOYER = "tori1zsgm6hvx4a3t08vsanwdcvvnv2xca9faavzccm"; + +const main = async () => { + const codeId = await deploy(WASM_FILE); + const initMsg = { + config: { + name: "Teritori launchpad", + supported_networks: [], + nft_code_id: 1, + deployer: DEPLOYER, + }, + }; + const contractAddress = await instantiate( + codeId, + "Teritori Launchpad", + initMsg, + ); + + console.log("CodeId:", codeId, "- Contract Address:", contractAddress); +}; + +main(); diff --git a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json new file mode 100644 index 0000000000..02c8f8c73e --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -0,0 +1,839 @@ +{ + "contract_name": "nft-launchpad", + "contract_version": "0.2.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "$ref": "#/definitions/Config" + } + }, + "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" + }, + "Config": { + "type": "object", + "required": [ + "name", + "owner", + "supported_networks" + ], + "properties": { + "deployer": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + }, + "supported_networks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + } + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "update_config" + ], + "properties": { + "update_config": { + "type": "object", + "required": [ + "changes" + ], + "properties": { + "changes": { + "$ref": "#/definitions/ConfigChanges" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "submit_collection" + ], + "properties": { + "submit_collection": { + "type": "object", + "required": [ + "collection" + ], + "properties": { + "collection": { + "$ref": "#/definitions/Collection" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_merkle_root" + ], + "properties": { + "update_merkle_root": { + "type": "object", + "required": [ + "collection_id", + "merkle_root" + ], + "properties": { + "collection_id": { + "type": "string" + }, + "merkle_root": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "deploy_collection" + ], + "properties": { + "deploy_collection": { + "type": "object", + "required": [ + "collection_id" + ], + "properties": { + "collection_id": { + "type": "string" + } + } + } + }, + "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": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "Collection": { + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "expected_mint_date", + "expected_public_mint_price", + "expected_supply", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_desc", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count" + ], + "properties": { + "artwork_desc": { + "type": "string" + }, + "base_token_uri": { + "type": [ + "string", + "null" + ] + }, + "contact_email": { + "type": "string" + }, + "cover_img_uri": { + "type": "string" + }, + "dao_whitelist_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "deployed_address": { + "type": [ + "string", + "null" + ] + }, + "desc": { + "type": "string" + }, + "escrow_mint_proceeds_period": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_mint_date": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_public_mint_price": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_supply": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "investment_desc": { + "type": "string" + }, + "investment_link": { + "type": "string" + }, + "is_applied_previously": { + "type": "boolean" + }, + "is_dox": { + "type": "boolean" + }, + "is_project_derivative": { + "type": "boolean" + }, + "is_ready_for_mint": { + "type": "boolean" + }, + "metadatas_merkle_root": { + "type": [ + "string", + "null" + ] + }, + "mint_periods": { + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + } + }, + "name": { + "type": "string" + }, + "owner": { + "type": [ + "string", + "null" + ] + }, + "partners": { + "type": "string" + }, + "project_desc": { + "type": "string" + }, + "project_type": { + "type": "string" + }, + "reveal_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "symbol": { + "type": "string" + }, + "target_network": { + "type": "string" + }, + "team_desc": { + "type": "string" + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "website_link": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "ConfigChanges": { + "type": "object", + "required": [ + "name", + "supported_networks" + ], + "properties": { + "deployer": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "type": [ + "string", + "null" + ] + }, + "supported_networks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "get_collection_by_id" + ], + "properties": { + "get_collection_by_id": { + "type": "object", + "required": [ + "collection_id" + ], + "properties": { + "collection_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "get_config" + ], + "properties": { + "get_config": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "get_collection_by_id": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Collection", + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "expected_mint_date", + "expected_public_mint_price", + "expected_supply", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_desc", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count" + ], + "properties": { + "artwork_desc": { + "type": "string" + }, + "base_token_uri": { + "type": [ + "string", + "null" + ] + }, + "contact_email": { + "type": "string" + }, + "cover_img_uri": { + "type": "string" + }, + "dao_whitelist_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "deployed_address": { + "type": [ + "string", + "null" + ] + }, + "desc": { + "type": "string" + }, + "escrow_mint_proceeds_period": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_mint_date": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_public_mint_price": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_supply": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "investment_desc": { + "type": "string" + }, + "investment_link": { + "type": "string" + }, + "is_applied_previously": { + "type": "boolean" + }, + "is_dox": { + "type": "boolean" + }, + "is_project_derivative": { + "type": "boolean" + }, + "is_ready_for_mint": { + "type": "boolean" + }, + "metadatas_merkle_root": { + "type": [ + "string", + "null" + ] + }, + "mint_periods": { + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + } + }, + "name": { + "type": "string" + }, + "owner": { + "type": [ + "string", + "null" + ] + }, + "partners": { + "type": "string" + }, + "project_desc": { + "type": "string" + }, + "project_type": { + "type": "string" + }, + "reveal_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "symbol": { + "type": "string" + }, + "target_network": { + "type": "string" + }, + "team_desc": { + "type": "string" + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "website_link": { + "type": [ + "string", + "null" + ] + } + }, + "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": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "get_config": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "type": "object", + "required": [ + "name", + "owner", + "supported_networks" + ], + "properties": { + "deployer": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + }, + "supported_networks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "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/rust/cw-contracts/nft-launchpad/schema/raw/execute.json b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json new file mode 100644 index 0000000000..3562556609 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json @@ -0,0 +1,409 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "update_config" + ], + "properties": { + "update_config": { + "type": "object", + "required": [ + "changes" + ], + "properties": { + "changes": { + "$ref": "#/definitions/ConfigChanges" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "submit_collection" + ], + "properties": { + "submit_collection": { + "type": "object", + "required": [ + "collection" + ], + "properties": { + "collection": { + "$ref": "#/definitions/Collection" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_merkle_root" + ], + "properties": { + "update_merkle_root": { + "type": "object", + "required": [ + "collection_id", + "merkle_root" + ], + "properties": { + "collection_id": { + "type": "string" + }, + "merkle_root": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "deploy_collection" + ], + "properties": { + "deploy_collection": { + "type": "object", + "required": [ + "collection_id" + ], + "properties": { + "collection_id": { + "type": "string" + } + } + } + }, + "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": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "Collection": { + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "expected_mint_date", + "expected_public_mint_price", + "expected_supply", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_desc", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count" + ], + "properties": { + "artwork_desc": { + "type": "string" + }, + "base_token_uri": { + "type": [ + "string", + "null" + ] + }, + "contact_email": { + "type": "string" + }, + "cover_img_uri": { + "type": "string" + }, + "dao_whitelist_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "deployed_address": { + "type": [ + "string", + "null" + ] + }, + "desc": { + "type": "string" + }, + "escrow_mint_proceeds_period": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_mint_date": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_public_mint_price": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_supply": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "investment_desc": { + "type": "string" + }, + "investment_link": { + "type": "string" + }, + "is_applied_previously": { + "type": "boolean" + }, + "is_dox": { + "type": "boolean" + }, + "is_project_derivative": { + "type": "boolean" + }, + "is_ready_for_mint": { + "type": "boolean" + }, + "metadatas_merkle_root": { + "type": [ + "string", + "null" + ] + }, + "mint_periods": { + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + } + }, + "name": { + "type": "string" + }, + "owner": { + "type": [ + "string", + "null" + ] + }, + "partners": { + "type": "string" + }, + "project_desc": { + "type": "string" + }, + "project_type": { + "type": "string" + }, + "reveal_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "symbol": { + "type": "string" + }, + "target_network": { + "type": "string" + }, + "team_desc": { + "type": "string" + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "website_link": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "ConfigChanges": { + "type": "object", + "required": [ + "name", + "supported_networks" + ], + "properties": { + "deployer": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "type": [ + "string", + "null" + ] + }, + "supported_networks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } +} diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json new file mode 100644 index 0000000000..7fb2e842ff --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json @@ -0,0 +1,56 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "$ref": "#/definitions/Config" + } + }, + "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" + }, + "Config": { + "type": "object", + "required": [ + "name", + "owner", + "supported_networks" + ], + "properties": { + "deployer": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + }, + "supported_networks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + } +} diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/query.json b/rust/cw-contracts/nft-launchpad/schema/raw/query.json new file mode 100644 index 0000000000..00344a51e1 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/query.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "get_collection_by_id" + ], + "properties": { + "get_collection_by_id": { + "type": "object", + "required": [ + "collection_id" + ], + "properties": { + "collection_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "get_config" + ], + "properties": { + "get_config": { + "type": "object" + } + }, + "additionalProperties": false + } + ] +} diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json new file mode 100644 index 0000000000..b7f5a27208 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json @@ -0,0 +1,282 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Collection", + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "expected_mint_date", + "expected_public_mint_price", + "expected_supply", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_desc", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count" + ], + "properties": { + "artwork_desc": { + "type": "string" + }, + "base_token_uri": { + "type": [ + "string", + "null" + ] + }, + "contact_email": { + "type": "string" + }, + "cover_img_uri": { + "type": "string" + }, + "dao_whitelist_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "deployed_address": { + "type": [ + "string", + "null" + ] + }, + "desc": { + "type": "string" + }, + "escrow_mint_proceeds_period": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_mint_date": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_public_mint_price": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "expected_supply": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "investment_desc": { + "type": "string" + }, + "investment_link": { + "type": "string" + }, + "is_applied_previously": { + "type": "boolean" + }, + "is_dox": { + "type": "boolean" + }, + "is_project_derivative": { + "type": "boolean" + }, + "is_ready_for_mint": { + "type": "boolean" + }, + "metadatas_merkle_root": { + "type": [ + "string", + "null" + ] + }, + "mint_periods": { + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + } + }, + "name": { + "type": "string" + }, + "owner": { + "type": [ + "string", + "null" + ] + }, + "partners": { + "type": "string" + }, + "project_desc": { + "type": "string" + }, + "project_type": { + "type": "string" + }, + "reveal_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "symbol": { + "type": "string" + }, + "target_network": { + "type": "string" + }, + "team_desc": { + "type": "string" + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "website_link": { + "type": [ + "string", + "null" + ] + } + }, + "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": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } +} diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json new file mode 100644 index 0000000000..8efdbdb35a --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json @@ -0,0 +1,45 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "type": "object", + "required": [ + "name", + "owner", + "supported_networks" + ], + "properties": { + "deployer": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + }, + "supported_networks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "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/rust/cw-contracts/nft-launchpad/src/bin/schema.rs b/rust/cw-contracts/nft-launchpad/src/bin/schema.rs new file mode 100644 index 0000000000..b7b08a6026 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/bin/schema.rs @@ -0,0 +1,10 @@ +use cosmwasm_schema::write_api; +use nft_launchpad::contract::sv::{ExecMsg, InstantiateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecMsg, + query: QueryMsg, + } +} diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs new file mode 100644 index 0000000000..533a32ef1d --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -0,0 +1,377 @@ + + +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{ + attr, to_json_binary, Addr, Order, Reply, Response, + StdResult, SubMsg, WasmMsg, +}; +use cw_storage_plus::{Item, Map}; +use cw_utils::parse_reply_instantiate_data; +use sylvia::{ + contract, entry_points, + types::{ExecCtx, InstantiateCtx, QueryCtx, ReplyCtx}, +}; + +use crate::error::ContractError; + +use nft_tr721::{ + contract::sv::InstantiateMsg as Tr721InstantiateMsg, + contract::{MintInfo as Tr721MintInfo, MintPeriod as Tr721MintPeriod}, +}; + +const INSTANTIATE_REPLY_ID: u64 = 1u64; + +// Contract states ------------------------------------------------------ +pub struct NftLaunchpad { + pub(crate) config: Item<'static, Config>, // nft launchpad config + pub(crate) collections: Map<'static, String, Collection>, // collection id => collection info + pub(crate) instantiating_collection_id: Item<'static, String>, +} + +// Contract implement ----------------------------------------------------- +#[entry_points] +#[contract] +#[error(ContractError)] +impl NftLaunchpad { + // Init states + pub const fn new() -> Self { + Self { + config: Item::new("config"), + collections: Map::new("collections"), + instantiating_collection_id: Item::new("instantiating_collection_id"), + } + } + + #[msg(instantiate)] + pub fn instantiate(&self, ctx: InstantiateCtx, config: Config) -> StdResult { + self.config.save(ctx.deps.storage, &config)?; + + Ok(Response::new() + .add_attribute("action", "instantiate") + .add_attribute("launchpad_name", config.name)) + } + + #[msg(exec)] + // Only owner can execute it. + pub fn update_config( + &self, + ctx: ExecCtx, + changes: ConfigChanges, + ) -> Result { + let mut config = self.config.load(ctx.deps.storage)?; + let mut attributes = vec![attr("action", "update_config")]; + + // Permission check + if ctx.info.sender != config.owner { + return Err(ContractError::Unauthorized); + } + // Save new config + config.deployer = changes.deployer; + config.nft_code_id = changes.nft_code_id; + config.supported_networks = changes.supported_networks; + if let Some(owner) = changes.owner { + config.owner = ctx.deps.api.addr_validate(&owner)?; + attributes.push(attr("new_owner", owner)) + } + self.config.save(ctx.deps.storage, &config)?; + + Ok(Response::new().add_attributes(attributes)) + } + + #[msg(exec)] + pub fn submit_collection( + &self, + ctx: ExecCtx, + collection: Collection, + ) -> Result { + let storage = ctx.deps.storage; + + // Check if collection symbol is alphanumeric + if !collection + .to_owned() + .symbol + .chars() + .all(|char| char.is_numeric() || char.is_uppercase()) + { + return Err(ContractError::CollectionSymbolInvalid); + } + + // Check if collection have at least 1 mint period + if collection.mint_periods.len() == 0 { + return Err(ContractError::MintPeriodRequired); + } + + // Check if collection symbol exists + let symbol_exist = self.collections.has(storage, collection.symbol.to_owned()); + if symbol_exist { + return Err(ContractError::CollectionSymbolExists); + } + + let collection_id = collection.to_owned().symbol; + + let sender = ctx.info.sender.to_string(); + + let mut collection_with_owner = collection.clone(); + collection_with_owner.owner = Some(sender.to_owned()); + + // Add new collection + self.collections + .save(storage, collection_id.to_owned(), &collection_with_owner)?; + + Ok(Response::new() + .add_attribute("action", "submit_collection") + .add_attribute("collection_id", collection_id) + .add_attribute("owner", sender)) + } + + #[msg(exec)] + pub fn update_merkle_root( + &self, + ctx: ExecCtx, + collection_id: String, + merkle_root: String, + ) -> Result { + let storage = ctx.deps.storage; + + let mut collection = self + .collections + .load(storage, collection_id.to_owned()) + .map_err(|_| ContractError::CollectionNotFound)?; + + let sender = ctx.info.sender.to_string(); + if sender != collection.owner.clone().unwrap() { + return Err(ContractError::WrongCollectionOwner); + } + + // Do not allow to update merke root if the collection has been deployed already + if collection.deployed_address.is_some() { + return Err(ContractError::AlreadyDeployed); + } + + // Update merkle root + collection.metadatas_merkle_root = Some(merkle_root.clone()); + + // Update collection + self.collections.save(storage, collection_id, &collection)?; + + Ok(Response::new() + .add_attribute("action", "update_merkle_root") + .add_attribute("merkle_root", merkle_root)) + } + + #[msg(exec)] + pub fn deploy_collection( + &self, + ctx: ExecCtx, + collection_id: String, + ) -> Result { + let sender = ctx.info.sender.to_string(); + let config = self.config.load(ctx.deps.storage)?; + + // Only allow deployer to deploy + if config.deployer.is_none() { + return Err(ContractError::DeployerMissing); + } + if sender != config.deployer.unwrap() { + return Err(ContractError::WrongDeployer); + } + + let collection = self + .collections + .load(ctx.deps.storage, collection_id.to_owned()) + .map_err(|_| ContractError::CollectionNotFound)?; + + // Do not allow to deploy collection if merkle root is not set + if collection.metadatas_merkle_root.is_none() { + return Err(ContractError::MerkleRootMissing); + } + + let nft_code_id = config.nft_code_id; + + // Do not allow to deploy collection is nft_code_is is not set + if nft_code_id.is_none() { + return Err(ContractError::NftCodeIdMissing); + } + + // NOTE: cannot use wasm_instantiate because we need to specify admin + let instantiate_msg = WasmMsg::Instantiate { + admin: Some(sender.clone()), + code_id: nft_code_id.unwrap(), + msg: to_json_binary(&Tr721InstantiateMsg { + admin: sender.clone(), + name: collection.name.clone(), + symbol: collection.symbol.clone(), + minter: sender, + launchpad_contract: "launchpad_contract".to_string(), + mint_info: Tr721MintInfo { + metadatas_merkle_root: collection.metadatas_merkle_root.unwrap(), + tokens_count: collection.tokens_count, + royalty_address: None, + royalty_percentage: None, + }, + mint_periods: collection.mint_periods, + })?, + funds: vec![], + label: format!( + "TR721 codeId:{} collectionId:{} symbol:{}", + nft_code_id.unwrap(), + collection_id, + collection.symbol + ), + }; + + // Update instantiating collection id + self.instantiating_collection_id + .save(ctx.deps.storage, &collection_id)?; + + let submessage = SubMsg::reply_on_success(instantiate_msg, INSTANTIATE_REPLY_ID); + + Ok(Response::new() + .add_submessage(submessage) + .add_attribute("action", "collection_deployed") + .add_attribute("collection_id", collection_id)) + } + + #[msg(query)] + pub fn get_collection_by_id( + &self, + ctx: QueryCtx, + collection_id: String, + ) -> StdResult { + let collection = self.collections.load(ctx.deps.storage, collection_id)?; + Ok(collection) + } + + #[msg(query)] + pub fn get_config(&self, ctx: QueryCtx) -> StdResult { + let config = self.config.load(ctx.deps.storage)?; + Ok(config) + } + + #[msg(reply)] + pub fn handle_reply(&self, ctx: ReplyCtx, msg: Reply) -> Result { + let msg_id = msg.id; + let storage = ctx.deps.storage; + + if msg_id == INSTANTIATE_REPLY_ID { + let resp = parse_reply_instantiate_data(msg).unwrap(); + let deployed_addr = resp.contract_address; + + // Get instantiating collection id + let collection_id = self.instantiating_collection_id.load(storage)?; + + // Update collection states + let mut collection = self.collections.load(storage, collection_id.to_owned())?; + collection.deployed_address = Some(deployed_addr.clone()); + self.collections + .save(storage, collection_id.to_owned(), &collection)?; + + return Ok(Response::new() + .add_attribute("action", "collection_instantiated") + .add_attribute("collection_id", collection_id) + .add_attribute("collection_addr", deployed_addr)); + } + + Err(ContractError::UnknownReply { reply_id: msg_id }) + } +} + +// Types definitions ------------------------------------------------------ +#[cw_serde] +pub struct Config { + pub name: String, + pub nft_code_id: Option, + pub supported_networks: Vec, + pub deployer: Option, + pub owner: Addr, +} + +#[cw_serde] +pub struct ConfigChanges { + pub name: String, + pub nft_code_id: Option, + pub supported_networks: Vec, + pub deployer: Option, + pub owner: Option, +} + +#[cw_serde] +#[derive(Default)] +pub struct Collection { + // Collection info ---------------------------- + pub name: String, + pub desc: String, + pub symbol: String, // Unique + pub cover_img_uri: String, + pub target_network: String, + // pub external_link: Option, + + // Collection details ---------------------------- + pub website_link: Option, + + // pub twitter_profile: String, + // pub twitter_followers_count: u64, + + // pub contact_discord_name: String, + pub contact_email: String, + + pub is_project_derivative: bool, + + pub project_type: String, + pub project_desc: String, + + pub is_applied_previously: bool, + + // Team info -------------------------------------- + pub team_desc: String, + // pub team_link: String, + + pub partners: String, + + pub investment_desc: String, + pub investment_link: String, + + // pub whitepaper_link: String, + // pub roadmap_link: String, + + // Additional info ---------------------------- + pub artwork_desc: String, + + pub is_ready_for_mint: bool, + + pub expected_supply: u64, + pub expected_public_mint_price: u64, + pub expected_mint_date: u64, + + pub escrow_mint_proceeds_period: u64, + pub is_dox: bool, + + pub dao_whitelist_count: u32, + + pub reveal_time: Option, + + // Minting details ---------------------------- + pub tokens_count: u64, + + // Mint periods -------------------------- + pub mint_periods: Vec, + + // Royalty -------------------------- + pub royalty_address: Option, + pub royalty_percentage: Option, + + // Extend info -------------------------- + pub base_token_uri: Option, + pub metadatas_merkle_root: Option, + pub deployed_address: Option, + pub owner: Option, +} + +#[cw_serde] +pub enum CollectionState { + Pending, // When user summit the collection but not deployed yet + Deployed, // When collection has been deployed +} + + + diff --git a/rust/cw-contracts/nft-launchpad/src/error.rs b/rust/cw-contracts/nft-launchpad/src/error.rs new file mode 100644 index 0000000000..e2a19ed93b --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/error.rs @@ -0,0 +1,54 @@ +use cosmwasm_std::{Instantiate2AddressError, StdError}; +use cw_utils::ParseReplyError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("NFT Code id missing.")] + NftCodeIdMissing, + + #[error("Merkle root missing.")] + MerkleRootMissing, + + #[error("Deployer missing.")] + DeployerMissing, + + #[error("Unauthorized.")] + Unauthorized, + + #[error("Must provide atleast 1 mint period.")] + MintPeriodRequired, + + #[error("Collection symbol exists.")] + CollectionSymbolExists, + + #[error("Collection symbol invalid. Only accept upper alphanumeric chars")] + CollectionSymbolInvalid, + + #[error("Collection not found.")] + CollectionNotFound, + + #[error("Collection not deployed.")] + CollectionNotDeployed, + + #[error("Wrong collection owner.")] + WrongCollectionOwner, + + #[error("Wrong deployer.")] + WrongDeployer, + + #[error("Already deployed.")] + AlreadyDeployed, + + #[error("Unable to parse reply.")] + ParseReplyError(#[from] ParseReplyError), + + #[error("Unknown reply id {reply_id}.")] + UnknownReply { reply_id: u64 }, + + #[error("{0}")] + Instantiate2AddressError(#[from] Instantiate2AddressError), +} diff --git a/rust/cw-contracts/nft-launchpad/src/lib.rs b/rust/cw-contracts/nft-launchpad/src/lib.rs new file mode 100644 index 0000000000..dd3e2d40ce --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/lib.rs @@ -0,0 +1,6 @@ +pub mod contract; +pub mod error; +pub mod responses; + +#[cfg(test)] +pub mod multitest; diff --git a/rust/cw-contracts/nft-launchpad/src/multitest.rs b/rust/cw-contracts/nft-launchpad/src/multitest.rs new file mode 100644 index 0000000000..94f98fd287 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -0,0 +1,363 @@ +use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; +use sylvia::multitest::App; + +use crate::{ + contract::{sv::multitest_utils::CodeId as LaunchpadCodeId, Collection, Config}, + error::ContractError, +}; + +use crate::contract::ConfigChanges; +use nft_tr721::contract::{ + sv::multitest_utils::CodeId as NftTr721CodeId, MintPeriod, WhitelistInfo, +}; + +fn get_default_collection() -> Collection { + let mint_periods = vec![MintPeriod { + price: Some(Coin { + amount: Uint128::new(10), + denom: "denom".to_string(), + }), + limit_per_address: Some(2), + start_time: u64::default(), + end_time: Some(u64::default()), + max_tokens: None, + + whitelist_info: Some(WhitelistInfo { + addresses_merkle_root: "addresses_merkle_root".to_string(), + addresses_count: 3, + addresses_ipfs: "addresses_ipfs".to_string(), + }), + }]; + + Collection { + // Collection info ---------------------------- + name: "name".to_string(), + desc: "desc".to_string(), + symbol: "SYMBOL".to_string(), + cover_img_uri: "img".to_string(), + target_network: "network".to_string(), + // external_link: None, + + // Collection details ---------------------------- + website_link: None, + + // twitter_profile: "twitter_profile".to_string(), + // twitter_followers_count: 1, + + // contact_discord_name: "contact_discord_name".to_string(), + contact_email: "contact_email".to_string(), + + is_project_derivative: true, + + project_type: "project_type".to_string(), + project_desc: "project_desc".to_string(), + + is_applied_previously: false, + + // Team info -------------------------------------- + team_desc: "team_desc".to_string(), + // team_link: "team_link".to_string(), + + partners: "partners".to_string(), + + investment_desc: "investment_desc".to_string(), + investment_link: "investment_link".to_string(), + + // whitepaper_link: "whitepaper_link".to_string(), + // roadmap_link: "roadmap_link".to_string(), + + // Additional info ---------------------------- + artwork_desc: "artwork_desc".to_string(), + + is_ready_for_mint: true, + + expected_supply: 1000, + expected_public_mint_price: 100, + expected_mint_date: u64::default(), + + escrow_mint_proceeds_period: u64::default(), + is_dox: true, + + dao_whitelist_count: 10, + + // Minting details ---------------------------- + tokens_count: 1000, + reveal_time: Some(u64::default()), + + // Whitelist minting -------------------------- + mint_periods, + + // Royalty -------------------------- + royalty_address: Some(Addr::unchecked("royalty_address")), + royalty_percentage: Some(50), + + // Extend info -------------------------- + base_token_uri: None, + metadatas_merkle_root: None, + deployed_address: None, + owner: Some("owner".to_string()), + } +} + +#[test] +fn instantiate() { + let app = App::default(); + let code_id = LaunchpadCodeId::store_code(&app); + let sender = "sender"; + + // Instantiate + let config = Config { + name: "teritori launchpad".to_string(), + supported_networks: vec![], + nft_code_id: None, + deployer: None, + owner: Addr::unchecked(sender), + }; + + let contract = code_id.instantiate(config).call(sender).unwrap(); + + // Check create config + let config = contract.get_config().unwrap(); + assert_eq!(config.name, "teritori launchpad".to_string()); +} + +#[test] +fn full_flow() { + // 1. Create + let default_collection = get_default_collection(); + + let app: App = App::default(); + let sender = "sender"; + + // Deploy NFT contract for non-sylvia contract + // let contract_wrapper = ContractWrapper::new(tr721_execute, tr721_instantiate, tr721_query); + // let launchpad_contract = Box::new(contract_wrapper); + // let deployed_nft_code_id = app.app_mut().store_code(launchpad_contract); + + // Deploy NFT for sylvia contract + let nft_contract = NftTr721CodeId::store_code(&app); + let deployed_nft_code_id = nft_contract.code_id(); + + // Instantiate launchpad --------------------------------------------------------- + let contract = LaunchpadCodeId::store_code(&app) + .instantiate(Config { + name: "teritori launchpad".to_string(), + supported_networks: vec![], + nft_code_id: None, + deployer: None, + owner: Addr::unchecked(sender), + }) + .call(sender) + .unwrap(); + + // Check instantiated launchpad + let config = contract.get_config().unwrap(); + assert_eq!(config.name, "teritori launchpad".to_string()); + + // Create collection without period ----------------------------------------- + { + let err = contract + .submit_collection(Collection { + mint_periods: vec![], + ..Collection::default() + }) + .call(sender) + .unwrap_err(); + + assert_eq!(err, ContractError::MintPeriodRequired); + } + + // Create collection with invalid symbol --------------------------------------------------------- + { + let err = contract + .submit_collection(Collection { + symbol: "a_123".to_string(), + ..default_collection.clone() + }) + .call(sender) + .unwrap_err(); + + assert_eq!(err, ContractError::CollectionSymbolInvalid) + } + + // Create collection --------------------------------------------------------- + { + let submit_collection_resp = contract + .submit_collection(default_collection.clone()) + .call(sender) + .unwrap(); + + // Check event + let attrs = submit_collection_resp.custom_attrs(1); + assert_eq!( + attrs[0], + Attribute { + key: "action".to_string(), + value: "submit_collection".to_string() + } + ); + + // Check created collection + let commited_collection = contract.get_collection_by_id("SYMBOL".to_string()).unwrap(); + assert_eq!(commited_collection.name, default_collection.name); + } + + // Submit collection with same symbol + { + let err = contract + .submit_collection(default_collection.clone()) + .call(sender) + .unwrap_err(); + + assert_eq!(err, ContractError::CollectionSymbolExists); + } + + // Deploy when deployer missing --------------------------------------------------------- + { + let err = contract + .deploy_collection("SYMBOL_NOT_EXIST".to_string()) + .call(sender) + .unwrap_err(); + assert_eq!(err, ContractError::DeployerMissing) + } + + // Update config when sender is not contract owner + { + let err = contract + .update_config(ConfigChanges { + name: "test".to_string(), + nft_code_id: Some(deployed_nft_code_id), + supported_networks: vec![], + deployer: Some(sender.to_string()), + owner: Some(sender.to_string()), + }) + .call("wrong_owner") + .unwrap_err(); + assert_eq!(err, ContractError::Unauthorized) + } + + // Deploy when sender is not deployer --------------------------------------------------------- + { + contract + .update_config(ConfigChanges { + name: "test".to_string(), + supported_networks: vec![], + nft_code_id: None, + deployer: Some("deployer".to_string()), + owner: Some(sender.to_string()), + }) + .call(sender) + .unwrap(); + + let err = contract + .deploy_collection("SYMBOL_NOT_EXIST".to_string()) + .call(sender) + .unwrap_err(); + assert_eq!(err, ContractError::WrongDeployer) + } + + // Set sender as deployer and Deploy inexist collection --------------------------------------------------------- + { + contract + .update_config(ConfigChanges { + name: "test".to_string(), + supported_networks: vec![], + nft_code_id: None, + deployer: Some(sender.to_string()), + owner: Some(sender.to_string()), + }) + .call(sender) + .unwrap(); + + let err = contract + .deploy_collection("SYMBOL_NOT_EXIST".to_string()) + .call(sender) + .unwrap_err(); + assert_eq!(err, ContractError::CollectionNotFound) + } + + // Deploy collection without merkle root --------------------------------------------------------- + { + let err = contract + .deploy_collection("SYMBOL".to_string()) + .call(sender) + .unwrap_err(); + assert_eq!(err, ContractError::MerkleRootMissing) + } + + // Update merkle root from unauthorized collection owner + { + let new_merkle_root = "new merkle root"; + let err = contract + .update_merkle_root("SYMBOL".to_string(), new_merkle_root.to_string()) + .call("unauthorized") + .unwrap_err(); + + assert_eq!(err, ContractError::WrongCollectionOwner); + } + + // Update merkle root + { + let new_merkle_root = "new merkle root"; + contract + .update_merkle_root("SYMBOL".to_string(), new_merkle_root.to_string()) + .call(sender) + .unwrap(); + + let collection_after = contract.get_collection_by_id("SYMBOL".to_string()).unwrap(); + + assert_eq!( + collection_after.metadatas_merkle_root, + Some(new_merkle_root.to_string()) + ); + } + + // Deploy collection with merkle root but dont have nft code id --------------------------------------------------------- + { + let err = contract + .deploy_collection("SYMBOL".to_string()) + .call(sender) + .unwrap_err(); + assert_eq!(err, ContractError::NftCodeIdMissing) + } + + // Update config to have deployed nft_code_id + { + contract + .update_config(ConfigChanges { + name: "test".to_string(), + nft_code_id: Some(deployed_nft_code_id), + supported_networks: vec![], + deployer: Some(sender.to_string()), + owner: Some(sender.to_string()), + }) + .call(sender) + .unwrap(); + + let resp = contract.get_config().unwrap(); + assert_eq!(resp.nft_code_id, Some(deployed_nft_code_id)) + } + + // Deploy completed collection after update merkle root + nft code id --------------------------------------------------------- + { + let collection_id = "SYMBOL".to_string(); + let resp = contract + .deploy_collection(collection_id.to_owned()) + .call(sender) + .unwrap(); + let attrs = resp.custom_attrs(1); + assert_eq!( + attrs[1], + Attribute { + key: "collection_id".to_string(), + value: "SYMBOL".to_string() + } + ); + + // Check deployed contract + let collection = contract.get_collection_by_id(collection_id).unwrap(); + assert_eq!(collection.deployed_address, Some("contract1".to_string())); + } +} + + diff --git a/rust/cw-contracts/nft-launchpad/src/responses.rs b/rust/cw-contracts/nft-launchpad/src/responses.rs new file mode 100644 index 0000000000..f236887448 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/responses.rs @@ -0,0 +1,26 @@ +use cosmwasm_schema::cw_serde; + +#[cw_serde] +pub struct TokensMintedToUserResp { + pub count: u128, +} + +#[cw_serde] +pub struct MintableTokensResp { + pub count: u128, +} + +#[cw_serde] +pub struct MintPriceResp { + pub expected_public_mint_price: u128, + pub unit_price: u128, + pub whitelist_unit_price: u128, +} + +#[cw_serde] +pub struct CollectionResp { + pub name: String, + pub cover_img_uri: String, + pub desc: String, + pub symbol: String, +} diff --git a/rust/cw-contracts/nft-tr721/.cargo/config.toml b/rust/cw-contracts/nft-tr721/.cargo/config.toml new file mode 100644 index 0000000000..cd32d4f0b1 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/.cargo/config.toml @@ -0,0 +1,6 @@ +[alias] +wasm = "build --target wasm32-unknown-unknown --release --lib" +wasm-debug = "build --target wasm32-unknown-unknown --lib" +unit-test = "test --lib" +integration-test = "test --test integration" +schema = "run --bin schema" \ No newline at end of file diff --git a/rust/cw-contracts/nft-tr721/Cargo.lock b/rust/cw-contracts/nft-tr721/Cargo.lock new file mode 100644 index 0000000000..38518151c4 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/Cargo.lock @@ -0,0 +1,814 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bnum" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cosmwasm-crypto" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9934c79e58d9676edfd592557dee765d2a6ef54c09d5aa2edb06156b00148966" +dependencies = [ + "digest 0.10.7", + "ecdsa", + "ed25519-zebra", + "k256", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5e72e330bd3bdab11c52b5ecbdeb6a8697a004c57964caeb5d876f0b088b3c" +dependencies = [ + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-schema" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e3a2136e2a60e8b6582f5dffca5d1a683ed77bf38537d330bc1dfccd69010" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d803bea6bd9ed61bd1ee0b4a2eb09ee20dbb539cc6e0b8795614d20952ebb1" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-std" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8666e572a3a2519010dde88c04d16e9339ae751b56b2bb35081fe3f7d6be74" +dependencies = [ + "base64", + "bech32", + "bnum", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm", + "sha2 0.10.8", + "static_assertions", + "thiserror", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cw-multi-test" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fff029689ae89127cf6d7655809a68d712f3edbdb9686c70b018ba438b26ca" +dependencies = [ + "anyhow", + "bech32", + "cosmwasm-std", + "cw-storage-plus", + "cw-utils", + "derivative", + "itertools 0.12.1", + "prost", + "schemars", + "serde", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "cw-storage-plus" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek", + "hashbrown", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.8", + "signature", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "nft-launchpad" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "cw-storage-plus", + "schemars", + "thiserror", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/rust/cw-contracts/nft-tr721/Cargo.toml b/rust/cw-contracts/nft-tr721/Cargo.toml new file mode 100644 index 0000000000..48618cd933 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "nft-tr721" +version = "0.2.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +library = [] + +[dependencies] +cosmwasm-std = { version = "1.5.3", features = ["cosmwasm_1_2"] } +cw2981-royalties = { version = "0.18.0", features = ["library"] } +cw721 = "0.18.0" +cw721-base = { version = "0.18.0", features = ["library"] } +cw721-metadata-onchain = { version = "0.15.0", features = ["library"] } +rs_merkle = { version = "1.4.2", default-features = false } + +cw-storage-plus = { workspace = true } +cosmwasm-schema = { workspace = true } +cw-utils = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +sylvia = { workspace = true } +prost = { workspace = true } +apipb = { workspace = true } +sha3 = "0.10.8" + +[dev-dependencies] +cw-multi-test = "0.20.0" +sylvia = { version = "0.9.3", features = ["mt"] } diff --git a/rust/cw-contracts/nft-tr721/Makefile b/rust/cw-contracts/nft-tr721/Makefile new file mode 100644 index 0000000000..8e312c7723 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/Makefile @@ -0,0 +1,22 @@ +ADMIN=testnet-adm +NODE_FLAG=--node https://rpc.testnet.teritori.com:443 +TX_FLAGS=--from $(ADMIN) --chain-id teritori-test-7 $(NODE_FLAG) --gas auto --gas-adjustment 1.3 -y -b sync --output json --keyring-backend test -o json +QUERY_FLAGS=$(NODE_FLAG) -o json +WORKSPACE_PATH := $(shell realpath $(shell dirname $(shell pwd))/../..) + +# only informative +# CODE_ID=0 + +.PHONY: artifacts/nft_tr721.wasm +artifacts/nft_tr721.wasm: + docker run --rm -v "$(WORKSPACE_PATH):/code" \ + --platform linux/amd64 \ + --mount type=volume,source=nft_tr721_cache,target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/rust-optimizer:0.14.0 + +.PHONY: deploy.testnet +deploy.testnet: artifacts/nft_tr721.wasm + set -o pipefail; \ + TXHASH=$$(teritorid tx wasm store $(WORKSPACE_PATH)/artifacts/nft_tr721.wasm $(TX_FLAGS) | jq -r .txhash); \ + while ! teritorid query tx $$TXHASH $(QUERY_FLAGS) 2>/dev/null | jq -r '.logs[0].events[] | select(.type=="store_code").attributes[] | select(.key=="code_id").value'; do sleep 1; done \ No newline at end of file diff --git a/rust/cw-contracts/nft-tr721/deploy.ts b/rust/cw-contracts/nft-tr721/deploy.ts new file mode 100644 index 0000000000..71fe342523 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/deploy.ts @@ -0,0 +1,9 @@ +import { deploy } from "../../utils/scripts"; +const WASM_FILE = "nft_tr721.wasm"; + +const main = async () => { + const codeId = await deploy(WASM_FILE); + console.log("CodeId:", codeId); +}; + +main(); diff --git a/rust/cw-contracts/nft-tr721/schema/nft-tr721.json b/rust/cw-contracts/nft-tr721/schema/nft-tr721.json new file mode 100644 index 0000000000..d22bc5ba75 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/nft-tr721.json @@ -0,0 +1,3301 @@ +{ + "contract_name": "nft-tr721", + "contract_version": "0.2.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "admin", + "launchpad_contract", + "mint_info", + "mint_periods", + "minter", + "name", + "symbol" + ], + "properties": { + "admin": { + "type": "string" + }, + "launchpad_contract": { + "type": "string" + }, + "mint_info": { + "$ref": "#/definitions/MintInfo" + }, + "mint_periods": { + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + } + }, + "minter": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + } + }, + "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": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "MintInfo": { + "type": "object", + "required": [ + "metadatas_merkle_root", + "tokens_count" + ], + "properties": { + "metadatas_merkle_root": { + "type": "string" + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "transfer_nft" + ], + "properties": { + "transfer_nft": { + "type": "object", + "required": [ + "recipient", + "token_id" + ], + "properties": { + "recipient": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "send_nft" + ], + "properties": { + "send_nft": { + "type": "object", + "required": [ + "contract", + "msg", + "token_id" + ], + "properties": { + "contract": { + "type": "string" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approve" + ], + "properties": { + "approve": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approve_all" + ], + "properties": { + "approve_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "operator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "revoke" + ], + "properties": { + "revoke": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "revoke_all" + ], + "properties": { + "revoke_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "operator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "mint" + ], + "properties": { + "mint": { + "type": "object", + "required": [ + "owner", + "token_id" + ], + "properties": { + "extension": { + "anyOf": [ + { + "$ref": "#/definitions/Metadata" + }, + { + "type": "null" + } + ] + }, + "owner": { + "type": "string" + }, + "token_id": { + "type": "string" + }, + "token_uri": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_mint_info" + ], + "properties": { + "update_mint_info": { + "type": "object", + "required": [ + "mint_info" + ], + "properties": { + "mint_info": { + "$ref": "#/definitions/MintInfo" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_mint_period" + ], + "properties": { + "update_mint_period": { + "type": "object", + "required": [ + "mint_period", + "mint_period_id" + ], + "properties": { + "mint_period": { + "$ref": "#/definitions/MintPeriod" + }, + "mint_period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_mint" + ], + "properties": { + "request_mint": { + "type": "object", + "required": [ + "period_id" + ], + "properties": { + "period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "whitelist_proof": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistProof" + }, + { + "type": "null" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claim" + ], + "properties": { + "claim": { + "type": "object", + "required": [ + "merkle_proof", + "metadata", + "token_id" + ], + "properties": { + "merkle_proof": { + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/Metadata" + }, + "token_id": { + "type": "string" + } + } + } + }, + "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" + }, + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "Coin": { + "type": "object", + "required": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Trait" + } + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "royalty_payment_address": { + "description": "The payment address, may be different to or the same as the minter addr question: how do we validate this?", + "type": [ + "string", + "null" + ] + }, + "royalty_percentage": { + "description": "This is how much the minter takes as a cut when sold royalties are owed on this token if it is Some", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "MintInfo": { + "type": "object", + "required": [ + "metadatas_merkle_root", + "tokens_count" + ], + "properties": { + "metadatas_merkle_root": { + "type": "string" + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Trait": { + "type": "object", + "required": [ + "trait_type", + "value" + ], + "properties": { + "display_type": { + "type": [ + "string", + "null" + ] + }, + "trait_type": { + "type": "string" + }, + "value": { + "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" + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + }, + "WhitelistProof": { + "type": "object", + "required": [ + "address_indice", + "merkle_proof" + ], + "properties": { + "address_indice": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "merkle_proof": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "total_minted" + ], + "properties": { + "total_minted": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minted_count_by_period" + ], + "properties": { + "minted_count_by_period": { + "type": "object", + "required": [ + "period_id" + ], + "properties": { + "period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minted_count_by_user" + ], + "properties": { + "minted_count_by_user": { + "type": "object", + "required": [ + "period_id", + "user" + ], + "properties": { + "period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "user": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_minted_count_by_user" + ], + "properties": { + "total_minted_count_by_user": { + "type": "object", + "required": [ + "user" + ], + "properties": { + "user": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "mint_info" + ], + "properties": { + "mint_info": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "mint_periods" + ], + "properties": { + "mint_periods": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minter" + ], + "properties": { + "minter": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "contract_info" + ], + "properties": { + "contract_info": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "nft_info" + ], + "properties": { + "nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "owner_of" + ], + "properties": { + "owner_of": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_nft_info" + ], + "properties": { + "all_nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "operator": { + "type": "object", + "required": [ + "operator", + "owner" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "operator": { + "type": "string" + }, + "owner": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_operators" + ], + "properties": { + "all_operators": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "num_tokens" + ], + "properties": { + "num_tokens": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_tokens" + ], + "properties": { + "all_tokens": { + "type": "object", + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approvals" + ], + "properties": { + "approvals": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "ownership" + ], + "properties": { + "ownership": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "contract_version" + ], + "properties": { + "contract_version": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "merkle_root" + ], + "properties": { + "merkle_root": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "royalty_info" + ], + "properties": { + "royalty_info": { + "type": "object", + "required": [ + "sale_price", + "token_id" + ], + "properties": { + "sale_price": { + "$ref": "#/definitions/Uint128" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "check_royalties" + ], + "properties": { + "check_royalties": { + "type": "object" + } + }, + "additionalProperties": false + } + ], + "definitions": { + "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" + } + } + }, + "migrate": null, + "sudo": null, + "responses": { + "all_nft_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AllNftInfoResponse_for_Metadata", + "type": "object", + "required": [ + "access", + "info" + ], + "properties": { + "access": { + "description": "Who can transfer the token", + "allOf": [ + { + "$ref": "#/definitions/OwnerOfResponse" + } + ] + }, + "info": { + "description": "Data on the token itself,", + "allOf": [ + { + "$ref": "#/definitions/NftInfoResponse_for_Metadata" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Trait" + } + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "royalty_payment_address": { + "description": "The payment address, may be different to or the same as the minter addr question: how do we validate this?", + "type": [ + "string", + "null" + ] + }, + "royalty_percentage": { + "description": "This is how much the minter takes as a cut when sold royalties are owed on this token if it is Some", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "NftInfoResponse_for_Metadata": { + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "description": "You can add any custom metadata here when you extend cw721-base", + "allOf": [ + { + "$ref": "#/definitions/Metadata" + } + ] + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "OwnerOfResponse": { + "type": "object", + "required": [ + "approvals", + "owner" + ], + "properties": { + "approvals": { + "description": "If set this address is approved to transfer/send the token as well", + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + }, + "owner": { + "description": "Owner of the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Trait": { + "type": "object", + "required": [ + "trait_type", + "value" + ], + "properties": { + "display_type": { + "type": [ + "string", + "null" + ] + }, + "trait_type": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false + }, + "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" + } + } + }, + "all_operators": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OperatorsResponse", + "type": "object", + "required": [ + "operators" + ], + "properties": { + "operators": { + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "all_tokens": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokensResponse", + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "description": "Contains all token_ids in lexicographical ordering If there are more than `limit`, use `start_after` in future queries to achieve pagination.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "approval": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ApprovalResponse", + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "$ref": "#/definitions/Approval" + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "approvals": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ApprovalsResponse", + "type": "object", + "required": [ + "approvals" + ], + "properties": { + "approvals": { + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "check_royalties": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CheckRoyaltiesResponse", + "description": "Shows if the contract implements royalties if royalty_payments is true, marketplaces should pay them", + "type": "object", + "required": [ + "royalty_payments" + ], + "properties": { + "royalty_payments": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "contract_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ContractInfoResponse", + "type": "object", + "required": [ + "name", + "symbol" + ], + "properties": { + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + } + }, + "additionalProperties": false + }, + "contract_version": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ContractVersion", + "type": "object", + "required": [ + "contract", + "version" + ], + "properties": { + "contract": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "additionalProperties": false + }, + "extension": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Response_for_Empty", + "description": "A response of a contract entry point, such as `instantiate`, `execute` or `migrate`.\n\nThis type can be constructed directly at the end of the call. Alternatively a mutable response instance can be created early in the contract's logic and incrementally be updated.\n\n## Examples\n\nDirect:\n\n``` # use cosmwasm_std::{Binary, DepsMut, Env, MessageInfo}; # type InstantiateMsg = (); # use cosmwasm_std::{attr, Response, StdResult};\n\npub fn instantiate( deps: DepsMut, _env: Env, _info: MessageInfo, msg: InstantiateMsg, ) -> StdResult { // ...\n\nOk(Response::new().add_attribute(\"action\", \"instantiate\")) } ```\n\nMutating:\n\n``` # use cosmwasm_std::{coins, BankMsg, Binary, DepsMut, Env, MessageInfo, SubMsg}; # type InstantiateMsg = (); # type MyError = (); # use cosmwasm_std::Response;\n\npub fn instantiate( deps: DepsMut, _env: Env, info: MessageInfo, msg: InstantiateMsg, ) -> Result { let mut response = Response::new() .add_attribute(\"Let the\", \"hacking begin\") .add_message(BankMsg::Send { to_address: String::from(\"recipient\"), amount: coins(128, \"uint\"), }) .add_attribute(\"foo\", \"bar\") .set_data(b\"the result data\"); Ok(response) } ```", + "type": "object", + "required": [ + "attributes", + "events", + "messages" + ], + "properties": { + "attributes": { + "description": "The attributes that will be emitted as part of a \"wasm\" event.\n\nMore info about events (and their attributes) can be found in [*Cosmos SDK* docs].\n\n[*Cosmos SDK* docs]: https://docs.cosmos.network/main/learn/advanced/events", + "type": "array", + "items": { + "$ref": "#/definitions/Attribute" + } + }, + "data": { + "description": "The binary payload to include in the response.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, + "events": { + "description": "Extra, custom events separate from the main `wasm` one. These will have `wasm-` prepended to the type.\n\nMore info about events can be found in [*Cosmos SDK* docs].\n\n[*Cosmos SDK* docs]: https://docs.cosmos.network/main/learn/advanced/events", + "type": "array", + "items": { + "$ref": "#/definitions/Event" + } + }, + "messages": { + "description": "Optional list of messages to pass. These will be executed in order. If the ReplyOn variant matches the result (Always, Success on Ok, Error on Err), the runtime will invoke this contract's `reply` entry point after execution. Otherwise, they act like \"fire and forget\". Use `SubMsg::new` to create messages with the older \"fire and forget\" semantics.", + "type": "array", + "items": { + "$ref": "#/definitions/SubMsg_for_Empty" + } + } + }, + "definitions": { + "Attribute": { + "description": "An key value pair that is used in the context of event attributes in logs", + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "BankMsg": { + "description": "The message types of the bank module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto", + "oneOf": [ + { + "description": "Sends native tokens from the contract to the given address.\n\nThis is translated to a [MsgSend](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto#L19-L28). `from_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "send" + ], + "properties": { + "send": { + "type": "object", + "required": [ + "amount", + "to_address" + ], + "properties": { + "amount": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "to_address": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This will burn the given coins from the contract's account. There is no Cosmos SDK message that performs this, but it can be done by calling the bank keeper. Important if a contract controls significant token supply that must be retired.", + "type": "object", + "required": [ + "burn" + ], + "properties": { + "burn": { + "type": "object", + "required": [ + "amount" + ], + "properties": { + "amount": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + } + } + } + }, + "additionalProperties": false + } + ] + }, + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "Coin": { + "type": "object", + "required": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "CosmosMsg_for_Empty": { + "oneOf": [ + { + "type": "object", + "required": [ + "bank" + ], + "properties": { + "bank": { + "$ref": "#/definitions/BankMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "custom" + ], + "properties": { + "custom": { + "$ref": "#/definitions/Empty" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "staking" + ], + "properties": { + "staking": { + "$ref": "#/definitions/StakingMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "distribution" + ], + "properties": { + "distribution": { + "$ref": "#/definitions/DistributionMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "wasm" + ], + "properties": { + "wasm": { + "$ref": "#/definitions/WasmMsg" + } + }, + "additionalProperties": false + } + ] + }, + "DistributionMsg": { + "description": "The message types of the distribution module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto", + "oneOf": [ + { + "description": "This is translated to a [MsgSetWithdrawAddress](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L29-L37). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "set_withdraw_address" + ], + "properties": { + "set_withdraw_address": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "description": "The `withdraw_address`", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This is translated to a [[MsgWithdrawDelegatorReward](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L42-L50). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "withdraw_delegator_reward" + ], + "properties": { + "withdraw_delegator_reward": { + "type": "object", + "required": [ + "validator" + ], + "properties": { + "validator": { + "description": "The `validator_address`", + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ] + }, + "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" + }, + "Event": { + "description": "A full [*Cosmos SDK* event].\n\nThis version uses string attributes (similar to [*Cosmos SDK* StringEvent]), which then get magically converted to bytes for Tendermint somewhere between the Rust-Go interface, JSON deserialization and the `NewEvent` call in Cosmos SDK.\n\n[*Cosmos SDK* event]: https://docs.cosmos.network/main/learn/advanced/events [*Cosmos SDK* StringEvent]: https://github.com/cosmos/cosmos-sdk/blob/v0.42.5/proto/cosmos/base/abci/v1beta1/abci.proto#L56-L70", + "type": "object", + "required": [ + "attributes", + "type" + ], + "properties": { + "attributes": { + "description": "The attributes to be included in the event.\n\nYou can learn more about these from [*Cosmos SDK* docs].\n\n[*Cosmos SDK* docs]: https://docs.cosmos.network/main/learn/advanced/events", + "type": "array", + "items": { + "$ref": "#/definitions/Attribute" + } + }, + "type": { + "description": "The event type. This is renamed to \"ty\" because \"type\" is reserved in Rust. This sucks, we know.", + "type": "string" + } + } + }, + "ReplyOn": { + "description": "Use this to define when the contract gets a response callback. If you only need it for errors or success you can select just those in order to save gas.", + "oneOf": [ + { + "description": "Always perform a callback after SubMsg is processed", + "type": "string", + "enum": [ + "always" + ] + }, + { + "description": "Only callback if SubMsg returned an error, no callback on success case", + "type": "string", + "enum": [ + "error" + ] + }, + { + "description": "Only callback if SubMsg was successful, no callback on error case", + "type": "string", + "enum": [ + "success" + ] + }, + { + "description": "Never make a callback - this is like the original CosmosMsg semantics", + "type": "string", + "enum": [ + "never" + ] + } + ] + }, + "StakingMsg": { + "description": "The message types of the staking module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto", + "oneOf": [ + { + "description": "This is translated to a [MsgDelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "delegate" + ], + "properties": { + "delegate": { + "type": "object", + "required": [ + "amount", + "validator" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Coin" + }, + "validator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This is translated to a [MsgUndelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "undelegate" + ], + "properties": { + "undelegate": { + "type": "object", + "required": [ + "amount", + "validator" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Coin" + }, + "validator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This is translated to a [MsgBeginRedelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "redelegate" + ], + "properties": { + "redelegate": { + "type": "object", + "required": [ + "amount", + "dst_validator", + "src_validator" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Coin" + }, + "dst_validator": { + "type": "string" + }, + "src_validator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ] + }, + "SubMsg_for_Empty": { + "description": "A submessage that will guarantee a `reply` call on success or error, depending on the `reply_on` setting. If you do not need to process the result, use regular messages instead.\n\nNote: On error the submessage execution will revert any partial state changes due to this message, but not revert any state changes in the calling contract. If this is required, it must be done manually in the `reply` entry point.", + "type": "object", + "required": [ + "id", + "msg", + "reply_on" + ], + "properties": { + "gas_limit": { + "description": "Gas limit measured in [Cosmos SDK gas](https://github.com/CosmWasm/cosmwasm/blob/main/docs/GAS.md).", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "id": { + "description": "An arbitrary ID chosen by the contract. This is typically used to match `Reply`s in the `reply` entry point to the submessage.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "msg": { + "$ref": "#/definitions/CosmosMsg_for_Empty" + }, + "reply_on": { + "$ref": "#/definitions/ReplyOn" + } + } + }, + "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" + }, + "WasmMsg": { + "description": "The message types of the wasm module.\n\nSee https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto", + "oneOf": [ + { + "description": "Dispatches a call to another contract at a known address (with known ABI).\n\nThis is translated to a [MsgExecuteContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L68-L78). `sender` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "execute" + ], + "properties": { + "execute": { + "type": "object", + "required": [ + "contract_addr", + "funds", + "msg" + ], + "properties": { + "contract_addr": { + "type": "string" + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "msg": { + "description": "msg is the json-encoded ExecuteMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThe contract address is non-predictable. But it is guaranteed that when emitting the same Instantiate message multiple times, multiple instances on different addresses will be generated. See also Instantiate2.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.29.2/proto/cosmwasm/wasm/v1/tx.proto#L53-L71). `sender` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "instantiate" + ], + "properties": { + "instantiate": { + "type": "object", + "required": [ + "code_id", + "funds", + "label", + "msg" + ], + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "label": { + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", + "type": "string" + }, + "msg": { + "description": "msg is the JSON-encoded InstantiateMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Instantiates a new contracts from previously uploaded Wasm code using a predictable address derivation algorithm implemented in [`cosmwasm_std::instantiate2_address`].\n\nThis is translated to a [MsgInstantiateContract2](https://github.com/CosmWasm/wasmd/blob/v0.29.2/proto/cosmwasm/wasm/v1/tx.proto#L73-L96). `sender` is automatically filled with the current contract's address. `fix_msg` is automatically set to false.", + "type": "object", + "required": [ + "instantiate2" + ], + "properties": { + "instantiate2": { + "type": "object", + "required": [ + "code_id", + "funds", + "label", + "msg", + "salt" + ], + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "label": { + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", + "type": "string" + }, + "msg": { + "description": "msg is the JSON-encoded InstantiateMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + }, + "salt": { + "$ref": "#/definitions/Binary" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Migrates a given contracts to use new wasm code. Passes a MigrateMsg to allow us to customize behavior.\n\nOnly the contract admin (as defined in wasmd), if any, is able to make this call.\n\nThis is translated to a [MsgMigrateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L86-L96). `sender` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "migrate" + ], + "properties": { + "migrate": { + "type": "object", + "required": [ + "contract_addr", + "msg", + "new_code_id" + ], + "properties": { + "contract_addr": { + "type": "string" + }, + "msg": { + "description": "msg is the json-encoded MigrateMsg struct that will be passed to the new code", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + }, + "new_code_id": { + "description": "the code_id of the new logic to place in the given contract", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Sets a new admin (for migrate) on the given contract. Fails if this contract is not currently admin of the target contract.", + "type": "object", + "required": [ + "update_admin" + ], + "properties": { + "update_admin": { + "type": "object", + "required": [ + "admin", + "contract_addr" + ], + "properties": { + "admin": { + "type": "string" + }, + "contract_addr": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Clears the admin on the given contract, so no more migration possible. Fails if this contract is not currently admin of the target contract.", + "type": "object", + "required": [ + "clear_admin" + ], + "properties": { + "clear_admin": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ] + } + } + }, + "merkle_root": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "String", + "type": "string" + }, + "mint_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MintInfo", + "type": "object", + "required": [ + "metadatas_merkle_root", + "tokens_count" + ], + "properties": { + "metadatas_merkle_root": { + "type": "string" + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "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" + } + } + }, + "mint_periods": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_MintPeriod", + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + }, + "definitions": { + "Coin": { + "type": "object", + "required": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "minted_count_by_period": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "minted_count_by_user": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "minter": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MinterResponse", + "description": "Shows who can mint these tokens", + "type": "object", + "properties": { + "minter": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "nft_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NftInfoResponse_for_Metadata", + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "description": "You can add any custom metadata here when you extend cw721-base", + "allOf": [ + { + "$ref": "#/definitions/Metadata" + } + ] + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false, + "definitions": { + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Trait" + } + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "royalty_payment_address": { + "description": "The payment address, may be different to or the same as the minter addr question: how do we validate this?", + "type": [ + "string", + "null" + ] + }, + "royalty_percentage": { + "description": "This is how much the minter takes as a cut when sold royalties are owed on this token if it is Some", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "Trait": { + "type": "object", + "required": [ + "trait_type", + "value" + ], + "properties": { + "display_type": { + "type": [ + "string", + "null" + ] + }, + "trait_type": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "num_tokens": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NumTokensResponse", + "type": "object", + "required": [ + "count" + ], + "properties": { + "count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "operator": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OperatorResponse", + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "$ref": "#/definitions/Approval" + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "owner_of": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OwnerOfResponse", + "type": "object", + "required": [ + "approvals", + "owner" + ], + "properties": { + "approvals": { + "description": "If set this address is approved to transfer/send the token as well", + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + }, + "owner": { + "description": "Owner of the token", + "type": "string" + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "ownership": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Ownership_for_Addr", + "description": "The contract's ownership info", + "type": "object", + "properties": { + "owner": { + "description": "The contract's current owner. `None` if the ownership has been renounced.", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "pending_expiry": { + "description": "The deadline for the pending owner to accept the ownership. `None` if there isn't a pending ownership transfer, or if a transfer exists and it doesn't have a deadline.", + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "pending_owner": { + "description": "The account who has been proposed to take over the ownership. `None` if there isn't a pending ownership transfer.", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "royalty_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "RoyaltiesInfoResponse", + "type": "object", + "required": [ + "address", + "royalty_amount" + ], + "properties": { + "address": { + "type": "string" + }, + "royalty_amount": { + "$ref": "#/definitions/Uint128" + } + }, + "additionalProperties": false, + "definitions": { + "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" + } + } + }, + "tokens": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokensResponse", + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "description": "Contains all token_ids in lexicographical ordering If there are more than `limit`, use `start_after` in future queries to achieve pagination.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, + "total_minted": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint64", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "total_minted_count_by_user": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint32", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/execute.json b/rust/cw-contracts/nft-tr721/schema/raw/execute.json new file mode 100644 index 0000000000..47deb362dc --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/execute.json @@ -0,0 +1,635 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "transfer_nft" + ], + "properties": { + "transfer_nft": { + "type": "object", + "required": [ + "recipient", + "token_id" + ], + "properties": { + "recipient": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "send_nft" + ], + "properties": { + "send_nft": { + "type": "object", + "required": [ + "contract", + "msg", + "token_id" + ], + "properties": { + "contract": { + "type": "string" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approve" + ], + "properties": { + "approve": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approve_all" + ], + "properties": { + "approve_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "operator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "revoke" + ], + "properties": { + "revoke": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "revoke_all" + ], + "properties": { + "revoke_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "operator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "mint" + ], + "properties": { + "mint": { + "type": "object", + "required": [ + "owner", + "token_id" + ], + "properties": { + "extension": { + "anyOf": [ + { + "$ref": "#/definitions/Metadata" + }, + { + "type": "null" + } + ] + }, + "owner": { + "type": "string" + }, + "token_id": { + "type": "string" + }, + "token_uri": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_mint_info" + ], + "properties": { + "update_mint_info": { + "type": "object", + "required": [ + "mint_info" + ], + "properties": { + "mint_info": { + "$ref": "#/definitions/MintInfo" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_mint_period" + ], + "properties": { + "update_mint_period": { + "type": "object", + "required": [ + "mint_period", + "mint_period_id" + ], + "properties": { + "mint_period": { + "$ref": "#/definitions/MintPeriod" + }, + "mint_period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "request_mint" + ], + "properties": { + "request_mint": { + "type": "object", + "required": [ + "period_id" + ], + "properties": { + "period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "whitelist_proof": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistProof" + }, + { + "type": "null" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claim" + ], + "properties": { + "claim": { + "type": "object", + "required": [ + "merkle_proof", + "metadata", + "token_id" + ], + "properties": { + "merkle_proof": { + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/Metadata" + }, + "token_id": { + "type": "string" + } + } + } + }, + "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" + }, + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "Coin": { + "type": "object", + "required": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Trait" + } + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "royalty_payment_address": { + "description": "The payment address, may be different to or the same as the minter addr question: how do we validate this?", + "type": [ + "string", + "null" + ] + }, + "royalty_percentage": { + "description": "This is how much the minter takes as a cut when sold royalties are owed on this token if it is Some", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "MintInfo": { + "type": "object", + "required": [ + "metadatas_merkle_root", + "tokens_count" + ], + "properties": { + "metadatas_merkle_root": { + "type": "string" + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Trait": { + "type": "object", + "required": [ + "trait_type", + "value" + ], + "properties": { + "display_type": { + "type": [ + "string", + "null" + ] + }, + "trait_type": { + "type": "string" + }, + "value": { + "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" + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + }, + "WhitelistProof": { + "type": "object", + "required": [ + "address_indice", + "merkle_proof" + ], + "properties": { + "address_indice": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "merkle_proof": { + "type": "string" + } + }, + "additionalProperties": false + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/instantiate.json b/rust/cw-contracts/nft-tr721/schema/raw/instantiate.json new file mode 100644 index 0000000000..67e81d2669 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/instantiate.json @@ -0,0 +1,181 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "admin", + "launchpad_contract", + "mint_info", + "mint_periods", + "minter", + "name", + "symbol" + ], + "properties": { + "admin": { + "type": "string" + }, + "launchpad_contract": { + "type": "string" + }, + "mint_info": { + "$ref": "#/definitions/MintInfo" + }, + "mint_periods": { + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + } + }, + "minter": { + "type": "string" + }, + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + } + }, + "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": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "MintInfo": { + "type": "object", + "required": [ + "metadatas_merkle_root", + "tokens_count" + ], + "properties": { + "metadatas_merkle_root": { + "type": "string" + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/query.json b/rust/cw-contracts/nft-tr721/schema/raw/query.json new file mode 100644 index 0000000000..749a9b121c --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/query.json @@ -0,0 +1,496 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "total_minted" + ], + "properties": { + "total_minted": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minted_count_by_period" + ], + "properties": { + "minted_count_by_period": { + "type": "object", + "required": [ + "period_id" + ], + "properties": { + "period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minted_count_by_user" + ], + "properties": { + "minted_count_by_user": { + "type": "object", + "required": [ + "period_id", + "user" + ], + "properties": { + "period_id": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "user": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_minted_count_by_user" + ], + "properties": { + "total_minted_count_by_user": { + "type": "object", + "required": [ + "user" + ], + "properties": { + "user": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "mint_info" + ], + "properties": { + "mint_info": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "mint_periods" + ], + "properties": { + "mint_periods": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minter" + ], + "properties": { + "minter": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "contract_info" + ], + "properties": { + "contract_info": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "nft_info" + ], + "properties": { + "nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "owner_of" + ], + "properties": { + "owner_of": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_nft_info" + ], + "properties": { + "all_nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "operator": { + "type": "object", + "required": [ + "operator", + "owner" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "operator": { + "type": "string" + }, + "owner": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_operators" + ], + "properties": { + "all_operators": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "num_tokens" + ], + "properties": { + "num_tokens": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "all_tokens" + ], + "properties": { + "all_tokens": { + "type": "object", + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "approvals" + ], + "properties": { + "approvals": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "ownership" + ], + "properties": { + "ownership": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "contract_version" + ], + "properties": { + "contract_version": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "merkle_root" + ], + "properties": { + "merkle_root": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "royalty_info" + ], + "properties": { + "royalty_info": { + "type": "object", + "required": [ + "sale_price", + "token_id" + ], + "properties": { + "sale_price": { + "$ref": "#/definitions/Uint128" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "check_royalties" + ], + "properties": { + "check_royalties": { + "type": "object" + } + }, + "additionalProperties": false + } + ], + "definitions": { + "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/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_nft_info.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_nft_info.json new file mode 100644 index 0000000000..cb45c91e7d --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_nft_info.json @@ -0,0 +1,257 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AllNftInfoResponse_for_Metadata", + "type": "object", + "required": [ + "access", + "info" + ], + "properties": { + "access": { + "description": "Who can transfer the token", + "allOf": [ + { + "$ref": "#/definitions/OwnerOfResponse" + } + ] + }, + "info": { + "description": "Data on the token itself,", + "allOf": [ + { + "$ref": "#/definitions/NftInfoResponse_for_Metadata" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Trait" + } + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "royalty_payment_address": { + "description": "The payment address, may be different to or the same as the minter addr question: how do we validate this?", + "type": [ + "string", + "null" + ] + }, + "royalty_percentage": { + "description": "This is how much the minter takes as a cut when sold royalties are owed on this token if it is Some", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "NftInfoResponse_for_Metadata": { + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "description": "You can add any custom metadata here when you extend cw721-base", + "allOf": [ + { + "$ref": "#/definitions/Metadata" + } + ] + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "OwnerOfResponse": { + "type": "object", + "required": [ + "approvals", + "owner" + ], + "properties": { + "approvals": { + "description": "If set this address is approved to transfer/send the token as well", + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + }, + "owner": { + "description": "Owner of the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Trait": { + "type": "object", + "required": [ + "trait_type", + "value" + ], + "properties": { + "display_type": { + "type": [ + "string", + "null" + ] + }, + "trait_type": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_operators.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_operators.json new file mode 100644 index 0000000000..533a096dd9 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_operators.json @@ -0,0 +1,100 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OperatorsResponse", + "type": "object", + "required": [ + "operators" + ], + "properties": { + "operators": { + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_tokens.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_tokens.json new file mode 100644 index 0000000000..4728d37e2d --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_all_tokens.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokensResponse", + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "description": "Contains all token_ids in lexicographical ordering If there are more than `limit`, use `start_after` in future queries to achieve pagination.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_approval.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_approval.json new file mode 100644 index 0000000000..b29eab59ec --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_approval.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ApprovalResponse", + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "$ref": "#/definitions/Approval" + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_approvals.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_approvals.json new file mode 100644 index 0000000000..7cdac00158 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_approvals.json @@ -0,0 +1,100 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ApprovalsResponse", + "type": "object", + "required": [ + "approvals" + ], + "properties": { + "approvals": { + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_check_royalties.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_check_royalties.json new file mode 100644 index 0000000000..485cda44db --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_check_royalties.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CheckRoyaltiesResponse", + "description": "Shows if the contract implements royalties if royalty_payments is true, marketplaces should pay them", + "type": "object", + "required": [ + "royalty_payments" + ], + "properties": { + "royalty_payments": { + "type": "boolean" + } + }, + "additionalProperties": false +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_info.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_info.json new file mode 100644 index 0000000000..4a805a8252 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_info.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ContractInfoResponse", + "type": "object", + "required": [ + "name", + "symbol" + ], + "properties": { + "name": { + "type": "string" + }, + "symbol": { + "type": "string" + } + }, + "additionalProperties": false +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_version.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_version.json new file mode 100644 index 0000000000..95156acd86 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_contract_version.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ContractVersion", + "type": "object", + "required": [ + "contract", + "version" + ], + "properties": { + "contract": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "additionalProperties": false +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_extension.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_extension.json new file mode 100644 index 0000000000..985f063aba --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_extension.json @@ -0,0 +1,659 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Response_for_Empty", + "description": "A response of a contract entry point, such as `instantiate`, `execute` or `migrate`.\n\nThis type can be constructed directly at the end of the call. Alternatively a mutable response instance can be created early in the contract's logic and incrementally be updated.\n\n## Examples\n\nDirect:\n\n``` # use cosmwasm_std::{Binary, DepsMut, Env, MessageInfo}; # type InstantiateMsg = (); # use cosmwasm_std::{attr, Response, StdResult};\n\npub fn instantiate( deps: DepsMut, _env: Env, _info: MessageInfo, msg: InstantiateMsg, ) -> StdResult { // ...\n\nOk(Response::new().add_attribute(\"action\", \"instantiate\")) } ```\n\nMutating:\n\n``` # use cosmwasm_std::{coins, BankMsg, Binary, DepsMut, Env, MessageInfo, SubMsg}; # type InstantiateMsg = (); # type MyError = (); # use cosmwasm_std::Response;\n\npub fn instantiate( deps: DepsMut, _env: Env, info: MessageInfo, msg: InstantiateMsg, ) -> Result { let mut response = Response::new() .add_attribute(\"Let the\", \"hacking begin\") .add_message(BankMsg::Send { to_address: String::from(\"recipient\"), amount: coins(128, \"uint\"), }) .add_attribute(\"foo\", \"bar\") .set_data(b\"the result data\"); Ok(response) } ```", + "type": "object", + "required": [ + "attributes", + "events", + "messages" + ], + "properties": { + "attributes": { + "description": "The attributes that will be emitted as part of a \"wasm\" event.\n\nMore info about events (and their attributes) can be found in [*Cosmos SDK* docs].\n\n[*Cosmos SDK* docs]: https://docs.cosmos.network/main/learn/advanced/events", + "type": "array", + "items": { + "$ref": "#/definitions/Attribute" + } + }, + "data": { + "description": "The binary payload to include in the response.", + "anyOf": [ + { + "$ref": "#/definitions/Binary" + }, + { + "type": "null" + } + ] + }, + "events": { + "description": "Extra, custom events separate from the main `wasm` one. These will have `wasm-` prepended to the type.\n\nMore info about events can be found in [*Cosmos SDK* docs].\n\n[*Cosmos SDK* docs]: https://docs.cosmos.network/main/learn/advanced/events", + "type": "array", + "items": { + "$ref": "#/definitions/Event" + } + }, + "messages": { + "description": "Optional list of messages to pass. These will be executed in order. If the ReplyOn variant matches the result (Always, Success on Ok, Error on Err), the runtime will invoke this contract's `reply` entry point after execution. Otherwise, they act like \"fire and forget\". Use `SubMsg::new` to create messages with the older \"fire and forget\" semantics.", + "type": "array", + "items": { + "$ref": "#/definitions/SubMsg_for_Empty" + } + } + }, + "definitions": { + "Attribute": { + "description": "An key value pair that is used in the context of event attributes in logs", + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "BankMsg": { + "description": "The message types of the bank module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto", + "oneOf": [ + { + "description": "Sends native tokens from the contract to the given address.\n\nThis is translated to a [MsgSend](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/bank/v1beta1/tx.proto#L19-L28). `from_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "send" + ], + "properties": { + "send": { + "type": "object", + "required": [ + "amount", + "to_address" + ], + "properties": { + "amount": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "to_address": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This will burn the given coins from the contract's account. There is no Cosmos SDK message that performs this, but it can be done by calling the bank keeper. Important if a contract controls significant token supply that must be retired.", + "type": "object", + "required": [ + "burn" + ], + "properties": { + "burn": { + "type": "object", + "required": [ + "amount" + ], + "properties": { + "amount": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + } + } + } + }, + "additionalProperties": false + } + ] + }, + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "Coin": { + "type": "object", + "required": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "CosmosMsg_for_Empty": { + "oneOf": [ + { + "type": "object", + "required": [ + "bank" + ], + "properties": { + "bank": { + "$ref": "#/definitions/BankMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "custom" + ], + "properties": { + "custom": { + "$ref": "#/definitions/Empty" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "staking" + ], + "properties": { + "staking": { + "$ref": "#/definitions/StakingMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "distribution" + ], + "properties": { + "distribution": { + "$ref": "#/definitions/DistributionMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "wasm" + ], + "properties": { + "wasm": { + "$ref": "#/definitions/WasmMsg" + } + }, + "additionalProperties": false + } + ] + }, + "DistributionMsg": { + "description": "The message types of the distribution module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto", + "oneOf": [ + { + "description": "This is translated to a [MsgSetWithdrawAddress](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L29-L37). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "set_withdraw_address" + ], + "properties": { + "set_withdraw_address": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "description": "The `withdraw_address`", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This is translated to a [[MsgWithdrawDelegatorReward](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L42-L50). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "withdraw_delegator_reward" + ], + "properties": { + "withdraw_delegator_reward": { + "type": "object", + "required": [ + "validator" + ], + "properties": { + "validator": { + "description": "The `validator_address`", + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ] + }, + "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" + }, + "Event": { + "description": "A full [*Cosmos SDK* event].\n\nThis version uses string attributes (similar to [*Cosmos SDK* StringEvent]), which then get magically converted to bytes for Tendermint somewhere between the Rust-Go interface, JSON deserialization and the `NewEvent` call in Cosmos SDK.\n\n[*Cosmos SDK* event]: https://docs.cosmos.network/main/learn/advanced/events [*Cosmos SDK* StringEvent]: https://github.com/cosmos/cosmos-sdk/blob/v0.42.5/proto/cosmos/base/abci/v1beta1/abci.proto#L56-L70", + "type": "object", + "required": [ + "attributes", + "type" + ], + "properties": { + "attributes": { + "description": "The attributes to be included in the event.\n\nYou can learn more about these from [*Cosmos SDK* docs].\n\n[*Cosmos SDK* docs]: https://docs.cosmos.network/main/learn/advanced/events", + "type": "array", + "items": { + "$ref": "#/definitions/Attribute" + } + }, + "type": { + "description": "The event type. This is renamed to \"ty\" because \"type\" is reserved in Rust. This sucks, we know.", + "type": "string" + } + } + }, + "ReplyOn": { + "description": "Use this to define when the contract gets a response callback. If you only need it for errors or success you can select just those in order to save gas.", + "oneOf": [ + { + "description": "Always perform a callback after SubMsg is processed", + "type": "string", + "enum": [ + "always" + ] + }, + { + "description": "Only callback if SubMsg returned an error, no callback on success case", + "type": "string", + "enum": [ + "error" + ] + }, + { + "description": "Only callback if SubMsg was successful, no callback on error case", + "type": "string", + "enum": [ + "success" + ] + }, + { + "description": "Never make a callback - this is like the original CosmosMsg semantics", + "type": "string", + "enum": [ + "never" + ] + } + ] + }, + "StakingMsg": { + "description": "The message types of the staking module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto", + "oneOf": [ + { + "description": "This is translated to a [MsgDelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "delegate" + ], + "properties": { + "delegate": { + "type": "object", + "required": [ + "amount", + "validator" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Coin" + }, + "validator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This is translated to a [MsgUndelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "undelegate" + ], + "properties": { + "undelegate": { + "type": "object", + "required": [ + "amount", + "validator" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Coin" + }, + "validator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "This is translated to a [MsgBeginRedelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105). `delegator_address` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "redelegate" + ], + "properties": { + "redelegate": { + "type": "object", + "required": [ + "amount", + "dst_validator", + "src_validator" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Coin" + }, + "dst_validator": { + "type": "string" + }, + "src_validator": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ] + }, + "SubMsg_for_Empty": { + "description": "A submessage that will guarantee a `reply` call on success or error, depending on the `reply_on` setting. If you do not need to process the result, use regular messages instead.\n\nNote: On error the submessage execution will revert any partial state changes due to this message, but not revert any state changes in the calling contract. If this is required, it must be done manually in the `reply` entry point.", + "type": "object", + "required": [ + "id", + "msg", + "reply_on" + ], + "properties": { + "gas_limit": { + "description": "Gas limit measured in [Cosmos SDK gas](https://github.com/CosmWasm/cosmwasm/blob/main/docs/GAS.md).", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "id": { + "description": "An arbitrary ID chosen by the contract. This is typically used to match `Reply`s in the `reply` entry point to the submessage.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "msg": { + "$ref": "#/definitions/CosmosMsg_for_Empty" + }, + "reply_on": { + "$ref": "#/definitions/ReplyOn" + } + } + }, + "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" + }, + "WasmMsg": { + "description": "The message types of the wasm module.\n\nSee https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto", + "oneOf": [ + { + "description": "Dispatches a call to another contract at a known address (with known ABI).\n\nThis is translated to a [MsgExecuteContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L68-L78). `sender` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "execute" + ], + "properties": { + "execute": { + "type": "object", + "required": [ + "contract_addr", + "funds", + "msg" + ], + "properties": { + "contract_addr": { + "type": "string" + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "msg": { + "description": "msg is the json-encoded ExecuteMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Instantiates a new contracts from previously uploaded Wasm code.\n\nThe contract address is non-predictable. But it is guaranteed that when emitting the same Instantiate message multiple times, multiple instances on different addresses will be generated. See also Instantiate2.\n\nThis is translated to a [MsgInstantiateContract](https://github.com/CosmWasm/wasmd/blob/v0.29.2/proto/cosmwasm/wasm/v1/tx.proto#L53-L71). `sender` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "instantiate" + ], + "properties": { + "instantiate": { + "type": "object", + "required": [ + "code_id", + "funds", + "label", + "msg" + ], + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "label": { + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", + "type": "string" + }, + "msg": { + "description": "msg is the JSON-encoded InstantiateMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Instantiates a new contracts from previously uploaded Wasm code using a predictable address derivation algorithm implemented in [`cosmwasm_std::instantiate2_address`].\n\nThis is translated to a [MsgInstantiateContract2](https://github.com/CosmWasm/wasmd/blob/v0.29.2/proto/cosmwasm/wasm/v1/tx.proto#L73-L96). `sender` is automatically filled with the current contract's address. `fix_msg` is automatically set to false.", + "type": "object", + "required": [ + "instantiate2" + ], + "properties": { + "instantiate2": { + "type": "object", + "required": [ + "code_id", + "funds", + "label", + "msg", + "salt" + ], + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "funds": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "label": { + "description": "A human-readable label for the contract.\n\nValid values should: - not be empty - not be bigger than 128 bytes (or some chain-specific limit) - not start / end with whitespace", + "type": "string" + }, + "msg": { + "description": "msg is the JSON-encoded InstantiateMsg struct (as raw Binary)", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + }, + "salt": { + "$ref": "#/definitions/Binary" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Migrates a given contracts to use new wasm code. Passes a MigrateMsg to allow us to customize behavior.\n\nOnly the contract admin (as defined in wasmd), if any, is able to make this call.\n\nThis is translated to a [MsgMigrateContract](https://github.com/CosmWasm/wasmd/blob/v0.14.0/x/wasm/internal/types/tx.proto#L86-L96). `sender` is automatically filled with the current contract's address.", + "type": "object", + "required": [ + "migrate" + ], + "properties": { + "migrate": { + "type": "object", + "required": [ + "contract_addr", + "msg", + "new_code_id" + ], + "properties": { + "contract_addr": { + "type": "string" + }, + "msg": { + "description": "msg is the json-encoded MigrateMsg struct that will be passed to the new code", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + }, + "new_code_id": { + "description": "the code_id of the new logic to place in the given contract", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Sets a new admin (for migrate) on the given contract. Fails if this contract is not currently admin of the target contract.", + "type": "object", + "required": [ + "update_admin" + ], + "properties": { + "update_admin": { + "type": "object", + "required": [ + "admin", + "contract_addr" + ], + "properties": { + "admin": { + "type": "string" + }, + "contract_addr": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Clears the admin on the given contract, so no more migration possible. Fails if this contract is not currently admin of the target contract.", + "type": "object", + "required": [ + "clear_admin" + ], + "properties": { + "clear_admin": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ] + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_merkle_root.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_merkle_root.json new file mode 100644 index 0000000000..f689acebfd --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_merkle_root.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "String", + "type": "string" +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_info.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_info.json new file mode 100644 index 0000000000..c0841ea591 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_info.json @@ -0,0 +1,44 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MintInfo", + "type": "object", + "required": [ + "metadatas_merkle_root", + "tokens_count" + ], + "properties": { + "metadatas_merkle_root": { + "type": "string" + }, + "royalty_address": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "royalty_percentage": { + "type": [ + "integer", + "null" + ], + "format": "uint8", + "minimum": 0.0 + }, + "tokens_count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "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/rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_periods.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_periods.json new file mode 100644 index 0000000000..f4c49a3dd2 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_mint_periods.json @@ -0,0 +1,109 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Array_of_MintPeriod", + "type": "array", + "items": { + "$ref": "#/definitions/MintPeriod" + }, + "definitions": { + "Coin": { + "type": "object", + "required": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "MintPeriod": { + "type": "object", + "required": [ + "start_time" + ], + "properties": { + "end_time": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "limit_per_address": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "max_tokens": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "price": { + "anyOf": [ + { + "$ref": "#/definitions/Coin" + }, + { + "type": "null" + } + ] + }, + "start_time": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "whitelist_info": { + "anyOf": [ + { + "$ref": "#/definitions/WhitelistInfo" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "WhitelistInfo": { + "type": "object", + "required": [ + "addresses_count", + "addresses_ipfs", + "addresses_merkle_root" + ], + "properties": { + "addresses_count": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "addresses_ipfs": { + "type": "string" + }, + "addresses_merkle_root": { + "type": "string" + } + }, + "additionalProperties": false + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_period.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_period.json new file mode 100644 index 0000000000..de85c3e56e --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_period.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/rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_user.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_user.json new file mode 100644 index 0000000000..de85c3e56e --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_minted_count_by_user.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/rust/cw-contracts/nft-tr721/schema/raw/response_to_minter.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_minter.json new file mode 100644 index 0000000000..e79df37e84 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_minter.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MinterResponse", + "description": "Shows who can mint these tokens", + "type": "object", + "properties": { + "minter": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_nft_info.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_nft_info.json new file mode 100644 index 0000000000..58a4c95b1c --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_nft_info.json @@ -0,0 +1,129 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NftInfoResponse_for_Metadata", + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "description": "You can add any custom metadata here when you extend cw721-base", + "allOf": [ + { + "$ref": "#/definitions/Metadata" + } + ] + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false, + "definitions": { + "Metadata": { + "type": "object", + "properties": { + "animation_url": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Trait" + } + }, + "background_color": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "external_url": { + "type": [ + "string", + "null" + ] + }, + "image": { + "type": [ + "string", + "null" + ] + }, + "image_data": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "royalty_payment_address": { + "description": "The payment address, may be different to or the same as the minter addr question: how do we validate this?", + "type": [ + "string", + "null" + ] + }, + "royalty_percentage": { + "description": "This is how much the minter takes as a cut when sold royalties are owed on this token if it is Some", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "youtube_url": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, + "Trait": { + "type": "object", + "required": [ + "trait_type", + "value" + ], + "properties": { + "display_type": { + "type": [ + "string", + "null" + ] + }, + "trait_type": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_num_tokens.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_num_tokens.json new file mode 100644 index 0000000000..aff5850c85 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_num_tokens.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NumTokensResponse", + "type": "object", + "required": [ + "count" + ], + "properties": { + "count": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_operator.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_operator.json new file mode 100644 index 0000000000..9e2dbd3d25 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_operator.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OperatorResponse", + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "$ref": "#/definitions/Approval" + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_owner_of.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_owner_of.json new file mode 100644 index 0000000000..abb9006d83 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_owner_of.json @@ -0,0 +1,106 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "OwnerOfResponse", + "type": "object", + "required": [ + "approvals", + "owner" + ], + "properties": { + "approvals": { + "description": "If set this address is approved to transfer/send the token as well", + "type": "array", + "items": { + "$ref": "#/definitions/Approval" + } + }, + "owner": { + "description": "Owner of the token", + "type": "string" + } + }, + "additionalProperties": false, + "definitions": { + "Approval": { + "type": "object", + "required": [ + "expires", + "spender" + ], + "properties": { + "expires": { + "description": "When the Approval expires (maybe Expiration::never)", + "allOf": [ + { + "$ref": "#/definitions/Expiration" + } + ] + }, + "spender": { + "description": "Account that can transfer/send the token", + "type": "string" + } + }, + "additionalProperties": false + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_ownership.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_ownership.json new file mode 100644 index 0000000000..f0b5195d9f --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_ownership.json @@ -0,0 +1,107 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Ownership_for_Addr", + "description": "The contract's ownership info", + "type": "object", + "properties": { + "owner": { + "description": "The contract's current owner. `None` if the ownership has been renounced.", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + }, + "pending_expiry": { + "description": "The deadline for the pending owner to accept the ownership. `None` if there isn't a pending ownership transfer, or if a transfer exists and it doesn't have a deadline.", + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "pending_owner": { + "description": "The account who has been proposed to take over the ownership. `None` if there isn't a pending ownership transfer.", + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } + ] + } + }, + "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" + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_royalty_info.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_royalty_info.json new file mode 100644 index 0000000000..49a85ab716 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_royalty_info.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "RoyaltiesInfoResponse", + "type": "object", + "required": [ + "address", + "royalty_amount" + ], + "properties": { + "address": { + "type": "string" + }, + "royalty_amount": { + "$ref": "#/definitions/Uint128" + } + }, + "additionalProperties": false, + "definitions": { + "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/rust/cw-contracts/nft-tr721/schema/raw/response_to_tokens.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_tokens.json new file mode 100644 index 0000000000..4728d37e2d --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_tokens.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TokensResponse", + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "description": "Contains all token_ids in lexicographical ordering If there are more than `limit`, use `start_after` in future queries to achieve pagination.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted.json new file mode 100644 index 0000000000..7b729a7b96 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint64", + "type": "integer", + "format": "uint64", + "minimum": 0.0 +} diff --git a/rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted_count_by_user.json b/rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted_count_by_user.json new file mode 100644 index 0000000000..de85c3e56e --- /dev/null +++ b/rust/cw-contracts/nft-tr721/schema/raw/response_to_total_minted_count_by_user.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/rust/cw-contracts/nft-tr721/src/bin/schema.rs b/rust/cw-contracts/nft-tr721/src/bin/schema.rs new file mode 100644 index 0000000000..db7495f126 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/bin/schema.rs @@ -0,0 +1,10 @@ +use cosmwasm_schema::write_api; +use nft_tr721::contract::sv::{ExecMsg, InstantiateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecMsg, + query: QueryMsg, + } +} diff --git a/rust/cw-contracts/nft-tr721/src/contract.rs b/rust/cw-contracts/nft-tr721/src/contract.rs new file mode 100644 index 0000000000..f804afd477 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/contract.rs @@ -0,0 +1,817 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{ + from_json, Addr, Binary, Coin, HexBinary, Order, Response, StdResult, Storage, Uint128, +}; +use cw2981_royalties::{ + check_royalties, + msg::{CheckRoyaltiesResponse, Cw2981QueryMsg, RoyaltiesInfoResponse}, + query_royalties_info, Cw2981Contract as Tr721Contract, ExecuteMsg as Tr721ExecuteMsg, + Extension, Metadata as Tr721Metadata, +}; +use cw721::{ + AllNftInfoResponse, ApprovalResponse, ApprovalsResponse, ContractInfoResponse, Expiration, + NftInfoResponse, NumTokensResponse, OperatorResponse, OperatorsResponse, OwnerOfResponse, + TokensResponse, +}; +use cw_storage_plus::{IndexedMap, Item, Map, MultiIndex}; +use rs_merkle::{Hasher, MerkleProof}; +use serde::de::DeserializeOwned; +use sylvia::{ + contract, + types::{ExecCtx, InstantiateCtx, QueryCtx}, +}; + +// This is used in #[cfg_attr(not(feature = "library"), entry_points)] even the IDE detect this is not used +use sylvia::entry_points; + +use crate::{error::ContractError, hasher::TrKeccak256, utils::proto_encode}; + +use cw721_base::{ + msg::InstantiateMsg as BaseInstantiateMsg, + state::{token_owner_idx, TokenIndexes, TokenInfo}, + MinterResponse, Ownership, +}; + +pub type NftExtension = Tr721Metadata; +pub type Tr721QueryMsg = cw721_base::QueryMsg; + +// Version info for migration +const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +// Contract states ------------------------------------------------------ +pub struct Tr721 { + pub(crate) contract_version: Item<'static, ContractVersion>, + pub(crate) admin: Item<'static, String>, + pub(crate) tokens: + IndexedMap<'static, &'static str, TokenInfo, TokenIndexes<'static, Tr721Metadata>>, + pub(crate) requested_mints: Map<'static, String, Addr>, // token id => User address + pub(crate) launchpad_contract: Item<'static, String>, + + pub(crate) mint_info: Item<'static, MintInfo>, + pub(crate) mint_periods: Map<'static, u32, MintPeriod>, + + pub(crate) user_minted_count: Map<'static, (u32, String), u32>, // Map (period, user) => count + pub(crate) user_total_minted_count: Map<'static, String, u32>, // Map user => count + pub(crate) period_minted_count: Map<'static, u32, u32>, // Map period => count +} + +// Contract implement ----------------------------------------------------- +#[cfg_attr(not(feature = "library"), entry_points)] +#[contract] +#[error(ContractError)] +impl Tr721 { + // Init states + pub const fn new() -> Self { + // The storage keys must not be changed, they link with Cw721 states + let indexes = TokenIndexes { + owner: MultiIndex::new(token_owner_idx, "tokens", "tokens__owner"), + }; + + Self { + // The storage keys must not be changed, they link with Cw721 states + contract_version: Item::new("contract_info"), + tokens: IndexedMap::new("tokens", indexes), + + launchpad_contract: Item::new("launchpad_contract"), + + // Custom states + admin: Item::new("admin"), + requested_mints: Map::new("tr721_requested_mints"), + + mint_info: Item::new("mint_info"), + mint_periods: Map::new("mint_periods"), + + user_total_minted_count: Map::new("user_total_minted_count"), + user_minted_count: Map::new("user_minted_count"), + period_minted_count: Map::new("period_minted_count"), + } + } + + fn assert_admin(&self, store: &dyn Storage, user: String) -> Result<(), ContractError> { + let admin = self.admin.load(store)?; + if user != admin { + return Err(ContractError::Unauthorized); + } + + Ok(()) + } + + pub fn assert_funds( + &self, + funds: &Vec, + expected_denom: String, + expected_amount: Uint128, + ) -> Result<(), ContractError> { + if funds.len() != 1 { + return Err(ContractError::InvalidFund); + } else if funds[0].denom != expected_denom { + return Err(ContractError::InvalidDenom); + } else if funds[0].amount != expected_amount { + return Err(ContractError::InvalidAmount); + } + + Ok(()) + } + + fn proxy_query(&self, ctx: QueryCtx, msg: Tr721QueryMsg) -> StdResult { + let bin = Tr721Contract::default().query(ctx.deps, ctx.env, msg)?; + let resp = from_json::(bin).unwrap(); + Ok(resp) + } + + fn proxy_exec(&self, ctx: ExecCtx, msg: Tr721ExecuteMsg) -> Result { + let resp = Tr721Contract::default().execute(ctx.deps, ctx.env, ctx.info, msg)?; + Ok(resp) + } + + #[msg(instantiate)] + pub fn instantiate( + &self, + ctx: InstantiateCtx, + admin: String, + name: String, + minter: String, + symbol: String, + launchpad_contract: String, + mint_info: MintInfo, + mint_periods: Vec, + ) -> StdResult { + // Set contract version + self.contract_version.save( + ctx.deps.storage, + &ContractVersion { + contract: format!("teritori:{CONTRACT_NAME}"), + version: CONTRACT_VERSION.to_string(), + }, + )?; + + self.admin.save(ctx.deps.storage, &admin)?; + + self.launchpad_contract + .save(ctx.deps.storage, &launchpad_contract)?; + + self.mint_info.save(ctx.deps.storage, &mint_info)?; + + for (idx, mint_periods) in mint_periods.iter().enumerate() { + self.mint_periods + .save(ctx.deps.storage, idx.try_into().unwrap(), mint_periods)?; + } + + let base_msg = BaseInstantiateMsg { + name, + minter, + symbol, + }; + + Ok(Tr721Contract::default().instantiate(ctx.deps, ctx.env, ctx.info, base_msg)?) + } + + #[msg(exec)] + pub fn transfer_nft( + &self, + ctx: ExecCtx, + recipient: String, + token_id: String, + ) -> Result { + let msg = Tr721ExecuteMsg::TransferNft { + recipient, + token_id, + }; + self.proxy_exec(ctx, msg) + } + + #[msg(exec)] + pub fn send_nft( + &self, + ctx: ExecCtx, + contract: String, + token_id: String, + msg: Binary, + ) -> Result { + let msg = Tr721ExecuteMsg::SendNft { + contract, + token_id, + msg, + }; + self.proxy_exec(ctx, msg) + } + + #[msg(exec)] + pub fn approve( + &self, + ctx: ExecCtx, + spender: String, + token_id: String, + expires: Option, + ) -> Result { + let msg = Tr721ExecuteMsg::Approve { + spender, + token_id, + expires, + }; + self.proxy_exec(ctx, msg) + } + + #[msg(exec)] + pub fn approve_all( + &self, + ctx: ExecCtx, + operator: String, + expires: Option, + ) -> Result { + let msg = Tr721ExecuteMsg::ApproveAll { operator, expires }; + self.proxy_exec(ctx, msg) + } + + #[msg(exec)] + pub fn revoke( + &self, + ctx: ExecCtx, + spender: String, + token_id: String, + ) -> Result { + let msg = Tr721ExecuteMsg::Revoke { spender, token_id }; + self.proxy_exec(ctx, msg) + } + + #[msg(exec)] + pub fn revoke_all(&self, ctx: ExecCtx, operator: String) -> Result { + let msg = Tr721ExecuteMsg::RevokeAll { operator }; + self.proxy_exec(ctx, msg) + } + + // ATTENTION !!!: Should not call mint for now, we have to pass by: request_mint => claim + // Deprecated: should remove this, leave it here for now just for testing + #[msg(exec)] + pub fn mint( + &self, + ctx: ExecCtx, + token_id: String, + owner: String, + token_uri: Option, + extension: Extension, + ) -> Result { + // validate royalty_percentage to be between 0 and 100 + // no need to check < 0 because royalty_percentage is u64 + if extension.to_owned().is_some() { + let metadata = extension.to_owned().unwrap(); + if metadata.royalty_percentage.is_some() { + if metadata.royalty_percentage.unwrap() > 100 { + return Err(ContractError::InvalidRoyaltyPercentage); + } + } + } + + let msg = Tr721ExecuteMsg::Mint { + token_id, + owner, + token_uri, + extension, + }; + self.proxy_exec(ctx, msg) + } + + // NOTE: Normally we should not update info, this endpoint exists mostly for testing or used in very urgent/critical case + #[msg(exec)] + pub fn update_mint_info( + &self, + ctx: ExecCtx, + mint_info: MintInfo, + ) -> Result { + self.assert_admin(ctx.deps.storage, ctx.info.sender.to_string())?; + + self.mint_info.save(ctx.deps.storage, &mint_info)?; + Ok(Response::new().add_attribute("action", "update_mint_info")) + } + + // NOTE: Normally we should not update mint period, this endpoint exists mostly for testing or used in very urgent/critical case + #[msg(exec)] + pub fn update_mint_period( + &self, + ctx: ExecCtx, + mint_period_id: u32, + mint_period: MintPeriod, + ) -> Result { + self.assert_admin(ctx.deps.storage, ctx.info.sender.to_string())?; + + self.mint_periods + .save(ctx.deps.storage, mint_period_id, &mint_period)?; + + Ok(Response::new().add_attribute("action", "update_mint_period")) + } + + #[msg(exec)] + pub fn request_mint( + &self, + ctx: ExecCtx, + period_id: u32, + whitelist_proof: Option, + ) -> Result { + // Check conditions: + let mint_info = self.mint_info.load(ctx.deps.storage)?; + let now = ctx.env.block.time.seconds(); + let sender = ctx.info.sender.to_string(); + + // Check if we reach to total tokens + let total_minted = Tr721Contract::default() + .token_count(ctx.deps.storage) + .unwrap(); + if total_minted >= mint_info.tokens_count { + return Err(ContractError::MintExceedMaxTokens); + } + + let period: MintPeriod = self + .mint_periods + .load(ctx.deps.storage, period_id) + .map_err(|_| ContractError::InvalidPeriod)?; + + // If not started yet then throw error + if now < period.start_time { + return Err(ContractError::MintNotStarted); + } + + // If end time is given and now has passed the end time then throw error + if period.end_time.is_some() && now > period.end_time.unwrap() { + return Err(ContractError::MintEnded); + } + + // If merkle is given then check whitelisted addresses + if period.whitelist_info.is_some() { + if whitelist_proof.is_none() { + return Err(ContractError::MintWhitelistOnly); + } + + let whitelist_info = period.whitelist_info.to_owned().unwrap(); + + let wp = whitelist_proof.to_owned().unwrap(); + + // Verify if sender is in whitelist addresses + let proof_hex = HexBinary::from_hex(&wp.merkle_proof).unwrap().to_vec(); + let proof_from_hex = + MerkleProof::::try_from(proof_hex.to_owned()).unwrap(); + + let root_hex: String = whitelist_info.to_owned().addresses_merkle_root; + let root_from_hex: [u8; 32] = HexBinary::from_hex(root_hex.as_str()) + .unwrap() + .to_vec() + .try_into() + .unwrap(); + + let leaf_indices = vec![wp.address_indice.try_into().unwrap()]; + let leaf_hashes = vec![TrKeccak256::hash(sender.as_bytes())]; + let total_leaves_count: usize = whitelist_info.addresses_count.try_into().unwrap(); + + let is_verified = proof_from_hex.verify( + root_from_hex, + &leaf_indices, + &leaf_hashes, + total_leaves_count, + ); + + if !is_verified { + return Err(ContractError::MintNotWhitelisted); + } + } + + // If max per period is given then check if we reach max tokens for current period + if period.max_tokens.is_some() { + let current_period_minted_count = self + .period_minted_count + .load(ctx.deps.storage, period_id) + .unwrap_or(0); + if current_period_minted_count >= period.max_tokens.unwrap() { + return Err(ContractError::MintExceedMaxPerPeriod); + } + } + + // If max per user then check if sender has reached max per user for given + if period.limit_per_address.is_some() { + let current_user_minted = self + .user_minted_count + .load(ctx.deps.storage, (period_id, sender)) + .unwrap_or(0); + if current_user_minted >= period.limit_per_address.unwrap() { + return Err(ContractError::MintExceedMaxPerUser); + } + } + + // If this period is not free mint then check the sent fund + if period.price.is_some() { + // Check sent fund + self.assert_funds( + &ctx.info.funds, + period.to_owned().price.unwrap().denom, + period.to_owned().price.unwrap().amount, + )?; + } + + let sender = ctx.deps.api.addr_validate(ctx.info.sender.as_str())?; + let token_id = Tr721Contract::default() + .increment_tokens(ctx.deps.storage) + .unwrap(); + + // If token already requested then throw error otherwise then assign to sender + self.requested_mints.update( + ctx.deps.storage, + token_id.to_string(), + |current| match current { + Some(_) => Err(ContractError::NftAlreadyRequested), + None => Ok(sender.clone()), + }, + )?; + + // Update minted count per period + self.period_minted_count.update( + ctx.deps.storage, + period_id, + |count| -> Result { Ok(count.unwrap_or(0) + 1) }, + )?; + + // Update minted count per user per period + self.user_minted_count.update( + ctx.deps.storage, + (period_id, sender.to_string()), + |count| -> Result { Ok(count.unwrap_or(0) + 1) }, + )?; + + // Update total minted count per user + self.user_total_minted_count.update( + ctx.deps.storage, + sender.to_string(), + |count| -> Result { Ok(count.unwrap_or(0) + 1) }, + )?; + + Ok(Response::new() + .add_attribute("action", "request_mint") + .add_attribute("minter", sender.clone()) + .add_attribute("owner", sender) + .add_attribute("token_id", token_id.to_string())) + } + + #[msg(exec)] + pub fn claim( + &self, + ctx: ExecCtx, + token_id: String, + metadata: Tr721Metadata, + merkle_proof: String, + ) -> Result { + let sender = ctx.deps.api.addr_validate(ctx.info.sender.as_str())?; + let requested_owner = self + .requested_mints + .load(ctx.deps.storage, token_id.clone()) + .map_err(|_| ContractError::NftNotRequested)?; + + if sender != requested_owner { + return Err(ContractError::Unauthorized); + } + + let collection_info = self.mint_info.load(ctx.deps.storage)?; + + let proof_hex = HexBinary::from_hex(&merkle_proof).unwrap().to_vec(); + let proof_from_hex = MerkleProof::::try_from(proof_hex.to_owned()).unwrap(); + + let root_hex = collection_info.metadatas_merkle_root; + let root_from_hex: [u8; 32] = HexBinary::from_hex(root_hex.as_str()) + .unwrap() + .to_vec() + .try_into() + .unwrap(); + + let token_id_uint: usize = token_id.parse().unwrap(); + let leaf_indices = vec![token_id_uint]; + let leaf_hashes = vec![TrKeccak256::hash(&proto_encode(&metadata))]; + let total_leaves_count: usize = collection_info.tokens_count.try_into().unwrap(); + + let is_verified = proof_from_hex.verify( + root_from_hex, + &leaf_indices, + &leaf_hashes, + total_leaves_count, + ); + + if !is_verified { + return Err(ContractError::InvalidMerkleProof); + } + + // Merkle verification is ok then mint NFT to sender + // In default mint, only contract owner can mint so we have to change that logic here: instead of proxy call to default method + // Create the token + let token = TokenInfo { + owner: sender.clone(), + approvals: vec![], + token_uri: None, + extension: metadata, + }; + self.tokens + .update(ctx.deps.storage, &token_id, |old| match old { + Some(_) => Err(ContractError::NftAlreadyClaimed), + None => Ok(token), + })?; + + Ok(Response::new() + .add_attribute("action", "claim") + .add_attribute("sender", sender.clone()) + .add_attribute("owner", sender) + .add_attribute("token_id", token_id.to_string())) + } + + #[msg(query)] + pub fn total_minted(&self, ctx: QueryCtx) -> StdResult { + let total_minted = Tr721Contract::default() + .token_count(ctx.deps.storage) + .unwrap(); + + Ok(total_minted) + } + + #[msg(query)] + pub fn minted_count_by_period(&self, ctx: QueryCtx, period_id: u32) -> StdResult { + let count = self + .period_minted_count + .load(ctx.deps.storage, period_id) + .unwrap_or(0); + Ok(count) + } + + #[msg(query)] + pub fn minted_count_by_user( + &self, + ctx: QueryCtx, + period_id: u32, + user: String, + ) -> StdResult { + let validated_addr = ctx.deps.api.addr_validate(&user)?.to_string(); + let count = self + .user_minted_count + .load(ctx.deps.storage, (period_id, validated_addr)) + .unwrap_or(0); + Ok(count) + } + + #[msg(query)] + pub fn total_minted_count_by_user(&self, ctx: QueryCtx, user: String) -> StdResult { + let validated_addr = ctx.deps.api.addr_validate(&user)?.to_string(); + let count = self + .user_total_minted_count + .load(ctx.deps.storage, validated_addr) + .unwrap_or(0); + Ok(count) + } + + #[msg(query)] + pub fn mint_info(&self, ctx: QueryCtx) -> StdResult { + let mint_info = self.mint_info.load(ctx.deps.storage)?; + Ok(mint_info) + } + + #[msg(query)] + pub fn mint_periods(&self, ctx: QueryCtx) -> StdResult> { + let mut mint_periods: Vec = vec![]; + + for item in self + .mint_periods + .range(ctx.deps.storage, None, None, Order::Ascending) + { + let (_key, info) = item?; + mint_periods.push(info); + } + + Ok(mint_periods) + } + + #[msg(query)] + pub fn minter(&self, ctx: QueryCtx) -> StdResult { + let msg = Tr721QueryMsg::Minter {}; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn contract_info(&self, ctx: QueryCtx) -> StdResult { + let msg = Tr721QueryMsg::ContractInfo {}; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn nft_info( + &self, + ctx: QueryCtx, + token_id: String, + ) -> StdResult> { + let msg = Tr721QueryMsg::NftInfo { token_id }; + self.proxy_query::>(ctx, msg) + } + + #[msg(query)] + pub fn owner_of( + &self, + ctx: QueryCtx, + token_id: String, + include_expired: Option, + ) -> StdResult { + let msg = Tr721QueryMsg::OwnerOf { + token_id, + include_expired, + }; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn all_nft_info( + &self, + ctx: QueryCtx, + token_id: String, + include_expired: Option, + ) -> StdResult> { + let msg = Tr721QueryMsg::AllNftInfo { + token_id, + include_expired, + }; + self.proxy_query::>(ctx, msg) + } + + #[msg(query)] + pub fn operator( + &self, + ctx: QueryCtx, + owner: String, + operator: String, + include_expired: Option, + ) -> StdResult { + let msg = Tr721QueryMsg::Operator { + owner, + operator, + include_expired, + }; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn all_operators( + &self, + ctx: QueryCtx, + owner: String, + include_expired: Option, + start_after: Option, + limit: Option, + ) -> StdResult { + let msg = Tr721QueryMsg::AllOperators { + owner, + include_expired, + start_after, + limit, + }; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn num_tokens(&self, ctx: QueryCtx) -> StdResult { + let msg = Tr721QueryMsg::NumTokens {}; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn tokens( + &self, + ctx: QueryCtx, + owner: String, + start_after: Option, + limit: Option, + ) -> StdResult { + let msg = Tr721QueryMsg::Tokens { + owner, + start_after, + limit, + }; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn all_tokens( + &self, + ctx: QueryCtx, + start_after: Option, + limit: Option, + ) -> StdResult { + let msg = Tr721QueryMsg::AllTokens { start_after, limit }; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn approval( + &self, + ctx: QueryCtx, + token_id: String, + spender: String, + include_expired: Option, + ) -> StdResult { + let msg = Tr721QueryMsg::Approval { + token_id, + spender, + include_expired, + }; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn approvals( + &self, + ctx: QueryCtx, + token_id: String, + include_expired: Option, + ) -> StdResult { + let msg = Tr721QueryMsg::Approvals { + token_id, + include_expired, + }; + self.proxy_query::(ctx, msg) + } + + #[msg(query)] + pub fn ownership(&self, ctx: QueryCtx) -> StdResult> { + let msg = Tr721QueryMsg::Ownership {}; + self.proxy_query::>(ctx, msg) + } + + #[msg(query)] + pub fn extension(&self, _ctx: QueryCtx) -> StdResult { + Ok(Response::new()) + } + + #[msg(query)] + pub fn contract_version(&self, ctx: QueryCtx) -> StdResult { + let contract_version = self.contract_version.load(ctx.deps.storage)?; + Ok(contract_version) + } + + #[msg(query)] + pub fn merkle_root(&self, ctx: QueryCtx) -> StdResult { + let merkle_root = self.mint_info.load(ctx.deps.storage)?.metadatas_merkle_root; + Ok(merkle_root) + } + + #[msg(query)] + pub fn royalty_info( + &self, + ctx: QueryCtx, + token_id: String, + sale_price: Uint128, + ) -> StdResult { + let resp = query_royalties_info(ctx.deps, token_id, sale_price).unwrap(); + Ok(resp) + } + + #[msg(query)] + pub fn check_royalties(&self, ctx: QueryCtx) -> StdResult { + let resp = check_royalties(ctx.deps).unwrap(); + Ok(resp) + } +} + +// Types definitions ------------------------------------------------------ +#[cw_serde] +pub struct ContractVersion { + pub contract: String, + pub version: String, +} + +#[cw_serde] +pub struct WhitelistProof { + pub merkle_proof: String, + pub address_indice: u32, +} + +#[cw_serde] +#[derive(Default)] +pub struct MintPeriod { + pub price: Option, + + pub max_tokens: Option, // If not given then there is no limit for minting for this period + pub limit_per_address: Option, // If not given then there is no limit + + pub start_time: u64, + pub end_time: Option, // If not given then there is no end date + + pub whitelist_info: Option, +} + +#[cw_serde] +#[derive(Default)] +pub struct WhitelistInfo { + pub addresses_merkle_root: String, // Merkle roof of addresses. If given then check the whitelist by merkle tree + pub addresses_count: u32, // If given, this is the total addresses in whitelist + pub addresses_ipfs: String, // If given, this is ipfs link contains all the whitelist addresses +} + +#[cw_serde] +#[derive(Default)] +pub struct MintInfo { + pub metadatas_merkle_root: String, // Merkle roof of metadatas. This is mandatory + pub tokens_count: u64, // Total tokens of the collection + + // Royalty -------------------------- + pub royalty_address: Option, + pub royalty_percentage: Option, +} + diff --git a/rust/cw-contracts/nft-tr721/src/error.rs b/rust/cw-contracts/nft-tr721/src/error.rs new file mode 100644 index 0000000000..2fdb9b7ef2 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/error.rs @@ -0,0 +1,62 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug, PartialEq)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error(transparent)] + Cw721BaseError(#[from] cw721_base::ContractError), + + #[error("Unauthorized")] + Unauthorized, + + #[error("NFT already requested")] + NftAlreadyRequested, + + #[error("NFT already claimed")] + NftAlreadyClaimed, + + #[error("NFT not requested yet")] + NftNotRequested, + + #[error("Merkle proof is invalid")] + InvalidMerkleProof, + + #[error("Royalty percentage must be between 0 and 100")] + InvalidRoyaltyPercentage, + + #[error("Mint has not started yet")] + MintNotStarted, + + #[error("Mint has ended")] + MintEnded, + + #[error("This period is only for whitelisted addresses")] + MintWhitelistOnly, + + #[error("Not in whitelisted addresses")] + MintNotWhitelisted, + + #[error("Exceed max tokens")] + MintExceedMaxTokens, + + #[error("Exceed max per period")] + MintExceedMaxPerPeriod, + + #[error("Exceed max per user")] + MintExceedMaxPerUser, + + #[error("Invalid fund")] + InvalidFund, + + #[error("Invalid denom")] + InvalidDenom, + + #[error("Invalid amount")] + InvalidAmount, + + #[error("Period does not exist")] + InvalidPeriod, +} diff --git a/rust/cw-contracts/nft-tr721/src/hasher.rs b/rust/cw-contracts/nft-tr721/src/hasher.rs new file mode 100644 index 0000000000..8e79421fd6 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/hasher.rs @@ -0,0 +1,16 @@ +use rs_merkle::Hasher; +use sha3::{digest::FixedOutput, Digest, Keccak256}; + +#[derive(Clone)] +pub struct TrKeccak256 {} + +impl Hasher for TrKeccak256 { + type Hash = [u8; 32]; + + fn hash(data: &[u8]) -> [u8; 32] { + let mut hasher = Keccak256::new(); + + hasher.update(data); + <[u8; 32]>::from(hasher.finalize_fixed()) + } +} diff --git a/rust/cw-contracts/nft-tr721/src/lib.rs b/rust/cw-contracts/nft-tr721/src/lib.rs new file mode 100644 index 0000000000..776c6812d1 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/lib.rs @@ -0,0 +1,9 @@ +pub mod contract; +pub mod error; +pub mod hasher; +pub mod utils; + +#[cfg(test)] +pub mod multitest; +#[cfg(test)] +pub mod test_helpers; diff --git a/rust/cw-contracts/nft-tr721/src/multitest.rs b/rust/cw-contracts/nft-tr721/src/multitest.rs new file mode 100644 index 0000000000..5ec76ad643 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/multitest.rs @@ -0,0 +1,685 @@ +use cosmwasm_std::{coin, Addr, Attribute, Coin, HexBinary, Uint128}; +use cw2981_royalties::Metadata; +use cw721::{Approval, ContractInfoResponse}; +use rs_merkle::{Hasher, MerkleProof, MerkleTree}; +use sylvia::multitest::App; + +use crate::{ + contract::{ + sv::multitest_utils::CodeId, ContractVersion, MintInfo, MintPeriod, WhitelistInfo, + WhitelistProof, + }, + error::ContractError, + hasher::TrKeccak256, + test_helpers::{ + assert_wasm_attr, get_default_mint_info, get_default_nfts, get_default_periods, + get_merkle_tree_info, DEFAULT_BLOCK_TIME, METADATAS_MERKLE_ROOT, + }, + utils::proto_encode, +}; + +const ADMIN: &str = "admin_user"; +const CREATOR: &str = "creator_user"; +const MINTER: &str = "minter_user"; +const OWNER: &str = "owner_user"; +const OPERATOR: &str = "operator_user"; +const UNAUTHOR: &str = "unauthor_user"; +const ROYALTY_ADDR: &str = "royalty_addr"; + +// Generated by merke root later in the code +const FIRST_TOKEN_ID: &str = "1"; + +#[test] +fn full_flow() { + // 1. Create + let app: App = App::default(); + + app.app_mut() + .init_modules(|router, _, storage| { + router.bank.init_balance( + storage, + &Addr::unchecked(OWNER.to_string()), + vec![coin(1000000, "utori"), coin(1000000, "uinvalid")], + )?; + Ok::<(), sylvia::anyhow::Error>(()) + }) + .unwrap(); + + // Instantiate NFT contract --------------------------------------------------------- + let mint_info = get_default_mint_info(); + let mint_periods = get_default_periods(); + let contract = CodeId::store_code(&app) + .instantiate( + ADMIN.to_string(), + "NFT name".to_string(), + MINTER.to_string(), + "SYMBOL".to_string(), + "launchpad_contract".to_string(), + mint_info, + mint_periods, + ) + .call(CREATOR) + .unwrap(); + + // Query minter + { + let resp = contract.minter().unwrap(); + assert_eq!(resp.minter, Some(MINTER.to_string())); + } + + // Query contract info + { + let resp = contract.contract_info().unwrap(); + assert_eq!( + resp, + ContractInfoResponse { + name: "NFT name".to_string(), + symbol: "SYMBOL".to_string() + } + ); + } + + // Query mint info + { + let resp = contract.mint_info().unwrap(); + assert_eq!(resp.tokens_count, 4); + assert_eq!( + resp.metadatas_merkle_root, + METADATAS_MERKLE_ROOT.to_string() + ); + } + + // Query periods + { + let resp = contract.mint_periods().unwrap(); + assert_eq!(resp, get_default_periods()); + } + + // Mint NFT with metadata onchain + royalty address and query NFT info + { + let token_id = FIRST_TOKEN_ID.to_string(); + let owner = OWNER.to_string(); + let token_uri = Some("token_uri".to_string()); + let extension = Some(Metadata { + name: Some("this is NFT name".to_string()), + royalty_payment_address: Some(ROYALTY_ADDR.to_string()), + royalty_percentage: Some(5), // royalty 5% + + ..Metadata::default() + }); + contract + .mint(token_id, owner, token_uri, extension) + .call(MINTER) + .unwrap(); + + let resp = contract.nft_info(FIRST_TOKEN_ID.to_string()).unwrap(); + let ext = resp.extension; + + assert_eq!(ext.name, Some("this is NFT name".to_string())); + assert_eq!(ext.royalty_payment_address, Some(ROYALTY_ADDR.to_string())); + + // Query balance + } + + // Query All NFT info + { + let resp = contract + .all_nft_info(FIRST_TOKEN_ID.to_string(), Some(true)) + .unwrap(); + assert_eq!(resp.info.token_uri, Some("token_uri".to_string())); + } + + // Query owner of + { + let resp = contract + .owner_of(FIRST_TOKEN_ID.to_string(), Some(true)) + .unwrap(); + assert_eq!(resp.owner, OWNER.to_string()); + } + + // Approve + { + let resp = contract + .approve(OPERATOR.to_string(), FIRST_TOKEN_ID.to_string(), None) + .call(OWNER) + .unwrap(); + + assert_wasm_attr( + resp, + Attribute { + key: "spender".to_string(), + value: OPERATOR.to_string(), + }, + ); + } + + // Approve all + { + let resp = contract + .approve_all(OPERATOR.to_string(), None) + .call(OWNER) + .unwrap(); + + assert_wasm_attr( + resp, + Attribute { + key: "operator".to_string(), + value: OPERATOR.to_string(), + }, + ); + } + + // Query operator + { + let resp = contract + .operator(OWNER.to_string(), OPERATOR.to_string(), Some(false)) + .unwrap(); + assert_eq!( + resp.approval, + Approval { + spender: OPERATOR.to_string(), + expires: cw721::Expiration::Never {} + } + ) + } + + // Check royalties + { + let resp = contract.check_royalties().unwrap(); + assert_eq!(resp.royalty_payments, true) + } + + // Query royalties info + { + let resp = contract + .royalty_info(FIRST_TOKEN_ID.to_string(), Uint128::new(1000)) + .unwrap(); + assert_eq!(resp.royalty_amount, Uint128::new(50)) + } + + // Query contract version + { + let resp = contract.contract_version().unwrap(); + assert_eq!( + resp, + ContractVersion { + contract: "teritori:nft-tr721".to_string(), + version: "0.2.0".to_string() + } + ) + } + + // Update mint info with unauthorized user + { + let mint_info = MintInfo::default(); + let err = contract + .update_mint_info(mint_info) + .call(UNAUTHOR) + .unwrap_err(); + assert_eq!(err, ContractError::Unauthorized); + } + + // Request mint: Error if reached max tokens + { + contract + .update_mint_info(MintInfo::default()) + .call(ADMIN) + .unwrap(); + + assert_eq!( + contract.request_mint(0, None).call(OWNER).unwrap_err(), + ContractError::MintExceedMaxTokens + ); + } + + // Request mint: Error period does not exist + { + contract + .update_mint_info(MintInfo { + tokens_count: 10, + ..MintInfo::default() + }) + .call(ADMIN) + .unwrap(); + + assert_eq!( + contract.request_mint(5, None).call(OWNER).unwrap_err(), + ContractError::InvalidPeriod + ); + } + + // Request mint: + // - Mint not started + // => ContractError::MintNotStarted + { + contract + .update_mint_period( + 0, + MintPeriod { + start_time: DEFAULT_BLOCK_TIME + 10, + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + assert_eq!( + contract.request_mint(0, None).call(OWNER).unwrap_err(), + ContractError::MintNotStarted + ); + } + + // Request mint: + // - Mint ended + // => ContractError::MintEnded + { + contract + .update_mint_period( + 0, + MintPeriod { + start_time: DEFAULT_BLOCK_TIME - 10, + end_time: Some(DEFAULT_BLOCK_TIME - 5), + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + assert_eq!( + contract.request_mint(0, None).call(OWNER).unwrap_err(), + ContractError::MintEnded + ); + } + + // Request mint: + // - Mint started + // - Merkle root not provided => ContractError::MintWhitelistOnly + // - Merkle provided but address not in whitelist => ContractError::MintNotWhitelisted + { + contract + .update_mint_period( + 0, + MintPeriod { + start_time: DEFAULT_BLOCK_TIME - 10, + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + let (root_hex, proof_hex) = get_merkle_tree_info(vec![OWNER], 0); + + contract + .update_mint_period( + 0, + MintPeriod { + whitelist_info: Some(WhitelistInfo { + addresses_merkle_root: root_hex, + addresses_count: 1, + addresses_ipfs: "".to_string(), + }), + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + // Not provide whitelist proof + assert_eq!( + contract.request_mint(0, None).call(OWNER).unwrap_err(), + ContractError::MintWhitelistOnly + ); + + // Address not match with proof + assert_eq!( + contract + .request_mint( + 0, + Some(WhitelistProof { + merkle_proof: proof_hex.to_string(), + address_indice: 0 + }) + ) + .call(UNAUTHOR) + .unwrap_err(), + ContractError::MintNotWhitelisted + ); + } + + // Request mint: + // - In period + // - In whitelist + // - Reach max token per period + // => ContractError::MintExceedMaxPerPeriod + { + let (_, proof_hex) = get_merkle_tree_info(vec![OWNER], 0); + + contract + .update_mint_period( + 0, + MintPeriod { + start_time: DEFAULT_BLOCK_TIME - 10, + max_tokens: Some(0), + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + assert_eq!( + contract + .request_mint( + 0, + Some(WhitelistProof { + merkle_proof: proof_hex.to_string(), + address_indice: 0 + }) + ) + .call(OWNER) + .unwrap_err(), + ContractError::MintExceedMaxPerPeriod + ); + } + + // Request mint: + // - Mint not started + // - In whitelist time and in whitelist + // - Not Reach max per whitelist user + // + // => Not send fund: ContractError::InvalidFund + // => Not send valid denom: ContractError::InvalidDenom + // => Not send valid amount: ContractError::InvalidAmount + { + let (root_hex, proof_hex) = + get_merkle_tree_info(vec!["addr0", "addr1", "addr2", "addr3", "addr4", OWNER], 5); + contract + .update_mint_period( + 0, + MintPeriod { + max_tokens: None, + limit_per_address: Some(1), + price: Some(Coin { + amount: Uint128::new(10), + denom: "utori".to_string(), + }), + start_time: DEFAULT_BLOCK_TIME - 10, + end_time: Some(DEFAULT_BLOCK_TIME + 10), + whitelist_info: Some(WhitelistInfo { + addresses_count: 6, + addresses_merkle_root: root_hex, + addresses_ipfs: "ipfs".to_string(), + }), + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + let whitelist_proof = Some(WhitelistProof { + merkle_proof: proof_hex, + address_indice: 5, + }); + + assert_eq!( + contract + .request_mint(0, whitelist_proof.to_owned()) + .call(OWNER) + .unwrap_err(), + ContractError::InvalidFund + ); + + assert_eq!( + contract + .request_mint(0, whitelist_proof.to_owned()) + .with_funds(&[coin(10, "uinvalid")]) + .call(OWNER) + .unwrap_err(), + ContractError::InvalidDenom + ); + + assert_eq!( + contract + .request_mint(0, whitelist_proof.to_owned()) + .with_funds(&[coin(1, "utori")]) + .call(OWNER) + .unwrap_err(), + ContractError::InvalidAmount + ); + } + + // Request mint: with the mint/whitelist info in previous step + // but with correct fund this time => mint successfully + { + let (_, proof_hex) = + get_merkle_tree_info(vec!["addr0", "addr1", "addr2", "addr3", "addr4", OWNER], 5); + let whitelist_proof = Some(WhitelistProof { + merkle_proof: proof_hex, + address_indice: 5, + }); + let resp = contract + .request_mint(0, whitelist_proof.to_owned()) + .with_funds(&[coin(10, "utori")]) + .call(OWNER) + .unwrap(); + + assert_wasm_attr( + resp.to_owned(), + Attribute { + key: "token_id".to_string(), + value: "2".to_string(), + }, + ); + + let total_minted = contract.total_minted().unwrap(); + assert_eq!(total_minted, 2); // We have already minted by minter previously + + let minted_by_user = contract.minted_count_by_user(0, OWNER.to_string()).unwrap(); + assert_eq!(minted_by_user, 1); + + let minted_by_user = contract.minted_count_by_user(5, OWNER.to_string()).unwrap(); + assert_eq!(minted_by_user, 0); + + // - Reached max token per user + // => ContractError::MintExceedMaxPerUser + assert_eq!( + contract + .request_mint(0, whitelist_proof) + .call(OWNER) + .unwrap_err(), + ContractError::MintExceedMaxPerUser + ); + } + + // Request mint: normal mint without whitelist + // - Not Reached max token per user + // - Send correct fund + // => success + { + contract + .update_mint_period( + 1, + MintPeriod { + start_time: DEFAULT_BLOCK_TIME - 10, + price: Some(Coin { + amount: Uint128::new(10), + denom: "utori".to_string(), + }), + whitelist_info: None, + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + let resp = contract + .request_mint(1, None) + .with_funds(&[coin(10, "utori")]) + .call(OWNER) + .unwrap(); + + assert_wasm_attr( + resp, + Attribute { + key: "token_id".to_string(), + value: "3".to_string(), + }, + ); + + let total_minted = contract.total_minted().unwrap(); + assert_eq!(total_minted, 3); + + let minted_by_user = contract.minted_count_by_user(1, OWNER.to_string()).unwrap(); + assert_eq!(minted_by_user, 1); + + let total_minted_by_user = contract + .total_minted_count_by_user(OWNER.to_string()) + .unwrap(); + assert_eq!(total_minted_by_user, 2); + } + + // Free mint period + { + contract + .update_mint_period( + 2, + MintPeriod { + start_time: DEFAULT_BLOCK_TIME - 10, + ..MintPeriod::default() + }, + ) + .call(ADMIN) + .unwrap(); + + contract.request_mint(2, None).call(OWNER).unwrap(); + + let total_minted = contract.total_minted().unwrap(); + assert_eq!(total_minted, 4); + + let minted_by_user = contract.minted_count_by_user(1, OWNER.to_string()).unwrap(); + assert_eq!(minted_by_user, 1); + + let total_minted_by_user = contract + .total_minted_count_by_user(OWNER.to_string()) + .unwrap(); + assert_eq!(total_minted_by_user, 3); + } + + // Query merke root + { + contract + .update_mint_info(get_default_mint_info()) + .call(ADMIN) + .unwrap(); + + let resp = contract.merkle_root().unwrap(); + assert_eq!(resp, METADATAS_MERKLE_ROOT.to_string()) + } + + // Test merkle tree + { + let leaf_values = ["addr1", "addr2", "addr3", "addr4", "add5"]; + let leaves: Vec<[u8; 32]> = leaf_values + .iter() + .map(|x| TrKeccak256::hash(x.as_bytes())) + .collect(); + + let idx = 1; + + let merkle_tree = MerkleTree::::from_leaves(&leaves); + + let leaf_indices = vec![idx]; + let leaf_hashes = leaves.get(idx..idx + 1).unwrap(); + + let merkle_proof = merkle_tree.proof(&leaf_indices); + + let merkle_root = merkle_tree.root().unwrap(); + + let proof_bytes = merkle_proof.to_bytes(); + let proof_hex = HexBinary::from(proof_bytes.to_owned()).to_string(); + let proof_bytes_from_hex = HexBinary::from_hex(&proof_hex).unwrap().to_vec(); + + let proof = MerkleProof::::try_from(proof_bytes_from_hex.to_owned()).unwrap(); + + let is_ok = proof.verify(merkle_root, &leaf_indices, leaf_hashes, leaves.len()); + assert!(is_ok); + + let root_hex = HexBinary::from(merkle_root).to_string(); + let root_from_hex: [u8; 32] = HexBinary::from_hex(root_hex.as_str()) + .unwrap() + .to_vec() + .try_into() + .unwrap(); + + assert!(merkle_root == root_from_hex); + // panic!("hex: {}, proof_hex: {}, root from hex: {:X?}, Is OK: {}, Root: {:X?}, Is equal: {}", root_hex, proof_hex, root_from_hex, is_ok, merkle_root, merkle_root == root_from_hex); + } + + // Test mint with merkle path + { + let nfts = get_default_nfts(); + let nft2 = &nfts[2]; + let nft_hashes: Vec<[u8; 32]> = nfts + .iter() + .map(|x| TrKeccak256::hash(&proto_encode(x))) + .collect(); + + let merkle_tree = MerkleTree::::from_leaves(&nft_hashes); + let merkle_root = merkle_tree.root().unwrap(); + let root_hex = HexBinary::from(merkle_root).to_string(); + + assert_eq!(root_hex, METADATAS_MERKLE_ROOT.to_string()); + + // Try to claim un-requested token + let not_requested_err = contract + .claim( + "inexist".to_string(), + Metadata::default(), + "merkle_proof".to_string(), + ) + .call(OWNER) + .unwrap_err(); + assert_eq!(not_requested_err, ContractError::NftNotRequested); + + // Claim a registed token from unauthorized user + let unauthor_claim_err = contract + .claim( + "2".to_string(), + Metadata::default(), + "merkle_proof".to_string(), + ) + .call(UNAUTHOR) + .unwrap_err(); + assert_eq!(unauthor_claim_err, ContractError::Unauthorized); + + // Claim registered token from correct owner => should be successull + let leaf_indices = vec![2]; + let merkle_proof = merkle_tree.proof(&leaf_indices); + let proof_bytes = merkle_proof.to_bytes(); + let proof_hex = HexBinary::from(proof_bytes.to_owned()).to_string(); + + let resp = contract + .claim("2".to_string(), nft2.clone(), proof_hex) + .call(OWNER) + .unwrap(); + + assert_wasm_attr( + resp.clone(), + Attribute { + key: "action".to_string(), + value: "claim".to_string(), + }, + ); + assert_wasm_attr( + resp.clone(), + Attribute { + key: "token_id".to_string(), + value: "2".to_string(), + }, + ); + + // At this step, token should exist and mint + let resp = contract.nft_info("2".to_string()).unwrap(); + assert_eq!(resp.token_uri, None); + assert_eq!(resp.extension.name, nft2.name); + } +} diff --git a/rust/cw-contracts/nft-tr721/src/test_helpers.rs b/rust/cw-contracts/nft-tr721/src/test_helpers.rs new file mode 100644 index 0000000000..1dc961e3d8 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/test_helpers.rs @@ -0,0 +1,138 @@ +use cosmwasm_std::{Attribute, Coin, HexBinary, Uint128}; +use cw2981_royalties::{Metadata, Trait}; +use cw_multi_test::AppResponse; +use rs_merkle::{Hasher, MerkleTree}; + +use crate::{ + contract::{MintInfo, MintPeriod, WhitelistInfo}, + hasher::TrKeccak256, +}; + +pub const METADATAS_MERKLE_ROOT: &str = + "0110bb1a773c10cce02033f0594eda56df7b9ca30137520327b804107b252001"; +pub const WHITELIST_USER: &str = "whitelist_user"; +pub const DEFAULT_BLOCK_TIME: u64 = 1_571_797_419; + +pub fn get_default_nfts() -> Vec { + let nft0 = Metadata { + name: Some("nft #0".to_string()), + image: Some("image0".to_string()), + attributes: Some(vec![ + Trait { + display_type: None, + trait_type: "type0".to_string(), + value: "value0".to_string(), + }, + Trait { + display_type: None, + trait_type: "type1".to_string(), + value: "value1".to_string(), + }, + ]), + royalty_percentage: Some(9), + ..Metadata::default() + }; + let nft1 = Metadata { + name: Some("nft #1".to_string()), + image: Some("image1".to_string()), + attributes: Some(vec![Trait { + display_type: None, + trait_type: "type1".to_string(), + value: "value1".to_string(), + }]), + royalty_percentage: Some(5), + ..Metadata::default() + }; + let nft2 = Metadata { + name: Some("nft #2".to_string()), + image: Some("image2".to_string()), + attributes: Some(vec![Trait { + display_type: Some("attr2".to_string()), + trait_type: "type2".to_string(), + value: "value2".to_string(), + }]), + ..Metadata::default() + }; + let nft3 = Metadata { + name: Some("nft #3".to_string()), + image: Some("image3".to_string()), + attributes: Some(vec![Trait { + display_type: Some("attr3".to_string()), + trait_type: "type3".to_string(), + value: "value3".to_string(), + }]), + ..Metadata::default() + }; + + vec![nft0, nft1, nft2, nft3] +} + +pub fn get_default_period() -> MintPeriod { + MintPeriod { + price: Some(Coin { + denom: "denom".to_string(), + amount: Uint128::new(1), + }), + limit_per_address: Some(2), + + start_time: DEFAULT_BLOCK_TIME, + end_time: Some(DEFAULT_BLOCK_TIME), + max_tokens: Some(1), + + whitelist_info: Some(WhitelistInfo { + addresses_merkle_root: "".to_string(), + addresses_count: 1, + addresses_ipfs: "ipfs_path".to_string(), + }), + } +} + +pub fn get_merkle_tree(leaf_values: Vec<&str>) -> MerkleTree { + let leaves: Vec<[u8; 32]> = leaf_values + .iter() + .map(|x| TrKeccak256::hash(x.as_bytes())) + .collect(); + MerkleTree::::from_leaves(&leaves) +} + +pub fn get_merkle_tree_info(leaf_values: Vec<&str>, needed_leaf_indice: usize) -> (String, String) { + let tree = get_merkle_tree(leaf_values); + let root_hex = HexBinary::from(tree.root().unwrap()).to_string(); + let proof = tree.proof(&vec![needed_leaf_indice]); + let proof_hex = HexBinary::from(proof.to_bytes().to_owned()).to_string(); + + (root_hex, proof_hex) +} + +pub fn get_default_periods() -> Vec { + vec![] +} + +pub fn get_default_mint_info() -> MintInfo { + MintInfo { + tokens_count: get_default_nfts().len().try_into().unwrap(), + metadatas_merkle_root: METADATAS_MERKLE_ROOT.to_string(), + royalty_address: None, + royalty_percentage: None, + } +} + +pub fn has_attr(given_attrs: &Vec, expected_attr: &Attribute) -> bool { + let resp = given_attrs + .iter() + .find(|item| item.key == expected_attr.key && item.value == expected_attr.value); + resp.is_some() +} + +pub fn assert_wasm_attr(resp: AppResponse, expected_attr: Attribute) { + // app.events[0]: exec events + // app.events[1]: wasm events + let wasm_attrs = &resp.events[1].attributes; + + if !has_attr(wasm_attrs, &expected_attr) { + panic!( + "Attribute not found. Wasm attrs: {:?} - Expected attr: {:?}", + wasm_attrs, expected_attr + ) + } +} diff --git a/rust/cw-contracts/nft-tr721/src/utils.rs b/rust/cw-contracts/nft-tr721/src/utils.rs new file mode 100644 index 0000000000..141e706cdf --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/utils.rs @@ -0,0 +1,32 @@ +use cw2981_royalties::Metadata; + +use apipb::launchpadpb; +use prost::Message; + +pub fn proto_encode(data: &Metadata) -> Vec { + let metadata_pb = launchpadpb::Metadata { + image: data.image.clone(), + image_data: data.image_data.clone(), + external_url: data.external_url.clone(), + description: data.description.clone(), + name: data.name.clone(), + attributes: data + .attributes + .clone() + .unwrap_or_default() + .iter() + .map(|item| launchpadpb::Trait { + display_type: item.display_type.clone(), + trait_type: item.trait_type.clone(), + value: item.value.clone(), + }) + .collect(), + background_color: data.background_color.clone(), + animation_url: data.animation_url.clone(), + youtube_url: data.youtube_url.clone(), + royalty_percentage: data.royalty_percentage, + royalty_payment_address: data.royalty_payment_address.clone(), + }; + + metadata_pb.encode_to_vec() +} diff --git a/rust/utils/scripts.ts b/rust/utils/scripts.ts new file mode 100644 index 0000000000..c6d63172f1 --- /dev/null +++ b/rust/utils/scripts.ts @@ -0,0 +1,56 @@ +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import { GasPrice } from "@cosmjs/stargate"; +import * as fs from "fs"; +import path from "path"; + +import { MNEMONIC } from "./mnemonic"; + +const GAS_PRICE = GasPrice.fromString("0.025utori"); + +const NODE_RPC = "https://rpc.testnet.teritori.com:443"; +// const CHAIN_ID = "teritori-test-7"; + +const getClientInfos = async () => { + const wallet = await DirectSecp256k1HdWallet.fromMnemonic(MNEMONIC, { + prefix: "tori", + }); + + const client = await SigningCosmWasmClient.connectWithSigner( + NODE_RPC, + wallet, + { gasPrice: GAS_PRICE }, + ); + + const sender = await wallet.getAccounts().then((res) => res[0]?.address); + console.log("Sender:", sender); + + return { wallet, client, sender }; +}; + +const getWasmFile = (wasmFile: string) => { + const filePath = path.join(__dirname, "../..", "artifacts", wasmFile); + console.log("filePath:", filePath); + return fs.readFileSync(filePath); +}; + +export const deploy = async (wasmFile: string) => { + const { client, sender } = await getClientInfos(); + const wasmCode = new Uint8Array(getWasmFile(wasmFile)); + const uploadRes = await client.upload(sender, wasmCode, "auto"); + + return uploadRes.codeId; +}; + +export const instantiate = async (codeId: number, label: string, msg: any) => { + const { client, sender } = await getClientInfos(); + + const instantiateRes = await client.instantiate( + sender, + codeId, + msg, + `${label} - ${codeId}`, + "auto", + ); + return instantiateRes.contractAddress; +}; From 78c89714c241acbdb0fd39c72b1da379d329b510 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 18 Oct 2024 14:13:05 -0400 Subject: [PATCH 02/33] fix: temporary allow push mnemonic --- .gitignore | 5 +---- rust/utils/mnemonic.ts | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) create mode 100644 rust/utils/mnemonic.ts diff --git a/.gitignore b/.gitignore index 1d5fca3586..4a858ff704 100644 --- a/.gitignore +++ b/.gitignore @@ -107,7 +107,4 @@ artifacts rust/cw-contracts/*/target # cypress -cypress/screenshots - -# secret files -rust/utils/mnemonic.ts \ No newline at end of file +cypress/screenshots \ No newline at end of file diff --git a/rust/utils/mnemonic.ts b/rust/utils/mnemonic.ts new file mode 100644 index 0000000000..4dd7881ee8 --- /dev/null +++ b/rust/utils/mnemonic.ts @@ -0,0 +1 @@ +export const MNEMONIC = "MNEMONIC"; From b0aca034924c799cbeb16d910947277512f52f2c Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 18 Oct 2024 14:13:24 -0400 Subject: [PATCH 03/33] fix: disallow push mnemonic --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4a858ff704..1d5fca3586 100644 --- a/.gitignore +++ b/.gitignore @@ -107,4 +107,7 @@ artifacts rust/cw-contracts/*/target # cypress -cypress/screenshots \ No newline at end of file +cypress/screenshots + +# secret files +rust/utils/mnemonic.ts \ No newline at end of file From fb4cbb2133fc0d84f5e970d0224f401f2a225599 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 18 Oct 2024 14:23:57 -0400 Subject: [PATCH 04/33] fix: Cargo.toml --- Cargo.lock | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 +++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 98c163bad7..bb2df7da98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,13 @@ version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +[[package]] +name = "apipb" +version = "0.1.0" +dependencies = [ + "prost 0.12.6", +] + [[package]] name = "base16ct" version = "0.1.1" @@ -935,6 +942,15 @@ dependencies = [ "signature 2.2.0", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + [[package]] name = "konst" version = "0.3.9" @@ -974,6 +990,24 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "nft-launchpad" +version = "0.2.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2981-royalties", + "cw721 0.18.0", + "cw721-base 0.18.0", + "nft-tr721", + "schemars", + "serde", + "sylvia 0.9.3", + "thiserror", +] + [[package]] name = "nft-marketplace" version = "0.1.0" @@ -988,6 +1022,29 @@ dependencies = [ "serde", ] +[[package]] +name = "nft-tr721" +version = "0.2.0" +dependencies = [ + "apipb", + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test 0.20.1", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2981-royalties", + "cw721 0.18.0", + "cw721-base 0.18.0", + "cw721-metadata-onchain", + "prost 0.12.6", + "rs_merkle", + "schemars", + "serde", + "sha3", + "sylvia 0.9.3", + "thiserror", +] + [[package]] name = "nfts-burner" version = "0.1.0" @@ -1174,6 +1231,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "rs_merkle" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b241d2e59b74ef9e98d94c78c47623d04c8392abaf82014dfd372a16041128f" +dependencies = [ + "sha2 0.10.8", +] + [[package]] name = "ryu" version = "1.0.18" @@ -1332,6 +1398,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "signature" version = "1.6.4" diff --git a/Cargo.toml b/Cargo.toml index 5c2677e06a..e9f7e57871 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,7 @@ schemars = "0.8.16" serde = { version = "1.0.197", features = ["derive"] } thiserror = "1.0.57" sylvia = "0.9.3" -prost = "0.12.3" \ No newline at end of file +prost = "0.12.3" +apipb = { version = "0.1.0", path = "rust/apipb" } +nft-tr721 = { version = "0.2.0", path = "rust/cw-contracts/nft-tr721" } +nft-launchpad = { version = "0.2.0", path = "rust/cw-contracts/nft-launchpad" } \ No newline at end of file From 9199111b67cb36d7bb4c868f427cf1474f09f502 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 20 Oct 2024 16:39:44 -0400 Subject: [PATCH 05/33] wip: two contracts scripts --- .../network-setup/deployNftLaunchpad.ts | 25 +++++++++ .../scripts/network-setup/deployNftTr721.ts | 10 ++++ rust/cw-contracts/nft-launchpad/deploy.ts | 25 --------- rust/cw-contracts/nft-tr721/deploy.ts | 9 --- rust/utils/mnemonic.ts | 1 - rust/utils/scripts.ts | 56 ------------------- 6 files changed, 35 insertions(+), 91 deletions(-) create mode 100644 packages/scripts/network-setup/deployNftLaunchpad.ts create mode 100644 packages/scripts/network-setup/deployNftTr721.ts delete mode 100644 rust/cw-contracts/nft-launchpad/deploy.ts delete mode 100644 rust/cw-contracts/nft-tr721/deploy.ts delete mode 100644 rust/utils/mnemonic.ts delete mode 100644 rust/utils/scripts.ts diff --git a/packages/scripts/network-setup/deployNftLaunchpad.ts b/packages/scripts/network-setup/deployNftLaunchpad.ts new file mode 100644 index 0000000000..d8f326b4f1 --- /dev/null +++ b/packages/scripts/network-setup/deployNftLaunchpad.ts @@ -0,0 +1,25 @@ +const nftLaunchpadFileName = "nft_tr721.wasm"; +const deployer = "tori1zsgm6hvx4a3t08vsanwdcvvnv2xca9faavzccm"; + +// TODO + +// const main = async () => { +// const codeId = await deployContract(WASM_FILE); +// const initMsg = { +// config: { +// name: "Teritori launchpad", +// supported_networks: [], +// nft_code_id: 1, +// deployer: DEPLOYER, +// }, +// }; +// const contractAddress = await instantiateContract( +// codeId, +// "Teritori Launchpad", +// initMsg, +// ); + +// console.log("CodeId:", codeId, "- Contract Address:", contractAddress); +// }; + +// main(); diff --git a/packages/scripts/network-setup/deployNftTr721.ts b/packages/scripts/network-setup/deployNftTr721.ts new file mode 100644 index 0000000000..bd8fe5bfda --- /dev/null +++ b/packages/scripts/network-setup/deployNftTr721.ts @@ -0,0 +1,10 @@ +const nftTr721FileName = "nft_tr721.wasm"; + +// TODO + +// const main = async () => { +// const codeId = await deployContract(WASM_FILE); +// console.log("CodeId:", codeId); +// }; + +// main(); diff --git a/rust/cw-contracts/nft-launchpad/deploy.ts b/rust/cw-contracts/nft-launchpad/deploy.ts deleted file mode 100644 index e5f469e3d1..0000000000 --- a/rust/cw-contracts/nft-launchpad/deploy.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { deploy, instantiate } from "../../utils/scripts"; - -const WASM_FILE = "nft_launchpad-aarch64.wasm"; -const DEPLOYER = "tori1zsgm6hvx4a3t08vsanwdcvvnv2xca9faavzccm"; - -const main = async () => { - const codeId = await deploy(WASM_FILE); - const initMsg = { - config: { - name: "Teritori launchpad", - supported_networks: [], - nft_code_id: 1, - deployer: DEPLOYER, - }, - }; - const contractAddress = await instantiate( - codeId, - "Teritori Launchpad", - initMsg, - ); - - console.log("CodeId:", codeId, "- Contract Address:", contractAddress); -}; - -main(); diff --git a/rust/cw-contracts/nft-tr721/deploy.ts b/rust/cw-contracts/nft-tr721/deploy.ts deleted file mode 100644 index 71fe342523..0000000000 --- a/rust/cw-contracts/nft-tr721/deploy.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { deploy } from "../../utils/scripts"; -const WASM_FILE = "nft_tr721.wasm"; - -const main = async () => { - const codeId = await deploy(WASM_FILE); - console.log("CodeId:", codeId); -}; - -main(); diff --git a/rust/utils/mnemonic.ts b/rust/utils/mnemonic.ts deleted file mode 100644 index 4dd7881ee8..0000000000 --- a/rust/utils/mnemonic.ts +++ /dev/null @@ -1 +0,0 @@ -export const MNEMONIC = "MNEMONIC"; diff --git a/rust/utils/scripts.ts b/rust/utils/scripts.ts deleted file mode 100644 index c6d63172f1..0000000000 --- a/rust/utils/scripts.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; -import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; -import { GasPrice } from "@cosmjs/stargate"; -import * as fs from "fs"; -import path from "path"; - -import { MNEMONIC } from "./mnemonic"; - -const GAS_PRICE = GasPrice.fromString("0.025utori"); - -const NODE_RPC = "https://rpc.testnet.teritori.com:443"; -// const CHAIN_ID = "teritori-test-7"; - -const getClientInfos = async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(MNEMONIC, { - prefix: "tori", - }); - - const client = await SigningCosmWasmClient.connectWithSigner( - NODE_RPC, - wallet, - { gasPrice: GAS_PRICE }, - ); - - const sender = await wallet.getAccounts().then((res) => res[0]?.address); - console.log("Sender:", sender); - - return { wallet, client, sender }; -}; - -const getWasmFile = (wasmFile: string) => { - const filePath = path.join(__dirname, "../..", "artifacts", wasmFile); - console.log("filePath:", filePath); - return fs.readFileSync(filePath); -}; - -export const deploy = async (wasmFile: string) => { - const { client, sender } = await getClientInfos(); - const wasmCode = new Uint8Array(getWasmFile(wasmFile)); - const uploadRes = await client.upload(sender, wasmCode, "auto"); - - return uploadRes.codeId; -}; - -export const instantiate = async (codeId: number, label: string, msg: any) => { - const { client, sender } = await getClientInfos(); - - const instantiateRes = await client.instantiate( - sender, - codeId, - msg, - `${label} - ${codeId}`, - "auto", - ); - return instantiateRes.contractAddress; -}; From 902628204bedf9854089cca05f5dd033c5d8bb7a Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 27 Oct 2024 19:56:57 -0400 Subject: [PATCH 06/33] chore: add script deploNftLaunchpad --- packages/networks/features.ts | 16 ++ packages/networks/teritori-testnet/index.ts | 18 +- .../scripts/network-setup/deployDA0DA0.ts | 36 +--- packages/scripts/network-setup/deployLib.ts | 63 +++++- .../network-setup/deployNftLaunchpad.ts | 194 +++++++++++++++--- .../scripts/network-setup/deployNftTr721.ts | 10 - rust/cw-contracts/nft-launchpad/config.json | 2 +- rust/cw-contracts/nft-launchpad/deploy.ts | 25 +++ .../nft-launchpad/src/contract.rs | 12 +- 9 files changed, 294 insertions(+), 82 deletions(-) delete mode 100644 packages/scripts/network-setup/deployNftTr721.ts create mode 100644 rust/cw-contracts/nft-launchpad/deploy.ts diff --git a/packages/networks/features.ts b/packages/networks/features.ts index 9f05394953..eae965f8aa 100644 --- a/packages/networks/features.ts +++ b/packages/networks/features.ts @@ -55,6 +55,20 @@ type CosmWasmSocialFeed = { feedContractAddress: string; }; +// CosmWasm Launchpad + +const zodCosmWasmLaunchpad = z.object({ + type: z.literal(NetworkFeature.NFTLaunchpad), + launchpadContractAddress: z.string(), + defaultMintDenom: z.string(), + launchpadEndpoint: z.string(), + codeId: z.number(), + nftTr721CodeId: z.number(), + // allowedMintDenoms: z.array(z.string()), // for future +}); + +export type CosmWasmLaunchpad = z.infer; + // Gno Project Manager const zodGnoProjectManager = z.object({ @@ -80,6 +94,7 @@ type LaunchpadERC20 = z.infer; export const allFeatureObjects = [ zodCosmWasmPremiumFeed, zodCosmWasmNFTsBurner, + zodCosmWasmLaunchpad, zodGnoProjectManager, zodLaunchpadERC20, zodNFTMarketplace, @@ -88,6 +103,7 @@ export const allFeatureObjects = [ export type NetworkFeatureObject = | CosmWasmPremiumFeed | CosmWasmSocialFeed + | CosmWasmLaunchpad | CosmWasmNFTsBurner | GnoProjectManager | LaunchpadERC20 diff --git a/packages/networks/teritori-testnet/index.ts b/packages/networks/teritori-testnet/index.ts index e0ed91553c..58ff60f849 100644 --- a/packages/networks/teritori-testnet/index.ts +++ b/packages/networks/teritori-testnet/index.ts @@ -1,5 +1,6 @@ import { teritoriTestnetCurrencies } from "./currencies"; import { + CosmWasmLaunchpad, CosmWasmNFTsBurner, CosmWasmPremiumFeed, NetworkFeature, @@ -29,6 +30,16 @@ const nftMarketplace: NFTMarketplace = { "tori1x72plnprsjnmszylmdm3cnvu5h6u55fyf0pe02lye9p6q2ws05ps33qmft", }; +const cosmwasmLaunchpadFeature: CosmWasmLaunchpad = { + type: NetworkFeature.NFTLaunchpad, + launchpadContractAddress: + "tori1dqy2areatyu6372d67a25t494x63n046qd83dyzrwl73yrnuky4qg8fqsh", + launchpadEndpoint: "https://dapp-backend.testnet.teritori.com", + nftTr721CodeId: 60, + codeId: 61, + defaultMintDenom: "utori", +}; + const riotContractAddressGen0 = "tori1r8raaqul4j05qtn0t05603mgquxfl8e9p7kcf7smwzcv2hc5rrlq0vket0"; const riotContractAddressGen1 = ""; @@ -53,7 +64,12 @@ export const teritoriTestnetNetwork: CosmosNetworkInfo = { NetworkFeature.NFTMarketplaceLeaderboard, NetworkFeature.CosmWasmNFTsBurner, ], - featureObjects: [premiumFeedFeature, nftsBurnerFeature, nftMarketplace], + featureObjects: [ + premiumFeedFeature, + nftsBurnerFeature, + nftMarketplace, + cosmwasmLaunchpadFeature, + ], currencies: teritoriTestnetCurrencies, txExplorer: "https://explorer.teritori.com/teritori-testnet/tx/$hash", accountExplorer: diff --git a/packages/scripts/network-setup/deployDA0DA0.ts b/packages/scripts/network-setup/deployDA0DA0.ts index db16ff80a7..074171b1d3 100644 --- a/packages/scripts/network-setup/deployDA0DA0.ts +++ b/packages/scripts/network-setup/deployDA0DA0.ts @@ -1,13 +1,12 @@ -import { OfflineSigner } from "@cosmjs/proto-signing"; import axios from "axios"; -import { bech32 } from "bech32"; import { program } from "commander"; import fs from "fs"; -import { cloneDeep } from "lodash"; import os from "os"; import path from "path"; import { + DeployOpts, + initDeploy, instantiateContract, instantiateNameService, registerTNSHandle, @@ -15,8 +14,7 @@ import { testTeritoriEcosystem, } from "./deployLib"; -import { CosmosNetworkInfo, getCosmosNetwork } from "@/networks"; -import { execPromise } from "@/scripts/lib"; +import { CosmosNetworkInfo } from "@/networks"; /** * Firstly, store name-service WASM binaries and instantiate name-service contract, if not present on the network @@ -25,11 +23,8 @@ import { execPromise } from "@/scripts/lib"; * And deploy cw_admin_factory contract */ export const deployDA0DA0 = async ( - opts: { - home: string; - binaryPath: string; + opts: DeployOpts & { keyringBackend?: string; - signer: OfflineSigner | undefined; }, networkId: string, wallet: string, @@ -46,24 +41,7 @@ export const deployDA0DA0 = async ( const daoPreProposeSingleWWasmFileName = "dao_pre_propose_single.wasm"; const daoProposalSingleWasmFileName = "dao_proposal_single.wasm"; - const network = cloneDeep(getCosmosNetwork(networkId)); - if (!network) { - console.error(`Cosmos network ${networkId} not found`); - process.exit(1); - } - console.log(`Deploying to ${network.displayName}`); - - let walletAddr = ( - await execPromise( - `${opts.binaryPath} keys show --keyring-backend ${opts.keyringBackend || "test"} -a ${wallet} --home ${opts.home}`, - { encoding: "utf-8" }, - ) - ).stdout.trim(); - if (walletAddr.startsWith("Successfully migrated")) { - walletAddr = walletAddr.substring(walletAddr.indexOf("\n")).trim(); - } - bech32.decode(walletAddr); - console.log("Wallet address:", walletAddr); + const { network, walletAddr } = await initDeploy({ opts, networkId, wallet }); if (!network.nameServiceContractAddress) { // ========= name-service @@ -156,7 +134,7 @@ export const deployDA0DA0 = async ( }; const instantiateCwAdminFactory = async ( - opts: { home: string; binaryPath: string; keyringBackend?: string }, + opts: DeployOpts, wallet: string, adminAddr: string, network: CosmosNetworkInfo, @@ -177,7 +155,7 @@ const instantiateCwAdminFactory = async ( }; const deployRemoteWASM = async ( - opts: { home: string; binaryPath: string; signer: OfflineSigner | undefined }, + opts: DeployOpts, wallet: string, network: CosmosNetworkInfo, url: string, diff --git a/packages/scripts/network-setup/deployLib.ts b/packages/scripts/network-setup/deployLib.ts index 113ca79a01..aa62faa1fb 100644 --- a/packages/scripts/network-setup/deployLib.ts +++ b/packages/scripts/network-setup/deployLib.ts @@ -6,6 +6,7 @@ import { bech32 } from "bech32"; import _, { cloneDeep } from "lodash"; import path from "path"; +import { instantiateNftLaunchpad } from "./deployNftLaunchpad"; import { InstantiateMsg as MarketplaceVaultInstantiateMsg } from "../../contracts-clients/nft-marketplace/NftMarketplace.types"; import { ExecuteMsg as NameServiceExecuteMsg, @@ -24,15 +25,28 @@ import { cosmosNetworkGasPrice, CosmosNetworkInfo, getCosmosNetwork, + getNetworkFeature, mustGetNonSigningCosmWasmClient, + NetworkFeature, } from "@/networks"; import { zodTryParseJSON } from "@/utils/sanitize"; -export const deployTeritoriEcosystem = async ( - opts: { home: string; binaryPath: string; signer: OfflineSigner | undefined }, - networkId: string, - wallet: string, -) => { +export interface DeployOpts { + home: string; + binaryPath: string; + signer?: OfflineSigner; + keyringBackend?: string; +} + +export const initDeploy = async ({ + opts, + networkId, + wallet, +}: { + opts: DeployOpts; + networkId: string; + wallet: string; +}) => { const network = cloneDeep(getCosmosNetwork(networkId)); if (!network) { console.error(`Cosmos network ${networkId} not found`); @@ -53,6 +67,17 @@ export const deployTeritoriEcosystem = async ( console.log("Wallet address:", walletAddr); + return { network, walletAddr }; +}; + +export const deployTeritoriEcosystem = async ( + opts: DeployOpts, + networkId: string, + wallet: string, +) => { + const { network, walletAddr } = await initDeploy({ opts, networkId, wallet }); + console.log("Wallet address:", walletAddr); + console.log("Storing name service"); const nameServiceWasmFilePath = path.join(__dirname, "name-service.wasm"); network.nameServiceCodeId = await storeWASM( @@ -110,6 +135,24 @@ export const deployTeritoriEcosystem = async ( network, ); + console.log("Instantiating NFT Launchpad", network.nameServiceCodeId); + const cosmwasmLaunchpadFeature = cloneDeep( + getNetworkFeature(networkId, NetworkFeature.NFTLaunchpad), + ); + if (!cosmwasmLaunchpadFeature) { + console.error(`Cosmwasm Launchpad feature not found on ${networkId}`); + } else { + cosmwasmLaunchpadFeature.launchpadContractAddress = + await instantiateNftLaunchpad( + opts, + wallet, + walletAddr, + "TODO DAO address", + network, + cosmwasmLaunchpadFeature, + ); + } + if (opts.signer) { await registerTNSHandle(network, opts.signer); await testTeritoriEcosystem(network); @@ -188,7 +231,7 @@ export const testTeritoriEcosystem = async (network: CosmosNetworkInfo) => { }; const instantiateMarketplaceVault = ( - opts: { home: string; binaryPath: string }, + opts: DeployOpts, wallet: string, adminAddr: string, network: CosmosNetworkInfo, @@ -210,7 +253,7 @@ const instantiateMarketplaceVault = ( }; const instantiateSocialFeed = async ( - opts: { home: string; binaryPath: string }, + opts: DeployOpts, wallet: string, adminAddr: string, network: CosmosNetworkInfo, @@ -232,7 +275,7 @@ const instantiateSocialFeed = async ( }; export const instantiateNameService = async ( - opts: { home: string; binaryPath: string }, + opts: DeployOpts, wallet: string, adminAddr: string, network: CosmosNetworkInfo, @@ -290,7 +333,7 @@ export const instantiateNameService = async ( }; export const instantiateContract = async ( - opts: { home: string; binaryPath: string; keyringBackend?: string }, + opts: DeployOpts, wallet: string, network: CosmosNetworkInfo, codeId: number, @@ -327,7 +370,7 @@ export const instantiateContract = async ( }; export const storeWASM = async ( - opts: { home: string; binaryPath: string; keyringBackend?: string }, + opts: DeployOpts, wallet: string, network: CosmosNetworkInfo, wasmFilePath: string, diff --git a/packages/scripts/network-setup/deployNftLaunchpad.ts b/packages/scripts/network-setup/deployNftLaunchpad.ts index d8f326b4f1..25c71fdfa4 100644 --- a/packages/scripts/network-setup/deployNftLaunchpad.ts +++ b/packages/scripts/network-setup/deployNftLaunchpad.ts @@ -1,25 +1,169 @@ -const nftLaunchpadFileName = "nft_tr721.wasm"; -const deployer = "tori1zsgm6hvx4a3t08vsanwdcvvnv2xca9faavzccm"; - -// TODO - -// const main = async () => { -// const codeId = await deployContract(WASM_FILE); -// const initMsg = { -// config: { -// name: "Teritori launchpad", -// supported_networks: [], -// nft_code_id: 1, -// deployer: DEPLOYER, -// }, -// }; -// const contractAddress = await instantiateContract( -// codeId, -// "Teritori Launchpad", -// initMsg, -// ); - -// console.log("CodeId:", codeId, "- Contract Address:", contractAddress); -// }; - -// main(); +import { program } from "commander"; +import { cloneDeep } from "lodash"; +import os from "os"; +import path from "path"; + +import { InstantiateMsg as NftLaunchpadInstantiateMsg } from "@/contracts-clients/nft-launchpad"; +import { + allNetworks, + CosmosNetworkInfo, + getNetworkFeature, + NetworkFeature, +} from "@/networks"; +import { CosmWasmLaunchpad } from "@/networks/features"; +import { + DeployOpts, + initDeploy, + instantiateContract, + storeWASM, +} from "@/scripts/network-setup/deployLib"; + +export const deployNftLaunchpad = async ({ + opts, + networkId, + wallet: deployerWallet, + launchpadAdmin, +}: { + networkId: string; + wallet: string; + launchpadAdmin: string; + opts: DeployOpts; +}) => { + const { network, walletAddr: deployerAddr } = await initDeploy({ + opts, + networkId, + wallet: deployerWallet, + }); + + const cosmwasmLaunchpadFeature = cloneDeep( + getNetworkFeature(networkId, NetworkFeature.NFTLaunchpad), + ); + if (!cosmwasmLaunchpadFeature) { + console.error(`Cosmwasm Launchpad feature not found on ${networkId}`); + process.exit(1); + } + console.log("Storing nft launchpad"); + const nftLaunchpadWasmFilePath = path.join(__dirname, "nft_launchpad.wasm"); + cosmwasmLaunchpadFeature.codeId = await storeWASM( + opts, + deployerWallet, + network, + nftLaunchpadWasmFilePath, + ); + + console.log("Instantiating nft launchpad", cosmwasmLaunchpadFeature.codeId); + cosmwasmLaunchpadFeature.launchpadContractAddress = + await instantiateNftLaunchpad( + opts, + deployerWallet, + deployerAddr, + launchpadAdmin, + network, + cosmwasmLaunchpadFeature, + ); + network.featureObjects = network.featureObjects?.map((featureObject) => { + if (featureObject.type === NetworkFeature.NFTLaunchpad) { + return cosmwasmLaunchpadFeature; + } else return featureObject; + }); +}; + +export const instantiateNftLaunchpad = async ( + opts: DeployOpts, + deployerWallet: string, + deployerAddr: string, + launchpadAdmin: string, + network: CosmosNetworkInfo, + featureObject: CosmWasmLaunchpad, +) => { + const codeId = featureObject.codeId; + if (!codeId) { + console.error("Nft Launchpad code ID not found"); + process.exit(1); + } + let nftCodeId = featureObject.nftTr721CodeId; + if (!nftCodeId) { + nftCodeId = await deployNftTr721({ + opts, + networkId: network.id, + deployerWallet, + }); + } + const instantiateMsg: NftLaunchpadInstantiateMsg = { + config: { + name: "Teritori NFT Launchpad", + supported_networks: allNetworks + .filter((n) => n.features.includes(NetworkFeature.NFTLaunchpad)) + .map((n) => n.id), + owner: deployerAddr, + launchpadAdmin, + nft_code_id: nftCodeId, + }, + }; + return await instantiateContract( + opts, + deployerWallet, + network, + codeId, + deployerAddr, + "Teritori NFT Launchpad", + instantiateMsg, + ); +}; + +const deployNftTr721 = async ({ + opts, + networkId, + deployerWallet, +}: { + networkId: string; + deployerWallet: string; + opts: DeployOpts; +}) => { + const { network } = await initDeploy({ + opts, + networkId, + wallet: deployerWallet, + }); + const cosmwasmLaunchpadFeature = cloneDeep( + getNetworkFeature(networkId, NetworkFeature.NFTLaunchpad), + ); + if (!cosmwasmLaunchpadFeature) { + console.error(`Cosmwasm Launchpad feature not found on ${networkId}`); + process.exit(1); + } + const nftTr721WasmFilePath = path.join(__dirname, "nft_tr721.wasm"); + cosmwasmLaunchpadFeature.nftTr721CodeId = await storeWASM( + opts, + deployerWallet, + network, + nftTr721WasmFilePath, + ); + return cosmwasmLaunchpadFeature.nftTr721CodeId; +}; + +const main = async () => { + program.argument("", "Network id to deploy to"); + program.argument("", "Wallet to deploy from"); + program.argument( + "", + "The DAO wallet adress to make admin things", + ); + program.option("--keyring-backend [keyring-backend]", "Keyring backend"); + program.parse(); + const [networkId, wallet, launchpadAdmin] = program.args; + const { keyringBackend } = program.opts(); + + await deployNftLaunchpad({ + opts: { + home: path.join(os.homedir(), ".teritorid"), + binaryPath: "teritorid", + keyringBackend, + signer: undefined, + }, + networkId, + wallet, + launchpadAdmin, + }); +}; +main(); diff --git a/packages/scripts/network-setup/deployNftTr721.ts b/packages/scripts/network-setup/deployNftTr721.ts deleted file mode 100644 index bd8fe5bfda..0000000000 --- a/packages/scripts/network-setup/deployNftTr721.ts +++ /dev/null @@ -1,10 +0,0 @@ -const nftTr721FileName = "nft_tr721.wasm"; - -// TODO - -// const main = async () => { -// const codeId = await deployContract(WASM_FILE); -// console.log("CodeId:", codeId); -// }; - -// main(); diff --git a/rust/cw-contracts/nft-launchpad/config.json b/rust/cw-contracts/nft-launchpad/config.json index 9d3e5e2c8a..530f1897d6 100644 --- a/rust/cw-contracts/nft-launchpad/config.json +++ b/rust/cw-contracts/nft-launchpad/config.json @@ -3,7 +3,7 @@ "name": "NFT Launchpad", "supported_networks": ["teritori-testnet"], "owner": "tori1llmym9upcpwnz7qte856ghlp5437ezz2gg7z0q", - "deployer": "tori1kjvyqf4mttwrhfuq5gfj9xgxx9jdt92xnxzf770x853567ymx8cscrnw05", + "launchpad_admin": "tori1kjvyqf4mttwrhfuq5gfj9xgxx9jdt92xnxzf770x853567ymx8cscrnw05", "nft_code_id": 60 } } diff --git a/rust/cw-contracts/nft-launchpad/deploy.ts b/rust/cw-contracts/nft-launchpad/deploy.ts new file mode 100644 index 0000000000..319e66d202 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/deploy.ts @@ -0,0 +1,25 @@ +import { deploy, instantiate } from "../../utils/scripts"; + +const WASM_FILE = "nft_launchpad-aarch64.wasm"; +const LAUNCHPAD_ADMIN = "tori1zsgm6hvx4a3t08vsanwdcvvnv2xca9faavzccm"; + +const main = async () => { + const codeId = await deploy(WASM_FILE); + const initMsg = { + config: { + name: "Teritori launchpad", + supported_networks: [], + nft_code_id: 1, + launchpad_admin: LAUNCHPAD_ADMIN, + }, + }; + const contractAddress = await instantiate( + codeId, + "Teritori Launchpad", + initMsg, + ); + + console.log("CodeId:", codeId, "- Contract Address:", contractAddress); +}; + +main(); diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index 533a32ef1d..cc7327323f 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -66,7 +66,7 @@ impl NftLaunchpad { return Err(ContractError::Unauthorized); } // Save new config - config.deployer = changes.deployer; + config.launchpad_admin = changes.launchpad_admin; config.nft_code_id = changes.nft_code_id; config.supported_networks = changes.supported_networks; if let Some(owner) = changes.owner { @@ -168,11 +168,11 @@ impl NftLaunchpad { let sender = ctx.info.sender.to_string(); let config = self.config.load(ctx.deps.storage)?; - // Only allow deployer to deploy - if config.deployer.is_none() { + // Only allow launchpad_admin to deploy + if config.launchpad_admin.is_none() { return Err(ContractError::DeployerMissing); } - if sender != config.deployer.unwrap() { + if sender != config.launchpad_admin.unwrap() { return Err(ContractError::WrongDeployer); } @@ -282,7 +282,7 @@ pub struct Config { pub name: String, pub nft_code_id: Option, pub supported_networks: Vec, - pub deployer: Option, + pub launchpad_admin: Option, pub owner: Addr, } @@ -291,7 +291,7 @@ pub struct ConfigChanges { pub name: String, pub nft_code_id: Option, pub supported_networks: Vec, - pub deployer: Option, + pub launchpad_admin: Option, pub owner: Option, } From bbdc11b4abf5c1c80e77382fe32dbef49f737986 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 27 Oct 2024 19:57:21 -0400 Subject: [PATCH 07/33] chore: remove comment --- packages/networks/features.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/networks/features.ts b/packages/networks/features.ts index eae965f8aa..85de0155da 100644 --- a/packages/networks/features.ts +++ b/packages/networks/features.ts @@ -64,7 +64,6 @@ const zodCosmWasmLaunchpad = z.object({ launchpadEndpoint: z.string(), codeId: z.number(), nftTr721CodeId: z.number(), - // allowedMintDenoms: z.array(z.string()), // for future }); export type CosmWasmLaunchpad = z.infer; From 4f11bd641d50860f589c7b12303f56a60932e933 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 27 Oct 2024 20:07:43 -0400 Subject: [PATCH 08/33] chore: remove unued row from .gitignore --- .gitignore | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 1d5fca3586..4a858ff704 100644 --- a/.gitignore +++ b/.gitignore @@ -107,7 +107,4 @@ artifacts rust/cw-contracts/*/target # cypress -cypress/screenshots - -# secret files -rust/utils/mnemonic.ts \ No newline at end of file +cypress/screenshots \ No newline at end of file From 8e25b213481bf78bf0a6159898173f1cb3d6d4df Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 27 Oct 2024 20:25:51 -0400 Subject: [PATCH 09/33] chore: remove unused file --- rust/cw-contracts/nft-launchpad/deploy.ts | 25 ----------------------- 1 file changed, 25 deletions(-) delete mode 100644 rust/cw-contracts/nft-launchpad/deploy.ts diff --git a/rust/cw-contracts/nft-launchpad/deploy.ts b/rust/cw-contracts/nft-launchpad/deploy.ts deleted file mode 100644 index 319e66d202..0000000000 --- a/rust/cw-contracts/nft-launchpad/deploy.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { deploy, instantiate } from "../../utils/scripts"; - -const WASM_FILE = "nft_launchpad-aarch64.wasm"; -const LAUNCHPAD_ADMIN = "tori1zsgm6hvx4a3t08vsanwdcvvnv2xca9faavzccm"; - -const main = async () => { - const codeId = await deploy(WASM_FILE); - const initMsg = { - config: { - name: "Teritori launchpad", - supported_networks: [], - nft_code_id: 1, - launchpad_admin: LAUNCHPAD_ADMIN, - }, - }; - const contractAddress = await instantiate( - codeId, - "Teritori Launchpad", - initMsg, - ); - - console.log("CodeId:", codeId, "- Contract Address:", contractAddress); -}; - -main(); From 26317e4e7aaeb8589abe25db26a8afd2ba47cb3e Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Mon, 28 Oct 2024 02:06:04 +0100 Subject: [PATCH 10/33] make generate --- go/pkg/networks/features.gen.go | 1 + networks.json | 8 + .../nft-launchpad/NftLaunchpad.client.ts | 136 ++++ .../nft-launchpad/NftLaunchpad.types.ts | 110 +++ .../contracts-clients/nft-launchpad/index.ts | 2 + .../nft-tr721/NftTr721.client.ts | 669 ++++++++++++++++++ .../nft-tr721/NftTr721.types.ts | 456 ++++++++++++ packages/contracts-clients/nft-tr721/index.ts | 2 + .../nft-launchpad/schema/nft-launchpad.json | 6 +- .../nft-launchpad/schema/raw/execute.json | 2 +- .../nft-launchpad/schema/raw/instantiate.json | 2 +- .../schema/raw/response_to_get_config.json | 2 +- 12 files changed, 1390 insertions(+), 6 deletions(-) create mode 100644 packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts create mode 100644 packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts create mode 100644 packages/contracts-clients/nft-launchpad/index.ts create mode 100644 packages/contracts-clients/nft-tr721/NftTr721.client.ts create mode 100644 packages/contracts-clients/nft-tr721/NftTr721.types.ts create mode 100644 packages/contracts-clients/nft-tr721/index.ts diff --git a/go/pkg/networks/features.gen.go b/go/pkg/networks/features.gen.go index ff8362cc8f..af776c4826 100644 --- a/go/pkg/networks/features.gen.go +++ b/go/pkg/networks/features.gen.go @@ -2,6 +2,7 @@ package networks import ( "encoding/json" + "github.com/pkg/errors" ) diff --git a/networks.json b/networks.json index 13cc298df9..91e9458ce8 100644 --- a/networks.json +++ b/networks.json @@ -11679,6 +11679,14 @@ "type": "NFTMarketplace", "cwAddressListCodeId": 63, "cwAddressListContractAddress": "tori1x72plnprsjnmszylmdm3cnvu5h6u55fyf0pe02lye9p6q2ws05ps33qmft" + }, + { + "type": "NFTLaunchpad", + "launchpadContractAddress": "tori1dqy2areatyu6372d67a25t494x63n046qd83dyzrwl73yrnuky4qg8fqsh", + "launchpadEndpoint": "https://dapp-backend.testnet.teritori.com", + "nftTr721CodeId": 60, + "codeId": 61, + "defaultMintDenom": "utori" } ], "currencies": [ diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts new file mode 100644 index 0000000000..73ab8e42ff --- /dev/null +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts @@ -0,0 +1,136 @@ +/** +* 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 { Addr, InstantiateMsg, Config, ExecuteMsg, Uint128, ConfigChanges, Collection, MintPeriod, Coin, WhitelistInfo, QueryMsg } from "./NftLaunchpad.types"; +export interface NftLaunchpadReadOnlyInterface { + contractAddress: string; + getCollectionById: ({ + collectionId + }: { + collectionId: string; + }) => Promise; + getConfig: () => Promise; +} +export class NftLaunchpadQueryClient implements NftLaunchpadReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.getCollectionById = this.getCollectionById.bind(this); + this.getConfig = this.getConfig.bind(this); + } + + getCollectionById = async ({ + collectionId + }: { + collectionId: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_collection_by_id: { + collection_id: collectionId + } + }); + }; + getConfig = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + get_config: {} + }); + }; +} +export interface NftLaunchpadInterface extends NftLaunchpadReadOnlyInterface { + contractAddress: string; + sender: string; + updateConfig: ({ + changes + }: { + changes: ConfigChanges; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + submitCollection: ({ + collection + }: { + collection: Collection; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMerkleRoot: ({ + collectionId, + merkleRoot + }: { + collectionId: string; + merkleRoot: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + deployCollection: ({ + collectionId + }: { + collectionId: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class NftLaunchpadClient extends NftLaunchpadQueryClient implements NftLaunchpadInterface { + 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.updateConfig = this.updateConfig.bind(this); + this.submitCollection = this.submitCollection.bind(this); + this.updateMerkleRoot = this.updateMerkleRoot.bind(this); + this.deployCollection = this.deployCollection.bind(this); + } + + updateConfig = async ({ + changes + }: { + changes: ConfigChanges; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_config: { + changes + } + }, fee, memo, _funds); + }; + submitCollection = async ({ + collection + }: { + collection: Collection; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + submit_collection: { + collection + } + }, fee, memo, _funds); + }; + updateMerkleRoot = async ({ + collectionId, + merkleRoot + }: { + collectionId: string; + merkleRoot: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_merkle_root: { + collection_id: collectionId, + merkle_root: merkleRoot + } + }, fee, memo, _funds); + }; + deployCollection = async ({ + collectionId + }: { + collectionId: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + deploy_collection: { + collection_id: collectionId + } + }, fee, memo, _funds); + }; +} \ No newline at end of file diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts new file mode 100644 index 0000000000..56ccc3f03a --- /dev/null +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts @@ -0,0 +1,110 @@ +/** +* 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 Addr = string; +export interface InstantiateMsg { + config: Config; + [k: string]: unknown; +} +export interface Config { + launchpad_admin?: string | null; + name: string; + nft_code_id?: number | null; + owner: Addr; + supported_networks: string[]; +} +export type ExecuteMsg = { + update_config: { + changes: ConfigChanges; + [k: string]: unknown; + }; +} | { + submit_collection: { + collection: Collection; + [k: string]: unknown; + }; +} | { + update_merkle_root: { + collection_id: string; + merkle_root: string; + [k: string]: unknown; + }; +} | { + deploy_collection: { + collection_id: string; + [k: string]: unknown; + }; +}; +export type Uint128 = string; +export interface ConfigChanges { + launchpad_admin?: string | null; + name: string; + nft_code_id?: number | null; + owner?: string | null; + supported_networks: string[]; +} +export interface Collection { + artwork_desc: string; + base_token_uri?: string | null; + contact_email: string; + cover_img_uri: string; + dao_whitelist_count: number; + deployed_address?: string | null; + desc: string; + escrow_mint_proceeds_period: number; + expected_mint_date: number; + expected_public_mint_price: number; + expected_supply: number; + investment_desc: string; + investment_link: string; + is_applied_previously: boolean; + is_dox: boolean; + is_project_derivative: boolean; + is_ready_for_mint: boolean; + metadatas_merkle_root?: string | null; + mint_periods: MintPeriod[]; + name: string; + owner?: string | null; + partners: string; + project_desc: string; + project_type: string; + reveal_time?: number | null; + royalty_address?: Addr | null; + royalty_percentage?: number | null; + symbol: string; + target_network: string; + team_desc: string; + tokens_count: number; + website_link?: string | null; +} +export interface MintPeriod { + end_time?: number | null; + limit_per_address?: number | null; + max_tokens?: number | null; + price?: Coin | null; + start_time: number; + whitelist_info?: WhitelistInfo | null; +} +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export interface WhitelistInfo { + addresses_count: number; + addresses_ipfs: string; + addresses_merkle_root: string; +} +export type QueryMsg = { + get_collection_by_id: { + collection_id: string; + [k: string]: unknown; + }; +} | { + get_config: { + [k: string]: unknown; + }; +}; \ No newline at end of file diff --git a/packages/contracts-clients/nft-launchpad/index.ts b/packages/contracts-clients/nft-launchpad/index.ts new file mode 100644 index 0000000000..320df6bfba --- /dev/null +++ b/packages/contracts-clients/nft-launchpad/index.ts @@ -0,0 +1,2 @@ +export * from "./NftLaunchpad.client"; +export * from "./NftLaunchpad.types"; \ No newline at end of file diff --git a/packages/contracts-clients/nft-tr721/NftTr721.client.ts b/packages/contracts-clients/nft-tr721/NftTr721.client.ts new file mode 100644 index 0000000000..9518c36d39 --- /dev/null +++ b/packages/contracts-clients/nft-tr721/NftTr721.client.ts @@ -0,0 +1,669 @@ +/** +* 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 { Addr, Uint128, InstantiateMsg, MintInfo, MintPeriod, Coin, WhitelistInfo, ExecuteMsg, Binary, Expiration, Timestamp, Uint64, Metadata, Trait, WhitelistProof, QueryMsg, AllNftInfoResponseForMetadata, OwnerOfResponse, Approval, NftInfoResponseForMetadata, OperatorsResponse, TokensResponse, ApprovalResponse, ApprovalsResponse, CheckRoyaltiesResponse, ContractInfoResponse, ContractVersion, CosmosMsgForEmpty, BankMsg, StakingMsg, DistributionMsg, WasmMsg, ReplyOn, ResponseForEmpty, Attribute, Event, SubMsgForEmpty, Empty, String, ArrayOfMintPeriod, Uint32, MinterResponse, NumTokensResponse, OperatorResponse, OwnershipForAddr, RoyaltiesInfoResponse } from "./NftTr721.types"; +export interface NftTr721ReadOnlyInterface { + contractAddress: string; + totalMinted: () => Promise; + mintedCountByPeriod: ({ + periodId + }: { + periodId: number; + }) => Promise; + mintedCountByUser: ({ + periodId, + user + }: { + periodId: number; + user: string; + }) => Promise; + totalMintedCountByUser: ({ + user + }: { + user: string; + }) => Promise; + mintInfo: () => Promise; + mintPeriods: () => Promise; + minter: () => Promise; + contractInfo: () => Promise; + nftInfo: ({ + tokenId + }: { + tokenId: string; + }) => Promise; + ownerOf: ({ + includeExpired, + tokenId + }: { + includeExpired?: boolean; + tokenId: string; + }) => Promise; + allNftInfo: ({ + includeExpired, + tokenId + }: { + includeExpired?: boolean; + tokenId: string; + }) => Promise; + operator: ({ + includeExpired, + operator, + owner + }: { + includeExpired?: boolean; + operator: string; + owner: string; + }) => Promise; + allOperators: ({ + includeExpired, + limit, + owner, + startAfter + }: { + includeExpired?: boolean; + limit?: number; + owner: string; + startAfter?: string; + }) => Promise; + numTokens: () => Promise; + tokens: ({ + limit, + owner, + startAfter + }: { + limit?: number; + owner: string; + startAfter?: string; + }) => Promise; + allTokens: ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }) => Promise; + approval: ({ + includeExpired, + spender, + tokenId + }: { + includeExpired?: boolean; + spender: string; + tokenId: string; + }) => Promise; + approvals: ({ + includeExpired, + tokenId + }: { + includeExpired?: boolean; + tokenId: string; + }) => Promise; + ownership: () => Promise; + extension: () => Promise; + contractVersion: () => Promise; + merkleRoot: () => Promise; + royaltyInfo: ({ + salePrice, + tokenId + }: { + salePrice: Uint128; + tokenId: string; + }) => Promise; + checkRoyalties: () => Promise; +} +export class NftTr721QueryClient implements NftTr721ReadOnlyInterface { + client: CosmWasmClient; + contractAddress: string; + + constructor(client: CosmWasmClient, contractAddress: string) { + this.client = client; + this.contractAddress = contractAddress; + this.totalMinted = this.totalMinted.bind(this); + this.mintedCountByPeriod = this.mintedCountByPeriod.bind(this); + this.mintedCountByUser = this.mintedCountByUser.bind(this); + this.totalMintedCountByUser = this.totalMintedCountByUser.bind(this); + this.mintInfo = this.mintInfo.bind(this); + this.mintPeriods = this.mintPeriods.bind(this); + this.minter = this.minter.bind(this); + this.contractInfo = this.contractInfo.bind(this); + this.nftInfo = this.nftInfo.bind(this); + this.ownerOf = this.ownerOf.bind(this); + this.allNftInfo = this.allNftInfo.bind(this); + this.operator = this.operator.bind(this); + this.allOperators = this.allOperators.bind(this); + this.numTokens = this.numTokens.bind(this); + this.tokens = this.tokens.bind(this); + this.allTokens = this.allTokens.bind(this); + this.approval = this.approval.bind(this); + this.approvals = this.approvals.bind(this); + this.ownership = this.ownership.bind(this); + this.extension = this.extension.bind(this); + this.contractVersion = this.contractVersion.bind(this); + this.merkleRoot = this.merkleRoot.bind(this); + this.royaltyInfo = this.royaltyInfo.bind(this); + this.checkRoyalties = this.checkRoyalties.bind(this); + } + + totalMinted = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + total_minted: {} + }); + }; + mintedCountByPeriod = async ({ + periodId + }: { + periodId: number; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + minted_count_by_period: { + period_id: periodId + } + }); + }; + mintedCountByUser = async ({ + periodId, + user + }: { + periodId: number; + user: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + minted_count_by_user: { + period_id: periodId, + user + } + }); + }; + totalMintedCountByUser = async ({ + user + }: { + user: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + total_minted_count_by_user: { + user + } + }); + }; + mintInfo = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + mint_info: {} + }); + }; + mintPeriods = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + mint_periods: {} + }); + }; + minter = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + minter: {} + }); + }; + contractInfo = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + contract_info: {} + }); + }; + nftInfo = async ({ + tokenId + }: { + tokenId: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + nft_info: { + token_id: tokenId + } + }); + }; + ownerOf = async ({ + includeExpired, + tokenId + }: { + includeExpired?: boolean; + tokenId: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + owner_of: { + include_expired: includeExpired, + token_id: tokenId + } + }); + }; + allNftInfo = async ({ + includeExpired, + tokenId + }: { + includeExpired?: boolean; + tokenId: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + all_nft_info: { + include_expired: includeExpired, + token_id: tokenId + } + }); + }; + operator = async ({ + includeExpired, + operator, + owner + }: { + includeExpired?: boolean; + operator: string; + owner: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + operator: { + include_expired: includeExpired, + operator, + owner + } + }); + }; + allOperators = async ({ + includeExpired, + limit, + owner, + startAfter + }: { + includeExpired?: boolean; + limit?: number; + owner: string; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + all_operators: { + include_expired: includeExpired, + limit, + owner, + start_after: startAfter + } + }); + }; + numTokens = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + num_tokens: {} + }); + }; + tokens = async ({ + limit, + owner, + startAfter + }: { + limit?: number; + owner: string; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + tokens: { + limit, + owner, + start_after: startAfter + } + }); + }; + allTokens = async ({ + limit, + startAfter + }: { + limit?: number; + startAfter?: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + all_tokens: { + limit, + start_after: startAfter + } + }); + }; + approval = async ({ + includeExpired, + spender, + tokenId + }: { + includeExpired?: boolean; + spender: string; + tokenId: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + approval: { + include_expired: includeExpired, + spender, + token_id: tokenId + } + }); + }; + approvals = async ({ + includeExpired, + tokenId + }: { + includeExpired?: boolean; + tokenId: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + approvals: { + include_expired: includeExpired, + token_id: tokenId + } + }); + }; + ownership = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + ownership: {} + }); + }; + extension = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + extension: {} + }); + }; + contractVersion = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + contract_version: {} + }); + }; + merkleRoot = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + merkle_root: {} + }); + }; + royaltyInfo = async ({ + salePrice, + tokenId + }: { + salePrice: Uint128; + tokenId: string; + }): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + royalty_info: { + sale_price: salePrice, + token_id: tokenId + } + }); + }; + checkRoyalties = async (): Promise => { + return this.client.queryContractSmart(this.contractAddress, { + check_royalties: {} + }); + }; +} +export interface NftTr721Interface extends NftTr721ReadOnlyInterface { + contractAddress: string; + sender: string; + transferNft: ({ + recipient, + tokenId + }: { + recipient: string; + tokenId: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + sendNft: ({ + contract, + msg, + tokenId + }: { + contract: string; + msg: Binary; + tokenId: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + approve: ({ + expires, + spender, + tokenId + }: { + expires?: Expiration; + spender: string; + tokenId: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + approveAll: ({ + expires, + operator + }: { + expires?: Expiration; + operator: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + revoke: ({ + spender, + tokenId + }: { + spender: string; + tokenId: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + revokeAll: ({ + operator + }: { + operator: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + mint: ({ + extension, + owner, + tokenId, + tokenUri + }: { + extension?: Metadata; + owner: string; + tokenId: string; + tokenUri?: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMintInfo: ({ + mintInfo + }: { + mintInfo: MintInfo; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + updateMintPeriod: ({ + mintPeriod, + mintPeriodId + }: { + mintPeriod: MintPeriod; + mintPeriodId: number; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + requestMint: ({ + periodId, + whitelistProof + }: { + periodId: number; + whitelistProof?: WhitelistProof; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; + claim: ({ + merkleProof, + metadata, + tokenId + }: { + merkleProof: string; + metadata: Metadata; + tokenId: string; + }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; +} +export class NftTr721Client extends NftTr721QueryClient implements NftTr721Interface { + 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.transferNft = this.transferNft.bind(this); + this.sendNft = this.sendNft.bind(this); + this.approve = this.approve.bind(this); + this.approveAll = this.approveAll.bind(this); + this.revoke = this.revoke.bind(this); + this.revokeAll = this.revokeAll.bind(this); + this.mint = this.mint.bind(this); + this.updateMintInfo = this.updateMintInfo.bind(this); + this.updateMintPeriod = this.updateMintPeriod.bind(this); + this.requestMint = this.requestMint.bind(this); + this.claim = this.claim.bind(this); + } + + transferNft = async ({ + recipient, + tokenId + }: { + recipient: string; + tokenId: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + transfer_nft: { + recipient, + token_id: tokenId + } + }, fee, memo, _funds); + }; + sendNft = async ({ + contract, + msg, + tokenId + }: { + contract: string; + msg: Binary; + tokenId: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + send_nft: { + contract, + msg, + token_id: tokenId + } + }, fee, memo, _funds); + }; + approve = async ({ + expires, + spender, + tokenId + }: { + expires?: Expiration; + spender: string; + tokenId: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + approve: { + expires, + spender, + token_id: tokenId + } + }, fee, memo, _funds); + }; + approveAll = async ({ + expires, + operator + }: { + expires?: Expiration; + operator: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + approve_all: { + expires, + operator + } + }, fee, memo, _funds); + }; + revoke = async ({ + spender, + tokenId + }: { + spender: string; + tokenId: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + revoke: { + spender, + token_id: tokenId + } + }, fee, memo, _funds); + }; + revokeAll = async ({ + operator + }: { + operator: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + revoke_all: { + operator + } + }, fee, memo, _funds); + }; + mint = async ({ + extension, + owner, + tokenId, + tokenUri + }: { + extension?: Metadata; + owner: string; + tokenId: string; + tokenUri?: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + mint: { + extension, + owner, + token_id: tokenId, + token_uri: tokenUri + } + }, fee, memo, _funds); + }; + updateMintInfo = async ({ + mintInfo + }: { + mintInfo: MintInfo; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mint_info: { + mint_info: mintInfo + } + }, fee, memo, _funds); + }; + updateMintPeriod = async ({ + mintPeriod, + mintPeriodId + }: { + mintPeriod: MintPeriod; + mintPeriodId: number; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + update_mint_period: { + mint_period: mintPeriod, + mint_period_id: mintPeriodId + } + }, fee, memo, _funds); + }; + requestMint = async ({ + periodId, + whitelistProof + }: { + periodId: number; + whitelistProof?: WhitelistProof; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + request_mint: { + period_id: periodId, + whitelist_proof: whitelistProof + } + }, fee, memo, _funds); + }; + claim = async ({ + merkleProof, + metadata, + tokenId + }: { + merkleProof: string; + metadata: Metadata; + tokenId: string; + }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { + return await this.client.execute(this.sender, this.contractAddress, { + claim: { + merkle_proof: merkleProof, + metadata, + token_id: tokenId + } + }, fee, memo, _funds); + }; +} \ No newline at end of file diff --git a/packages/contracts-clients/nft-tr721/NftTr721.types.ts b/packages/contracts-clients/nft-tr721/NftTr721.types.ts new file mode 100644 index 0000000000..4281fc76b1 --- /dev/null +++ b/packages/contracts-clients/nft-tr721/NftTr721.types.ts @@ -0,0 +1,456 @@ +/** +* 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 Addr = string; +export type Uint128 = string; +export interface InstantiateMsg { + admin: string; + launchpad_contract: string; + mint_info: MintInfo; + mint_periods: MintPeriod[]; + minter: string; + name: string; + symbol: string; + [k: string]: unknown; +} +export interface MintInfo { + metadatas_merkle_root: string; + royalty_address?: Addr | null; + royalty_percentage?: number | null; + tokens_count: number; +} +export interface MintPeriod { + end_time?: number | null; + limit_per_address?: number | null; + max_tokens?: number | null; + price?: Coin | null; + start_time: number; + whitelist_info?: WhitelistInfo | null; +} +export interface Coin { + amount: Uint128; + denom: string; + [k: string]: unknown; +} +export interface WhitelistInfo { + addresses_count: number; + addresses_ipfs: string; + addresses_merkle_root: string; +} +export type ExecuteMsg = { + transfer_nft: { + recipient: string; + token_id: string; + [k: string]: unknown; + }; +} | { + send_nft: { + contract: string; + msg: Binary; + token_id: string; + [k: string]: unknown; + }; +} | { + approve: { + expires?: Expiration | null; + spender: string; + token_id: string; + [k: string]: unknown; + }; +} | { + approve_all: { + expires?: Expiration | null; + operator: string; + [k: string]: unknown; + }; +} | { + revoke: { + spender: string; + token_id: string; + [k: string]: unknown; + }; +} | { + revoke_all: { + operator: string; + [k: string]: unknown; + }; +} | { + mint: { + extension?: Metadata | null; + owner: string; + token_id: string; + token_uri?: string | null; + [k: string]: unknown; + }; +} | { + update_mint_info: { + mint_info: MintInfo; + [k: string]: unknown; + }; +} | { + update_mint_period: { + mint_period: MintPeriod; + mint_period_id: number; + [k: string]: unknown; + }; +} | { + request_mint: { + period_id: number; + whitelist_proof?: WhitelistProof | null; + [k: string]: unknown; + }; +} | { + claim: { + merkle_proof: string; + metadata: Metadata; + token_id: string; + [k: string]: unknown; + }; +}; +export type Binary = string; +export type Expiration = { + at_height: number; +} | { + at_time: Timestamp; +} | { + never: {}; +}; +export type Timestamp = Uint64; +export type Uint64 = number; +export interface Metadata { + animation_url?: string | null; + attributes?: Trait[] | null; + background_color?: string | null; + description?: string | null; + external_url?: string | null; + image?: string | null; + image_data?: string | null; + name?: string | null; + royalty_payment_address?: string | null; + royalty_percentage?: number | null; + youtube_url?: string | null; +} +export interface Trait { + display_type?: string | null; + trait_type: string; + value: string; +} +export interface WhitelistProof { + address_indice: number; + merkle_proof: string; +} +export type QueryMsg = { + total_minted: { + [k: string]: unknown; + }; +} | { + minted_count_by_period: { + period_id: number; + [k: string]: unknown; + }; +} | { + minted_count_by_user: { + period_id: number; + user: string; + [k: string]: unknown; + }; +} | { + total_minted_count_by_user: { + user: string; + [k: string]: unknown; + }; +} | { + mint_info: { + [k: string]: unknown; + }; +} | { + mint_periods: { + [k: string]: unknown; + }; +} | { + minter: { + [k: string]: unknown; + }; +} | { + contract_info: { + [k: string]: unknown; + }; +} | { + nft_info: { + token_id: string; + [k: string]: unknown; + }; +} | { + owner_of: { + include_expired?: boolean | null; + token_id: string; + [k: string]: unknown; + }; +} | { + all_nft_info: { + include_expired?: boolean | null; + token_id: string; + [k: string]: unknown; + }; +} | { + operator: { + include_expired?: boolean | null; + operator: string; + owner: string; + [k: string]: unknown; + }; +} | { + all_operators: { + include_expired?: boolean | null; + limit?: number | null; + owner: string; + start_after?: string | null; + [k: string]: unknown; + }; +} | { + num_tokens: { + [k: string]: unknown; + }; +} | { + tokens: { + limit?: number | null; + owner: string; + start_after?: string | null; + [k: string]: unknown; + }; +} | { + all_tokens: { + limit?: number | null; + start_after?: string | null; + [k: string]: unknown; + }; +} | { + approval: { + include_expired?: boolean | null; + spender: string; + token_id: string; + [k: string]: unknown; + }; +} | { + approvals: { + include_expired?: boolean | null; + token_id: string; + [k: string]: unknown; + }; +} | { + ownership: { + [k: string]: unknown; + }; +} | { + extension: { + [k: string]: unknown; + }; +} | { + contract_version: { + [k: string]: unknown; + }; +} | { + merkle_root: { + [k: string]: unknown; + }; +} | { + royalty_info: { + sale_price: Uint128; + token_id: string; + [k: string]: unknown; + }; +} | { + check_royalties: { + [k: string]: unknown; + }; +}; +export interface AllNftInfoResponseForMetadata { + access: OwnerOfResponse; + info: NftInfoResponseForMetadata; +} +export interface OwnerOfResponse { + approvals: Approval[]; + owner: string; +} +export interface Approval { + expires: Expiration; + spender: string; +} +export interface NftInfoResponseForMetadata { + extension: Metadata; + token_uri?: string | null; +} +export interface OperatorsResponse { + operators: Approval[]; +} +export interface TokensResponse { + tokens: string[]; +} +export interface ApprovalResponse { + approval: Approval; +} +export interface ApprovalsResponse { + approvals: Approval[]; +} +export interface CheckRoyaltiesResponse { + royalty_payments: boolean; +} +export interface ContractInfoResponse { + name: string; + symbol: string; +} +export interface ContractVersion { + contract: string; + version: string; +} +export type CosmosMsgForEmpty = { + bank: BankMsg; +} | { + custom: Empty; +} | { + staking: StakingMsg; +} | { + distribution: DistributionMsg; +} | { + wasm: WasmMsg; +}; +export type BankMsg = { + send: { + amount: Coin[]; + to_address: string; + [k: string]: unknown; + }; +} | { + burn: { + amount: Coin[]; + [k: string]: unknown; + }; +}; +export type StakingMsg = { + delegate: { + amount: Coin; + validator: string; + [k: string]: unknown; + }; +} | { + undelegate: { + amount: Coin; + validator: string; + [k: string]: unknown; + }; +} | { + redelegate: { + amount: Coin; + dst_validator: string; + src_validator: string; + [k: string]: unknown; + }; +}; +export type DistributionMsg = { + set_withdraw_address: { + address: string; + [k: string]: unknown; + }; +} | { + withdraw_delegator_reward: { + validator: string; + [k: string]: unknown; + }; +}; +export type WasmMsg = { + execute: { + contract_addr: string; + funds: Coin[]; + msg: Binary; + [k: string]: unknown; + }; +} | { + instantiate: { + admin?: string | null; + code_id: number; + funds: Coin[]; + label: string; + msg: Binary; + [k: string]: unknown; + }; +} | { + instantiate2: { + admin?: string | null; + code_id: number; + funds: Coin[]; + label: string; + msg: Binary; + salt: Binary; + [k: string]: unknown; + }; +} | { + migrate: { + contract_addr: string; + msg: Binary; + new_code_id: number; + [k: string]: unknown; + }; +} | { + update_admin: { + admin: string; + contract_addr: string; + [k: string]: unknown; + }; +} | { + clear_admin: { + contract_addr: string; + [k: string]: unknown; + }; +}; +export type ReplyOn = "always" | "error" | "success" | "never"; +export interface ResponseForEmpty { + attributes: Attribute[]; + data?: Binary | null; + events: Event[]; + messages: SubMsgForEmpty[]; + [k: string]: unknown; +} +export interface Attribute { + key: string; + value: string; + [k: string]: unknown; +} +export interface Event { + attributes: Attribute[]; + type: string; + [k: string]: unknown; +} +export interface SubMsgForEmpty { + gas_limit?: number | null; + id: number; + msg: CosmosMsgForEmpty; + reply_on: ReplyOn; + [k: string]: unknown; +} +export interface Empty { + [k: string]: unknown; +} +export type String = string; +export type ArrayOfMintPeriod = MintPeriod[]; +export type Uint32 = number; +export interface MinterResponse { + minter?: string | null; +} +export interface NumTokensResponse { + count: number; +} +export interface OperatorResponse { + approval: Approval; +} +export interface OwnershipForAddr { + owner?: Addr | null; + pending_expiry?: Expiration | null; + pending_owner?: Addr | null; +} +export interface RoyaltiesInfoResponse { + address: string; + royalty_amount: Uint128; +} \ No newline at end of file diff --git a/packages/contracts-clients/nft-tr721/index.ts b/packages/contracts-clients/nft-tr721/index.ts new file mode 100644 index 0000000000..bcb3190fe9 --- /dev/null +++ b/packages/contracts-clients/nft-tr721/index.ts @@ -0,0 +1,2 @@ +export * from "./NftTr721.client"; +export * from "./NftTr721.types"; \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json index 02c8f8c73e..1b28a10252 100644 --- a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -27,7 +27,7 @@ "supported_networks" ], "properties": { - "deployer": { + "launchpad_admin": { "type": [ "string", "null" @@ -349,7 +349,7 @@ "supported_networks" ], "properties": { - "deployer": { + "launchpad_admin": { "type": [ "string", "null" @@ -800,7 +800,7 @@ "supported_networks" ], "properties": { - "deployer": { + "launchpad_admin": { "type": [ "string", "null" diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json index 3562556609..1bdc0e5f5d 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json @@ -289,7 +289,7 @@ "supported_networks" ], "properties": { - "deployer": { + "launchpad_admin": { "type": [ "string", "null" diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json index 7fb2e842ff..360632ceb1 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json @@ -23,7 +23,7 @@ "supported_networks" ], "properties": { - "deployer": { + "launchpad_admin": { "type": [ "string", "null" diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json index 8efdbdb35a..1b0a37012d 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json @@ -8,7 +8,7 @@ "supported_networks" ], "properties": { - "deployer": { + "launchpad_admin": { "type": [ "string", "null" From aa5cbd71737ca9a558576f7e5ce50e10361c64f2 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Mon, 28 Oct 2024 02:19:12 +0100 Subject: [PATCH 11/33] chore: new nft-launchpad contract instantiation --- networks.json | 4 ++-- packages/networks/teritori-testnet/index.ts | 4 ++-- rust/cw-contracts/nft-launchpad/Makefile | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/networks.json b/networks.json index 91e9458ce8..3073099b90 100644 --- a/networks.json +++ b/networks.json @@ -11682,10 +11682,10 @@ }, { "type": "NFTLaunchpad", - "launchpadContractAddress": "tori1dqy2areatyu6372d67a25t494x63n046qd83dyzrwl73yrnuky4qg8fqsh", + "launchpadContractAddress": "tori1lp4qdzknyzwtsp45jn3vau4c9eedgafutkqq2j3lrc25u8jpftdqmsqxhu", "launchpadEndpoint": "https://dapp-backend.testnet.teritori.com", "nftTr721CodeId": 60, - "codeId": 61, + "codeId": 62, "defaultMintDenom": "utori" } ], diff --git a/packages/networks/teritori-testnet/index.ts b/packages/networks/teritori-testnet/index.ts index 58ff60f849..7b628d235d 100644 --- a/packages/networks/teritori-testnet/index.ts +++ b/packages/networks/teritori-testnet/index.ts @@ -33,10 +33,10 @@ const nftMarketplace: NFTMarketplace = { const cosmwasmLaunchpadFeature: CosmWasmLaunchpad = { type: NetworkFeature.NFTLaunchpad, launchpadContractAddress: - "tori1dqy2areatyu6372d67a25t494x63n046qd83dyzrwl73yrnuky4qg8fqsh", + "tori1lp4qdzknyzwtsp45jn3vau4c9eedgafutkqq2j3lrc25u8jpftdqmsqxhu", launchpadEndpoint: "https://dapp-backend.testnet.teritori.com", nftTr721CodeId: 60, - codeId: 61, + codeId: 62, defaultMintDenom: "utori", }; diff --git a/rust/cw-contracts/nft-launchpad/Makefile b/rust/cw-contracts/nft-launchpad/Makefile index 1b5911d4ac..cd69461e24 100644 --- a/rust/cw-contracts/nft-launchpad/Makefile +++ b/rust/cw-contracts/nft-launchpad/Makefile @@ -3,7 +3,7 @@ ADMIN_ADDR_TESTNET=$(shell teritorid keys show $(ADMIN_TESTNET) --keyring-backen NODE_FLAG_TESTNET=--node https://rpc.testnet.teritori.com:443 TX_FLAGS_TESTNET=--from $(ADMIN_TESTNET) --chain-id teritori-test-7 $(NODE_FLAG_TESTNET) --gas auto --gas-adjustment 1.3 -y -b sync --output json --keyring-backend test -o json QUERY_FLAGS_TESTNET=$(NODE_FLAG_TESTNET) -o json -CODE_ID_TESTNET=61 +CODE_ID_TESTNET=62 CONFIG_TESTNET=$(shell cat config.json | jq -r '.owner="$(ADMIN_ADDR_TESTNET)" | tojson | @sh') ADMIN_MAINNET=mainnet-adm @@ -18,7 +18,7 @@ CONFIG_MAINNET=$(shell cat config-mainnet.json | jq -r '.owner="$(ADMIN_ADDR_MAI WORKSPACE_PATH := $(shell realpath $(shell dirname $(shell pwd))/../..) # only informative -# CONTRACT_ADDRESS_TESTNET=tori1dqy2areatyu6372d67a25t494x63n046qd83dyzrwl73yrnuky4qg8fqsh +# CONTRACT_ADDRESS_TESTNET=tori1lp4qdzknyzwtsp45jn3vau4c9eedgafutkqq2j3lrc25u8jpftdqmsqxhu # CONTRACT_ADDRESS_MAINNET= .PHONY: artifacts/nft_launchpad.wasm From a5e7f20a84aa552518267f0deec71804ca208368 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Mon, 28 Oct 2024 02:49:38 +0100 Subject: [PATCH 12/33] fix: features gen --- go/pkg/networks/features.gen.go | 55 ++++++++++--------- .../codegen/generateGoNetworkFeatures.ts | 1 + 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/go/pkg/networks/features.gen.go b/go/pkg/networks/features.gen.go index af776c4826..b73f962292 100644 --- a/go/pkg/networks/features.gen.go +++ b/go/pkg/networks/features.gen.go @@ -64,6 +64,29 @@ func (nb *NetworkBase) GetFeatureCosmWasmNFTsBurner() (*FeatureCosmWasmNFTsBurne return feature.(*FeatureCosmWasmNFTsBurner), nil } +type FeatureNFTLaunchpad struct { + *FeatureBase + LaunchpadContractAddress string `json:"launchpadContractAddress"` + DefaultMintDenom string `json:"defaultMintDenom"` + LaunchpadEndpoint string `json:"launchpadEndpoint"` + CodeId float64 `json:"codeId"` + NftTr721CodeId float64 `json:"nftTr721CodeId"` +} + +var _ Feature = &FeatureNFTLaunchpad{} + +func (f FeatureNFTLaunchpad) Type() FeatureType { + return FeatureTypeNFTLaunchpad +} + +func (nb *NetworkBase) GetFeatureNFTLaunchpad() (*FeatureNFTLaunchpad, error) { + feature, err := nb.GetFeature(FeatureTypeNFTLaunchpad) + if err != nil { + return nil, err + } + return feature.(*FeatureNFTLaunchpad), nil +} + type FeatureGnoProjectManager struct { *FeatureBase ProjectsManagerPkgPath string `json:"projectsManagerPkgPath"` @@ -104,26 +127,6 @@ func (nb *NetworkBase) GetFeatureLaunchpadERC20() (*FeatureLaunchpadERC20, error return feature.(*FeatureLaunchpadERC20), nil } -type FeatureNFTMarketplace struct { - *FeatureBase - CwAddressListContractAddress string `json:"cwAddressListContractAddress"` - CwAddressListCodeId float64 `json:"cwAddressListCodeId"` -} - -var _ Feature = &FeatureNFTMarketplace{} - -func (f FeatureNFTMarketplace) Type() FeatureType { - return FeatureTypeNFTMarketplace -} - -func (nb *NetworkBase) GetFeatureNFTMarketplace() (*FeatureNFTMarketplace, error) { - feature, err := nb.GetFeature(FeatureTypeNFTMarketplace) - if err != nil { - return nil, err - } - return feature.(*FeatureNFTMarketplace), nil -} - func UnmarshalFeature(b []byte) (Feature, error) { var base FeatureBase if err := json.Unmarshal(b, &base); err != nil { @@ -142,6 +145,12 @@ func UnmarshalFeature(b []byte) (Feature, error) { return nil, errors.Wrap(err, "failed to unmarshal feature CosmWasmNFTsBurner") } return &f, nil + case FeatureTypeNFTLaunchpad: + var f FeatureNFTLaunchpad + if err := json.Unmarshal(b, &f); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal feature NFTLaunchpad") + } + return &f, nil case FeatureTypeGnoProjectManager: var f FeatureGnoProjectManager if err := json.Unmarshal(b, &f); err != nil { @@ -154,12 +163,6 @@ func UnmarshalFeature(b []byte) (Feature, error) { return nil, errors.Wrap(err, "failed to unmarshal feature LaunchpadERC20") } return &f, nil - case FeatureTypeNFTMarketplace: - var f FeatureNFTMarketplace - if err := json.Unmarshal(b, &f); err != nil { - return nil, errors.Wrap(err, "failed to unmarshal feature NFTMarketplace") - } - return &f, nil } return nil, errors.Errorf("unknown feature type %s", base.Type) } diff --git a/packages/scripts/codegen/generateGoNetworkFeatures.ts b/packages/scripts/codegen/generateGoNetworkFeatures.ts index 60897ffc80..adbbb31438 100644 --- a/packages/scripts/codegen/generateGoNetworkFeatures.ts +++ b/packages/scripts/codegen/generateGoNetworkFeatures.ts @@ -109,3 +109,4 @@ func UnmarshalFeature(b []byte) (Feature, error) { }; main(); + From 94f2de2256f31f1380863efaae39deff932cb510 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 1 Nov 2024 14:44:52 -0400 Subject: [PATCH 13/33] chore: launchpad scripst: remove unused arg, fix instantiate --- packages/scripts/codegen/generateGoNetworkFeatures.ts | 1 - packages/scripts/network-setup/deployNftLaunchpad.ts | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/scripts/codegen/generateGoNetworkFeatures.ts b/packages/scripts/codegen/generateGoNetworkFeatures.ts index adbbb31438..60897ffc80 100644 --- a/packages/scripts/codegen/generateGoNetworkFeatures.ts +++ b/packages/scripts/codegen/generateGoNetworkFeatures.ts @@ -109,4 +109,3 @@ func UnmarshalFeature(b []byte) (Feature, error) { }; main(); - diff --git a/packages/scripts/network-setup/deployNftLaunchpad.ts b/packages/scripts/network-setup/deployNftLaunchpad.ts index 25c71fdfa4..122beb5db8 100644 --- a/packages/scripts/network-setup/deployNftLaunchpad.ts +++ b/packages/scripts/network-setup/deployNftLaunchpad.ts @@ -96,7 +96,7 @@ export const instantiateNftLaunchpad = async ( .filter((n) => n.features.includes(NetworkFeature.NFTLaunchpad)) .map((n) => n.id), owner: deployerAddr, - launchpadAdmin, + launchpad_admin: launchpadAdmin, nft_code_id: nftCodeId, }, }; @@ -159,7 +159,6 @@ const main = async () => { home: path.join(os.homedir(), ".teritorid"), binaryPath: "teritorid", keyringBackend, - signer: undefined, }, networkId, wallet, From 415a7b46e88caace4f26c3301bc90c5c87e6b960 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 1 Nov 2024 18:32:47 -0400 Subject: [PATCH 14/33] fix: launchpad: plug data in contract --- rust/cw-contracts/nft-launchpad/src/contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index cc7327323f..680c2408ca 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -206,8 +206,8 @@ impl NftLaunchpad { mint_info: Tr721MintInfo { metadatas_merkle_root: collection.metadatas_merkle_root.unwrap(), tokens_count: collection.tokens_count, - royalty_address: None, - royalty_percentage: None, + royalty_address: collection.royalty_address, + royalty_percentage: collection.royalty_percentage, }, mint_periods: collection.mint_periods, })?, From 6c4f92549ec7cd7f38523a1bfc6901c187351519 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 1 Nov 2024 18:54:38 -0400 Subject: [PATCH 15/33] chore: update .gitattributes --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitattributes b/.gitattributes index 96732ba1e2..4ccab66486 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,3 +9,5 @@ /packages/evm-contracts-clients/**/*.ts linguist-generated /.expo-shared/assets.json linguist-generated *.gno linguist-language=Go +/rust/**/schema/raw/**/*.json linguist-generated +/rust/apipb/src/**/*.rs linguist-generated From 1238cdbb5a22c7b912859d0620b652d1f3382ed9 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 3 Nov 2024 17:11:54 -0500 Subject: [PATCH 16/33] chore(launchpad): remove script usage from deploy teritori ecosystem script --- packages/scripts/network-setup/deployLib.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/packages/scripts/network-setup/deployLib.ts b/packages/scripts/network-setup/deployLib.ts index aa62faa1fb..ee0224f8ee 100644 --- a/packages/scripts/network-setup/deployLib.ts +++ b/packages/scripts/network-setup/deployLib.ts @@ -6,7 +6,6 @@ import { bech32 } from "bech32"; import _, { cloneDeep } from "lodash"; import path from "path"; -import { instantiateNftLaunchpad } from "./deployNftLaunchpad"; import { InstantiateMsg as MarketplaceVaultInstantiateMsg } from "../../contracts-clients/nft-marketplace/NftMarketplace.types"; import { ExecuteMsg as NameServiceExecuteMsg, @@ -25,9 +24,7 @@ import { cosmosNetworkGasPrice, CosmosNetworkInfo, getCosmosNetwork, - getNetworkFeature, mustGetNonSigningCosmWasmClient, - NetworkFeature, } from "@/networks"; import { zodTryParseJSON } from "@/utils/sanitize"; @@ -135,24 +132,6 @@ export const deployTeritoriEcosystem = async ( network, ); - console.log("Instantiating NFT Launchpad", network.nameServiceCodeId); - const cosmwasmLaunchpadFeature = cloneDeep( - getNetworkFeature(networkId, NetworkFeature.NFTLaunchpad), - ); - if (!cosmwasmLaunchpadFeature) { - console.error(`Cosmwasm Launchpad feature not found on ${networkId}`); - } else { - cosmwasmLaunchpadFeature.launchpadContractAddress = - await instantiateNftLaunchpad( - opts, - wallet, - walletAddr, - "TODO DAO address", - network, - cosmwasmLaunchpadFeature, - ); - } - if (opts.signer) { await registerTNSHandle(network, opts.signer); await testTeritoriEcosystem(network); From e11c4a1c881b1feadcf00a35a5bd606f1208f419 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 3 Nov 2024 19:03:32 +0100 Subject: [PATCH 17/33] chore: make a Collection peroperty mandatory --- .../nft-launchpad/NftLaunchpad.types.ts | 2 +- .../nft-launchpad/schema/nft-launchpad.json | 16 ++++------ .../nft-launchpad/schema/raw/execute.json | 8 ++--- .../raw/response_to_get_collection_by_id.json | 8 ++--- .../nft-launchpad/src/contract.rs | 30 ++----------------- 5 files changed, 15 insertions(+), 49 deletions(-) diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts index 56ccc3f03a..2e7c36f44d 100644 --- a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts @@ -78,7 +78,7 @@ export interface Collection { target_network: string; team_desc: string; tokens_count: number; - website_link?: string | null; + website_link: string; } export interface MintPeriod { end_time?: number | null; diff --git a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json index 1b28a10252..a21d7b0f03 100644 --- a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -193,7 +193,8 @@ "symbol", "target_network", "team_desc", - "tokens_count" + "tokens_count", + "website_link" ], "properties": { "artwork_desc": { @@ -334,10 +335,7 @@ "minimum": 0.0 }, "website_link": { - "type": [ - "string", - "null" - ] + "type": "string" } }, "additionalProperties": false @@ -536,7 +534,8 @@ "symbol", "target_network", "team_desc", - "tokens_count" + "tokens_count", + "website_link" ], "properties": { "artwork_desc": { @@ -677,10 +676,7 @@ "minimum": 0.0 }, "website_link": { - "type": [ - "string", - "null" - ] + "type": "string" } }, "additionalProperties": false, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json index 1bdc0e5f5d..10a1f0fff6 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json @@ -133,7 +133,8 @@ "symbol", "target_network", "team_desc", - "tokens_count" + "tokens_count", + "website_link" ], "properties": { "artwork_desc": { @@ -274,10 +275,7 @@ "minimum": 0.0 }, "website_link": { - "type": [ - "string", - "null" - ] + "type": "string" } }, "additionalProperties": false diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json index b7f5a27208..4c6faf9d40 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json @@ -26,7 +26,8 @@ "symbol", "target_network", "team_desc", - "tokens_count" + "tokens_count", + "website_link" ], "properties": { "artwork_desc": { @@ -167,10 +168,7 @@ "minimum": 0.0 }, "website_link": { - "type": [ - "string", - "null" - ] + "type": "string" } }, "additionalProperties": false, diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index 680c2408ca..4597fa1abb 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -304,62 +304,35 @@ pub struct Collection { pub symbol: String, // Unique pub cover_img_uri: String, pub target_network: String, - // pub external_link: Option, - // Collection details ---------------------------- - pub website_link: Option, - - // pub twitter_profile: String, - // pub twitter_followers_count: u64, - - // pub contact_discord_name: String, + pub website_link: String, pub contact_email: String, - pub is_project_derivative: bool, - pub project_type: String, pub project_desc: String, - pub is_applied_previously: bool, - // Team info -------------------------------------- pub team_desc: String, - // pub team_link: String, - pub partners: String, - pub investment_desc: String, pub investment_link: String, - - // pub whitepaper_link: String, - // pub roadmap_link: String, - // Additional info ---------------------------- pub artwork_desc: String, - pub is_ready_for_mint: bool, - pub expected_supply: u64, pub expected_public_mint_price: u64, pub expected_mint_date: u64, - pub escrow_mint_proceeds_period: u64, pub is_dox: bool, - pub dao_whitelist_count: u32, - pub reveal_time: Option, - // Minting details ---------------------------- pub tokens_count: u64, - // Mint periods -------------------------- pub mint_periods: Vec, - // Royalty -------------------------- pub royalty_address: Option, pub royalty_percentage: Option, - // Extend info -------------------------- pub base_token_uri: Option, pub metadatas_merkle_root: Option, @@ -375,3 +348,4 @@ pub enum CollectionState { + From b02533861594152dd201f2118fe476b038cecb72 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Mon, 4 Nov 2024 13:27:57 -0500 Subject: [PATCH 18/33] fix(launchpad): set launchpad_admin as mandatory in Config, fix usages in contract --- .../nft-launchpad/src/contract.rs | 19 ++++---- rust/cw-contracts/nft-launchpad/src/error.rs | 8 ++-- .../nft-launchpad/src/multitest.rs | 46 +++++-------------- 3 files changed, 23 insertions(+), 50 deletions(-) diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index 4597fa1abb..7bd2acdbff 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -2,7 +2,7 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::{ - attr, to_json_binary, Addr, Order, Reply, Response, + to_json_binary, Addr, Reply, Response, StdResult, SubMsg, WasmMsg, }; use cw_storage_plus::{Item, Map}; @@ -59,23 +59,23 @@ impl NftLaunchpad { changes: ConfigChanges, ) -> Result { let mut config = self.config.load(ctx.deps.storage)?; - let mut attributes = vec![attr("action", "update_config")]; // Permission check if ctx.info.sender != config.owner { return Err(ContractError::Unauthorized); } // Save new config - config.launchpad_admin = changes.launchpad_admin; config.nft_code_id = changes.nft_code_id; config.supported_networks = changes.supported_networks; + if let Some(launchpad_admin) = changes.launchpad_admin { + config.launchpad_admin = ctx.deps.api.addr_validate(&launchpad_admin)?; + } if let Some(owner) = changes.owner { config.owner = ctx.deps.api.addr_validate(&owner)?; - attributes.push(attr("new_owner", owner)) } self.config.save(ctx.deps.storage, &config)?; - Ok(Response::new().add_attributes(attributes)) + Ok(Response::default()) } #[msg(exec)] @@ -169,11 +169,8 @@ impl NftLaunchpad { let config = self.config.load(ctx.deps.storage)?; // Only allow launchpad_admin to deploy - if config.launchpad_admin.is_none() { - return Err(ContractError::DeployerMissing); - } - if sender != config.launchpad_admin.unwrap() { - return Err(ContractError::WrongDeployer); + if sender != config.launchpad_admin { + return Err(ContractError::WrongAdmin); } let collection = self @@ -282,7 +279,7 @@ pub struct Config { pub name: String, pub nft_code_id: Option, pub supported_networks: Vec, - pub launchpad_admin: Option, + pub launchpad_admin: Addr, pub owner: Addr, } diff --git a/rust/cw-contracts/nft-launchpad/src/error.rs b/rust/cw-contracts/nft-launchpad/src/error.rs index e2a19ed93b..1536f82f15 100644 --- a/rust/cw-contracts/nft-launchpad/src/error.rs +++ b/rust/cw-contracts/nft-launchpad/src/error.rs @@ -13,8 +13,8 @@ pub enum ContractError { #[error("Merkle root missing.")] MerkleRootMissing, - #[error("Deployer missing.")] - DeployerMissing, + #[error("Admin missing.")] + AdminMissing, #[error("Unauthorized.")] Unauthorized, @@ -37,8 +37,8 @@ pub enum ContractError { #[error("Wrong collection owner.")] WrongCollectionOwner, - #[error("Wrong deployer.")] - WrongDeployer, + #[error("Wrong admin.")] + WrongAdmin, #[error("Already deployed.")] AlreadyDeployed, diff --git a/rust/cw-contracts/nft-launchpad/src/multitest.rs b/rust/cw-contracts/nft-launchpad/src/multitest.rs index 94f98fd287..886230f169 100644 --- a/rust/cw-contracts/nft-launchpad/src/multitest.rs +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -36,61 +36,35 @@ fn get_default_collection() -> Collection { symbol: "SYMBOL".to_string(), cover_img_uri: "img".to_string(), target_network: "network".to_string(), - // external_link: None, - // Collection details ---------------------------- - website_link: None, - - // twitter_profile: "twitter_profile".to_string(), - // twitter_followers_count: 1, - - // contact_discord_name: "contact_discord_name".to_string(), + website_link: "website_link".to_string(), contact_email: "contact_email".to_string(), - is_project_derivative: true, - project_type: "project_type".to_string(), project_desc: "project_desc".to_string(), - is_applied_previously: false, - // Team info -------------------------------------- team_desc: "team_desc".to_string(), - // team_link: "team_link".to_string(), - partners: "partners".to_string(), - investment_desc: "investment_desc".to_string(), investment_link: "investment_link".to_string(), - - // whitepaper_link: "whitepaper_link".to_string(), - // roadmap_link: "roadmap_link".to_string(), - // Additional info ---------------------------- artwork_desc: "artwork_desc".to_string(), - is_ready_for_mint: true, - expected_supply: 1000, expected_public_mint_price: 100, expected_mint_date: u64::default(), - escrow_mint_proceeds_period: u64::default(), is_dox: true, - dao_whitelist_count: 10, - // Minting details ---------------------------- tokens_count: 1000, reveal_time: Some(u64::default()), - // Whitelist minting -------------------------- mint_periods, - // Royalty -------------------------- royalty_address: Some(Addr::unchecked("royalty_address")), royalty_percentage: Some(50), - // Extend info -------------------------- base_token_uri: None, metadatas_merkle_root: None, @@ -104,13 +78,14 @@ fn instantiate() { let app = App::default(); let code_id = LaunchpadCodeId::store_code(&app); let sender = "sender"; + let admin: &str = "admin"; // Instantiate let config = Config { name: "teritori launchpad".to_string(), supported_networks: vec![], nft_code_id: None, - deployer: None, + launchpad_admin: Addr::unchecked(admin), owner: Addr::unchecked(sender), }; @@ -128,6 +103,7 @@ fn full_flow() { let app: App = App::default(); let sender = "sender"; + let admin: &str = "admin"; // Deploy NFT contract for non-sylvia contract // let contract_wrapper = ContractWrapper::new(tr721_execute, tr721_instantiate, tr721_query); @@ -144,7 +120,7 @@ fn full_flow() { name: "teritori launchpad".to_string(), supported_networks: vec![], nft_code_id: None, - deployer: None, + launchpad_admin: Addr::unchecked(admin), owner: Addr::unchecked(sender), }) .call(sender) @@ -218,7 +194,7 @@ fn full_flow() { .deploy_collection("SYMBOL_NOT_EXIST".to_string()) .call(sender) .unwrap_err(); - assert_eq!(err, ContractError::DeployerMissing) + assert_eq!(err, ContractError::AdminMissing) } // Update config when sender is not contract owner @@ -228,7 +204,7 @@ fn full_flow() { name: "test".to_string(), nft_code_id: Some(deployed_nft_code_id), supported_networks: vec![], - deployer: Some(sender.to_string()), + launchpad_admin: Some(admin.to_string()), owner: Some(sender.to_string()), }) .call("wrong_owner") @@ -243,7 +219,7 @@ fn full_flow() { name: "test".to_string(), supported_networks: vec![], nft_code_id: None, - deployer: Some("deployer".to_string()), + launchpad_admin: Some(admin.to_string()), owner: Some(sender.to_string()), }) .call(sender) @@ -253,7 +229,7 @@ fn full_flow() { .deploy_collection("SYMBOL_NOT_EXIST".to_string()) .call(sender) .unwrap_err(); - assert_eq!(err, ContractError::WrongDeployer) + assert_eq!(err, ContractError::WrongAdmin) } // Set sender as deployer and Deploy inexist collection --------------------------------------------------------- @@ -263,7 +239,7 @@ fn full_flow() { name: "test".to_string(), supported_networks: vec![], nft_code_id: None, - deployer: Some(sender.to_string()), + launchpad_admin: Some(admin.to_string()), owner: Some(sender.to_string()), }) .call(sender) @@ -328,7 +304,7 @@ fn full_flow() { name: "test".to_string(), nft_code_id: Some(deployed_nft_code_id), supported_networks: vec![], - deployer: Some(sender.to_string()), + launchpad_admin: Some(admin.to_string()), owner: Some(sender.to_string()), }) .call(sender) From 419b918cc5bdc2544d5a2c41750b4c0f96ef8e2a Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Mon, 4 Nov 2024 19:33:35 +0100 Subject: [PATCH 19/33] chore(launchpad): make generate --- .../nft-launchpad/NftLaunchpad.types.ts | 2 +- .../nft-launchpad/schema/nft-launchpad.json | 12 ++++-------- .../nft-launchpad/schema/raw/instantiate.json | 6 ++---- .../schema/raw/response_to_get_config.json | 6 ++---- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts index 2e7c36f44d..ede14d66c5 100644 --- a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts @@ -10,7 +10,7 @@ export interface InstantiateMsg { [k: string]: unknown; } export interface Config { - launchpad_admin?: string | null; + launchpad_admin: Addr; name: string; nft_code_id?: number | null; owner: Addr; diff --git a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json index a21d7b0f03..40967edf77 100644 --- a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -22,16 +22,14 @@ "Config": { "type": "object", "required": [ + "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "type": [ - "string", - "null" - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" @@ -791,16 +789,14 @@ "title": "Config", "type": "object", "required": [ + "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "type": [ - "string", - "null" - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json index 360632ceb1..201cac4558 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json @@ -18,16 +18,14 @@ "Config": { "type": "object", "required": [ + "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "type": [ - "string", - "null" - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json index 1b0a37012d..f1c5110571 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json @@ -3,16 +3,14 @@ "title": "Config", "type": "object", "required": [ + "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "type": [ - "string", - "null" - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" From 975e22d706e9c7b91f3c578a97672bbd8230800b Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Mon, 4 Nov 2024 13:53:18 -0500 Subject: [PATCH 20/33] fix(launchpad): fix multitest, remove unused error --- rust/cw-contracts/nft-launchpad/src/error.rs | 3 --- rust/cw-contracts/nft-launchpad/src/multitest.rs | 15 +++------------ 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/rust/cw-contracts/nft-launchpad/src/error.rs b/rust/cw-contracts/nft-launchpad/src/error.rs index 1536f82f15..faefb38eef 100644 --- a/rust/cw-contracts/nft-launchpad/src/error.rs +++ b/rust/cw-contracts/nft-launchpad/src/error.rs @@ -13,9 +13,6 @@ pub enum ContractError { #[error("Merkle root missing.")] MerkleRootMissing, - #[error("Admin missing.")] - AdminMissing, - #[error("Unauthorized.")] Unauthorized, diff --git a/rust/cw-contracts/nft-launchpad/src/multitest.rs b/rust/cw-contracts/nft-launchpad/src/multitest.rs index 886230f169..9dcaa25d93 100644 --- a/rust/cw-contracts/nft-launchpad/src/multitest.rs +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -188,15 +188,6 @@ fn full_flow() { assert_eq!(err, ContractError::CollectionSymbolExists); } - // Deploy when deployer missing --------------------------------------------------------- - { - let err = contract - .deploy_collection("SYMBOL_NOT_EXIST".to_string()) - .call(sender) - .unwrap_err(); - assert_eq!(err, ContractError::AdminMissing) - } - // Update config when sender is not contract owner { let err = contract @@ -212,7 +203,7 @@ fn full_flow() { assert_eq!(err, ContractError::Unauthorized) } - // Deploy when sender is not deployer --------------------------------------------------------- + // Deploy when sender is not launchpad_admin --------------------------------------------------------- { contract .update_config(ConfigChanges { @@ -239,7 +230,7 @@ fn full_flow() { name: "test".to_string(), supported_networks: vec![], nft_code_id: None, - launchpad_admin: Some(admin.to_string()), + launchpad_admin: Some(sender.to_string()), owner: Some(sender.to_string()), }) .call(sender) @@ -319,7 +310,7 @@ fn full_flow() { let collection_id = "SYMBOL".to_string(); let resp = contract .deploy_collection(collection_id.to_owned()) - .call(sender) + .call(admin) .unwrap(); let attrs = resp.custom_attrs(1); assert_eq!( From c0f49d864e77a9b0e1f71668cc2d1b3a4a0642e8 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Tue, 5 Nov 2024 20:25:05 +0100 Subject: [PATCH 21/33] chore(launchpad): make generate to fix features.gen.go after rebase --- go/pkg/networks/features.gen.go | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/go/pkg/networks/features.gen.go b/go/pkg/networks/features.gen.go index b73f962292..6185540f36 100644 --- a/go/pkg/networks/features.gen.go +++ b/go/pkg/networks/features.gen.go @@ -2,7 +2,6 @@ package networks import ( "encoding/json" - "github.com/pkg/errors" ) @@ -127,6 +126,26 @@ func (nb *NetworkBase) GetFeatureLaunchpadERC20() (*FeatureLaunchpadERC20, error return feature.(*FeatureLaunchpadERC20), nil } +type FeatureNFTMarketplace struct { + *FeatureBase + CwAddressListContractAddress string `json:"cwAddressListContractAddress"` + CwAddressListCodeId float64 `json:"cwAddressListCodeId"` +} + +var _ Feature = &FeatureNFTMarketplace{} + +func (f FeatureNFTMarketplace) Type() FeatureType { + return FeatureTypeNFTMarketplace +} + +func (nb *NetworkBase) GetFeatureNFTMarketplace() (*FeatureNFTMarketplace, error) { + feature, err := nb.GetFeature(FeatureTypeNFTMarketplace) + if err != nil { + return nil, err + } + return feature.(*FeatureNFTMarketplace), nil +} + func UnmarshalFeature(b []byte) (Feature, error) { var base FeatureBase if err := json.Unmarshal(b, &base); err != nil { @@ -163,6 +182,12 @@ func UnmarshalFeature(b []byte) (Feature, error) { return nil, errors.Wrap(err, "failed to unmarshal feature LaunchpadERC20") } return &f, nil + case FeatureTypeNFTMarketplace: + var f FeatureNFTMarketplace + if err := json.Unmarshal(b, &f); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal feature NFTMarketplace") + } + return &f, nil } return nil, errors.Errorf("unknown feature type %s", base.Type) } From 5eb4431784bc1c6644eb5ca6edb73b5b87e4a24a Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Wed, 6 Nov 2024 17:47:43 -0500 Subject: [PATCH 22/33] fix(launchpad): enhance contract --- packages/networks/teritori-testnet/index.ts | 4 +- rust/cw-contracts/nft-launchpad/Makefile | 7 ++- .../nft-launchpad/src/contract.rs | 28 +++++----- rust/cw-contracts/nft-launchpad/src/error.rs | 9 ++-- rust/cw-contracts/nft-launchpad/src/lib.rs | 1 - .../nft-launchpad/src/multitest.rs | 52 +++++++++++++------ .../nft-launchpad/src/responses.rs | 26 ---------- 7 files changed, 58 insertions(+), 69 deletions(-) delete mode 100644 rust/cw-contracts/nft-launchpad/src/responses.rs diff --git a/packages/networks/teritori-testnet/index.ts b/packages/networks/teritori-testnet/index.ts index 7b628d235d..8d9e9404f0 100644 --- a/packages/networks/teritori-testnet/index.ts +++ b/packages/networks/teritori-testnet/index.ts @@ -33,10 +33,10 @@ const nftMarketplace: NFTMarketplace = { const cosmwasmLaunchpadFeature: CosmWasmLaunchpad = { type: NetworkFeature.NFTLaunchpad, launchpadContractAddress: - "tori1lp4qdzknyzwtsp45jn3vau4c9eedgafutkqq2j3lrc25u8jpftdqmsqxhu", + "tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf", launchpadEndpoint: "https://dapp-backend.testnet.teritori.com", nftTr721CodeId: 60, - codeId: 62, + codeId: 71, defaultMintDenom: "utori", }; diff --git a/rust/cw-contracts/nft-launchpad/Makefile b/rust/cw-contracts/nft-launchpad/Makefile index cd69461e24..d89889f4bb 100644 --- a/rust/cw-contracts/nft-launchpad/Makefile +++ b/rust/cw-contracts/nft-launchpad/Makefile @@ -3,7 +3,7 @@ ADMIN_ADDR_TESTNET=$(shell teritorid keys show $(ADMIN_TESTNET) --keyring-backen NODE_FLAG_TESTNET=--node https://rpc.testnet.teritori.com:443 TX_FLAGS_TESTNET=--from $(ADMIN_TESTNET) --chain-id teritori-test-7 $(NODE_FLAG_TESTNET) --gas auto --gas-adjustment 1.3 -y -b sync --output json --keyring-backend test -o json QUERY_FLAGS_TESTNET=$(NODE_FLAG_TESTNET) -o json -CODE_ID_TESTNET=62 +CODE_ID_TESTNET=71 CONFIG_TESTNET=$(shell cat config.json | jq -r '.owner="$(ADMIN_ADDR_TESTNET)" | tojson | @sh') ADMIN_MAINNET=mainnet-adm @@ -18,7 +18,7 @@ CONFIG_MAINNET=$(shell cat config-mainnet.json | jq -r '.owner="$(ADMIN_ADDR_MAI WORKSPACE_PATH := $(shell realpath $(shell dirname $(shell pwd))/../..) # only informative -# CONTRACT_ADDRESS_TESTNET=tori1lp4qdzknyzwtsp45jn3vau4c9eedgafutkqq2j3lrc25u8jpftdqmsqxhu +# CONTRACT_ADDRESS_TESTNET=tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf # CONTRACT_ADDRESS_MAINNET= .PHONY: artifacts/nft_launchpad.wasm @@ -51,5 +51,4 @@ deploy.mainnet: artifacts/nft_launchpad.wasm instantiate.mainnet: config-mainnet.json set -o pipefail; \ TXHASH=$$(teritorid tx wasm instantiate $(CODE_ID_MAINNET) $(CONFIG_MAINNET) --label NftsBurner --admin $(ADMIN_ADDR_MAINNET) $(TX_FLAGS_MAINNET) | jq -r .txhash); \ - while ! teritorid query tx $$TXHASH $(QUERY_FLAGS_MAINNET) 2>/dev/null | jq -r '.logs[0].events[] | select(.type=="instantiate").attributes[] | select(.key=="_contract_address").value'; do sleep 1; done - + while ! teritorid query tx $$TXHASH $(QUERY_FLAGS_MAINNET) 2>/dev/null | jq -r '.logs[0].events[] | select(.type=="instantiate").attributes[] | select(.key=="_contract_address").value'; do sleep 1; done \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index 7bd2acdbff..dc2b5431db 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -2,7 +2,7 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::{ - to_json_binary, Addr, Reply, Response, + attr, to_json_binary, Addr, Reply, Response, StdResult, SubMsg, WasmMsg, }; use cw_storage_plus::{Item, Map}; @@ -59,23 +59,23 @@ impl NftLaunchpad { changes: ConfigChanges, ) -> Result { let mut config = self.config.load(ctx.deps.storage)?; + let mut attributes = vec![attr("action", "update_config")]; // Permission check if ctx.info.sender != config.owner { return Err(ContractError::Unauthorized); } // Save new config + config.launchpad_admin = changes.launchpad_admin; config.nft_code_id = changes.nft_code_id; config.supported_networks = changes.supported_networks; - if let Some(launchpad_admin) = changes.launchpad_admin { - config.launchpad_admin = ctx.deps.api.addr_validate(&launchpad_admin)?; - } if let Some(owner) = changes.owner { config.owner = ctx.deps.api.addr_validate(&owner)?; + attributes.push(attr("new_owner", owner)) } self.config.save(ctx.deps.storage, &config)?; - Ok(Response::default()) + Ok(Response::new().add_attributes(attributes)) } #[msg(exec)] @@ -169,8 +169,11 @@ impl NftLaunchpad { let config = self.config.load(ctx.deps.storage)?; // Only allow launchpad_admin to deploy - if sender != config.launchpad_admin { - return Err(ContractError::WrongAdmin); + if config.launchpad_admin.is_none() { + return Err(ContractError::DeployerMissing); + } + if sender != config.launchpad_admin.unwrap() { + return Err(ContractError::WrongDeployer); } let collection = self @@ -279,7 +282,7 @@ pub struct Config { pub name: String, pub nft_code_id: Option, pub supported_networks: Vec, - pub launchpad_admin: Addr, + pub launchpad_admin: Option, pub owner: Addr, } @@ -316,9 +319,6 @@ pub struct Collection { // Additional info ---------------------------- pub artwork_desc: String, pub is_ready_for_mint: bool, - pub expected_supply: u64, - pub expected_public_mint_price: u64, - pub expected_mint_date: u64, pub escrow_mint_proceeds_period: u64, pub is_dox: bool, pub dao_whitelist_count: u32, @@ -341,8 +341,4 @@ pub struct Collection { pub enum CollectionState { Pending, // When user summit the collection but not deployed yet Deployed, // When collection has been deployed -} - - - - +} \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/src/error.rs b/rust/cw-contracts/nft-launchpad/src/error.rs index faefb38eef..386461b3c1 100644 --- a/rust/cw-contracts/nft-launchpad/src/error.rs +++ b/rust/cw-contracts/nft-launchpad/src/error.rs @@ -13,6 +13,9 @@ pub enum ContractError { #[error("Merkle root missing.")] MerkleRootMissing, + #[error("Deployer missing.")] + DeployerMissing, + #[error("Unauthorized.")] Unauthorized, @@ -34,8 +37,8 @@ pub enum ContractError { #[error("Wrong collection owner.")] WrongCollectionOwner, - #[error("Wrong admin.")] - WrongAdmin, + #[error("Wrong deployer.")] + WrongDeployer, #[error("Already deployed.")] AlreadyDeployed, @@ -48,4 +51,4 @@ pub enum ContractError { #[error("{0}")] Instantiate2AddressError(#[from] Instantiate2AddressError), -} +} \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/src/lib.rs b/rust/cw-contracts/nft-launchpad/src/lib.rs index dd3e2d40ce..dfc3c2d15a 100644 --- a/rust/cw-contracts/nft-launchpad/src/lib.rs +++ b/rust/cw-contracts/nft-launchpad/src/lib.rs @@ -1,6 +1,5 @@ pub mod contract; pub mod error; -pub mod responses; #[cfg(test)] pub mod multitest; diff --git a/rust/cw-contracts/nft-launchpad/src/multitest.rs b/rust/cw-contracts/nft-launchpad/src/multitest.rs index 9dcaa25d93..1ce369bc5d 100644 --- a/rust/cw-contracts/nft-launchpad/src/multitest.rs +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -36,35 +36,57 @@ fn get_default_collection() -> Collection { symbol: "SYMBOL".to_string(), cover_img_uri: "img".to_string(), target_network: "network".to_string(), + // external_link: None, + // Collection details ---------------------------- - website_link: "website_link".to_string(), + website_link: "aaa".to_string(), + + // twitter_profile: "twitter_profile".to_string(), + // twitter_followers_count: 1, + + // contact_discord_name: "contact_discord_name".to_string(), contact_email: "contact_email".to_string(), + is_project_derivative: true, + project_type: "project_type".to_string(), project_desc: "project_desc".to_string(), + is_applied_previously: false, + // Team info -------------------------------------- team_desc: "team_desc".to_string(), + // team_link: "team_link".to_string(), + partners: "partners".to_string(), + investment_desc: "investment_desc".to_string(), investment_link: "investment_link".to_string(), + + // whitepaper_link: "whitepaper_link".to_string(), + // roadmap_link: "roadmap_link".to_string(), + // Additional info ---------------------------- artwork_desc: "artwork_desc".to_string(), + is_ready_for_mint: true, - expected_supply: 1000, - expected_public_mint_price: 100, - expected_mint_date: u64::default(), + escrow_mint_proceeds_period: u64::default(), is_dox: true, + dao_whitelist_count: 10, + // Minting details ---------------------------- tokens_count: 1000, reveal_time: Some(u64::default()), + // Whitelist minting -------------------------- mint_periods, + // Royalty -------------------------- royalty_address: Some(Addr::unchecked("royalty_address")), royalty_percentage: Some(50), + // Extend info -------------------------- base_token_uri: None, metadatas_merkle_root: None, @@ -78,14 +100,13 @@ fn instantiate() { let app = App::default(); let code_id = LaunchpadCodeId::store_code(&app); let sender = "sender"; - let admin: &str = "admin"; // Instantiate let config = Config { name: "teritori launchpad".to_string(), supported_networks: vec![], nft_code_id: None, - launchpad_admin: Addr::unchecked(admin), + launchpad_admin: Some("admin".to_string()), owner: Addr::unchecked(sender), }; @@ -103,7 +124,6 @@ fn full_flow() { let app: App = App::default(); let sender = "sender"; - let admin: &str = "admin"; // Deploy NFT contract for non-sylvia contract // let contract_wrapper = ContractWrapper::new(tr721_execute, tr721_instantiate, tr721_query); @@ -120,7 +140,7 @@ fn full_flow() { name: "teritori launchpad".to_string(), supported_networks: vec![], nft_code_id: None, - launchpad_admin: Addr::unchecked(admin), + launchpad_admin: Some("admin".to_string()), owner: Addr::unchecked(sender), }) .call(sender) @@ -195,7 +215,7 @@ fn full_flow() { name: "test".to_string(), nft_code_id: Some(deployed_nft_code_id), supported_networks: vec![], - launchpad_admin: Some(admin.to_string()), + launchpad_admin: Some(sender.to_string()), owner: Some(sender.to_string()), }) .call("wrong_owner") @@ -203,14 +223,14 @@ fn full_flow() { assert_eq!(err, ContractError::Unauthorized) } - // Deploy when sender is not launchpad_admin --------------------------------------------------------- + // Deploy when sender is not deployer --------------------------------------------------------- { contract .update_config(ConfigChanges { name: "test".to_string(), supported_networks: vec![], nft_code_id: None, - launchpad_admin: Some(admin.to_string()), + launchpad_admin: Some("deployer".to_string()), owner: Some(sender.to_string()), }) .call(sender) @@ -220,7 +240,7 @@ fn full_flow() { .deploy_collection("SYMBOL_NOT_EXIST".to_string()) .call(sender) .unwrap_err(); - assert_eq!(err, ContractError::WrongAdmin) + assert_eq!(err, ContractError::WrongDeployer) } // Set sender as deployer and Deploy inexist collection --------------------------------------------------------- @@ -295,7 +315,7 @@ fn full_flow() { name: "test".to_string(), nft_code_id: Some(deployed_nft_code_id), supported_networks: vec![], - launchpad_admin: Some(admin.to_string()), + launchpad_admin: Some(sender.to_string()), owner: Some(sender.to_string()), }) .call(sender) @@ -310,7 +330,7 @@ fn full_flow() { let collection_id = "SYMBOL".to_string(); let resp = contract .deploy_collection(collection_id.to_owned()) - .call(admin) + .call(sender) .unwrap(); let attrs = resp.custom_attrs(1); assert_eq!( @@ -325,6 +345,4 @@ fn full_flow() { let collection = contract.get_collection_by_id(collection_id).unwrap(); assert_eq!(collection.deployed_address, Some("contract1".to_string())); } -} - - +} \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/src/responses.rs b/rust/cw-contracts/nft-launchpad/src/responses.rs deleted file mode 100644 index f236887448..0000000000 --- a/rust/cw-contracts/nft-launchpad/src/responses.rs +++ /dev/null @@ -1,26 +0,0 @@ -use cosmwasm_schema::cw_serde; - -#[cw_serde] -pub struct TokensMintedToUserResp { - pub count: u128, -} - -#[cw_serde] -pub struct MintableTokensResp { - pub count: u128, -} - -#[cw_serde] -pub struct MintPriceResp { - pub expected_public_mint_price: u128, - pub unit_price: u128, - pub whitelist_unit_price: u128, -} - -#[cw_serde] -pub struct CollectionResp { - pub name: String, - pub cover_img_uri: String, - pub desc: String, - pub symbol: String, -} From b6c1751a2156df47599f05740d8c6a485c4db976 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Wed, 6 Nov 2024 23:50:29 +0100 Subject: [PATCH 23/33] chore(launchpad): make generate --- networks.json | 4 +- .../nft-launchpad/NftLaunchpad.types.ts | 5 +- .../nft-launchpad/schema/nft-launchpad.json | 48 ++++--------------- .../nft-launchpad/schema/raw/execute.json | 18 ------- .../nft-launchpad/schema/raw/instantiate.json | 6 ++- .../raw/response_to_get_collection_by_id.json | 18 ------- .../schema/raw/response_to_get_config.json | 6 ++- 7 files changed, 19 insertions(+), 86 deletions(-) diff --git a/networks.json b/networks.json index 3073099b90..6b2bd671f1 100644 --- a/networks.json +++ b/networks.json @@ -11682,10 +11682,10 @@ }, { "type": "NFTLaunchpad", - "launchpadContractAddress": "tori1lp4qdzknyzwtsp45jn3vau4c9eedgafutkqq2j3lrc25u8jpftdqmsqxhu", + "launchpadContractAddress": "tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf", "launchpadEndpoint": "https://dapp-backend.testnet.teritori.com", "nftTr721CodeId": 60, - "codeId": 62, + "codeId": 71, "defaultMintDenom": "utori" } ], diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts index ede14d66c5..94abc9d7a8 100644 --- a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts @@ -10,7 +10,7 @@ export interface InstantiateMsg { [k: string]: unknown; } export interface Config { - launchpad_admin: Addr; + launchpad_admin?: string | null; name: string; nft_code_id?: number | null; owner: Addr; @@ -55,9 +55,6 @@ export interface Collection { deployed_address?: string | null; desc: string; escrow_mint_proceeds_period: number; - expected_mint_date: number; - expected_public_mint_price: number; - expected_supply: number; investment_desc: string; investment_link: string; is_applied_previously: boolean; diff --git a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json index 40967edf77..200f9143bb 100644 --- a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -22,14 +22,16 @@ "Config": { "type": "object", "required": [ - "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "$ref": "#/definitions/Addr" + "type": [ + "string", + "null" + ] }, "name": { "type": "string" @@ -174,9 +176,6 @@ "dao_whitelist_count", "desc", "escrow_mint_proceeds_period", - "expected_mint_date", - "expected_public_mint_price", - "expected_supply", "investment_desc", "investment_link", "is_applied_previously", @@ -229,21 +228,6 @@ "format": "uint64", "minimum": 0.0 }, - "expected_mint_date": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_public_mint_price": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_supply": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, "investment_desc": { "type": "string" }, @@ -515,9 +499,6 @@ "dao_whitelist_count", "desc", "escrow_mint_proceeds_period", - "expected_mint_date", - "expected_public_mint_price", - "expected_supply", "investment_desc", "investment_link", "is_applied_previously", @@ -570,21 +551,6 @@ "format": "uint64", "minimum": 0.0 }, - "expected_mint_date": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_public_mint_price": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_supply": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, "investment_desc": { "type": "string" }, @@ -789,14 +755,16 @@ "title": "Config", "type": "object", "required": [ - "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "$ref": "#/definitions/Addr" + "type": [ + "string", + "null" + ] }, "name": { "type": "string" diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json index 10a1f0fff6..9adc84b551 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json @@ -116,9 +116,6 @@ "dao_whitelist_count", "desc", "escrow_mint_proceeds_period", - "expected_mint_date", - "expected_public_mint_price", - "expected_supply", "investment_desc", "investment_link", "is_applied_previously", @@ -171,21 +168,6 @@ "format": "uint64", "minimum": 0.0 }, - "expected_mint_date": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_public_mint_price": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_supply": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, "investment_desc": { "type": "string" }, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json index 201cac4558..360632ceb1 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json @@ -18,14 +18,16 @@ "Config": { "type": "object", "required": [ - "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "$ref": "#/definitions/Addr" + "type": [ + "string", + "null" + ] }, "name": { "type": "string" diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json index 4c6faf9d40..88c1a1d3e6 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json @@ -9,9 +9,6 @@ "dao_whitelist_count", "desc", "escrow_mint_proceeds_period", - "expected_mint_date", - "expected_public_mint_price", - "expected_supply", "investment_desc", "investment_link", "is_applied_previously", @@ -64,21 +61,6 @@ "format": "uint64", "minimum": 0.0 }, - "expected_mint_date": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_public_mint_price": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "expected_supply": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, "investment_desc": { "type": "string" }, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json index f1c5110571..1b0a37012d 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json @@ -3,14 +3,16 @@ "title": "Config", "type": "object", "required": [ - "launchpad_admin", "name", "owner", "supported_networks" ], "properties": { "launchpad_admin": { - "$ref": "#/definitions/Addr" + "type": [ + "string", + "null" + ] }, "name": { "type": "string" From e60a7bf5cd73e09c9635d07ac7ca1ef1998b869a Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Thu, 7 Nov 2024 10:57:51 -0500 Subject: [PATCH 24/33] chore(launchpad): change feature name --- packages/networks/ethereum-goerli/index.ts | 2 +- packages/networks/ethereum/index.ts | 2 +- packages/networks/features.ts | 12 ++++++------ packages/networks/teritori-localnet/index.ts | 2 +- packages/networks/teritori-testnet/index.ts | 12 ++++++------ packages/networks/teritori/index.ts | 2 +- .../Launchpad/LaunchpadHome/LaunchpadScreen.tsx | 4 +++- packages/screens/Launchpad/MintCollectionScreen.tsx | 2 +- 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/networks/ethereum-goerli/index.ts b/packages/networks/ethereum-goerli/index.ts index 8ebb9dc659..609eb61e4b 100644 --- a/packages/networks/ethereum-goerli/index.ts +++ b/packages/networks/ethereum-goerli/index.ts @@ -11,7 +11,7 @@ export const ethereumGoerliNetwork: EthereumNetworkInfo = { features: [ NetworkFeature.NFTMarketplace, NetworkFeature.RiotP2E, - NetworkFeature.NFTLaunchpad, + NetworkFeature.CosmWasmNFTLaunchpad, NetworkFeature.NFTBridge, ], currencies: ethereumGoerliCurrencies, diff --git a/packages/networks/ethereum/index.ts b/packages/networks/ethereum/index.ts index ba6c5ef64f..bc75e29a2a 100644 --- a/packages/networks/ethereum/index.ts +++ b/packages/networks/ethereum/index.ts @@ -11,7 +11,7 @@ export const ethereumNetwork: EthereumNetworkInfo = { features: [ NetworkFeature.NFTMarketplace, NetworkFeature.RiotP2E, - NetworkFeature.NFTLaunchpad, + NetworkFeature.CosmWasmNFTLaunchpad, NetworkFeature.NFTBridge, ], currencies: ethereumCurrencies, diff --git a/packages/networks/features.ts b/packages/networks/features.ts index 85de0155da..12094116dc 100644 --- a/packages/networks/features.ts +++ b/packages/networks/features.ts @@ -2,7 +2,7 @@ import { z } from "zod"; export enum NetworkFeature { NFTMarketplace = "NFTMarketplace", - NFTLaunchpad = "NFTLaunchpad", + CosmWasmNFTLaunchpad = "CosmWasmNFTLaunchpad", NameService = "NameService", Swap = "Swap", BurnTokens = "BurnTokens", @@ -57,8 +57,8 @@ type CosmWasmSocialFeed = { // CosmWasm Launchpad -const zodCosmWasmLaunchpad = z.object({ - type: z.literal(NetworkFeature.NFTLaunchpad), +const zodCosmWasmNFTLaunchpad = z.object({ + type: z.literal(NetworkFeature.CosmWasmNFTLaunchpad), launchpadContractAddress: z.string(), defaultMintDenom: z.string(), launchpadEndpoint: z.string(), @@ -66,7 +66,7 @@ const zodCosmWasmLaunchpad = z.object({ nftTr721CodeId: z.number(), }); -export type CosmWasmLaunchpad = z.infer; +export type CosmWasmNFTLaunchpad = z.infer; // Gno Project Manager @@ -93,7 +93,7 @@ type LaunchpadERC20 = z.infer; export const allFeatureObjects = [ zodCosmWasmPremiumFeed, zodCosmWasmNFTsBurner, - zodCosmWasmLaunchpad, + zodCosmWasmNFTLaunchpad, zodGnoProjectManager, zodLaunchpadERC20, zodNFTMarketplace, @@ -102,7 +102,7 @@ export const allFeatureObjects = [ export type NetworkFeatureObject = | CosmWasmPremiumFeed | CosmWasmSocialFeed - | CosmWasmLaunchpad + | CosmWasmNFTLaunchpad | CosmWasmNFTsBurner | GnoProjectManager | LaunchpadERC20 diff --git a/packages/networks/teritori-localnet/index.ts b/packages/networks/teritori-localnet/index.ts index d8738204ad..3beea66aad 100644 --- a/packages/networks/teritori-localnet/index.ts +++ b/packages/networks/teritori-localnet/index.ts @@ -19,7 +19,7 @@ export const teritoriLocalnetNetwork: NetworkInfo = { NetworkFeature.UPP, NetworkFeature.NameService, NetworkFeature.BurnTokens, - NetworkFeature.NFTLaunchpad, + NetworkFeature.CosmWasmNFTLaunchpad, NetworkFeature.RiotP2E, NetworkFeature.NFTMarketplaceLeaderboard, ], diff --git a/packages/networks/teritori-testnet/index.ts b/packages/networks/teritori-testnet/index.ts index 8d9e9404f0..d6d4c3ee12 100644 --- a/packages/networks/teritori-testnet/index.ts +++ b/packages/networks/teritori-testnet/index.ts @@ -1,6 +1,6 @@ import { teritoriTestnetCurrencies } from "./currencies"; import { - CosmWasmLaunchpad, + CosmWasmNFTLaunchpad, CosmWasmNFTsBurner, CosmWasmPremiumFeed, NetworkFeature, @@ -30,8 +30,8 @@ const nftMarketplace: NFTMarketplace = { "tori1x72plnprsjnmszylmdm3cnvu5h6u55fyf0pe02lye9p6q2ws05ps33qmft", }; -const cosmwasmLaunchpadFeature: CosmWasmLaunchpad = { - type: NetworkFeature.NFTLaunchpad, +const cosmwasmNftLaunchpadFeature: CosmWasmNFTLaunchpad = { + type: NetworkFeature.CosmWasmNFTLaunchpad, launchpadContractAddress: "tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf", launchpadEndpoint: "https://dapp-backend.testnet.teritori.com", @@ -59,16 +59,16 @@ export const teritoriTestnetNetwork: CosmosNetworkInfo = { NetworkFeature.UPP, NetworkFeature.NameService, NetworkFeature.BurnTokens, - NetworkFeature.NFTLaunchpad, + NetworkFeature.CosmWasmNFTLaunchpad, NetworkFeature.CosmWasmPremiumFeed, NetworkFeature.NFTMarketplaceLeaderboard, NetworkFeature.CosmWasmNFTsBurner, ], featureObjects: [ premiumFeedFeature, - nftsBurnerFeature, + nftsBurnerFeature, nftMarketplace, - cosmwasmLaunchpadFeature, + cosmwasmNftLaunchpadFeature, ], currencies: teritoriTestnetCurrencies, txExplorer: "https://explorer.teritori.com/teritori-testnet/tx/$hash", diff --git a/packages/networks/teritori/index.ts b/packages/networks/teritori/index.ts index 8df8010c78..d779743586 100644 --- a/packages/networks/teritori/index.ts +++ b/packages/networks/teritori/index.ts @@ -27,7 +27,7 @@ export const teritoriNetwork: CosmosNetworkInfo = { NetworkFeature.UPP, NetworkFeature.NameService, NetworkFeature.BurnTokens, - NetworkFeature.NFTLaunchpad, + NetworkFeature.CosmWasmNFTLaunchpad, NetworkFeature.NFTMarketplaceLeaderboard, NetworkFeature.CosmWasmNFTsBurner, ], diff --git a/packages/screens/Launchpad/LaunchpadHome/LaunchpadScreen.tsx b/packages/screens/Launchpad/LaunchpadHome/LaunchpadScreen.tsx index a66357861b..6337588388 100644 --- a/packages/screens/Launchpad/LaunchpadHome/LaunchpadScreen.tsx +++ b/packages/screens/Launchpad/LaunchpadHome/LaunchpadScreen.tsx @@ -19,7 +19,9 @@ export const LaunchpadScreen: ScreenFC<"Launchpad"> = () => { const selectedNetworkId = useSelectedNetworkId(); return ( - + = ({ }; }, [info.unitPrice, info?.priceDenom]); const canPayForMint = useCanPay({ userId, cost }); - const forceNetworkFeature = NetworkFeature.NFTLaunchpad; + const forceNetworkFeature = NetworkFeature.CosmWasmNFTLaunchpad; const imageSize = viewWidth < maxImageSize ? viewWidth : maxImageSize; const mintButtonDisabled = minted; From 6b03eda08442bbbfde281cde13f683adcd7828cc Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Thu, 7 Nov 2024 10:58:38 -0500 Subject: [PATCH 25/33] chore(launchpad): remove unused exports --- packages/scripts/network-setup/deployNftLaunchpad.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/scripts/network-setup/deployNftLaunchpad.ts b/packages/scripts/network-setup/deployNftLaunchpad.ts index 122beb5db8..734352c222 100644 --- a/packages/scripts/network-setup/deployNftLaunchpad.ts +++ b/packages/scripts/network-setup/deployNftLaunchpad.ts @@ -18,7 +18,7 @@ import { storeWASM, } from "@/scripts/network-setup/deployLib"; -export const deployNftLaunchpad = async ({ +const deployNftLaunchpad = async ({ opts, networkId, wallet: deployerWallet, @@ -68,7 +68,7 @@ export const deployNftLaunchpad = async ({ }); }; -export const instantiateNftLaunchpad = async ( +const instantiateNftLaunchpad = async ( opts: DeployOpts, deployerWallet: string, deployerAddr: string, From 59af3a3726aa26a67c01e1fc0d89422fdd9a8e6b Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Thu, 7 Nov 2024 11:28:03 -0500 Subject: [PATCH 26/33] chore(launchpad): modify contract Remove unused supported_networks Set ConfigChanges all fields optional Rename struct Collection Remove unused CollectionState Remove comments --- rust/cw-contracts/nft-launchpad/config.json | 2 +- .../nft-launchpad/src/contract.rs | 45 ++++++------- .../nft-launchpad/src/multitest.rs | 67 +++++-------------- 3 files changed, 40 insertions(+), 74 deletions(-) diff --git a/rust/cw-contracts/nft-launchpad/config.json b/rust/cw-contracts/nft-launchpad/config.json index 530f1897d6..affee6a7f6 100644 --- a/rust/cw-contracts/nft-launchpad/config.json +++ b/rust/cw-contracts/nft-launchpad/config.json @@ -3,7 +3,7 @@ "name": "NFT Launchpad", "supported_networks": ["teritori-testnet"], "owner": "tori1llmym9upcpwnz7qte856ghlp5437ezz2gg7z0q", - "launchpad_admin": "tori1kjvyqf4mttwrhfuq5gfj9xgxx9jdt92xnxzf770x853567ymx8cscrnw05", + "admin": "tori1kjvyqf4mttwrhfuq5gfj9xgxx9jdt92xnxzf770x853567ymx8cscrnw05", "nft_code_id": 60 } } diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index dc2b5431db..b15ef57b1c 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -24,7 +24,7 @@ const INSTANTIATE_REPLY_ID: u64 = 1u64; // Contract states ------------------------------------------------------ pub struct NftLaunchpad { pub(crate) config: Item<'static, Config>, // nft launchpad config - pub(crate) collections: Map<'static, String, Collection>, // collection id => collection info + pub(crate) collections: Map<'static, String, CollectionProject>, // collection id => collection info pub(crate) instantiating_collection_id: Item<'static, String>, } @@ -65,10 +65,16 @@ impl NftLaunchpad { if ctx.info.sender != config.owner { return Err(ContractError::Unauthorized); } + // Save new config - config.launchpad_admin = changes.launchpad_admin; - config.nft_code_id = changes.nft_code_id; - config.supported_networks = changes.supported_networks; + if let Some(nft_code_id) = changes.nft_code_id { + config.nft_code_id = Some(nft_code_id); + attributes.push(attr("new_nft_code_id", nft_code_id.to_string())) + } + if let Some(admin) = &changes.admin { + config.admin = Some(ctx.deps.api.addr_validate(&admin)?); + attributes.push(attr("new_admin", admin)) + } if let Some(owner) = changes.owner { config.owner = ctx.deps.api.addr_validate(&owner)?; attributes.push(attr("new_owner", owner)) @@ -82,7 +88,7 @@ impl NftLaunchpad { pub fn submit_collection( &self, ctx: ExecCtx, - collection: Collection, + collection: CollectionProject, ) -> Result { let storage = ctx.deps.storage; @@ -169,10 +175,10 @@ impl NftLaunchpad { let config = self.config.load(ctx.deps.storage)?; // Only allow launchpad_admin to deploy - if config.launchpad_admin.is_none() { + if config.admin.is_none() { return Err(ContractError::DeployerMissing); } - if sender != config.launchpad_admin.unwrap() { + if sender != config.admin.unwrap() { return Err(ContractError::WrongDeployer); } @@ -187,12 +193,11 @@ impl NftLaunchpad { } let nft_code_id = config.nft_code_id; - // Do not allow to deploy collection is nft_code_is is not set if nft_code_id.is_none() { return Err(ContractError::NftCodeIdMissing); } - + // NOTE: cannot use wasm_instantiate because we need to specify admin let instantiate_msg = WasmMsg::Instantiate { admin: Some(sender.clone()), @@ -237,7 +242,7 @@ impl NftLaunchpad { &self, ctx: QueryCtx, collection_id: String, - ) -> StdResult { + ) -> StdResult { let collection = self.collections.load(ctx.deps.storage, collection_id)?; Ok(collection) } @@ -281,30 +286,28 @@ impl NftLaunchpad { pub struct Config { pub name: String, pub nft_code_id: Option, - pub supported_networks: Vec, - pub launchpad_admin: Option, + pub admin: Option, pub owner: Addr, } #[cw_serde] pub struct ConfigChanges { - pub name: String, + pub name: Option, pub nft_code_id: Option, - pub supported_networks: Vec, - pub launchpad_admin: Option, + pub admin: Option, pub owner: Option, } #[cw_serde] #[derive(Default)] -pub struct Collection { - // Collection info ---------------------------- +pub struct CollectionProject { + // Info ---------------------------- pub name: String, pub desc: String, pub symbol: String, // Unique pub cover_img_uri: String, pub target_network: String, - // Collection details ---------------------------- + // Details ---------------------------- pub website_link: String, pub contact_email: String, pub is_project_derivative: bool, @@ -335,10 +338,4 @@ pub struct Collection { pub metadatas_merkle_root: Option, pub deployed_address: Option, pub owner: Option, -} - -#[cw_serde] -pub enum CollectionState { - Pending, // When user summit the collection but not deployed yet - Deployed, // When collection has been deployed } \ No newline at end of file diff --git a/rust/cw-contracts/nft-launchpad/src/multitest.rs b/rust/cw-contracts/nft-launchpad/src/multitest.rs index 1ce369bc5d..00a296cac0 100644 --- a/rust/cw-contracts/nft-launchpad/src/multitest.rs +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -2,7 +2,7 @@ use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; use sylvia::multitest::App; use crate::{ - contract::{sv::multitest_utils::CodeId as LaunchpadCodeId, Collection, Config}, + contract::{sv::multitest_utils::CodeId as LaunchpadCodeId, CollectionProject, Config}, error::ContractError, }; @@ -11,7 +11,7 @@ use nft_tr721::contract::{ sv::multitest_utils::CodeId as NftTr721CodeId, MintPeriod, WhitelistInfo, }; -fn get_default_collection() -> Collection { +fn get_default_collection() -> CollectionProject { let mint_periods = vec![MintPeriod { price: Some(Coin { amount: Uint128::new(10), @@ -29,64 +29,39 @@ fn get_default_collection() -> Collection { }), }]; - Collection { - // Collection info ---------------------------- + CollectionProject { + // Info ---------------------------- name: "name".to_string(), desc: "desc".to_string(), symbol: "SYMBOL".to_string(), cover_img_uri: "img".to_string(), target_network: "network".to_string(), - // external_link: None, - - // Collection details ---------------------------- + // Details ---------------------------- website_link: "aaa".to_string(), - - // twitter_profile: "twitter_profile".to_string(), - // twitter_followers_count: 1, - - // contact_discord_name: "contact_discord_name".to_string(), contact_email: "contact_email".to_string(), - is_project_derivative: true, - project_type: "project_type".to_string(), project_desc: "project_desc".to_string(), - is_applied_previously: false, - // Team info -------------------------------------- team_desc: "team_desc".to_string(), - // team_link: "team_link".to_string(), - partners: "partners".to_string(), - investment_desc: "investment_desc".to_string(), investment_link: "investment_link".to_string(), - - // whitepaper_link: "whitepaper_link".to_string(), - // roadmap_link: "roadmap_link".to_string(), - // Additional info ---------------------------- artwork_desc: "artwork_desc".to_string(), - is_ready_for_mint: true, - escrow_mint_proceeds_period: u64::default(), is_dox: true, - dao_whitelist_count: 10, - // Minting details ---------------------------- tokens_count: 1000, reveal_time: Some(u64::default()), - // Whitelist minting -------------------------- mint_periods, - // Royalty -------------------------- royalty_address: Some(Addr::unchecked("royalty_address")), royalty_percentage: Some(50), - // Extend info -------------------------- base_token_uri: None, metadatas_merkle_root: None, @@ -104,9 +79,8 @@ fn instantiate() { // Instantiate let config = Config { name: "teritori launchpad".to_string(), - supported_networks: vec![], nft_code_id: None, - launchpad_admin: Some("admin".to_string()), + admin: Some(Addr::unchecked("admin")), owner: Addr::unchecked(sender), }; @@ -138,9 +112,8 @@ fn full_flow() { let contract = LaunchpadCodeId::store_code(&app) .instantiate(Config { name: "teritori launchpad".to_string(), - supported_networks: vec![], nft_code_id: None, - launchpad_admin: Some("admin".to_string()), + admin: Some(Addr::unchecked("admin")), owner: Addr::unchecked(sender), }) .call(sender) @@ -153,9 +126,9 @@ fn full_flow() { // Create collection without period ----------------------------------------- { let err = contract - .submit_collection(Collection { + .submit_collection(CollectionProject { mint_periods: vec![], - ..Collection::default() + ..CollectionProject::default() }) .call(sender) .unwrap_err(); @@ -166,7 +139,7 @@ fn full_flow() { // Create collection with invalid symbol --------------------------------------------------------- { let err = contract - .submit_collection(Collection { + .submit_collection(CollectionProject { symbol: "a_123".to_string(), ..default_collection.clone() }) @@ -212,10 +185,9 @@ fn full_flow() { { let err = contract .update_config(ConfigChanges { - name: "test".to_string(), + name: Some("test".to_string()), nft_code_id: Some(deployed_nft_code_id), - supported_networks: vec![], - launchpad_admin: Some(sender.to_string()), + admin: Some(sender.to_string()), owner: Some(sender.to_string()), }) .call("wrong_owner") @@ -227,10 +199,9 @@ fn full_flow() { { contract .update_config(ConfigChanges { - name: "test".to_string(), - supported_networks: vec![], + name: Some("test".to_string()), nft_code_id: None, - launchpad_admin: Some("deployer".to_string()), + admin: Some("deployer".to_string()), owner: Some(sender.to_string()), }) .call(sender) @@ -247,10 +218,9 @@ fn full_flow() { { contract .update_config(ConfigChanges { - name: "test".to_string(), - supported_networks: vec![], + name: Some("test".to_string()), nft_code_id: None, - launchpad_admin: Some(sender.to_string()), + admin: Some(sender.to_string()), owner: Some(sender.to_string()), }) .call(sender) @@ -312,10 +282,9 @@ fn full_flow() { { contract .update_config(ConfigChanges { - name: "test".to_string(), + name: Some("test".to_string()), nft_code_id: Some(deployed_nft_code_id), - supported_networks: vec![], - launchpad_admin: Some(sender.to_string()), + admin: Some(sender.to_string()), owner: Some(sender.to_string()), }) .call(sender) From b7f91f60ebd574254bae8c078445cc374c6d9dea Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Thu, 7 Nov 2024 11:36:09 -0500 Subject: [PATCH 27/33] fix(launchpad): feature usage in script --- packages/scripts/network-setup/deployNftLaunchpad.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/scripts/network-setup/deployNftLaunchpad.ts b/packages/scripts/network-setup/deployNftLaunchpad.ts index 734352c222..90e0f2e49b 100644 --- a/packages/scripts/network-setup/deployNftLaunchpad.ts +++ b/packages/scripts/network-setup/deployNftLaunchpad.ts @@ -10,7 +10,7 @@ import { getNetworkFeature, NetworkFeature, } from "@/networks"; -import { CosmWasmLaunchpad } from "@/networks/features"; +import { CosmWasmNFTLaunchpad } from "@/networks/features"; import { DeployOpts, initDeploy, @@ -36,7 +36,7 @@ const deployNftLaunchpad = async ({ }); const cosmwasmLaunchpadFeature = cloneDeep( - getNetworkFeature(networkId, NetworkFeature.NFTLaunchpad), + getNetworkFeature(networkId, NetworkFeature.CosmWasmNFTLaunchpad), ); if (!cosmwasmLaunchpadFeature) { console.error(`Cosmwasm Launchpad feature not found on ${networkId}`); @@ -62,7 +62,7 @@ const deployNftLaunchpad = async ({ cosmwasmLaunchpadFeature, ); network.featureObjects = network.featureObjects?.map((featureObject) => { - if (featureObject.type === NetworkFeature.NFTLaunchpad) { + if (featureObject.type === NetworkFeature.CosmWasmNFTLaunchpad) { return cosmwasmLaunchpadFeature; } else return featureObject; }); @@ -74,7 +74,7 @@ const instantiateNftLaunchpad = async ( deployerAddr: string, launchpadAdmin: string, network: CosmosNetworkInfo, - featureObject: CosmWasmLaunchpad, + featureObject: CosmWasmNFTLaunchpad, ) => { const codeId = featureObject.codeId; if (!codeId) { @@ -93,7 +93,7 @@ const instantiateNftLaunchpad = async ( config: { name: "Teritori NFT Launchpad", supported_networks: allNetworks - .filter((n) => n.features.includes(NetworkFeature.NFTLaunchpad)) + .filter((n) => n.features.includes(NetworkFeature.CosmWasmNFTLaunchpad)) .map((n) => n.id), owner: deployerAddr, launchpad_admin: launchpadAdmin, @@ -126,7 +126,7 @@ const deployNftTr721 = async ({ wallet: deployerWallet, }); const cosmwasmLaunchpadFeature = cloneDeep( - getNetworkFeature(networkId, NetworkFeature.NFTLaunchpad), + getNetworkFeature(networkId, NetworkFeature.CosmWasmNFTLaunchpad), ); if (!cosmwasmLaunchpadFeature) { console.error(`Cosmwasm Launchpad feature not found on ${networkId}`); From 4bdc5947466b2ef502add2add6d1961e6b07b9ac Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Thu, 7 Nov 2024 17:54:29 +0100 Subject: [PATCH 28/33] chore(launchpad): make generate --- go/pkg/networks/features.gen.go | 22 +++---- networks.json | 12 ++-- .../nft-launchpad/NftLaunchpad.client.ts | 10 +-- .../nft-launchpad/NftLaunchpad.types.ts | 12 ++-- .../nft-launchpad/schema/nft-launchpad.json | 65 ++++++++----------- .../nft-launchpad/schema/raw/execute.json | 21 ++---- .../nft-launchpad/schema/raw/instantiate.json | 21 +++--- .../raw/response_to_get_collection_by_id.json | 2 +- .../schema/raw/response_to_get_config.json | 21 +++--- 9 files changed, 79 insertions(+), 107 deletions(-) diff --git a/go/pkg/networks/features.gen.go b/go/pkg/networks/features.gen.go index 6185540f36..07bcc8646a 100644 --- a/go/pkg/networks/features.gen.go +++ b/go/pkg/networks/features.gen.go @@ -7,7 +7,7 @@ import ( const ( FeatureTypeNFTMarketplace = FeatureType("NFTMarketplace") - FeatureTypeNFTLaunchpad = FeatureType("NFTLaunchpad") + FeatureTypeCosmWasmNFTLaunchpad = FeatureType("CosmWasmNFTLaunchpad") FeatureTypeNameService = FeatureType("NameService") FeatureTypeSwap = FeatureType("Swap") FeatureTypeBurnTokens = FeatureType("BurnTokens") @@ -63,7 +63,7 @@ func (nb *NetworkBase) GetFeatureCosmWasmNFTsBurner() (*FeatureCosmWasmNFTsBurne return feature.(*FeatureCosmWasmNFTsBurner), nil } -type FeatureNFTLaunchpad struct { +type FeatureCosmWasmNFTLaunchpad struct { *FeatureBase LaunchpadContractAddress string `json:"launchpadContractAddress"` DefaultMintDenom string `json:"defaultMintDenom"` @@ -72,18 +72,18 @@ type FeatureNFTLaunchpad struct { NftTr721CodeId float64 `json:"nftTr721CodeId"` } -var _ Feature = &FeatureNFTLaunchpad{} +var _ Feature = &FeatureCosmWasmNFTLaunchpad{} -func (f FeatureNFTLaunchpad) Type() FeatureType { - return FeatureTypeNFTLaunchpad +func (f FeatureCosmWasmNFTLaunchpad) Type() FeatureType { + return FeatureTypeCosmWasmNFTLaunchpad } -func (nb *NetworkBase) GetFeatureNFTLaunchpad() (*FeatureNFTLaunchpad, error) { - feature, err := nb.GetFeature(FeatureTypeNFTLaunchpad) +func (nb *NetworkBase) GetFeatureCosmWasmNFTLaunchpad() (*FeatureCosmWasmNFTLaunchpad, error) { + feature, err := nb.GetFeature(FeatureTypeCosmWasmNFTLaunchpad) if err != nil { return nil, err } - return feature.(*FeatureNFTLaunchpad), nil + return feature.(*FeatureCosmWasmNFTLaunchpad), nil } type FeatureGnoProjectManager struct { @@ -164,10 +164,10 @@ func UnmarshalFeature(b []byte) (Feature, error) { return nil, errors.Wrap(err, "failed to unmarshal feature CosmWasmNFTsBurner") } return &f, nil - case FeatureTypeNFTLaunchpad: - var f FeatureNFTLaunchpad + case FeatureTypeCosmWasmNFTLaunchpad: + var f FeatureCosmWasmNFTLaunchpad if err := json.Unmarshal(b, &f); err != nil { - return nil, errors.Wrap(err, "failed to unmarshal feature NFTLaunchpad") + return nil, errors.Wrap(err, "failed to unmarshal feature CosmWasmNFTLaunchpad") } return &f, nil case FeatureTypeGnoProjectManager: diff --git a/networks.json b/networks.json index 6b2bd671f1..0bc499b1bd 100644 --- a/networks.json +++ b/networks.json @@ -3880,7 +3880,7 @@ "features": [ "NFTMarketplace", "RiotP2E", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "NFTBridge" ], "currencies": [ @@ -3926,7 +3926,7 @@ "features": [ "NFTMarketplace", "RiotP2E", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "NFTBridge" ], "currencies": [ @@ -11483,7 +11483,7 @@ "UPP", "NameService", "BurnTokens", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "NFTMarketplaceLeaderboard", "CosmWasmNFTsBurner" ], @@ -11581,7 +11581,7 @@ "UPP", "NameService", "BurnTokens", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "RiotP2E", "NFTMarketplaceLeaderboard" ], @@ -11660,7 +11660,7 @@ "UPP", "NameService", "BurnTokens", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "CosmWasmPremiumFeed", "NFTMarketplaceLeaderboard", "CosmWasmNFTsBurner" @@ -11681,7 +11681,7 @@ "cwAddressListContractAddress": "tori1x72plnprsjnmszylmdm3cnvu5h6u55fyf0pe02lye9p6q2ws05ps33qmft" }, { - "type": "NFTLaunchpad", + "type": "CosmWasmNFTLaunchpad", "launchpadContractAddress": "tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf", "launchpadEndpoint": "https://dapp-backend.testnet.teritori.com", "nftTr721CodeId": 60, diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts index 73ab8e42ff..4766c6f717 100644 --- a/packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.client.ts @@ -6,14 +6,14 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { StdFee } from "@cosmjs/amino"; -import { Addr, InstantiateMsg, Config, ExecuteMsg, Uint128, ConfigChanges, Collection, MintPeriod, Coin, WhitelistInfo, QueryMsg } from "./NftLaunchpad.types"; +import { Addr, InstantiateMsg, Config, ExecuteMsg, Uint128, ConfigChanges, CollectionProject, MintPeriod, Coin, WhitelistInfo, QueryMsg } from "./NftLaunchpad.types"; export interface NftLaunchpadReadOnlyInterface { contractAddress: string; getCollectionById: ({ collectionId }: { collectionId: string; - }) => Promise; + }) => Promise; getConfig: () => Promise; } export class NftLaunchpadQueryClient implements NftLaunchpadReadOnlyInterface { @@ -31,7 +31,7 @@ export class NftLaunchpadQueryClient implements NftLaunchpadReadOnlyInterface { collectionId }: { collectionId: string; - }): Promise => { + }): Promise => { return this.client.queryContractSmart(this.contractAddress, { get_collection_by_id: { collection_id: collectionId @@ -55,7 +55,7 @@ export interface NftLaunchpadInterface extends NftLaunchpadReadOnlyInterface { submitCollection: ({ collection }: { - collection: Collection; + collection: CollectionProject; }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; updateMerkleRoot: ({ collectionId, @@ -100,7 +100,7 @@ export class NftLaunchpadClient extends NftLaunchpadQueryClient implements NftLa submitCollection = async ({ collection }: { - collection: Collection; + collection: CollectionProject; }, fee: number | StdFee | "auto" = "auto", memo?: string, _funds?: Coin[]): Promise => { return await this.client.execute(this.sender, this.contractAddress, { submit_collection: { diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts index 94abc9d7a8..77bd065577 100644 --- a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts @@ -10,11 +10,10 @@ export interface InstantiateMsg { [k: string]: unknown; } export interface Config { - launchpad_admin?: string | null; + admin?: Addr | null; name: string; nft_code_id?: number | null; owner: Addr; - supported_networks: string[]; } export type ExecuteMsg = { update_config: { @@ -23,7 +22,7 @@ export type ExecuteMsg = { }; } | { submit_collection: { - collection: Collection; + collection: CollectionProject; [k: string]: unknown; }; } | { @@ -40,13 +39,12 @@ export type ExecuteMsg = { }; export type Uint128 = string; export interface ConfigChanges { - launchpad_admin?: string | null; - name: string; + admin?: string | null; + name?: string | null; nft_code_id?: number | null; owner?: string | null; - supported_networks: string[]; } -export interface Collection { +export interface CollectionProject { artwork_desc: string; base_token_uri?: string | null; contact_email: string; diff --git a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json index 200f9143bb..f49d73cfb4 100644 --- a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -23,14 +23,17 @@ "type": "object", "required": [ "name", - "owner", - "supported_networks" + "owner" ], "properties": { - "launchpad_admin": { - "type": [ - "string", - "null" + "admin": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } ] }, "name": { @@ -46,12 +49,6 @@ }, "owner": { "$ref": "#/definitions/Addr" - }, - "supported_networks": { - "type": "array", - "items": { - "type": "string" - } } }, "additionalProperties": false @@ -95,7 +92,7 @@ ], "properties": { "collection": { - "$ref": "#/definitions/Collection" + "$ref": "#/definitions/CollectionProject" } } } @@ -167,7 +164,7 @@ } } }, - "Collection": { + "CollectionProject": { "type": "object", "required": [ "artwork_desc", @@ -324,19 +321,18 @@ }, "ConfigChanges": { "type": "object", - "required": [ - "name", - "supported_networks" - ], "properties": { - "launchpad_admin": { + "admin": { "type": [ "string", "null" ] }, "name": { - "type": "string" + "type": [ + "string", + "null" + ] }, "nft_code_id": { "type": [ @@ -351,12 +347,6 @@ "string", "null" ] - }, - "supported_networks": { - "type": "array", - "items": { - "type": "string" - } } }, "additionalProperties": false @@ -490,7 +480,7 @@ "responses": { "get_collection_by_id": { "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Collection", + "title": "CollectionProject", "type": "object", "required": [ "artwork_desc", @@ -756,14 +746,17 @@ "type": "object", "required": [ "name", - "owner", - "supported_networks" + "owner" ], "properties": { - "launchpad_admin": { - "type": [ - "string", - "null" + "admin": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } ] }, "name": { @@ -779,12 +772,6 @@ }, "owner": { "$ref": "#/definitions/Addr" - }, - "supported_networks": { - "type": "array", - "items": { - "type": "string" - } } }, "additionalProperties": false, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json index 9adc84b551..ef7e0529d9 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json @@ -35,7 +35,7 @@ ], "properties": { "collection": { - "$ref": "#/definitions/Collection" + "$ref": "#/definitions/CollectionProject" } } } @@ -107,7 +107,7 @@ } } }, - "Collection": { + "CollectionProject": { "type": "object", "required": [ "artwork_desc", @@ -264,19 +264,18 @@ }, "ConfigChanges": { "type": "object", - "required": [ - "name", - "supported_networks" - ], "properties": { - "launchpad_admin": { + "admin": { "type": [ "string", "null" ] }, "name": { - "type": "string" + "type": [ + "string", + "null" + ] }, "nft_code_id": { "type": [ @@ -291,12 +290,6 @@ "string", "null" ] - }, - "supported_networks": { - "type": "array", - "items": { - "type": "string" - } } }, "additionalProperties": false diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json index 360632ceb1..1024313808 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json @@ -19,14 +19,17 @@ "type": "object", "required": [ "name", - "owner", - "supported_networks" + "owner" ], "properties": { - "launchpad_admin": { - "type": [ - "string", - "null" + "admin": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } ] }, "name": { @@ -42,12 +45,6 @@ }, "owner": { "$ref": "#/definitions/Addr" - }, - "supported_networks": { - "type": "array", - "items": { - "type": "string" - } } }, "additionalProperties": false diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json index 88c1a1d3e6..c290b42dc5 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Collection", + "title": "CollectionProject", "type": "object", "required": [ "artwork_desc", diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json index 1b0a37012d..ed0310c38a 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json @@ -4,14 +4,17 @@ "type": "object", "required": [ "name", - "owner", - "supported_networks" + "owner" ], "properties": { - "launchpad_admin": { - "type": [ - "string", - "null" + "admin": { + "anyOf": [ + { + "$ref": "#/definitions/Addr" + }, + { + "type": "null" + } ] }, "name": { @@ -27,12 +30,6 @@ }, "owner": { "$ref": "#/definitions/Addr" - }, - "supported_networks": { - "type": "array", - "items": { - "type": "string" - } } }, "additionalProperties": false, From 14f4a9a5b258b3489b489d00d0c006dd6a17a247 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Thu, 7 Nov 2024 13:57:15 -0500 Subject: [PATCH 29/33] fix(launchapd): deployNftLaunchpad.ts fix --- packages/scripts/network-setup/deployNftLaunchpad.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/scripts/network-setup/deployNftLaunchpad.ts b/packages/scripts/network-setup/deployNftLaunchpad.ts index 90e0f2e49b..cad793aeb3 100644 --- a/packages/scripts/network-setup/deployNftLaunchpad.ts +++ b/packages/scripts/network-setup/deployNftLaunchpad.ts @@ -5,7 +5,6 @@ import path from "path"; import { InstantiateMsg as NftLaunchpadInstantiateMsg } from "@/contracts-clients/nft-launchpad"; import { - allNetworks, CosmosNetworkInfo, getNetworkFeature, NetworkFeature, @@ -92,11 +91,8 @@ const instantiateNftLaunchpad = async ( const instantiateMsg: NftLaunchpadInstantiateMsg = { config: { name: "Teritori NFT Launchpad", - supported_networks: allNetworks - .filter((n) => n.features.includes(NetworkFeature.CosmWasmNFTLaunchpad)) - .map((n) => n.id), owner: deployerAddr, - launchpad_admin: launchpadAdmin, + admin: launchpadAdmin, nft_code_id: nftCodeId, }, }; From 963b8391cd35228550f1309381df292ed4b1211c Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 8 Nov 2024 15:50:53 -0500 Subject: [PATCH 30/33] chore(launchpad): Set admin anf nft_code_id as mandatory. Remove unused project_desc. --- .../nft-launchpad/src/contract.rs | 24 +++++-------- .../nft-launchpad/src/multitest.rs | 34 ++++++------------- 2 files changed, 19 insertions(+), 39 deletions(-) diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index b15ef57b1c..e607e2962d 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -68,11 +68,11 @@ impl NftLaunchpad { // Save new config if let Some(nft_code_id) = changes.nft_code_id { - config.nft_code_id = Some(nft_code_id); + config.nft_code_id = nft_code_id; attributes.push(attr("new_nft_code_id", nft_code_id.to_string())) } if let Some(admin) = &changes.admin { - config.admin = Some(ctx.deps.api.addr_validate(&admin)?); + config.admin = ctx.deps.api.addr_validate(&admin)?; attributes.push(attr("new_admin", admin)) } if let Some(owner) = changes.owner { @@ -175,10 +175,7 @@ impl NftLaunchpad { let config = self.config.load(ctx.deps.storage)?; // Only allow launchpad_admin to deploy - if config.admin.is_none() { - return Err(ContractError::DeployerMissing); - } - if sender != config.admin.unwrap() { + if sender != config.admin { return Err(ContractError::WrongDeployer); } @@ -193,15 +190,11 @@ impl NftLaunchpad { } let nft_code_id = config.nft_code_id; - // Do not allow to deploy collection is nft_code_is is not set - if nft_code_id.is_none() { - return Err(ContractError::NftCodeIdMissing); - } - + // NOTE: cannot use wasm_instantiate because we need to specify admin let instantiate_msg = WasmMsg::Instantiate { admin: Some(sender.clone()), - code_id: nft_code_id.unwrap(), + code_id: nft_code_id, msg: to_json_binary(&Tr721InstantiateMsg { admin: sender.clone(), name: collection.name.clone(), @@ -219,7 +212,7 @@ impl NftLaunchpad { funds: vec![], label: format!( "TR721 codeId:{} collectionId:{} symbol:{}", - nft_code_id.unwrap(), + nft_code_id, collection_id, collection.symbol ), @@ -285,8 +278,8 @@ impl NftLaunchpad { #[cw_serde] pub struct Config { pub name: String, - pub nft_code_id: Option, - pub admin: Option, + pub nft_code_id: u64, + pub admin: Addr, pub owner: Addr, } @@ -312,7 +305,6 @@ pub struct CollectionProject { pub contact_email: String, pub is_project_derivative: bool, pub project_type: String, - pub project_desc: String, pub is_applied_previously: bool, // Team info -------------------------------------- pub team_desc: String, diff --git a/rust/cw-contracts/nft-launchpad/src/multitest.rs b/rust/cw-contracts/nft-launchpad/src/multitest.rs index 00a296cac0..4fcc5f39cb 100644 --- a/rust/cw-contracts/nft-launchpad/src/multitest.rs +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -41,7 +41,6 @@ fn get_default_collection() -> CollectionProject { contact_email: "contact_email".to_string(), is_project_derivative: true, project_type: "project_type".to_string(), - project_desc: "project_desc".to_string(), is_applied_previously: false, // Team info -------------------------------------- team_desc: "team_desc".to_string(), @@ -75,12 +74,15 @@ fn instantiate() { let app = App::default(); let code_id = LaunchpadCodeId::store_code(&app); let sender = "sender"; + // Deploy NFT TR721 for sylvia contract + let nft_contract = NftTr721CodeId::store_code(&app); + let deployed_nft_code_id = nft_contract.code_id(); // Instantiate let config = Config { name: "teritori launchpad".to_string(), - nft_code_id: None, - admin: Some(Addr::unchecked("admin")), + nft_code_id: deployed_nft_code_id, + admin: Addr::unchecked("admin"), owner: Addr::unchecked(sender), }; @@ -99,12 +101,7 @@ fn full_flow() { let app: App = App::default(); let sender = "sender"; - // Deploy NFT contract for non-sylvia contract - // let contract_wrapper = ContractWrapper::new(tr721_execute, tr721_instantiate, tr721_query); - // let launchpad_contract = Box::new(contract_wrapper); - // let deployed_nft_code_id = app.app_mut().store_code(launchpad_contract); - - // Deploy NFT for sylvia contract + // Deploy NFT TR721 for sylvia contract let nft_contract = NftTr721CodeId::store_code(&app); let deployed_nft_code_id = nft_contract.code_id(); @@ -112,8 +109,8 @@ fn full_flow() { let contract = LaunchpadCodeId::store_code(&app) .instantiate(Config { name: "teritori launchpad".to_string(), - nft_code_id: None, - admin: Some(Addr::unchecked("admin")), + nft_code_id: deployed_nft_code_id, + admin: Addr::unchecked("admin"), owner: Addr::unchecked(sender), }) .call(sender) @@ -200,7 +197,7 @@ fn full_flow() { contract .update_config(ConfigChanges { name: Some("test".to_string()), - nft_code_id: None, + nft_code_id: Some(deployed_nft_code_id), admin: Some("deployer".to_string()), owner: Some(sender.to_string()), }) @@ -219,7 +216,7 @@ fn full_flow() { contract .update_config(ConfigChanges { name: Some("test".to_string()), - nft_code_id: None, + nft_code_id: Some(deployed_nft_code_id), admin: Some(sender.to_string()), owner: Some(sender.to_string()), }) @@ -269,15 +266,6 @@ fn full_flow() { ); } - // Deploy collection with merkle root but dont have nft code id --------------------------------------------------------- - { - let err = contract - .deploy_collection("SYMBOL".to_string()) - .call(sender) - .unwrap_err(); - assert_eq!(err, ContractError::NftCodeIdMissing) - } - // Update config to have deployed nft_code_id { contract @@ -291,7 +279,7 @@ fn full_flow() { .unwrap(); let resp = contract.get_config().unwrap(); - assert_eq!(resp.nft_code_id, Some(deployed_nft_code_id)) + assert_eq!(resp.nft_code_id, deployed_nft_code_id) } // Deploy completed collection after update merkle root + nft code id --------------------------------------------------------- From 4ba5107d198ee3dc5cf4ae878083984dd12d12f4 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Fri, 8 Nov 2024 21:59:59 +0100 Subject: [PATCH 31/33] chore(launchpad): make generate --- .../nft-launchpad/NftLaunchpad.types.ts | 5 +-- .../nft-launchpad/schema/nft-launchpad.json | 40 ++++--------------- .../nft-launchpad/schema/raw/execute.json | 4 -- .../nft-launchpad/schema/raw/instantiate.json | 16 ++------ .../raw/response_to_get_collection_by_id.json | 4 -- .../schema/raw/response_to_get_config.json | 16 ++------ 6 files changed, 18 insertions(+), 67 deletions(-) diff --git a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts index 77bd065577..9f0b37c279 100644 --- a/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts @@ -10,9 +10,9 @@ export interface InstantiateMsg { [k: string]: unknown; } export interface Config { - admin?: Addr | null; + admin: Addr; name: string; - nft_code_id?: number | null; + nft_code_id: number; owner: Addr; } export type ExecuteMsg = { @@ -64,7 +64,6 @@ export interface CollectionProject { name: string; owner?: string | null; partners: string; - project_desc: string; project_type: string; reveal_time?: number | null; royalty_address?: Addr | null; diff --git a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json index f49d73cfb4..22a25df230 100644 --- a/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -22,28 +22,20 @@ "Config": { "type": "object", "required": [ + "admin", "name", + "nft_code_id", "owner" ], "properties": { "admin": { - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" }, "nft_code_id": { - "type": [ - "integer", - "null" - ], + "type": "integer", "format": "uint64", "minimum": 0.0 }, @@ -182,7 +174,6 @@ "mint_periods", "name", "partners", - "project_desc", "project_type", "symbol", "target_network", @@ -267,9 +258,6 @@ "partners": { "type": "string" }, - "project_desc": { - "type": "string" - }, "project_type": { "type": "string" }, @@ -498,7 +486,6 @@ "mint_periods", "name", "partners", - "project_desc", "project_type", "symbol", "target_network", @@ -583,9 +570,6 @@ "partners": { "type": "string" }, - "project_desc": { - "type": "string" - }, "project_type": { "type": "string" }, @@ -745,28 +729,20 @@ "title": "Config", "type": "object", "required": [ + "admin", "name", + "nft_code_id", "owner" ], "properties": { "admin": { - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" }, "nft_code_id": { - "type": [ - "integer", - "null" - ], + "type": "integer", "format": "uint64", "minimum": 0.0 }, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json index ef7e0529d9..80935c8a3e 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/execute.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json @@ -125,7 +125,6 @@ "mint_periods", "name", "partners", - "project_desc", "project_type", "symbol", "target_network", @@ -210,9 +209,6 @@ "partners": { "type": "string" }, - "project_desc": { - "type": "string" - }, "project_type": { "type": "string" }, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json index 1024313808..33c4480887 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json @@ -18,28 +18,20 @@ "Config": { "type": "object", "required": [ + "admin", "name", + "nft_code_id", "owner" ], "properties": { "admin": { - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" }, "nft_code_id": { - "type": [ - "integer", - "null" - ], + "type": "integer", "format": "uint64", "minimum": 0.0 }, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json index c290b42dc5..aa2eb34d55 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json @@ -18,7 +18,6 @@ "mint_periods", "name", "partners", - "project_desc", "project_type", "symbol", "target_network", @@ -103,9 +102,6 @@ "partners": { "type": "string" }, - "project_desc": { - "type": "string" - }, "project_type": { "type": "string" }, diff --git a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json index ed0310c38a..f58adb6046 100644 --- a/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json @@ -3,28 +3,20 @@ "title": "Config", "type": "object", "required": [ + "admin", "name", + "nft_code_id", "owner" ], "properties": { "admin": { - "anyOf": [ - { - "$ref": "#/definitions/Addr" - }, - { - "type": "null" - } - ] + "$ref": "#/definitions/Addr" }, "name": { "type": "string" }, "nft_code_id": { - "type": [ - "integer", - "null" - ], + "type": "integer", "format": "uint64", "minimum": 0.0 }, From 43ed58f0ffab16e362441d6b4e2665172154fd49 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 10 Nov 2024 18:26:01 +0100 Subject: [PATCH 32/33] chore(launchpad): cargo fmt --- rust/cw-contracts/nft-launchpad/src/contract.rs | 13 +++---------- rust/cw-contracts/nft-launchpad/src/error.rs | 2 +- rust/cw-contracts/nft-launchpad/src/multitest.rs | 4 ++-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/rust/cw-contracts/nft-launchpad/src/contract.rs b/rust/cw-contracts/nft-launchpad/src/contract.rs index e607e2962d..d993eb1c23 100644 --- a/rust/cw-contracts/nft-launchpad/src/contract.rs +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -1,10 +1,5 @@ - - use cosmwasm_schema::cw_serde; -use cosmwasm_std::{ - attr, to_json_binary, Addr, Reply, Response, - StdResult, SubMsg, WasmMsg, -}; +use cosmwasm_std::{attr, to_json_binary, Addr, Reply, Response, StdResult, SubMsg, WasmMsg}; use cw_storage_plus::{Item, Map}; use cw_utils::parse_reply_instantiate_data; use sylvia::{ @@ -212,9 +207,7 @@ impl NftLaunchpad { funds: vec![], label: format!( "TR721 codeId:{} collectionId:{} symbol:{}", - nft_code_id, - collection_id, - collection.symbol + nft_code_id, collection_id, collection.symbol ), }; @@ -330,4 +323,4 @@ pub struct CollectionProject { pub metadatas_merkle_root: Option, pub deployed_address: Option, pub owner: Option, -} \ No newline at end of file +} diff --git a/rust/cw-contracts/nft-launchpad/src/error.rs b/rust/cw-contracts/nft-launchpad/src/error.rs index 386461b3c1..e2a19ed93b 100644 --- a/rust/cw-contracts/nft-launchpad/src/error.rs +++ b/rust/cw-contracts/nft-launchpad/src/error.rs @@ -51,4 +51,4 @@ pub enum ContractError { #[error("{0}")] Instantiate2AddressError(#[from] Instantiate2AddressError), -} \ No newline at end of file +} diff --git a/rust/cw-contracts/nft-launchpad/src/multitest.rs b/rust/cw-contracts/nft-launchpad/src/multitest.rs index 4fcc5f39cb..ad0b550c3e 100644 --- a/rust/cw-contracts/nft-launchpad/src/multitest.rs +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -178,7 +178,7 @@ fn full_flow() { assert_eq!(err, ContractError::CollectionSymbolExists); } - // Update config when sender is not contract owner + // Update config when sender is not contract owner { let err = contract .update_config(ConfigChanges { @@ -302,4 +302,4 @@ fn full_flow() { let collection = contract.get_collection_by_id(collection_id).unwrap(); assert_eq!(collection.deployed_address, Some("contract1".to_string())); } -} \ No newline at end of file +} From e30436091589ab39a636c3178fa7b1f16081b7d7 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Sun, 10 Nov 2024 18:32:49 +0100 Subject: [PATCH 33/33] chore(launchpad): cargo fmt from root --- rust/apipb/src/launchpad.v1.rs | 114 ++++++++++---------- rust/cw-contracts/nft-tr721/src/contract.rs | 9 +- 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/rust/apipb/src/launchpad.v1.rs b/rust/apipb/src/launchpad.v1.rs index bce910d3e1..f401063ff1 100644 --- a/rust/apipb/src/launchpad.v1.rs +++ b/rust/apipb/src/launchpad.v1.rs @@ -4,131 +4,131 @@ #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectsByCreatorRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub creator_id: ::prost::alloc::string::String, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub network_id: ::prost::alloc::string::String, - #[prost(int32, tag="3")] + #[prost(int32, tag = "3")] pub limit: i32, - #[prost(int32, tag="4")] + #[prost(int32, tag = "4")] pub offset: i32, - #[prost(enumeration="Sort", tag="5")] + #[prost(enumeration = "Sort", tag = "5")] pub sort: i32, - #[prost(enumeration="SortDirection", tag="6")] + #[prost(enumeration = "SortDirection", tag = "6")] pub sort_direction: i32, - #[prost(enumeration="Status", optional, tag="7")] + #[prost(enumeration = "Status", optional, tag = "7")] pub status: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectsByCreatorResponse { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub projects: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectsRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub network_id: ::prost::alloc::string::String, - #[prost(int32, tag="2")] + #[prost(int32, tag = "2")] pub limit: i32, - #[prost(int32, tag="3")] + #[prost(int32, tag = "3")] pub offset: i32, - #[prost(enumeration="Sort", tag="4")] + #[prost(enumeration = "Sort", tag = "4")] pub sort: i32, - #[prost(enumeration="SortDirection", tag="5")] + #[prost(enumeration = "SortDirection", tag = "5")] pub sort_direction: i32, - #[prost(enumeration="Status", optional, tag="6")] + #[prost(enumeration = "Status", optional, tag = "6")] pub status: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectsResponse { - #[prost(message, repeated, tag="1")] + #[prost(message, repeated, tag = "1")] pub projects: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectByIdRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub network_id: ::prost::alloc::string::String, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub project_id: ::prost::alloc::string::String, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectByIdResponse { - #[prost(message, optional, tag="1")] + #[prost(message, optional, tag = "1")] pub project: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct UploadMetadatasRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub sender: ::prost::alloc::string::String, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub network_id: ::prost::alloc::string::String, - #[prost(string, tag="3")] + #[prost(string, tag = "3")] pub project_id: ::prost::alloc::string::String, - #[prost(message, repeated, tag="4")] + #[prost(message, repeated, tag = "4")] pub metadatas: ::prost::alloc::vec::Vec, - #[prost(string, optional, tag="5")] + #[prost(string, optional, tag = "5")] pub pinata_jwt: ::core::option::Option<::prost::alloc::string::String>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct UploadMetadatasResponse { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub merkle_root: ::prost::alloc::string::String, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct CalculateCollectionMerkleRootRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub sender: ::prost::alloc::string::String, - #[prost(message, repeated, tag="2")] + #[prost(message, repeated, tag = "2")] pub metadatas: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct CalculateCollectionMerkleRootResponse { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub merkle_root: ::prost::alloc::string::String, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct TokenMetadataRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub sender: ::prost::alloc::string::String, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub network_id: ::prost::alloc::string::String, - #[prost(string, tag="3")] + #[prost(string, tag = "3")] pub project_id: ::prost::alloc::string::String, - #[prost(uint32, tag="4")] + #[prost(uint32, tag = "4")] pub token_id: u32, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct TokenMetadataResponse { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub merkle_root: ::prost::alloc::string::String, - #[prost(message, optional, tag="2")] + #[prost(message, optional, tag = "2")] pub metadata: ::core::option::Option, - #[prost(string, repeated, tag="3")] + #[prost(string, repeated, tag = "3")] pub merkle_proof: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectsCountRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub network_id: ::prost::alloc::string::String, - #[prost(enumeration="Status", optional, tag="2")] + #[prost(enumeration = "Status", optional, tag = "2")] pub status: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProjectsCountResponse { - #[prost(uint32, tag="1")] + #[prost(uint32, tag = "1")] pub count: u32, } // ------------------------------- @@ -136,53 +136,53 @@ pub struct LaunchpadProjectsCountResponse { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct LaunchpadProject { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub id: ::prost::alloc::string::String, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub network_id: ::prost::alloc::string::String, - #[prost(string, tag="3")] + #[prost(string, tag = "3")] pub creator_id: ::prost::alloc::string::String, - #[prost(string, tag="4")] + #[prost(string, tag = "4")] pub collection_data: ::prost::alloc::string::String, - #[prost(string, optional, tag="5")] + #[prost(string, optional, tag = "5")] pub merkle_root: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag="6")] + #[prost(string, optional, tag = "6")] pub deployed_address: ::core::option::Option<::prost::alloc::string::String>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Metadata { - #[prost(string, optional, tag="1")] + #[prost(string, optional, tag = "1")] pub image: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag="2")] + #[prost(string, optional, tag = "2")] pub image_data: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag="3")] + #[prost(string, optional, tag = "3")] pub external_url: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag="4")] + #[prost(string, optional, tag = "4")] pub description: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag="5")] + #[prost(string, optional, tag = "5")] pub name: ::core::option::Option<::prost::alloc::string::String>, - #[prost(message, repeated, tag="6")] + #[prost(message, repeated, tag = "6")] pub attributes: ::prost::alloc::vec::Vec, - #[prost(string, optional, tag="7")] + #[prost(string, optional, tag = "7")] pub background_color: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag="8")] + #[prost(string, optional, tag = "8")] pub animation_url: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag="9")] + #[prost(string, optional, tag = "9")] pub youtube_url: ::core::option::Option<::prost::alloc::string::String>, - #[prost(uint64, optional, tag="10")] + #[prost(uint64, optional, tag = "10")] pub royalty_percentage: ::core::option::Option, - #[prost(string, optional, tag="11")] + #[prost(string, optional, tag = "11")] pub royalty_payment_address: ::core::option::Option<::prost::alloc::string::String>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Trait { - #[prost(string, optional, tag="1")] + #[prost(string, optional, tag = "1")] pub display_type: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub trait_type: ::prost::alloc::string::String, - #[prost(string, tag="3")] + #[prost(string, tag = "3")] pub value: ::prost::alloc::string::String, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] diff --git a/rust/cw-contracts/nft-tr721/src/contract.rs b/rust/cw-contracts/nft-tr721/src/contract.rs index f804afd477..f135ed21a7 100644 --- a/rust/cw-contracts/nft-tr721/src/contract.rs +++ b/rust/cw-contracts/nft-tr721/src/contract.rs @@ -43,8 +43,12 @@ const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub struct Tr721 { pub(crate) contract_version: Item<'static, ContractVersion>, pub(crate) admin: Item<'static, String>, - pub(crate) tokens: - IndexedMap<'static, &'static str, TokenInfo, TokenIndexes<'static, Tr721Metadata>>, + pub(crate) tokens: IndexedMap< + 'static, + &'static str, + TokenInfo, + TokenIndexes<'static, Tr721Metadata>, + >, pub(crate) requested_mints: Map<'static, String, Addr>, // token id => User address pub(crate) launchpad_contract: Item<'static, String>, @@ -814,4 +818,3 @@ pub struct MintInfo { pub royalty_address: Option, pub royalty_percentage: Option, } -