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 diff --git a/.gitignore b/.gitignore index d6e7b05ea6..4a858ff704 100644 --- a/.gitignore +++ b/.gitignore @@ -104,6 +104,7 @@ temp/ # rust /target/ artifacts +rust/cw-contracts/*/target # cypress cypress/screenshots \ No newline at end of file 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 diff --git a/go/pkg/networks/features.gen.go b/go/pkg/networks/features.gen.go index ff8362cc8f..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,6 +63,29 @@ func (nb *NetworkBase) GetFeatureCosmWasmNFTsBurner() (*FeatureCosmWasmNFTsBurne return feature.(*FeatureCosmWasmNFTsBurner), nil } +type FeatureCosmWasmNFTLaunchpad struct { + *FeatureBase + LaunchpadContractAddress string `json:"launchpadContractAddress"` + DefaultMintDenom string `json:"defaultMintDenom"` + LaunchpadEndpoint string `json:"launchpadEndpoint"` + CodeId float64 `json:"codeId"` + NftTr721CodeId float64 `json:"nftTr721CodeId"` +} + +var _ Feature = &FeatureCosmWasmNFTLaunchpad{} + +func (f FeatureCosmWasmNFTLaunchpad) Type() FeatureType { + return FeatureTypeCosmWasmNFTLaunchpad +} + +func (nb *NetworkBase) GetFeatureCosmWasmNFTLaunchpad() (*FeatureCosmWasmNFTLaunchpad, error) { + feature, err := nb.GetFeature(FeatureTypeCosmWasmNFTLaunchpad) + if err != nil { + return nil, err + } + return feature.(*FeatureCosmWasmNFTLaunchpad), nil +} + type FeatureGnoProjectManager struct { *FeatureBase ProjectsManagerPkgPath string `json:"projectsManagerPkgPath"` @@ -141,6 +164,12 @@ func UnmarshalFeature(b []byte) (Feature, error) { return nil, errors.Wrap(err, "failed to unmarshal feature CosmWasmNFTsBurner") } return &f, nil + case FeatureTypeCosmWasmNFTLaunchpad: + var f FeatureCosmWasmNFTLaunchpad + if err := json.Unmarshal(b, &f); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal feature CosmWasmNFTLaunchpad") + } + return &f, nil case FeatureTypeGnoProjectManager: var f FeatureGnoProjectManager if err := json.Unmarshal(b, &f); err != nil { diff --git a/networks.json b/networks.json index f6d967ea00..31c8e54b83 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": [ @@ -11427,7 +11427,7 @@ "UPP", "NameService", "BurnTokens", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "NFTMarketplaceLeaderboard", "CosmWasmNFTsBurner" ], @@ -11524,7 +11524,7 @@ "UPP", "NameService", "BurnTokens", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "RiotP2E", "NFTMarketplaceLeaderboard" ], @@ -11602,7 +11602,7 @@ "UPP", "NameService", "BurnTokens", - "NFTLaunchpad", + "CosmWasmNFTLaunchpad", "CosmWasmPremiumFeed", "NFTMarketplaceLeaderboard", "CosmWasmNFTsBurner" @@ -11621,6 +11621,14 @@ "type": "NFTMarketplace", "cwAddressListCodeId": 63, "cwAddressListContractAddress": "tori1x72plnprsjnmszylmdm3cnvu5h6u55fyf0pe02lye9p6q2ws05ps33qmft" + }, + { + "type": "CosmWasmNFTLaunchpad", + "launchpadContractAddress": "tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf", + "launchpadEndpoint": "https://dapp-backend.testnet.teritori.com", + "nftTr721CodeId": 60, + "codeId": 71, + "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..4766c6f717 --- /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, CollectionProject, 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: CollectionProject; + }, 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: CollectionProject; + }, 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..9f0b37c279 --- /dev/null +++ b/packages/contracts-clients/nft-launchpad/NftLaunchpad.types.ts @@ -0,0 +1,104 @@ +/** +* 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 { + admin: Addr; + name: string; + nft_code_id: number; + owner: Addr; +} +export type ExecuteMsg = { + update_config: { + changes: ConfigChanges; + [k: string]: unknown; + }; +} | { + submit_collection: { + collection: CollectionProject; + [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 { + admin?: string | null; + name?: string | null; + nft_code_id?: number | null; + owner?: string | null; +} +export interface CollectionProject { + 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; + 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_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; +} +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/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 9f05394953..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", @@ -55,6 +55,19 @@ type CosmWasmSocialFeed = { feedContractAddress: string; }; +// CosmWasm Launchpad + +const zodCosmWasmNFTLaunchpad = z.object({ + type: z.literal(NetworkFeature.CosmWasmNFTLaunchpad), + launchpadContractAddress: z.string(), + defaultMintDenom: z.string(), + launchpadEndpoint: z.string(), + codeId: z.number(), + nftTr721CodeId: z.number(), +}); + +export type CosmWasmNFTLaunchpad = z.infer; + // Gno Project Manager const zodGnoProjectManager = z.object({ @@ -80,6 +93,7 @@ type LaunchpadERC20 = z.infer; export const allFeatureObjects = [ zodCosmWasmPremiumFeed, zodCosmWasmNFTsBurner, + zodCosmWasmNFTLaunchpad, zodGnoProjectManager, zodLaunchpadERC20, zodNFTMarketplace, @@ -88,6 +102,7 @@ export const allFeatureObjects = [ export type NetworkFeatureObject = | CosmWasmPremiumFeed | CosmWasmSocialFeed + | CosmWasmNFTLaunchpad | CosmWasmNFTsBurner | GnoProjectManager | LaunchpadERC20 diff --git a/packages/networks/teritori-localnet/index.ts b/packages/networks/teritori-localnet/index.ts index 518544a2a8..d6ba71562e 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 4aa32d14d0..667f98dae3 100644 --- a/packages/networks/teritori-testnet/index.ts +++ b/packages/networks/teritori-testnet/index.ts @@ -1,5 +1,6 @@ import { teritoriTestnetCurrencies } from "./currencies"; import { + CosmWasmNFTLaunchpad, CosmWasmNFTsBurner, CosmWasmPremiumFeed, NetworkFeature, @@ -29,6 +30,16 @@ const nftMarketplace: NFTMarketplace = { "tori1x72plnprsjnmszylmdm3cnvu5h6u55fyf0pe02lye9p6q2ws05ps33qmft", }; +const cosmwasmNftLaunchpadFeature: CosmWasmNFTLaunchpad = { + type: NetworkFeature.CosmWasmNFTLaunchpad, + launchpadContractAddress: + "tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf", + launchpadEndpoint: "https://dapp-backend.testnet.teritori.com", + nftTr721CodeId: 60, + codeId: 71, + defaultMintDenom: "utori", +}; + const riotContractAddressGen0 = "tori1r8raaqul4j05qtn0t05603mgquxfl8e9p7kcf7smwzcv2hc5rrlq0vket0"; const riotContractAddressGen1 = ""; @@ -48,12 +59,17 @@ export const teritoriTestnetNetwork: CosmosNetworkInfo = { NetworkFeature.UPP, NetworkFeature.NameService, NetworkFeature.BurnTokens, - NetworkFeature.NFTLaunchpad, + NetworkFeature.CosmWasmNFTLaunchpad, NetworkFeature.CosmWasmPremiumFeed, NetworkFeature.NFTMarketplaceLeaderboard, NetworkFeature.CosmWasmNFTsBurner, ], - featureObjects: [premiumFeedFeature, nftsBurnerFeature, nftMarketplace], + featureObjects: [ + premiumFeedFeature, + nftsBurnerFeature, + nftMarketplace, + cosmwasmNftLaunchpadFeature, + ], currencies: teritoriTestnetCurrencies, txExplorer: "https://explorer.teritori.com/teritori-testnet/tx/$hash", accountExplorer: diff --git a/packages/networks/teritori/index.ts b/packages/networks/teritori/index.ts index f836a12770..4244c27b4e 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; 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..ee0224f8ee 100644 --- a/packages/scripts/network-setup/deployLib.ts +++ b/packages/scripts/network-setup/deployLib.ts @@ -28,11 +28,22 @@ import { } 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 +64,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( @@ -188,7 +210,7 @@ export const testTeritoriEcosystem = async (network: CosmosNetworkInfo) => { }; const instantiateMarketplaceVault = ( - opts: { home: string; binaryPath: string }, + opts: DeployOpts, wallet: string, adminAddr: string, network: CosmosNetworkInfo, @@ -210,7 +232,7 @@ const instantiateMarketplaceVault = ( }; const instantiateSocialFeed = async ( - opts: { home: string; binaryPath: string }, + opts: DeployOpts, wallet: string, adminAddr: string, network: CosmosNetworkInfo, @@ -232,7 +254,7 @@ const instantiateSocialFeed = async ( }; export const instantiateNameService = async ( - opts: { home: string; binaryPath: string }, + opts: DeployOpts, wallet: string, adminAddr: string, network: CosmosNetworkInfo, @@ -290,7 +312,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 +349,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 new file mode 100644 index 0000000000..cad793aeb3 --- /dev/null +++ b/packages/scripts/network-setup/deployNftLaunchpad.ts @@ -0,0 +1,164 @@ +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 { + CosmosNetworkInfo, + getNetworkFeature, + NetworkFeature, +} from "@/networks"; +import { CosmWasmNFTLaunchpad } from "@/networks/features"; +import { + DeployOpts, + initDeploy, + instantiateContract, + storeWASM, +} from "@/scripts/network-setup/deployLib"; + +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.CosmWasmNFTLaunchpad), + ); + 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.CosmWasmNFTLaunchpad) { + return cosmwasmLaunchpadFeature; + } else return featureObject; + }); +}; + +const instantiateNftLaunchpad = async ( + opts: DeployOpts, + deployerWallet: string, + deployerAddr: string, + launchpadAdmin: string, + network: CosmosNetworkInfo, + featureObject: CosmWasmNFTLaunchpad, +) => { + 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", + owner: deployerAddr, + admin: 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.CosmWasmNFTLaunchpad), + ); + 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, + }, + networkId, + wallet, + launchpadAdmin, + }); +}; +main(); 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..f401063ff1 --- /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..d89889f4bb --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/Makefile @@ -0,0 +1,54 @@ +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=71 +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=tori1te7ku4de0k4rl8lhyuvpmhygaq7k7vy5zpsjq9y638efxsnx3aaqck2utf +# 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 \ No newline at end of file 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..affee6a7f6 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/config.json @@ -0,0 +1,9 @@ +{ + "config": { + "name": "NFT Launchpad", + "supported_networks": ["teritori-testnet"], + "owner": "tori1llmym9upcpwnz7qte856ghlp5437ezz2gg7z0q", + "admin": "tori1kjvyqf4mttwrhfuq5gfj9xgxx9jdt92xnxzf770x853567ymx8cscrnw05", + "nft_code_id": 60 + } +} 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..22a25df230 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/nft-launchpad.json @@ -0,0 +1,762 @@ +{ + "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": [ + "admin", + "name", + "nft_code_id", + "owner" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + } + }, + "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/CollectionProject" + } + } + } + }, + "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" + } + } + }, + "CollectionProject": { + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count", + "website_link" + ], + "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 + }, + "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_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" + } + }, + "additionalProperties": false + }, + "ConfigChanges": { + "type": "object", + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "type": [ + "string", + "null" + ] + } + }, + "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": "CollectionProject", + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count", + "website_link" + ], + "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 + }, + "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_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" + } + }, + "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": [ + "admin", + "name", + "nft_code_id", + "owner" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } + } + } +} diff --git a/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..80935c8a3e --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/execute.json @@ -0,0 +1,378 @@ +{ + "$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/CollectionProject" + } + } + } + }, + "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" + } + } + }, + "CollectionProject": { + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count", + "website_link" + ], + "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 + }, + "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_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" + } + }, + "additionalProperties": false + }, + "ConfigChanges": { + "type": "object", + "properties": { + "admin": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "nft_code_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "type": [ + "string", + "null" + ] + } + }, + "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..33c4480887 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/instantiate.json @@ -0,0 +1,45 @@ +{ + "$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": [ + "admin", + "name", + "nft_code_id", + "owner" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + } + }, + "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..aa2eb34d55 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_collection_by_id.json @@ -0,0 +1,258 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CollectionProject", + "type": "object", + "required": [ + "artwork_desc", + "contact_email", + "cover_img_uri", + "dao_whitelist_count", + "desc", + "escrow_mint_proceeds_period", + "investment_desc", + "investment_link", + "is_applied_previously", + "is_dox", + "is_project_derivative", + "is_ready_for_mint", + "mint_periods", + "name", + "partners", + "project_type", + "symbol", + "target_network", + "team_desc", + "tokens_count", + "website_link" + ], + "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 + }, + "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_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" + } + }, + "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..f58adb6046 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/schema/raw/response_to_get_config.json @@ -0,0 +1,34 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "type": "object", + "required": [ + "admin", + "name", + "nft_code_id", + "owner" + ], + "properties": { + "admin": { + "$ref": "#/definitions/Addr" + }, + "name": { + "type": "string" + }, + "nft_code_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + } + } +} diff --git a/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..d993eb1c23 --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/contract.rs @@ -0,0 +1,326 @@ +use cosmwasm_schema::cw_serde; +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::{ + 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, CollectionProject>, // 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 + if let Some(nft_code_id) = changes.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 = 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)) + } + self.config.save(ctx.deps.storage, &config)?; + + Ok(Response::new().add_attributes(attributes)) + } + + #[msg(exec)] + pub fn submit_collection( + &self, + ctx: ExecCtx, + collection: CollectionProject, + ) -> 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 launchpad_admin to deploy + if sender != config.admin { + 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; + + // 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, + 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: collection.royalty_address, + royalty_percentage: collection.royalty_percentage, + }, + mint_periods: collection.mint_periods, + })?, + funds: vec![], + label: format!( + "TR721 codeId:{} collectionId:{} symbol:{}", + nft_code_id, 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: u64, + pub admin: Addr, + pub owner: Addr, +} + +#[cw_serde] +pub struct ConfigChanges { + pub name: Option, + pub nft_code_id: Option, + pub admin: Option, + pub owner: Option, +} + +#[cw_serde] +#[derive(Default)] +pub struct CollectionProject { + // Info ---------------------------- + pub name: String, + pub desc: String, + pub symbol: String, // Unique + pub cover_img_uri: String, + pub target_network: String, + // Details ---------------------------- + pub website_link: String, + pub contact_email: String, + pub is_project_derivative: bool, + pub project_type: String, + pub is_applied_previously: bool, + // Team info -------------------------------------- + pub team_desc: String, + pub partners: String, + pub investment_desc: String, + pub investment_link: String, + // Additional info ---------------------------- + pub artwork_desc: String, + pub is_ready_for_mint: bool, + 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, +} 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..dfc3c2d15a --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/lib.rs @@ -0,0 +1,5 @@ +pub mod contract; +pub mod error; + +#[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..ad0b550c3e --- /dev/null +++ b/rust/cw-contracts/nft-launchpad/src/multitest.rs @@ -0,0 +1,305 @@ +use cosmwasm_std::{Addr, Attribute, Coin, Uint128}; +use sylvia::multitest::App; + +use crate::{ + contract::{sv::multitest_utils::CodeId as LaunchpadCodeId, CollectionProject, Config}, + error::ContractError, +}; + +use crate::contract::ConfigChanges; +use nft_tr721::contract::{ + sv::multitest_utils::CodeId as NftTr721CodeId, MintPeriod, WhitelistInfo, +}; + +fn get_default_collection() -> CollectionProject { + 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(), + }), + }]; + + 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(), + // Details ---------------------------- + website_link: "aaa".to_string(), + contact_email: "contact_email".to_string(), + is_project_derivative: true, + project_type: "project_type".to_string(), + is_applied_previously: false, + // Team info -------------------------------------- + team_desc: "team_desc".to_string(), + partners: "partners".to_string(), + investment_desc: "investment_desc".to_string(), + investment_link: "investment_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, + 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"; + // 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: deployed_nft_code_id, + admin: Addr::unchecked("admin"), + 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 TR721 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(), + nft_code_id: deployed_nft_code_id, + admin: Addr::unchecked("admin"), + 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(CollectionProject { + mint_periods: vec![], + ..CollectionProject::default() + }) + .call(sender) + .unwrap_err(); + + assert_eq!(err, ContractError::MintPeriodRequired); + } + + // Create collection with invalid symbol --------------------------------------------------------- + { + let err = contract + .submit_collection(CollectionProject { + 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); + } + + // Update config when sender is not contract owner + { + let err = contract + .update_config(ConfigChanges { + name: Some("test".to_string()), + nft_code_id: Some(deployed_nft_code_id), + admin: 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: Some("test".to_string()), + nft_code_id: Some(deployed_nft_code_id), + admin: 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: Some("test".to_string()), + nft_code_id: Some(deployed_nft_code_id), + admin: 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()) + ); + } + + // Update config to have deployed nft_code_id + { + contract + .update_config(ConfigChanges { + name: Some("test".to_string()), + nft_code_id: Some(deployed_nft_code_id), + admin: Some(sender.to_string()), + owner: Some(sender.to_string()), + }) + .call(sender) + .unwrap(); + + let resp = contract.get_config().unwrap(); + assert_eq!(resp.nft_code_id, 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-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/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..f135ed21a7 --- /dev/null +++ b/rust/cw-contracts/nft-tr721/src/contract.rs @@ -0,0 +1,820 @@ +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() +}