From c234397797edfe73cb62a3029c7fd8abf488bbd7 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Wed, 21 Feb 2024 21:27:25 +0100 Subject: [PATCH] feat: bring cosmwasm nft marketplace contract in monorepo history of previously called teritori-vault repo: commit 75a692533b9188587ebfa909c5576376b8d65999 Author: yieldoption <100329165+yieldoption@users.noreply.github.com> Date: Thu Nov 3 23:26:23 2022 -0400 gas optimization for nft vault contract (#6) commit 0794cc77e08e1bc72c7d914ea391208dba25b9ca Author: yieldoption <100329165+yieldoption@users.noreply.github.com> Date: Thu Nov 3 12:16:51 2022 -0400 fix royalty query (#5) commit f48c7fe8869f2d83dc61308ceb37c64d3bb7e4c6 Merge: 6d528f0 b11d308 Author: n0izn0iz Date: Thu Oct 6 18:14:13 2022 +0200 Merge pull request #4 from TERITORI/feature/royalty feature / royalty commit b11d3082666d4a4df3dcef08a4e69d327ebf3be9 Author: yieldoption Date: Wed Oct 5 22:02:29 2022 -0400 cargo fmt commit 6f284d07f205e3256d0a7db0c6da458f20aa38f3 Author: yieldoption Date: Wed Oct 5 22:00:09 2022 -0400 add cosmwasm binary commit 01e4bbdef8968af5c94d3708202ea372bf2bb424 Author: yieldoption Date: Wed Oct 5 21:58:16 2022 -0400 update schema commit 6ada5b2346d12f27a7680a69fc93df016898e0cc Author: yieldoption Date: Wed Oct 5 21:58:06 2022 -0400 implement royalty feature commit 6d528f06ee0d0a98daa5301578e495cf5386a62e Merge: e3a2d0e 68b85a8 Author: n0izn0iz Date: Tue Oct 4 16:24:19 2022 +0200 Merge pull request #3 from TERITORI/ci chore: add ci checks commit 68b85a80fdd602c22296eb6d8fe6703e7df6e943 Author: Norman Meier Date: Tue Oct 4 16:20:25 2022 +0200 chore: add ci checks Signed-off-by: Norman Meier commit e3a2d0e8f943445a44b085d1bbbac8f65d7e0d76 Author: yieldoption Date: Mon Sep 26 22:37:32 2022 -0400 add tests for nft vault contract commit a04e44fe54ed798d96659098914af72a0c36d8f5 Merge: 8aad97c 48f7ba2 Author: n0izn0iz Date: Tue Sep 13 01:00:08 2022 +0200 Merge pull request #2 from TERITORI/schema-and-deploy chore: generate schema and deploy commit 48f7ba2b07f6dcf220ff79b4ee9088e24b4b2c63 Author: Norman Meier Date: Mon Sep 12 22:13:25 2022 +0200 chore: generate schema and deploy Signed-off-by: Norman Meier commit 8aad97ceb33e93f5c605e930074019a80ed5abb1 Author: sarawut Date: Wed Jun 8 19:24:19 2022 +0700 upgrade cosmwasm version commit aef4da7c70376056cef6e2dc9f2a6a758a9012c7 Merge: c610270 c80a675 Author: Yannis Date: Thu Mar 10 18:04:51 2022 +0100 Merge pull request #1 from POPSmartContract/fixed fix receivenft hook, save process commit c80a675f2c92b2dea0f82e7a1ca050908ccfff26 Author: unknown Date: Thu Mar 10 12:01:30 2022 -0500 fix receivenft hook, save process commit c6102700dd3a51706bd2f2a1ba1a1b2be5ca2cdf Author: devstar Date: Wed Mar 2 00:15:54 2022 +0700 set initial price for deposit, transfer nft when buy commit 20f335c01e44779ce8781d83d2a62bdad3272d42 Author: devstar Date: Thu Feb 24 21:20:28 2022 +0700 add fee withdraw function, query_all_nft_list in vault commit 9963a9d7f413aed5942ee873283be6d0762ec533 Author: devstar Date: Tue Feb 22 01:00:06 2022 +0700 complete buy function, add more queries commit 2fbcdcf01d2b335baff30783d444e6df2098d016 Author: devstar Date: Thu Feb 10 20:08:30 2022 +0700 initial vault contract --- .gitattributes | 14 +- .github/workflows/gen.yml | 3 +- .github/workflows/rust.yml | 3 + Makefile | 72 +- .../nft-marketplace/.cargo/config | 6 + .../nft-marketplace/.editorconfig | 11 + cosmwasm-contracts/nft-marketplace/.gitignore | 15 + cosmwasm-contracts/nft-marketplace/Cargo.lock | 799 +++++++++++++++ cosmwasm-contracts/nft-marketplace/Cargo.toml | 26 + .../nft-marketplace/examples/schema.rs | 38 + .../nft-marketplace/rustfmt.toml | 15 + .../schema/all_nfts_in_vault_response.json | 33 + .../schema/config_response.json | 23 + .../nft-marketplace/schema/execute_msg.json | 170 ++++ .../schema/instantiate_msg.json | 19 + .../schema/nft_info_response.json | 27 + .../schema/nft_list_response.json | 33 + .../schema/nft_owner_info_response.json | 5 + .../nft-marketplace/schema/nft_query_msg.json | 366 +++++++ .../nft-marketplace/schema/query_msg.json | 42 + .../schema/royalties_info_response.json | 23 + .../nft-marketplace/src/contract.rs | 914 ++++++++++++++++++ cosmwasm-contracts/nft-marketplace/src/lib.rs | 3 + .../nft-marketplace/src/state.rs | 24 + .../nft-marketplace/src/vault.rs | 89 ++ .../nftDetails/components/NFTSellInfo.tsx | 4 +- .../NftMarketplace.client.ts} | 10 +- .../NftMarketplace.types.ts} | 0 .../nft-marketplace/index.ts | 2 + packages/hooks/useCancelNFTListing.ts | 4 +- packages/hooks/useNFTInfo.ts | 10 +- packages/hooks/useVaultNFTInfo.ts | 4 +- packages/hooks/vault/useVaultConfig.ts | 4 +- packages/screens/CoreDAO/CoreDAOScreen.tsx | 4 +- .../screens/Marketplace/NFTDetailScreen.tsx | 6 +- packages/scripts/network-setup/deployLib.ts | 2 +- packages/scripts/vaultInfo.ts | 4 +- 37 files changed, 2760 insertions(+), 67 deletions(-) create mode 100644 cosmwasm-contracts/nft-marketplace/.cargo/config create mode 100644 cosmwasm-contracts/nft-marketplace/.editorconfig create mode 100644 cosmwasm-contracts/nft-marketplace/.gitignore create mode 100644 cosmwasm-contracts/nft-marketplace/Cargo.lock create mode 100644 cosmwasm-contracts/nft-marketplace/Cargo.toml create mode 100644 cosmwasm-contracts/nft-marketplace/examples/schema.rs create mode 100644 cosmwasm-contracts/nft-marketplace/rustfmt.toml create mode 100644 cosmwasm-contracts/nft-marketplace/schema/all_nfts_in_vault_response.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/config_response.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/execute_msg.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/instantiate_msg.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/nft_info_response.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/nft_list_response.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/nft_owner_info_response.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/nft_query_msg.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/query_msg.json create mode 100644 cosmwasm-contracts/nft-marketplace/schema/royalties_info_response.json create mode 100644 cosmwasm-contracts/nft-marketplace/src/contract.rs create mode 100644 cosmwasm-contracts/nft-marketplace/src/lib.rs create mode 100644 cosmwasm-contracts/nft-marketplace/src/state.rs create mode 100644 cosmwasm-contracts/nft-marketplace/src/vault.rs rename packages/contracts-clients/{teritori-nft-vault/TeritoriNftVault.client.ts => nft-marketplace/NftMarketplace.client.ts} (93%) rename packages/contracts-clients/{teritori-nft-vault/TeritoriNftVault.types.ts => nft-marketplace/NftMarketplace.types.ts} (100%) create mode 100644 packages/contracts-clients/nft-marketplace/index.ts diff --git a/.gitattributes b/.gitattributes index af3ad12812..f00b56d027 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,10 @@ -/.yarn/** linguist-vendored -/.yarn/releases/* binary -/.yarn/plugins/**/* binary -/.pnp.* binary linguist-generated +/.yarn/** linguist-vendored +/.yarn/releases/* binary +/.yarn/plugins/**/* binary +/.pnp.* binary linguist-generated +/cosmwasm-contracts/*/schema/**/* linguist-generated +/packages/contracts-clients/**/* linguist-generated +/packages/api/**/* linguist-generated +/go/pkg/*pb/**/* linguist-generated +/packages/evm-contracts-clients/**/*.ts linguist-generated +/.expo-shared/assets.json linguist-generated diff --git a/.github/workflows/gen.yml b/.github/workflows/gen.yml index fd7ba553a9..5ce66170fc 100644 --- a/.github/workflows/gen.yml +++ b/.github/workflows/gen.yml @@ -21,6 +21,8 @@ jobs: with: go-version: "1.19" + - uses: dtolnay/rust-toolchain@stable + - uses: bufbuild/buf-setup-action@v1.28.0 with: version: 1.28.0 @@ -33,7 +35,6 @@ jobs: with: ssh-private-key: | ${{ secrets.NFTS_DEPLOY_KEY }} - ${{ secrets.VAULT_DEPLOY_KEY }} ${{ secrets.FOOTER_DEPLOY_KEY }} ${{ secrets.TNS_DEPLOY_KEY }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b10ce77b26..98d491bc62 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,6 +14,9 @@ jobs: - uses: dtolnay/rust-toolchain@stable + - name: Build + run: make build.rust + - name: Test run: make test.rust diff --git a/Makefile b/Makefile index eba4ac86f5..b71a3dcd45 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,9 @@ BUNKER_MINTER_PACKAGE=teritori-bunker-minter GO?=go GOFMT?=$(shell $(GO) env GOROOT)/bin/gofmt +COSMWASM_CONTRACTS_DIR=cosmwasm-contracts +INTERNAL_COSMWASM_CONTRACTS=$(wildcard $(COSMWASM_CONTRACTS_DIR)/*) + TOKEN_REPO=teritori-nfts TOKEN_PACKAGE=teritori-nft SQUAD_STAKING_PACKAGE=teritori-squad-staking @@ -15,9 +18,6 @@ NAME_SERVICE_PACKAGE=teritori-name-service RIOTER_FOOTER_REPO=rioters-footer-nft RIOTER_FOOTER_PACKAGE=rioter-footer-nft -VAULT_REPO=teritori-vault -VAULT_PACKAGE=teritori-nft-vault - ADDR_LIST_REPO=cw_addr_list ADDR_LIST_PACKAGE=cw-address-list @@ -89,26 +89,13 @@ docker.backend: docker build . -f go/cmd/teritori-dapp-backend/Dockerfile -t teritori/teritori-dapp-backend:$(shell git rev-parse --short HEAD) .PHONY: generate.contracts-clients -generate.contracts-clients: $(CONTRACTS_CLIENTS_DIR)/$(BUNKER_MINTER_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(NAME_SERVICE_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(RIOTER_FOOTER_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(TOKEN_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(VAULT_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/cw721-membership +generate.contracts-clients: generate.internal-contracts-clients $(CONTRACTS_CLIENTS_DIR)/$(BUNKER_MINTER_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(NAME_SERVICE_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(RIOTER_FOOTER_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(TOKEN_PACKAGE) .PHONY: generate.go-networks generate.go-networks: node_modules validate-networks npx tsx packages/scripts/generateGoNetworks.ts | $(GOFMT) > go/pkg/networks/networks.gen.go npx tsx packages/scripts/codegen/generateGoNetworkFeatures.ts | $(GOFMT) > go/pkg/networks/features.gen.go -.PHONY/: $(CONTRACTS_CLIENTS_DIR)/cw721-membership -$(CONTRACTS_CLIENTS_DIR)/cw721-membership: node_modules - rm -fr $@ - cd cosmwasm-contracts/cw721-membership && cargo schema - npx cosmwasm-ts-codegen generate \ - --plugin client \ - --schema cosmwasm-contracts/cw721-membership/schema \ - --out $@ \ - --name cw721-membership \ - --no-bundle - npx tsx packages/scripts/makeTypescriptIndex $@ - touch $@ - .PHONY: $(CONTRACTS_CLIENTS_DIR)/$(BUNKER_MINTER_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(BUNKER_MINTER_PACKAGE): node_modules rm -fr $(CANDYMACHINE_REPO) @@ -216,23 +203,6 @@ $(CONTRACTS_CLIENTS_DIR)/$(BREEDING_PACKAGE): node_modules go fmt ./go/pkg/contracts/breeding_minter_types rm -fr $(CANDYMACHINE_REPO) -.PHONY: $(CONTRACTS_CLIENTS_DIR)/$(VAULT_PACKAGE) -$(CONTRACTS_CLIENTS_DIR)/$(VAULT_PACKAGE): node_modules - rm -fr $(VAULT_REPO) - git clone git@github.com:TERITORI/$(VAULT_REPO).git - cd $(VAULT_REPO) && git checkout 75a692533b9188587ebfa909c5576376b8d65999 - rm -fr $@ - npx cosmwasm-ts-codegen generate \ - --plugin client \ - --schema $(VAULT_REPO)/contracts/nft-vault/schema \ - --out $@ \ - --name $(VAULT_PACKAGE) \ - --no-bundle - mkdir -p go/pkg/contracts/vault_types - go run github.com/a-h/generate/cmd/schema-generate@v0.0.0-20220105161013-96c14dfdfb60 -i $(VAULT_REPO)/contracts/nft-vault/schema/execute_msg.json -o go/pkg/contracts/vault_types/execute_msg.go -p vault_types - go fmt ./go/pkg/contracts/vault_types - rm -fr $(VAULT_REPO) - .PHONY: $(CONTRACTS_CLIENTS_DIR)/$(ADDR_LIST_PACKAGE) $(CONTRACTS_CLIENTS_DIR)/$(ADDR_LIST_PACKAGE): node_modules rm -fr $(ADDR_LIST_REPO) @@ -404,8 +374,38 @@ bump-app-build-number: .PHONY: test.rust test.rust: - cd cosmwasm-contracts/cw721-membership && cargo test + for file in $(INTERNAL_COSMWASM_CONTRACTS); do \ + echo "> Testing $${file}" ; \ + cd $${file} ; \ + cargo test ; \ + cd - ; \ + done .PHONY: build.rust build.rust: - cd cosmwasm-contracts/cw721-membership && cargo wasm + for file in $(INTERNAL_COSMWASM_CONTRACTS); do \ + echo "> Building $${file}" ; \ + cd $${file} ; \ + cargo wasm ; \ + cd - ; \ + done + +.PHONY: generate.internal-contracts-clients +generate.internal-contracts-clients: node_modules + for indir in $(INTERNAL_COSMWASM_CONTRACTS) ; do \ + echo "> Generating client for $${indir}" ; \ + rm -fr $${indir}/schema ; \ + (cd $${indir} && cargo schema && cd -) || exit 1 ; \ + pkgname="$$(basename $${indir})" ; \ + outdir="$(CONTRACTS_CLIENTS_DIR)/$${pkgname}" ; \ + rm -fr $${outdir} ; \ + npx cosmwasm-ts-codegen generate \ + --plugin client \ + --schema $${indir}/schema \ + --out $${outdir} \ + --name $${pkgname} \ + --no-bundle \ + || exit 1 ;\ + npx tsx packages/scripts/makeTypescriptIndex $${outdir} || exit 1 ; \ + done + diff --git a/cosmwasm-contracts/nft-marketplace/.cargo/config b/cosmwasm-contracts/nft-marketplace/.cargo/config new file mode 100644 index 0000000000..8d4bc738b1 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/.cargo/config @@ -0,0 +1,6 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +wasm-debug = "build --target wasm32-unknown-unknown" +unit-test = "test --lib" +integration-test = "test --test integration" +schema = "run --example schema" diff --git a/cosmwasm-contracts/nft-marketplace/.editorconfig b/cosmwasm-contracts/nft-marketplace/.editorconfig new file mode 100644 index 0000000000..3d36f20b19 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.rs] +indent_size = 4 diff --git a/cosmwasm-contracts/nft-marketplace/.gitignore b/cosmwasm-contracts/nft-marketplace/.gitignore new file mode 100644 index 0000000000..dfdaaa6bcd --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/.gitignore @@ -0,0 +1,15 @@ +# Build results +/target + +# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327) +.cargo-ok + +# Text file backups +**/*.rs.bk + +# macOS +.DS_Store + +# IDEs +*.iml +.idea diff --git a/cosmwasm-contracts/nft-marketplace/Cargo.lock b/cosmwasm-contracts/nft-marketplace/Cargo.lock new file mode 100644 index 0000000000..082d759199 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/Cargo.lock @@ -0,0 +1,799 @@ +# 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 = "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 = "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-storage-plus" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw-utils" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "schemars", + "serde", +] + +[[package]] +name = "cw721" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "035818368a74c07dd9ed5c5a93340199ba251530162010b9f34c3809e3b97df1" +dependencies = [ + "cosmwasm-std", + "cw-utils 0.13.4", + "schemars", + "serde", +] + +[[package]] +name = "cw721" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20dfe04f86e5327956b559ffcc86d9a43167391f37402afd8bf40b0be16bee4d" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.15.1", + "schemars", + "serde", +] + +[[package]] +name = "cw721-base" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62c3ee3b669fc2a8094301a73fd7be97a7454d4df2650c33599f737e8f254d24" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "cw-utils 0.15.1", + "cw2", + "cw721 0.15.0", + "schemars", + "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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" + +[[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 = "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 = "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-marketplace" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.13.4", + "cw721 0.13.4", + "cw721-base", + "schemars", + "serde", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[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 = "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.50", +] + +[[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.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +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.50", +] + +[[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/cosmwasm-contracts/nft-marketplace/Cargo.toml b/cosmwasm-contracts/nft-marketplace/Cargo.toml new file mode 100644 index 0000000000..7f3871069f --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "nft-marketplace" +version = "0.1.0" +edition = "2018" +license = "MIT" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# for quicker tests, cargo testing --lib +# for more explicit tests, cargo testing --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] + +[dependencies] +cw721 = { version = "0.13.2" } +cw721-base = { version = "0.15.0", features = ["library"] } +cosmwasm-std = { version = "1.0.0" } +cw-storage-plus = { version = "0.13.4" } +schemars = "0.8.10" +serde = { version = "1.0.137", default-features = false, features = ["derive"] } + +[dev-dependencies] +cosmwasm-schema = { version = "1.1.0" } diff --git a/cosmwasm-contracts/nft-marketplace/examples/schema.rs b/cosmwasm-contracts/nft-marketplace/examples/schema.rs new file mode 100644 index 0000000000..772ae7b5b8 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/examples/schema.rs @@ -0,0 +1,38 @@ +use std::env::current_dir; +use std::fs::create_dir_all; + +use cosmwasm_schema::{export_schema, export_schema_with_title, remove_schemas, schema_for}; +use nft_marketplace::{ + state::NFTInfo, + vault::{ + ConfigResponse, ExecuteMsg, InstantiateMsg, NftQueryMsg, QueryMsg, RoyaltiesInfoResponse, + }, +}; + +fn main() { + let mut out_dir = current_dir().unwrap(); + out_dir.push("schema"); + create_dir_all(&out_dir).unwrap(); + remove_schemas(&out_dir).unwrap(); + + export_schema(&schema_for!(InstantiateMsg), &out_dir); + export_schema(&schema_for!(ExecuteMsg), &out_dir); + export_schema(&schema_for!(QueryMsg), &out_dir); + + // Query responses + export_schema(&schema_for!(ConfigResponse), &out_dir); + export_schema_with_title(&schema_for!(Vec), &out_dir, "NftListResponse"); + export_schema_with_title( + &schema_for!(Vec), + &out_dir, + "AllNftsInVaultResponse", + ); + export_schema_with_title(&schema_for!(NFTInfo), &out_dir, "NftInfoResponse"); + export_schema_with_title(&schema_for!(String), &out_dir, "NftOwnerInfoResponse"); + export_schema_with_title(&schema_for!(NftQueryMsg), &out_dir, "NftQueryMsg"); + export_schema_with_title( + &schema_for!(RoyaltiesInfoResponse), + &out_dir, + "RoyaltiesInfoResponse", + ); +} diff --git a/cosmwasm-contracts/nft-marketplace/rustfmt.toml b/cosmwasm-contracts/nft-marketplace/rustfmt.toml new file mode 100644 index 0000000000..11a85e6a9c --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/rustfmt.toml @@ -0,0 +1,15 @@ +# stable +newline_style = "unix" +hard_tabs = false +tab_spaces = 4 + +# unstable... should we require `rustup run nightly cargo fmt` ? +# or just update the style guide when they are stable? +#fn_single_line = true +#format_code_in_doc_comments = true +#overflow_delimited_expr = true +#reorder_impl_items = true +#struct_field_align_threshold = 20 +#struct_lit_single_line = true +#report_todo = "Always" + diff --git a/cosmwasm-contracts/nft-marketplace/schema/all_nfts_in_vault_response.json b/cosmwasm-contracts/nft-marketplace/schema/all_nfts_in_vault_response.json new file mode 100644 index 0000000000..335ba0ae27 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/all_nfts_in_vault_response.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "AllNftsInVaultResponse", + "type": "array", + "items": { + "$ref": "#/definitions/NFTInfo" + }, + "definitions": { + "NFTInfo": { + "type": "object", + "required": [ + "amount", + "denom", + "owner" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + }, + "owner": { + "type": "string" + } + } + }, + "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/cosmwasm-contracts/nft-marketplace/schema/config_response.json b/cosmwasm-contracts/nft-marketplace/schema/config_response.json new file mode 100644 index 0000000000..a5e1f68252 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/config_response.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ConfigResponse", + "type": "object", + "required": [ + "fee_bp", + "owner" + ], + "properties": { + "fee_bp": { + "$ref": "#/definitions/Uint128" + }, + "owner": { + "type": "string" + } + }, + "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/cosmwasm-contracts/nft-marketplace/schema/execute_msg.json b/cosmwasm-contracts/nft-marketplace/schema/execute_msg.json new file mode 100644 index 0000000000..1936fa27d5 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/execute_msg.json @@ -0,0 +1,170 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "update_config" + ], + "properties": { + "update_config": { + "type": "object", + "properties": { + "fee_bp": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "owner": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "receive_nft" + ], + "properties": { + "receive_nft": { + "$ref": "#/definitions/Cw721ReceiveMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "withdraw" + ], + "properties": { + "withdraw": { + "type": "object", + "required": [ + "nft_contract_addr", + "nft_token_id" + ], + "properties": { + "nft_contract_addr": { + "type": "string" + }, + "nft_token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_price" + ], + "properties": { + "update_price": { + "type": "object", + "required": [ + "amount", + "denom", + "nft_contract_addr", + "nft_token_id" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + }, + "nft_contract_addr": { + "type": "string" + }, + "nft_token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "buy" + ], + "properties": { + "buy": { + "type": "object", + "required": [ + "nft_contract_addr", + "nft_token_id" + ], + "properties": { + "nft_contract_addr": { + "type": "string" + }, + "nft_token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "withdraw_fee" + ], + "properties": { + "withdraw_fee": { + "type": "object" + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "Cw721ReceiveMsg": { + "description": "Cw721ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", + "type": "object", + "required": [ + "msg", + "sender", + "token_id" + ], + "properties": { + "msg": { + "$ref": "#/definitions/Binary" + }, + "sender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + } + }, + "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/cosmwasm-contracts/nft-marketplace/schema/instantiate_msg.json b/cosmwasm-contracts/nft-marketplace/schema/instantiate_msg.json new file mode 100644 index 0000000000..f2ba4b0bbc --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/instantiate_msg.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "fee_bp" + ], + "properties": { + "fee_bp": { + "$ref": "#/definitions/Uint128" + } + }, + "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/cosmwasm-contracts/nft-marketplace/schema/nft_info_response.json b/cosmwasm-contracts/nft-marketplace/schema/nft_info_response.json new file mode 100644 index 0000000000..1bae17b264 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/nft_info_response.json @@ -0,0 +1,27 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NftInfoResponse", + "type": "object", + "required": [ + "amount", + "denom", + "owner" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + }, + "owner": { + "type": "string" + } + }, + "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/cosmwasm-contracts/nft-marketplace/schema/nft_list_response.json b/cosmwasm-contracts/nft-marketplace/schema/nft_list_response.json new file mode 100644 index 0000000000..e7c1ea58fa --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/nft_list_response.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NftListResponse", + "type": "array", + "items": { + "$ref": "#/definitions/NFTInfo" + }, + "definitions": { + "NFTInfo": { + "type": "object", + "required": [ + "amount", + "denom", + "owner" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + }, + "owner": { + "type": "string" + } + } + }, + "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/cosmwasm-contracts/nft-marketplace/schema/nft_owner_info_response.json b/cosmwasm-contracts/nft-marketplace/schema/nft_owner_info_response.json new file mode 100644 index 0000000000..05c5152367 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/nft_owner_info_response.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NftOwnerInfoResponse", + "type": "string" +} diff --git a/cosmwasm-contracts/nft-marketplace/schema/nft_query_msg.json b/cosmwasm-contracts/nft-marketplace/schema/nft_query_msg.json new file mode 100644 index 0000000000..1fe7b95fd7 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/nft_query_msg.json @@ -0,0 +1,366 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "NftQueryMsg", + "oneOf": [ + { + "description": "Return the owner of the given token, error if token does not exist Return type: OwnerOfResponse", + "type": "object", + "required": [ + "owner_of" + ], + "properties": { + "owner_of": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "description": "unset or false will filter out expired approvals, you must set to true to see them", + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Return operator that can access all of the owner's tokens. Return type: `ApprovalResponse`", + "type": "object", + "required": [ + "approval" + ], + "properties": { + "approval": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Return approvals that a token has Return type: `ApprovalsResponse`", + "type": "object", + "required": [ + "approvals" + ], + "properties": { + "approvals": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "List all operators that can access all of the owner's tokens Return type: `OperatorsResponse`", + "type": "object", + "required": [ + "all_operators" + ], + "properties": { + "all_operators": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "include_expired": { + "description": "unset or false will filter out expired items, you must set to true to see them", + "type": [ + "boolean", + "null" + ] + }, + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Total number of tokens issued", + "type": "object", + "required": [ + "num_tokens" + ], + "properties": { + "num_tokens": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "With MetaData Extension. Returns top-level metadata about the contract: `ContractInfoResponse`", + "type": "object", + "required": [ + "contract_info" + ], + "properties": { + "contract_info": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "With MetaData Extension. Returns metadata about one particular token, based on *ERC721 Metadata JSON Schema* but directly from the contract: `NftInfoResponse`", + "type": "object", + "required": [ + "nft_info" + ], + "properties": { + "nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "With MetaData Extension. Returns the result of both `NftInfo` and `OwnerOf` as one query as an optimization for clients: `AllNftInfo`", + "type": "object", + "required": [ + "all_nft_info" + ], + "properties": { + "all_nft_info": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "include_expired": { + "description": "unset or false will filter out expired approvals, you must set to true to see them", + "type": [ + "boolean", + "null" + ] + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "With Enumerable extension. Returns all tokens owned by the given address, [] if unset. Return type: TokensResponse.", + "type": "object", + "required": [ + "tokens" + ], + "properties": { + "tokens": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "owner": { + "type": "string" + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "With Enumerable extension. Requires pagination. Lists all token_ids controlled by the contract. Return type: TokensResponse.", + "type": "object", + "required": [ + "all_tokens" + ], + "properties": { + "all_tokens": { + "type": "object", + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "minter" + ], + "properties": { + "minter": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Extension query", + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/Cw2981QueryMsg" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Cw2981QueryMsg": { + "oneOf": [ + { + "description": "Should be called on sale to see if royalties are owed by the marketplace selling the NFT, if CheckRoyalties returns true See https://eips.ethereum.org/EIPS/eip-2981", + "type": "object", + "required": [ + "RoyaltyInfo" + ], + "properties": { + "RoyaltyInfo": { + "type": "object", + "required": [ + "sale_price", + "token_id" + ], + "properties": { + "sale_price": { + "$ref": "#/definitions/Uint128" + }, + "token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Called against contract to determine if this NFT implements royalties. Should return a boolean as part of CheckRoyaltiesResponse - default can simply be true if royalties are implemented at token level (i.e. always check on sale)", + "type": "object", + "required": [ + "CheckRoyalties" + ], + "properties": { + "CheckRoyalties": { + "type": "object" + } + }, + "additionalProperties": false + } + ] + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + } + } +} diff --git a/cosmwasm-contracts/nft-marketplace/schema/query_msg.json b/cosmwasm-contracts/nft-marketplace/schema/query_msg.json new file mode 100644 index 0000000000..45c8fcf7c2 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/query_msg.json @@ -0,0 +1,42 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "nft_info" + ], + "properties": { + "nft_info": { + "type": "object", + "required": [ + "nft_contract_addr", + "nft_token_id" + ], + "properties": { + "nft_contract_addr": { + "type": "string" + }, + "nft_token_id": { + "type": "string" + } + } + } + }, + "additionalProperties": false + } + ] +} diff --git a/cosmwasm-contracts/nft-marketplace/schema/royalties_info_response.json b/cosmwasm-contracts/nft-marketplace/schema/royalties_info_response.json new file mode 100644 index 0000000000..fc2c7bd93d --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/schema/royalties_info_response.json @@ -0,0 +1,23 @@ +{ + "$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" + } + }, + "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/cosmwasm-contracts/nft-marketplace/src/contract.rs b/cosmwasm-contracts/nft-marketplace/src/contract.rs new file mode 100644 index 0000000000..4c43178ca3 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/src/contract.rs @@ -0,0 +1,914 @@ +use crate::state::{Config, NFTInfo, CONFIG, NFT_LIST}; + +use crate::vault::{ + ConfigResponse, Cw2981QueryMsg, Cw721HookMsg, ExecuteMsg, InstantiateMsg, NftQueryMsg, + QueryMsg, RoyaltiesInfoResponse, +}; +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{ + attr, from_binary, to_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, + MessageInfo, QueryRequest, Response, StdError, StdResult, Uint128, WasmMsg, WasmQuery, +}; +use cw721::{Cw721ExecuteMsg, Cw721ReceiveMsg}; + +//Initialize the contract. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { + let config = Config { + owner: info.sender, + fee_bp: msg.fee_bp, + }; + + CONFIG.save(deps.storage, &config)?; + + Ok(Response::new()) +} + +//Execute the handle messages. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { + match msg { + ExecuteMsg::UpdateConfig { owner, fee_bp } => { + execute_update_config(deps, env, info, owner, fee_bp) + } + ExecuteMsg::ReceiveNft(msg) => receive_cw721(deps, env, info, msg), + ExecuteMsg::Withdraw { + nft_contract_addr, + nft_token_id, + } => execute_withdraw(deps, env, info, nft_contract_addr, nft_token_id), + ExecuteMsg::UpdatePrice { + nft_contract_addr, + nft_token_id, + denom, + amount, + } => execute_update_price( + deps, + env, + info, + nft_contract_addr, + nft_token_id, + denom, + amount, + ), + ExecuteMsg::Buy { + nft_contract_addr, + nft_token_id, + } => execute_buy(deps, env, info, nft_contract_addr, nft_token_id), + ExecuteMsg::WithdrawFee {} => execute_withdraw_fee(deps, env, info), + } +} + +pub fn receive_cw721( + deps: DepsMut, + env: Env, + info: MessageInfo, + cw721_msg: Cw721ReceiveMsg, +) -> StdResult { + let nft_contract_addr = info.sender; + + match from_binary(&cw721_msg.msg)? { + Cw721HookMsg::Deposit { denom, amount } => execute_deposit( + deps, + env, + Addr::unchecked(cw721_msg.sender), + nft_contract_addr, + cw721_msg.token_id, + denom, + amount, + ), + } +} + +// Only owner can execute it. +pub fn execute_update_config( + deps: DepsMut, + _env: Env, + info: MessageInfo, + owner: Option, + fee_bp: Option, +) -> StdResult { + let mut config: Config = CONFIG.load(deps.storage)?; + let mut attributes = vec![attr("action", "update_config")]; + + // permission check + if info.sender != config.owner { + return Err(StdError::generic_err("unauthorized")); + } + + if let Some(owner) = owner { + config.owner = deps.api.addr_validate(&owner)?; + attributes.push(attr("new_owner", owner.as_str())) + } + + if let Some(fee_bp) = fee_bp { + config.fee_bp = fee_bp; + attributes.push(attr("new_fee_bp", fee_bp)) + } + + CONFIG.save(deps.storage, &config)?; + + Ok(Response::new().add_attributes(attributes)) +} + +pub fn execute_deposit( + deps: DepsMut, + _env: Env, + sender: Addr, + nft_contract_addr: Addr, + nft_token_id: String, + denom: String, + amount: Uint128, +) -> StdResult { + let key = query_nft_info_key(nft_contract_addr.to_string(), nft_token_id.to_string()); + + if None != NFT_LIST.may_load(deps.storage, key.to_string())? { + return Err(StdError::generic_err("NFT already listed!")); + } + + NFT_LIST.save( + deps.storage, + key, + &NFTInfo { + owner: sender.to_string(), + denom, + amount, + }, + )?; + + Ok( + Response::new() + .add_attributes(vec![("action", "deposit"), ("sender", &sender.to_string())]), + ) +} + +pub fn execute_withdraw( + deps: DepsMut, + _env: Env, + info: MessageInfo, + nft_contract_addr: String, + nft_token_id: String, +) -> StdResult { + let mut messages: Vec = vec![]; + + let key = query_nft_info_key(nft_contract_addr.to_string(), nft_token_id.to_string()); + if let Some(nft_info) = NFT_LIST.may_load(deps.storage, key.to_string())? { + if nft_info.owner != info.sender { + return Err(StdError::generic_err("This NFT is not owned to the user!")); + } + + NFT_LIST.remove(deps.storage, key); + + messages.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: nft_contract_addr, + msg: to_binary(&Cw721ExecuteMsg::TransferNft { + recipient: info.sender.to_string(), + token_id: nft_token_id, + })?, + funds: vec![], + })); + } else { + return Err(StdError::generic_err("NFT is not listed!")); + } + + Ok(Response::new() + .add_messages(messages) + .add_attribute("action", "withdraw")) +} + +pub fn execute_update_price( + deps: DepsMut, + _env: Env, + info: MessageInfo, + nft_contract_addr: String, + nft_token_id: String, + denom: String, + amount: Uint128, +) -> StdResult { + let key = query_nft_info_key(nft_contract_addr, nft_token_id); + if let Some(nft_info) = NFT_LIST.may_load(deps.storage, key.to_string())? { + if nft_info.owner != info.sender.to_string() { + return Err(StdError::generic_err("This NFT is not owned to the user!")); + } + + NFT_LIST.save( + deps.storage, + key, + &NFTInfo { + owner: nft_info.owner, + denom, + amount, + }, + )?; + } else { + return Err(StdError::generic_err("NFT is not listed!")); + } + + Ok(Response::new().add_attribute("action", "update_price")) +} + +pub fn execute_buy( + deps: DepsMut, + _env: Env, + info: MessageInfo, + nft_contract_addr: String, + nft_token_id: String, +) -> StdResult { + let mut messages: Vec = vec![]; + let config: Config = CONFIG.load(deps.storage)?; + + let key = query_nft_info_key(nft_contract_addr.to_string(), nft_token_id.to_string()); + if let Some(nft_info) = NFT_LIST.may_load(deps.storage, key.to_string())? { + let mut fund = info.funds[0].clone(); + if nft_info.denom != fund.denom || nft_info.amount != fund.amount { + return Err(StdError::generic_err( + "The payment is not matched with the selling price!", + )); + } + + messages.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: nft_contract_addr.clone(), + msg: to_binary(&Cw721ExecuteMsg::TransferNft { + recipient: info.sender.to_string(), + token_id: nft_token_id.clone(), + })?, + funds: vec![], + })); + + let fee_amount = fund + .amount + .checked_mul(config.fee_bp)? + .checked_div(Uint128::from(10000u128))?; + fund.amount = fund.amount.checked_sub(fee_amount)?; + + // check royalty + if let Ok(royalty_info) = query_royalties_info( + deps.as_ref(), + nft_contract_addr, + nft_token_id, + nft_info.amount, + ) { + fund.amount = fund.amount.checked_sub(royalty_info.royalty_amount)?; + + messages.push(CosmosMsg::Bank(BankMsg::Send { + to_address: royalty_info.address, + amount: vec![Coin { + amount: royalty_info.royalty_amount, + denom: fund.denom.clone(), + }], + })); + } + + messages.push(CosmosMsg::Bank(BankMsg::Send { + to_address: nft_info.owner.to_string(), + amount: vec![fund], + })); + + NFT_LIST.remove(deps.storage, key); + } else { + return Err(StdError::generic_err("NFT is not listed!")); + } + + Ok(Response::new() + .add_messages(messages) + .add_attribute("action", "buy")) +} + +// Only owner can execute it. +pub fn execute_withdraw_fee(deps: DepsMut, env: Env, info: MessageInfo) -> StdResult { + let config: Config = CONFIG.load(deps.storage)?; + // permission check + if info.sender != config.owner { + return Err(StdError::generic_err("unauthorized")); + } + + let coins = deps.querier.query_all_balances(env.contract.address)?; + + Ok(Response::new() + .add_message(CosmosMsg::Bank(BankMsg::Send { + to_address: info.sender.to_string(), + amount: coins, + })) + .add_attributes(vec![attr("action", "withdraw_fee")])) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Config {} => to_binary(&query_config(deps)?), + QueryMsg::NftInfo { + nft_contract_addr, + nft_token_id, + } => to_binary(&query_nft_info(deps, nft_contract_addr, nft_token_id)?), + } +} + +pub fn query_config(deps: Deps) -> StdResult { + let config = CONFIG.load(deps.storage)?; + + Ok(ConfigResponse { + owner: config.owner.to_string(), + fee_bp: config.fee_bp, + }) +} + +pub fn query_nft_info( + deps: Deps, + nft_contract_addr: String, + nft_token_id: String, +) -> StdResult> { + Ok(NFT_LIST.may_load( + deps.storage, + query_nft_info_key(nft_contract_addr, nft_token_id), + )?) +} + +pub fn query_nft_info_key(nft_contract_addr: String, nft_token_id: String) -> String { + nft_contract_addr.to_string() + &nft_token_id +} + +pub fn query_royalties_info( + deps: Deps, + contract_addr: String, + token_id: String, + sale_price: Uint128, +) -> StdResult { + deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr, + msg: to_binary(&NftQueryMsg::Extension { + msg: Cw2981QueryMsg::RoyaltyInfo { + token_id, + sale_price, + }, + })?, + })) +} + +#[cfg(test)] +mod tests { + use crate::{contract::query_nft_info, state::NFTInfo}; + + use super::{ + execute, instantiate, query_config, Cw721ExecuteMsg, Cw721ReceiveMsg, ExecuteMsg, + InstantiateMsg, + }; + use crate::vault::Cw721HookMsg; + use cosmwasm_std::{ + testing::{mock_dependencies, mock_dependencies_with_balance, mock_env, mock_info}, + to_binary, BankMsg, Coin, CosmosMsg, Uint128, WasmMsg, + }; + + fn mock_instantiate_msg(fee_bp: Uint128) -> InstantiateMsg { + InstantiateMsg { fee_bp: fee_bp } + } + + #[test] + fn test_instantiate() { + let mut deps = mock_dependencies(); + + // create owner + let owner_address = "owner-addr".to_string(); + let owner_info = mock_info(&owner_address, &[]); + + // instantiate minter + let init_msg = mock_instantiate_msg(Uint128::new(100)); // 1% fee_bp + instantiate( + deps.as_mut(), + mock_env(), + owner_info.clone(), + init_msg.clone(), + ) + .unwrap(); + + // check config + let config = query_config(deps.as_ref()).unwrap(); + assert_eq!(config.owner, owner_address); + assert_eq!(config.fee_bp, Uint128::new(100)); + } + + #[test] + fn test_update_config() { + let mut deps = mock_dependencies(); + + // create owner + let owner_address = "owner-addr".to_string(); + let owner_info = mock_info(&owner_address, &[]); + + // instantiate minter + let init_msg = mock_instantiate_msg(Uint128::new(100)); // 1% fee_bp + instantiate( + deps.as_mut(), + mock_env(), + owner_info.clone(), + init_msg.clone(), + ) + .unwrap(); + + let user_address = "user-addr".to_string(); + let user_info = mock_info(&user_address, &[]); + + // 1. only owner can update config + let err = execute( + deps.as_mut(), + mock_env(), + user_info.clone(), + ExecuteMsg::UpdateConfig { + owner: None, + fee_bp: Some(Uint128::new(200)), // 2% + }, + ) + .unwrap_err(); + assert_eq!(err.to_string(), "Generic error: unauthorized"); + + // 2. owner field can be none and it will only update fee_bp + execute( + deps.as_mut(), + mock_env(), + owner_info.clone(), + ExecuteMsg::UpdateConfig { + owner: None, + fee_bp: Some(Uint128::new(200)), // 2% + }, + ) + .unwrap(); + let config = query_config(deps.as_ref()).unwrap(); + assert_eq!(config.owner, owner_address); + assert_eq!(config.fee_bp, Uint128::new(200)); + + // 3. owner can transfer ownership + execute( + deps.as_mut(), + mock_env(), + owner_info.clone(), + ExecuteMsg::UpdateConfig { + owner: Some(user_address.clone()), + fee_bp: Some(Uint128::new(200)), // 2% + }, + ) + .unwrap(); + let config = query_config(deps.as_ref()).unwrap(); + assert_eq!(config.owner, user_address); + assert_eq!(config.fee_bp, Uint128::new(200)); + } + + #[test] + fn test_nft_list() { + let mut deps = mock_dependencies(); + + // create owner + let owner_address = "owner-addr".to_string(); + let owner_info = mock_info(&owner_address, &[]); + + // instantiate minter + let init_msg = mock_instantiate_msg(Uint128::new(100)); // 1% fee_bp + instantiate( + deps.as_mut(), + mock_env(), + owner_info.clone(), + init_msg.clone(), + ) + .unwrap(); + + let user_address = "user-addr".to_string(); + let contract_address = "contract-addr".to_string(); + let token_id = "1".to_string(); + let denom = "utori".to_string(); + let amount = Uint128::new(100000000); // 100 TORI + + execute( + deps.as_mut(), + mock_env(), + mock_info(&contract_address, &[]), + ExecuteMsg::ReceiveNft(Cw721ReceiveMsg { + sender: user_address.clone(), + token_id: token_id.clone(), + msg: to_binary(&Cw721HookMsg::Deposit { + denom: denom.clone(), + amount, + }) + .unwrap(), + }), + ) + .unwrap(); + + let nft_info = query_nft_info(deps.as_ref(), contract_address, token_id).unwrap(); + assert_eq!( + nft_info, + Some(NFTInfo { + owner: user_address, + denom, + amount, + }) + ); + } + + #[test] + fn test_nft_withdraw() { + let mut deps = mock_dependencies(); + + // create owner + let owner_address = "owner-addr".to_string(); + let owner_info = mock_info(&owner_address, &[]); + + // instantiate minter + let init_msg = mock_instantiate_msg(Uint128::new(100)); // 1% fee_bp + instantiate( + deps.as_mut(), + mock_env(), + owner_info.clone(), + init_msg.clone(), + ) + .unwrap(); + + let user_address = "user-addr".to_string(); + let contract_address = "contract-addr".to_string(); + let token_id = "1".to_string(); + let denom = "utori".to_string(); + let amount = Uint128::new(100000000); // 100 TORI + + execute( + deps.as_mut(), + mock_env(), + mock_info(&contract_address, &[]), + ExecuteMsg::ReceiveNft(Cw721ReceiveMsg { + sender: user_address.clone(), + token_id: token_id.clone(), + msg: to_binary(&Cw721HookMsg::Deposit { + denom: denom.clone(), + amount, + }) + .unwrap(), + }), + ) + .unwrap(); + + // 1. only nft owner can withdraw + let err = execute( + deps.as_mut(), + mock_env(), + mock_info(&owner_address, &[]), + ExecuteMsg::Withdraw { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + }, + ) + .unwrap_err(); + assert_eq!( + err.to_string(), + "Generic error: This NFT is not owned to the user!" + ); + + // 2. withdarw nft and it will be unlisted from marketplace + execute( + deps.as_mut(), + mock_env(), + mock_info(&user_address, &[]), + ExecuteMsg::Withdraw { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + }, + ) + .unwrap(); + + let nft_info = query_nft_info(deps.as_ref(), contract_address, token_id).unwrap(); + assert_eq!(nft_info, None); + } + + #[test] + fn test_update_price() { + let mut deps = mock_dependencies(); + + // create owner + let owner_address = "owner-addr".to_string(); + let owner_info = mock_info(&owner_address, &[]); + + // instantiate minter + let init_msg = mock_instantiate_msg(Uint128::new(100)); // 1% fee_bp + instantiate( + deps.as_mut(), + mock_env(), + owner_info.clone(), + init_msg.clone(), + ) + .unwrap(); + + let user_address = "user-addr".to_string(); + let contract_address = "contract-addr".to_string(); + let token_id = "1".to_string(); + let denom = "utori".to_string(); + let amount = Uint128::new(100000000); // 100 TORI + + execute( + deps.as_mut(), + mock_env(), + mock_info(&contract_address, &[]), + ExecuteMsg::ReceiveNft(Cw721ReceiveMsg { + sender: user_address.clone(), + token_id: token_id.clone(), + msg: to_binary(&Cw721HookMsg::Deposit { + denom: denom.clone(), + amount, + }) + .unwrap(), + }), + ) + .unwrap(); + + let new_denom = "new-denom".to_string(); + let new_amount = Uint128::new(1000000000); // 1000 + + // 1. only nft owner can update price + let err = execute( + deps.as_mut(), + mock_env(), + mock_info(&owner_address, &[]), + ExecuteMsg::UpdatePrice { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + denom: new_denom.clone(), + amount: new_amount, + }, + ) + .unwrap_err(); + assert_eq!( + err.to_string(), + "Generic error: This NFT is not owned to the user!" + ); + + // 2. withdarw nft and it will be unlisted from marketplace + execute( + deps.as_mut(), + mock_env(), + mock_info(&user_address, &[]), + ExecuteMsg::UpdatePrice { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + denom: new_denom.clone(), + amount: new_amount, + }, + ) + .unwrap(); + + let nft_info = query_nft_info(deps.as_ref(), contract_address, token_id).unwrap(); + assert_eq!( + nft_info, + Some(NFTInfo { + owner: user_address, + denom: new_denom, + amount: new_amount, + }) + ); + } + + #[test] + fn test_nft_buy() { + let mut deps = mock_dependencies(); + + // create owner + let owner_address = "owner-addr".to_string(); + let owner_info = mock_info(&owner_address, &[]); + + // instantiate minter + let init_msg = mock_instantiate_msg(Uint128::new(100)); // 1% fee_bp + instantiate( + deps.as_mut(), + mock_env(), + owner_info.clone(), + init_msg.clone(), + ) + .unwrap(); + + let user_address = "user-addr".to_string(); + let contract_address = "contract-addr".to_string(); + let token_id = "1".to_string(); + let denom = "utori".to_string(); + let amount = Uint128::new(100000000); // 100 TORI + + execute( + deps.as_mut(), + mock_env(), + mock_info(&contract_address, &[]), + ExecuteMsg::ReceiveNft(Cw721ReceiveMsg { + sender: user_address.clone(), + token_id: token_id.clone(), + msg: to_binary(&Cw721HookMsg::Deposit { + denom: denom.clone(), + amount, + }) + .unwrap(), + }), + ) + .unwrap(); + + let buyer_address = "buyer-addr".to_string(); + // 1. can buy only listed asset + let invalid_token_id = "2".to_string(); + let err = execute( + deps.as_mut(), + mock_env(), + mock_info(&buyer_address, &[]), + ExecuteMsg::Buy { + nft_contract_addr: contract_address.clone(), + nft_token_id: invalid_token_id.clone(), + }, + ) + .unwrap_err(); + assert_eq!(err.to_string(), "Generic error: NFT is not listed!"); + + // 2. check correct fund denom + let invalid_denom = "invalid-denom".to_string(); + let err = execute( + deps.as_mut(), + mock_env(), + mock_info( + &buyer_address, + &[{ + Coin { + denom: invalid_denom, + amount: Uint128::new(0), + } + }], + ), + ExecuteMsg::Buy { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + }, + ) + .unwrap_err(); + assert_eq!( + err.to_string(), + "Generic error: The payment is not matched with the selling price!" + ); + + // 3. check correct fund amount + let err = execute( + deps.as_mut(), + mock_env(), + mock_info( + &buyer_address, + &[{ + Coin { + denom: denom.to_string(), + amount: Uint128::new(0), + } + }], + ), + ExecuteMsg::Buy { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + }, + ) + .unwrap_err(); + assert_eq!( + err.to_string(), + "Generic error: The payment is not matched with the selling price!" + ); + + // 4. can buy nft & it's unlsited + let resp = execute( + deps.as_mut(), + mock_env(), + mock_info( + &buyer_address, + &[{ + Coin { + denom: denom.to_string(), + amount: amount, + } + }], + ), + ExecuteMsg::Buy { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + }, + ) + .unwrap(); + assert_eq!( + resp.messages[0].msg, + CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: contract_address.clone(), + msg: to_binary(&Cw721ExecuteMsg::TransferNft { + recipient: buyer_address.clone(), + token_id: token_id.clone(), + }) + .unwrap(), + funds: vec![], + }) + ); + assert_eq!( + resp.messages[1].msg, + CosmosMsg::Bank(BankMsg::Send { + to_address: user_address, + amount: vec![{ + Coin { + amount: Uint128::new(100000000) * Uint128::new(99) / Uint128::new(100), // fee is removed + denom: denom.clone(), + } + }], + }) + ); + + let nft_info = query_nft_info(deps.as_ref(), contract_address, token_id).unwrap(); + assert_eq!(nft_info, None); + } + + #[test] + fn test_withdraw_fee() { + let denom = "utori".to_string(); + let amount = Uint128::new(100000000); // 100 TORI + let mut deps = mock_dependencies_with_balance(&[Coin { + denom: denom.clone(), + amount: amount / Uint128::new(100), + }]); + + // create owner + let owner_address = "owner-addr".to_string(); + let owner_info = mock_info(&owner_address, &[]); + + // instantiate minter + let init_msg = mock_instantiate_msg(Uint128::new(100)); // 1% fee_bp + instantiate( + deps.as_mut(), + mock_env(), + owner_info.clone(), + init_msg.clone(), + ) + .unwrap(); + + let user_address = "user-addr".to_string(); + let contract_address = "contract-addr".to_string(); + let token_id = "1".to_string(); + + execute( + deps.as_mut(), + mock_env(), + mock_info(&contract_address, &[]), + ExecuteMsg::ReceiveNft(Cw721ReceiveMsg { + sender: user_address.clone(), + token_id: token_id.clone(), + msg: to_binary(&Cw721HookMsg::Deposit { + denom: denom.clone(), + amount, + }) + .unwrap(), + }), + ) + .unwrap(); + + let buyer_address = "buyer-addr".to_string(); + execute( + deps.as_mut(), + mock_env(), + mock_info( + &buyer_address, + &[{ + Coin { + denom: denom.to_string(), + amount: amount, + } + }], + ), + ExecuteMsg::Buy { + nft_contract_addr: contract_address.clone(), + nft_token_id: token_id.clone(), + }, + ) + .unwrap(); + + // 1. only owner can update config + let err = execute( + deps.as_mut(), + mock_env(), + mock_info(&user_address, &[]), + ExecuteMsg::WithdrawFee {}, + ) + .unwrap_err(); + assert_eq!(err.to_string(), "Generic error: unauthorized"); + + // 2. can withdraw fees from contract + let resp = execute( + deps.as_mut(), + mock_env(), + mock_info(&owner_address, &[]), + ExecuteMsg::WithdrawFee {}, + ) + .unwrap(); + assert_eq!( + resp.messages[0].msg, + CosmosMsg::Bank(BankMsg::Send { + to_address: owner_address, + amount: vec![{ + Coin { + amount: Uint128::new(100000000) / Uint128::new(100), // fee is removed + denom: denom.clone(), + } + }], + }) + ); + } +} diff --git a/cosmwasm-contracts/nft-marketplace/src/lib.rs b/cosmwasm-contracts/nft-marketplace/src/lib.rs new file mode 100644 index 0000000000..4e7b0cd947 --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/src/lib.rs @@ -0,0 +1,3 @@ +pub mod contract; +pub mod state; +pub mod vault; diff --git a/cosmwasm-contracts/nft-marketplace/src/state.rs b/cosmwasm-contracts/nft-marketplace/src/state.rs new file mode 100644 index 0000000000..4261ff65ac --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/src/state.rs @@ -0,0 +1,24 @@ +use cosmwasm_std::{Addr, Uint128}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use cw_storage_plus::{Item, Map}; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct Config { + pub owner: Addr, + pub fee_bp: Uint128, // based on 10000 +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct NFTInfo { + pub owner: String, + pub denom: String, + pub amount: Uint128, +} + +// put the length bytes at the first for compatibility with legacy singleton store +pub const CONFIG: Item = Item::new("config"); + +// nft_contract_addr + nft_token_id => nft list info +pub const NFT_LIST: Map = Map::new("nft_list"); diff --git a/cosmwasm-contracts/nft-marketplace/src/vault.rs b/cosmwasm-contracts/nft-marketplace/src/vault.rs new file mode 100644 index 0000000000..16edc48bdf --- /dev/null +++ b/cosmwasm-contracts/nft-marketplace/src/vault.rs @@ -0,0 +1,89 @@ +use cosmwasm_std::Uint128; +use cw721::Cw721ReceiveMsg; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct InstantiateMsg { + pub fee_bp: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ExecuteMsg { + UpdateConfig { + owner: Option, + fee_bp: Option, + }, + ReceiveNft(Cw721ReceiveMsg), + Withdraw { + nft_contract_addr: String, + nft_token_id: String, + }, + UpdatePrice { + nft_contract_addr: String, + nft_token_id: String, + denom: String, + amount: Uint128, + }, + Buy { + nft_contract_addr: String, + nft_token_id: String, + }, + WithdrawFee {}, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum Cw721HookMsg { + Deposit { denom: String, amount: Uint128 }, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum QueryMsg { + Config {}, + NftInfo { + nft_contract_addr: String, + nft_token_id: String, + }, +} + +// We define a custom struct for each query response +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ConfigResponse { + pub owner: String, + pub fee_bp: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct RoyaltiesInfoResponse { + pub address: String, + // Note that this must be the same denom as that passed in to RoyaltyInfo + // rounding up or down is at the discretion of the implementer + pub royalty_amount: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub enum Cw2981QueryMsg { + /// Should be called on sale to see if royalties are owed + /// by the marketplace selling the NFT, if CheckRoyalties + /// returns true + /// See https://eips.ethereum.org/EIPS/eip-2981 + RoyaltyInfo { + token_id: String, + // the denom of this sale must also be the denom returned by RoyaltiesInfoResponse + // this was originally implemented as a Coin + // however that would mean you couldn't buy using CW20s + // as CW20 is just mapping of addr -> balance + sale_price: Uint128, + }, + /// Called against contract to determine if this NFT + /// implements royalties. Should return a boolean as part of + /// CheckRoyaltiesResponse - default can simply be true + /// if royalties are implemented at token level + /// (i.e. always check on sale) + CheckRoyalties {}, +} + +pub type NftQueryMsg = cw721_base::QueryMsg; diff --git a/packages/components/nftDetails/components/NFTSellInfo.tsx b/packages/components/nftDetails/components/NFTSellInfo.tsx index 768447e91c..ab88237b0d 100644 --- a/packages/components/nftDetails/components/NFTSellInfo.tsx +++ b/packages/components/nftDetails/components/NFTSellInfo.tsx @@ -1,7 +1,7 @@ import { Decimal } from "@cosmjs/math"; import { useQuery } from "@tanstack/react-query"; -import { TeritoriNftVaultQueryClient } from "../../../contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; +import { NftMarketplaceQueryClient } from "../../../contracts-clients/nft-marketplace/NftMarketplace.client"; import { getNativeCurrency, getNetwork, @@ -78,7 +78,7 @@ const useVaultConfig = (networkId: string | undefined) => { } const cosmwasmClient = await mustGetNonSigningCosmWasmClient(network.id); - const vaultClient = new TeritoriNftVaultQueryClient( + const vaultClient = new NftMarketplaceQueryClient( cosmwasmClient, network.vaultContractAddress, ); diff --git a/packages/contracts-clients/teritori-nft-vault/TeritoriNftVault.client.ts b/packages/contracts-clients/nft-marketplace/NftMarketplace.client.ts similarity index 93% rename from packages/contracts-clients/teritori-nft-vault/TeritoriNftVault.client.ts rename to packages/contracts-clients/nft-marketplace/NftMarketplace.client.ts index 52b82eba5e..2fd67b2785 100644 --- a/packages/contracts-clients/teritori-nft-vault/TeritoriNftVault.client.ts +++ b/packages/contracts-clients/nft-marketplace/NftMarketplace.client.ts @@ -6,8 +6,8 @@ import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; import { Coin, StdFee } from "@cosmjs/amino"; -import { Uint128, AllNftsInVaultResponse, NFTInfo, ConfigResponse, ExecuteMsg, Binary, Cw721ReceiveMsg, InstantiateMsg, NftInfoResponse, NftListResponse, NftOwnerInfoResponse, NftQueryMsg, Cw2981QueryMsg, QueryMsg, RoyaltiesInfoResponse } from "./TeritoriNftVault.types"; -export interface TeritoriNftVaultReadOnlyInterface { +import { Uint128, AllNftsInVaultResponse, NFTInfo, ConfigResponse, ExecuteMsg, Binary, Cw721ReceiveMsg, InstantiateMsg, NftInfoResponse, NftListResponse, NftOwnerInfoResponse, NftQueryMsg, Cw2981QueryMsg, QueryMsg, RoyaltiesInfoResponse } from "./NftMarketplace.types"; +export interface NftMarketplaceReadOnlyInterface { contractAddress: string; config: () => Promise; nftInfo: ({ @@ -18,7 +18,7 @@ export interface TeritoriNftVaultReadOnlyInterface { nftTokenId: string; }) => Promise; } -export class TeritoriNftVaultQueryClient implements TeritoriNftVaultReadOnlyInterface { +export class NftMarketplaceQueryClient implements NftMarketplaceReadOnlyInterface { client: CosmWasmClient; contractAddress: string; @@ -49,7 +49,7 @@ export class TeritoriNftVaultQueryClient implements TeritoriNftVaultReadOnlyInte }); }; } -export interface TeritoriNftVaultInterface extends TeritoriNftVaultReadOnlyInterface { +export interface NftMarketplaceInterface extends NftMarketplaceReadOnlyInterface { contractAddress: string; sender: string; updateConfig: ({ @@ -95,7 +95,7 @@ export interface TeritoriNftVaultInterface extends TeritoriNftVaultReadOnlyInter }, fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; withdrawFee: (fee?: number | StdFee | "auto", memo?: string, _funds?: Coin[]) => Promise; } -export class TeritoriNftVaultClient extends TeritoriNftVaultQueryClient implements TeritoriNftVaultInterface { +export class NftMarketplaceClient extends NftMarketplaceQueryClient implements NftMarketplaceInterface { client: SigningCosmWasmClient; sender: string; contractAddress: string; diff --git a/packages/contracts-clients/teritori-nft-vault/TeritoriNftVault.types.ts b/packages/contracts-clients/nft-marketplace/NftMarketplace.types.ts similarity index 100% rename from packages/contracts-clients/teritori-nft-vault/TeritoriNftVault.types.ts rename to packages/contracts-clients/nft-marketplace/NftMarketplace.types.ts diff --git a/packages/contracts-clients/nft-marketplace/index.ts b/packages/contracts-clients/nft-marketplace/index.ts new file mode 100644 index 0000000000..107d66df4a --- /dev/null +++ b/packages/contracts-clients/nft-marketplace/index.ts @@ -0,0 +1,2 @@ +export * from "./NftMarketplace.client"; +export * from "./NftMarketplace.types"; \ No newline at end of file diff --git a/packages/hooks/useCancelNFTListing.ts b/packages/hooks/useCancelNFTListing.ts index d6af19d416..c68fb12a16 100644 --- a/packages/hooks/useCancelNFTListing.ts +++ b/packages/hooks/useCancelNFTListing.ts @@ -2,7 +2,7 @@ import { useCallback } from "react"; import useSelectedWallet from "./useSelectedWallet"; -import { TeritoriNftVaultClient } from "@/contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; +import { NftMarketplaceClient } from "@/contracts-clients/nft-marketplace/NftMarketplace.client"; import { NFTVault__factory } from "@/evm-contracts-clients/teritori-nft-vault/NFTVault__factory"; import { getKeplrSigningCosmWasmClient, @@ -24,7 +24,7 @@ const teritoriCancelNFTListing = async ( throw new Error("network not supported"); } const cosmwasmClient = await getKeplrSigningCosmWasmClient(networkId); - const vaultClient = new TeritoriNftVaultClient( + const vaultClient = new NftMarketplaceClient( cosmwasmClient, sender, network.vaultContractAddress, diff --git a/packages/hooks/useNFTInfo.ts b/packages/hooks/useNFTInfo.ts index ab05936a34..4233b0f287 100644 --- a/packages/hooks/useNFTInfo.ts +++ b/packages/hooks/useNFTInfo.ts @@ -5,11 +5,11 @@ import { useBreedingConfig } from "./useBreedingConfig"; import { ConfigResponse as BreedingConfigResponse } from "../contracts-clients/teritori-breeding/TeritoriBreeding.types"; import { Metadata as Cw721MembershipMetadata } from "@/contracts-clients/cw721-membership"; +import { NftMarketplaceQueryClient } from "@/contracts-clients/nft-marketplace/NftMarketplace.client"; import { TeritoriBreedingQueryClient } from "@/contracts-clients/teritori-breeding/TeritoriBreeding.client"; import { TeritoriBunkerMinterQueryClient } from "@/contracts-clients/teritori-bunker-minter/TeritoriBunkerMinter.client"; import { TeritoriNameServiceQueryClient } from "@/contracts-clients/teritori-name-service/TeritoriNameService.client"; import { TeritoriNftQueryClient } from "@/contracts-clients/teritori-nft/TeritoriNft.client"; -import { TeritoriNftVaultQueryClient } from "@/contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; import { TeritoriMinter__factory } from "@/evm-contracts-clients/teritori-bunker-minter/TeritoriMinter__factory"; import { TeritoriNft__factory } from "@/evm-contracts-clients/teritori-nft/TeritoriNft__factory"; import { NFTVault__factory } from "@/evm-contracts-clients/teritori-nft-vault/NFTVault__factory"; @@ -130,7 +130,7 @@ const getTNSNFTInfo = async ( // ======== Getting NFT owner const { owner } = await tnsClient.ownerOf({ tokenId }); // ======== Getting vault stuff (For selling) - const vaultClient = new TeritoriNftVaultQueryClient( + const vaultClient = new NftMarketplaceQueryClient( cosmwasmClient, network.vaultContractAddress, ); @@ -362,7 +362,7 @@ const getTeritoriBunkerNFTInfo = async ( // ======== Getting NFT metadata // ======== Getting vault stuff (For selling) - const vaultClient = new TeritoriNftVaultQueryClient( + const vaultClient = new NftMarketplaceQueryClient( cosmwasmClient, network.vaultContractAddress, ); @@ -472,7 +472,7 @@ const getTeritoriRiotBreedingNFTInfo = async ( // ======== Getting NFT metadata // ======== Getting vault stuff (For selling) - const vaultClient = new TeritoriNftVaultQueryClient( + const vaultClient = new NftMarketplaceQueryClient( cosmwasmClient, network.vaultContractAddress, ); @@ -600,7 +600,7 @@ const getNFTVaultInfo = async ( throw new Error("network not supported"); } const cosmwasmClient = await mustGetNonSigningCosmWasmClient(network.id); - const vaultClient = new TeritoriNftVaultQueryClient( + const vaultClient = new NftMarketplaceQueryClient( cosmwasmClient, network.vaultContractAddress, ); diff --git a/packages/hooks/useVaultNFTInfo.ts b/packages/hooks/useVaultNFTInfo.ts index 21af2a7fe7..7eecf9dea8 100644 --- a/packages/hooks/useVaultNFTInfo.ts +++ b/packages/hooks/useVaultNFTInfo.ts @@ -1,6 +1,6 @@ import { useQuery } from "@tanstack/react-query"; -import { TeritoriNftVaultQueryClient } from "@/contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; +import { NftMarketplaceQueryClient } from "@/contracts-clients/nft-marketplace/NftMarketplace.client"; import { getCosmosNetwork, mustGetNonSigningCosmWasmClient, @@ -28,7 +28,7 @@ export const useVaultNFTInfo = (nftId: string | undefined) => { console.log("network nft info", network); const client = await mustGetNonSigningCosmWasmClient(network.id); - const vaultClient = new TeritoriNftVaultQueryClient( + const vaultClient = new NftMarketplaceQueryClient( client, network?.vaultContractAddress, ); diff --git a/packages/hooks/vault/useVaultConfig.ts b/packages/hooks/vault/useVaultConfig.ts index 342dc4685c..726478823d 100644 --- a/packages/hooks/vault/useVaultConfig.ts +++ b/packages/hooks/vault/useVaultConfig.ts @@ -1,6 +1,6 @@ import { useQuery } from "@tanstack/react-query"; -import { TeritoriNftVaultQueryClient } from "@/contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; +import { NftMarketplaceQueryClient } from "@/contracts-clients/nft-marketplace/NftMarketplace.client"; import { getCosmosNetwork, mustGetNonSigningCosmWasmClient } from "@/networks"; export const useVaultConfig = (networkId: string) => { @@ -12,7 +12,7 @@ export const useVaultConfig = (networkId: string) => { return undefined; } const cosmwasmClient = await mustGetNonSigningCosmWasmClient(networkId); - const client = new TeritoriNftVaultQueryClient( + const client = new NftMarketplaceQueryClient( cosmwasmClient, network.vaultContractAddress, ); diff --git a/packages/screens/CoreDAO/CoreDAOScreen.tsx b/packages/screens/CoreDAO/CoreDAOScreen.tsx index 9874854910..4a934c5b35 100644 --- a/packages/screens/CoreDAO/CoreDAOScreen.tsx +++ b/packages/screens/CoreDAO/CoreDAOScreen.tsx @@ -12,8 +12,8 @@ import { ScreenContainer } from "@/components/ScreenContainer"; import { PrimaryButton } from "@/components/buttons/PrimaryButton"; import { SpacerColumn } from "@/components/spacer"; import { useFeedbacks } from "@/context/FeedbacksProvider"; +import { NftMarketplaceClient } from "@/contracts-clients/nft-marketplace/NftMarketplace.client"; import { TeritoriNameServiceQueryClient } from "@/contracts-clients/teritori-name-service/TeritoriNameService.client"; -import { TeritoriNftVaultClient } from "@/contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; import { useDAOMakeProposal } from "@/hooks/dao/useDAOMakeProposal"; import { useFeedConfig } from "@/hooks/feed/useFeedConfig"; import { useBalances } from "@/hooks/useBalances"; @@ -177,7 +177,7 @@ const VaultManager: React.FC<{ networkId: string }> = ({ networkId }) => { const cosmWasmClient = await getKeplrSigningCosmWasmClient( selectedWallet.networkId, ); - const vaultClient = new TeritoriNftVaultClient( + const vaultClient = new NftMarketplaceClient( cosmWasmClient, selectedWallet.address, network.vaultContractAddress, diff --git a/packages/screens/Marketplace/NFTDetailScreen.tsx b/packages/screens/Marketplace/NFTDetailScreen.tsx index 173a5023a5..c81ad5734b 100644 --- a/packages/screens/Marketplace/NFTDetailScreen.tsx +++ b/packages/screens/Marketplace/NFTDetailScreen.tsx @@ -11,7 +11,7 @@ import { SpacerColumn } from "@/components/spacer"; import { Tabs } from "@/components/tabs/Tabs"; import { initialToastError, useFeedbacks } from "@/context/FeedbacksProvider"; import { Wallet } from "@/context/WalletsProvider"; -import { TeritoriNftVaultClient } from "@/contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; +import { NftMarketplaceClient } from "@/contracts-clients/nft-marketplace/NftMarketplace.client"; import { NFTVault__factory } from "@/evm-contracts-clients/teritori-nft-vault/NFTVault__factory"; import { useMintEnded } from "@/hooks/collection/useMintEnded"; import { useCancelNFTListing } from "@/hooks/useCancelNFTListing"; @@ -163,7 +163,7 @@ const Content: React.FC<{ if (!cosmosNetwork.vaultContractAddress) { throw new Error("network not supported"); } - const vaultClient = new TeritoriNftVaultClient( + const vaultClient = new NftMarketplaceClient( client, sender, cosmosNetwork.vaultContractAddress, @@ -295,7 +295,7 @@ const teritoriBuy = async (wallet: Wallet, info: NFTInfo) => { throw new Error("network not supported"); } const signingCosmwasmClient = await getKeplrSigningCosmWasmClient(network.id); - const signingVaultClient = new TeritoriNftVaultClient( + const signingVaultClient = new NftMarketplaceClient( signingCosmwasmClient, wallet.address, network.vaultContractAddress, diff --git a/packages/scripts/network-setup/deployLib.ts b/packages/scripts/network-setup/deployLib.ts index 8eec9f1e62..e2a9bf0f46 100644 --- a/packages/scripts/network-setup/deployLib.ts +++ b/packages/scripts/network-setup/deployLib.ts @@ -5,6 +5,7 @@ import { bech32 } from "bech32"; import _, { cloneDeep } from "lodash"; import path from "path"; +import { InstantiateMsg as MarketplaceVaultInstantiateMsg } from "../../contracts-clients/nft-marketplace/NftMarketplace.types"; import { TeritoriNameServiceClient, TeritoriNameServiceQueryClient, @@ -14,7 +15,6 @@ import { ExecuteMsg as NameServiceExecuteMsg, InstantiateMsg as NameServiceInstantiateMsg, } from "../../contracts-clients/teritori-name-service/TeritoriNameService.types"; -import { InstantiateMsg as MarketplaceVaultInstantiateMsg } from "../../contracts-clients/teritori-nft-vault/TeritoriNftVault.types"; import { InstantiateMsg as SocialFeedInstantiateMsg } from "../../contracts-clients/teritori-social-feed/TeritoriSocialFeed.types"; import { CosmosNetworkInfo, diff --git a/packages/scripts/vaultInfo.ts b/packages/scripts/vaultInfo.ts index 61bc6451c5..9fc03420e4 100644 --- a/packages/scripts/vaultInfo.ts +++ b/packages/scripts/vaultInfo.ts @@ -1,4 +1,4 @@ -import { TeritoriNftVaultQueryClient } from "../contracts-clients/teritori-nft-vault/TeritoriNftVault.client"; +import { NftMarketplaceQueryClient } from "../contracts-clients/nft-marketplace/NftMarketplace.client"; import { mustGetNonSigningCosmWasmClient } from "../networks"; import { teritoriNetwork } from "../networks/teritori"; @@ -10,7 +10,7 @@ const main = async () => { console.log("contract address:", network.vaultContractAddress); - const client = new TeritoriNftVaultQueryClient( + const client = new NftMarketplaceQueryClient( await mustGetNonSigningCosmWasmClient(network.id), network.vaultContractAddress, );