Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/CosmWasm/cw-nfts
Examples and helpers to build NFT contracts on CosmWasm
https://github.com/CosmWasm/cw-nfts
Last synced: 26 days ago
JSON representation
Examples and helpers to build NFT contracts on CosmWasm
- Host: GitHub
- URL: https://github.com/CosmWasm/cw-nfts
- Owner: public-awesome
- License: apache-2.0
- Created: 2021-09-27T14:21:02.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-08-17T10:28:02.000Z (4 months ago)
- Last Synced: 2024-10-14T22:18:20.924Z (about 2 months ago)
- Language: Rust
- Size: 1.14 MB
- Stars: 189
- Watchers: 11
- Forks: 181
- Open Issues: 31
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
- awesome-cosmwasm - cw-nfts - non-fungible tokens. Official (Smart Contracts / Other Contracts)
- awesome-cosmwasm - cw-nfts
README
# CosmWasm NFTS
This repo is the official repository to work on all NFT standard and examples
in the CosmWasm ecosystem. `cw721` and `cw721-base` were moved from
[`cw-plus`](https://github.com/CosmWasm/cw-plus) to start this repo, but it shall evolve
as driven by the community's needs.Please feel free to modify `cw721-base` as you need to support these projects and add many extensions
and additional standards (like [cw-2981](https://github.com/CosmWasm/cw-plus/pull/414)) to meet
the demands of the various NFT projects springing forth.## Maintainers
This repo is not maintained directly by Confio (although we can provide some code reviews and support),
but rather by 4 highly active community members working on NFT projects of their own:* [mr t](https://github.com/taitruong)
* [alwin-peng](https://github.com/alwin-peng)
* [ben2x4](https://github.com/ben2x4)
* [Callum-A](https://github.com/Callum-A)
* [ekez](https://github.com/ezekiiel)
* [JakeHartnell](https://github.com/JakeHartnell)
* [John Y](https://github.com/yubrew)
* [orkunkl](https://github.com/orkunkl)
* [shanev](https://github.com/shanev)
* [the-frey](https://github.com/the-frey)## Contributing
If you are working on an NFT project as well and wish to give input, please raise issues and/or PRs.
Additional maintainers can be added if they show commitment to the project.You can also join the `#nfts` channel on [CosmWasm Discord](https://docs.cosmwasm.com/chat)
for more interactive discussion on these themes.## Contracts and Libs
### `cw721` Package
tl;dr: contracts may use `Cw721OnchainExtensions` for onchain, `Cw721BaseExtensions` for offchain nft extension and optional onchain collection extension, `Cw721EmptyExtensions` for no extensions, or `Cw721Extensions` for custom metadata. These extension implements `Cw721Query` and `Cw721Execute` traits. Both traits provide default implemtations. A contract may customize and adjust specific trait functions.
[traits.rs](./packages/cw721/src/traits.rs) in `cw721` package provides `Cw721Query` and `Cw721Execute` provides. Both traits have default implementations and may be customized by contracts. Default
queries and operations are provided in [query.rs](./packages/cw721/src/query.rs) and [execute.rs](./packages/cw721/src/execute.rs).
3rd party contracts may call query and execute messages using `Cw721Helper` in [helpers.rs](./packages/cw721/src/helpers.rs).This package provides generics for onchain nft and collection extensions. It allows custom cw721 contracts providing
their own data for nft and collection metadata. Based on ERC721 the following structs are provided:* [msg.rs](./packages/cw721/src/msg.rs): `CollectionExtensionMsg` and `NftExtensionMsg`
* [state.rs](./packages/cw721/src/state.rs): `CollectionExtension` and `NftExtension`These structs and default types in [libs.rs](./packages/cw721/src/lib.rs) may be used in contracts:
```rust
/// Type for `Option>`
pub type DefaultOptionalCollectionExtension = Option>;
/// Type for `Option`
pub type EmptyOptionalCollectionExtension = Option;/// Type for `Option>`
pub type DefaultOptionalCollectionExtensionMsg =
Option>;
/// Type for `Option`
pub type EmptyOptionalCollectionExtensionMsg = Option;/// Type for `Option`.
pub type DefaultOptionalNftExtension = Option;
/// Type for `Option`
pub type EmptyOptionalNftExtension = Option;/// Type for `Option`.
pub type DefaultOptionalNftExtensionMsg = Option;
/// Type for `Option`
pub type EmptyOptionalNftExtensionMsg = Option;
```For better developer experience there are these opionated helpers: `DefaultCw721Helper` and `EmptyCw721Helper`. Example:
```rust
// DefaultCw721Helper for handling optional onchain nft and collection extensions.
let mint_msg = Cw721ExecuteMsg::<
DefaultOptionalNftExtensionMsg,
DefaultOptionalCollectionExtensionMsg,
Empty,
>::Mint {
token_id: config.unused_token_id.to_string(),
owner: sender,
token_uri: config.token_uri.clone().into(),
extension,
};
let msg = DefaultCw721Helper::new(cw721).call(mint_msg)?;
Ok(Response::new().add_message(msg))
// Alternative for custom extensions using generic Cw721Helper:
let msg = Cw721Helper::<
CustomNftExtension,
CustomNftExtensionMsg,
CustomCollectionExtension,
CustomCollectionExtensionMsg,
Empty,
Empty,
>(
cw721,
PhantomData,
PhantomData,
PhantomData,
PhantomData,
PhantomData,
PhantomData,
)
.call(mint_msg)?;
```### `cw721-base`
This contracts uses `Cw721BaseExtensions` for storing metadata offchain.
[lib.rs](./contracts/cw721-base/src/lib.rs):
```rust
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: Cw721InstantiateMsg,
) -> Result {
let contract = Cw721BaseExtensions::default();
contract.instantiate_with_version(deps, &env, &info, msg, CONTRACT_NAME, CONTRACT_VERSION)
}#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: Cw721ExecuteMsg<
EmptyOptionalNftExtensionMsg,
EmptyOptionalCollectionExtensionMsg,
Empty,
>,
) -> Result {
let contract = Cw721BaseExtensions::default();
contract.execute(deps, &env, &info, msg)
}#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(
deps: Deps,
env: Env,
msg: Cw721QueryMsg,
) -> Result {
let contract = Cw721BaseExtensions::default();
contract.query(deps, &env, msg)
}#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(
deps: DepsMut,
env: Env,
msg: Cw721MigrateMsg,
) -> Result {
let contract = Cw721BaseExtensions::default();
contract.migrate(deps, env, msg, CONTRACT_NAME, CONTRACT_VERSION)
}
````Cw721BaseExtensions` in [extension.rs](./packages/cw721/src/extension.rs):
```rust
/// Opionated version of generic `Cw721Extensions` with `EmptyOptionalNftExtension` and `DefaultOptionalCollectionExtension` using:
/// - `Empty` for NftInfo extension (onchain metadata).
/// - `Empty` for NftInfo extension msg for onchain metadata.
/// - `DefaultOptionalCollectionExtension` for CollectionInfo extension (onchain attributes).
/// - `DefaultOptionalCollectionExtensionMsg` for CollectionInfo extension msg for onchain collection attributes.
/// - `Empty` for custom extension msg for custom contract logic.
/// - `Empty` for custom query msg for custom contract logic.
/// - `Empty` for custom response msg for custom contract logic.
pub struct Cw721BaseExtensions<'a> {
pub config: Cw721Config<'a, EmptyOptionalNftExtension>,
pub(crate) _collection_extension: PhantomData,
pub(crate) _nft_extension_msg: PhantomData,
pub(crate) _collection_extension_msg: PhantomData,
pub(crate) _extension_msg: PhantomData,
pub(crate) _extension_query_msg: PhantomData,
pub(crate) _custom_response_msg: PhantomData,
}impl Default for Cw721BaseExtensions<'static> {
fn default() -> Self {
Self {
config: Cw721Config::::default(),
_collection_extension: PhantomData,
_nft_extension_msg: PhantomData,
_collection_extension_msg: PhantomData,
_extension_msg: PhantomData,
_extension_query_msg: PhantomData,
_custom_response_msg: PhantomData,
}
}
}
```### `cw721-metadata-onchain`
This contract uses `Cw721OnchainExtensions` for storing metadata onchain.
[lib.rs](./contracts/cw721-metadata-onchain/src/lib.rs):
```rust
#[entry_point]
pub fn instantiate(
mut deps: DepsMut,
env: Env,
info: MessageInfo,
msg: Cw721InstantiateMsg,
) -> Result {
Cw721MetadataContract::default().instantiate_with_version(
deps.branch(),
&env,
&info,
msg,
CONTRACT_NAME,
CONTRACT_VERSION,
)
}#[entry_point]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result {
Cw721MetadataContract::default().execute(deps, &env, &info, msg)
}#[entry_point]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result {
Cw721MetadataContract::default().query(deps, &env, msg)
}
```### Custom Contracts
Custom contracts may use `Cw721Extensions` and provide their custom structs for e.g. for `TNftExtension` and `TCollectionExtension`:
[extension.rs](./packages/cw721/src/extension.rs):
```rust
impl<
TNftExtension,
TNftExtensionMsg,
TCollectionExtension,
TCollectionExtensionMsg,
TExtensionMsg,
TExtensionQueryMsg,
TCustomResponseMsg,
> Default
for Cw721Extensions<
'static,
TNftExtension,
TNftExtensionMsg,
TCollectionExtension,
TCollectionExtensionMsg,
TExtensionMsg,
TExtensionQueryMsg,
TCustomResponseMsg,
>
where
TNftExtension: Cw721State,
TNftExtensionMsg: Cw721CustomMsg,
TCollectionExtension: Cw721State,
TCollectionExtensionMsg: Cw721CustomMsg,
{
fn default() -> Self {
Self {
config: Cw721Config::default(),
_collection_extension: PhantomData,
_nft_extension_msg: PhantomData,
_collection_extension_msg: PhantomData,
_extension_msg: PhantomData,
_extension_query_msg: PhantomData,
_custom_response_msg: PhantomData,
}
}
}
```