Coder Social home page Coder Social logo

onflow / flow-nft Goto Github PK

View Code? Open in Web Editor NEW
465.0 52.0 165.0 2.82 MB

The non-fungible token standard on the Flow blockchain

Home Page: https://onflow.org

License: The Unlicense

Go 21.46% Makefile 0.46% Cadence 78.08%
blockchain smart-contracts linear-types nft onflow

flow-nft's Introduction

Flow Non-Fungible Token Standard

This standard defines the minimum functionality required to implement a safe, secure, and easy-to-use non-fungible token contract on the Flow blockchain

The version of the contracts in the master branch is the Cadence 1.0 version of the contracts and is not the same as the ones that are currently deployed to testnet and mainnet. See the cadence-0.42 branch for the currently deployed versions.

What is Cadence?

Cadence is the resource-oriented programming language for developing smart contracts on Flow.

Before reading this standard, we recommend completing the Cadence tutorials to build a basic understanding of the programming language.

Resource-oriented programming, and by extension Cadence, provides an ideal programming model for non-fungible tokens (NFTs). Users are able to store their NFT objects directly in their accounts and transact peer-to-peer. Learn more in this blog post about resources.

Import Addresses

The NonFungibleToken, ViewResolver, and MetadataViews contracts are already deployed on various networks. You can import them in your contracts from these addresses. There is no need to deploy them yourself.

Note: With the emulator, you must use the -contracts flag to deploy these contracts.

Network Contract Address
Emulator/Canary 0xf8d6e0586b0a20c7
PreviewNet 0xb6763b4399a888c8
Testnet/Crescendo 0x631e88ae7f1d7c20
Mainnet 0x1d7e57aa55817448

Core Types

Contracts that implement the NonFungibleToken interface are expected to utilize two resource interfaces:

  • NFT - A resource interface that describes the structure of a single NFT.

  • Collection - A resource interface that describes an object that can hold multiple NFTs of the same type and defines ways to deposit, withdraw, and query information about the stored NFTs.

    Users typically store one collection per NFT type, saved at a well-known location in their account storage.

    For example, all NBA Top Shot Moments owned by a single user are held in a TopShot.Collection stored in their account at the path /storage/MomentCollection.

Core Features

The NonFungibleToken contract defines the following set of functionality that should be included in each implementation:

Create a new NFT collection

Create a new collection using the Token.createEmptyCollection(nftType: Type) function.

This function MUST return an empty collection that contains no NFTs.

Users typically save new collections to a contract-defined location in their account and public a capability to their collection.

Withdraw an NFT

Withdraw an NFT from a Collection using the withdraw() function. This function emits the NonFungibleToken.Withdrawn event automatically.

Deposit an NFT

Deposit an NFT into a Collection using the deposit() function. This function emits the NonFungibleToken.Deposited event automatically.

⚠️ Important

In order to comply with the deposit function in the interface, an implementation MUST take a @{NonFungibleToken.NFT} resource as an argument. This means that anyone can send a resource object that conforms to {NonFungibleToken.NFT} to a deposit function. In an implementation, you MUST cast the token as your specific token type before depositing it or you will deposit another token type into your collection. For example:

/// `ExampleNFT` much be changed to the name of your contract
let token <- token as! @ExampleNFT.NFT

List NFTs in an account

Return a list of NFTs in a Collection using the getIDs function.

Return the NFT type that a collection can accept in a deposit

Return types of NFTs that a Collection can accept in a deposit using the getSupportedNFTTypes functions.

Get Available SubNFTs, if any

Some NFTs can own other NFTs, the standard provides a function that projects can optionally implement to return information the owned NFTs.

NFT Metadata

The primary documentation for metadata views is on the Flow developer portal. Please refer to that for the most thorough exploration of the views with examples.

NFT metadata is represented in a flexible and modular way using the standard proposed in FLIP-0636.

When writing an NFT contract, you should implement the MetadataViews.Resolver interface, which allows your NFT to utilize one or more metadata types called views.

Each view represents a different type of metadata, such as an on-chain creator biography or an off-chain video clip. Views do not specify or require how to store your metadata, they only specify the format to query and return them, so projects can still be flexible with how they store their data.

How to read metadata

This example shows how to read basic information about an NFT including the name, description, image and owner.

Source: get_nft_metadata.cdc

How to implement metadata

The example NFT contract shows a basic example for how to implement metadata views.

List of views

The views marked as Core views are considered the minimum required views to provide a full picture of any NFT. If you want your NFT to be able to be easily accessed and understood by third-party apps such as the Flow NFT Catalog it should implement all of them as a pre-requisite.

Name Purpose Status Source Core view
NFTView Basic view that includes the name, description and thumbnail. Implemented MetadataViews.cdc
Display Return the basic representation of an NFT. Implemented MetadataViews.cdc
HTTPFile A file available at an HTTP(S) URL. Implemented MetadataViews.cdc
IPFSFile A file stored in IPFS. Implemented MetadataViews.cdc
Edition Return information about one or more editions for an NFT. Implemented MetadataViews.cdc
Editions Wrapper for multiple edition views. Implemented MetadataViews.cdc
Serial Serial number for an NFT. Implemented MetadataViews.cdc
Royalty A Royalty Cut for a given NFT. Implemented MetadataViews.cdc
Royalties Wrapper for multiple Royalty views. Implemented MetadataViews.cdc
Media Represents a file with a corresponding mediaType Implemented MetadataViews.cdc
Medias Wrapper for multiple Media views. Implemented MetadataViews.cdc
License Represents a license according to https://spdx.org/licenses/ Implemented MetadataViews.cdc
ExternalURL Exposes a URL to an NFT on an external site. Implemented MetadataViews.cdc
NFTCollectionData Provides storage and retrieval information of an NFT Implemented MetadataViews.cdc
NFTCollectionDisplay Returns the basic representation of an NFT's Collection. Implemented MetadataViews.cdc
Rarity Expose rarity information for an NFT Implemented MetadataViews.cdc
Trait Represents a single field of metadata on an NFT. Implemented MetadataViews.cdc
Traits Wrapper for multiple Trait views Implemented MetadataViews.cdc

How to propose a new view

Please open a issue or a pull request to propose a new metadata view or changes to an existing view.

Feedback

We'd love to hear from anyone who has feedback. For example:

  • Are there any features that are missing from the standard?
  • Are the current features defined in the best way possible?
  • Are there any pre and post conditions that are missing?
  • Are the pre and post conditions defined well enough? Error messages?
  • Are there any other actions that need an event defined for them?
  • Are the current event definitions clear enough and do they provide enough information?
  • Are there any openings for bugs or vulnerabilities that we are not noticing?

Please create an issue in this repository if there is a feature that you believe needs discussing or changing.

Comparison to other standards on Ethereum

This standard covers much of the same ground as ERC-721 and ERC-1155, but without most of the downsides.

  • Tokens cannot be sent to contracts that don't understand how to use them, because an account needs to have a Receiver or Collection in its storage to receive tokens.
  • If the recipient is a contract that has a stored Collection, the tokens can just be deposited to that Collection without having to do a clunky approve, transferFrom.
  • Events are defined in the contract for withdrawing and depositing, so a recipient will always be notified that someone has sent them tokens with their own deposit event.
  • This version can support batch transfers of NFTs. Even though it isn't explicitly defined in the contract, a batch transfer can be done within a transaction by just withdrawing all the tokens to transfer, then depositing them wherever they need to be, all atomically.
  • Transfers can trigger actions because users can define custom Receivers to execute certain code when a token is sent.
  • Easy ownership indexing: rather than iterating through all tokens to find which ones you own, you have them all stored in your account's collection and can get the list of the ones you own instantly.

How to test the standard

If you want to test out these contracts, we recommend either testing them with the Flow Playground or with the Visual Studio Code Extension.

If you are not making/testing any modifications to the standard contracts, they are already deployed to the addresses listed above and you can just import from those directly instead of deploying them yourself.

If you want to test changes to the standards, the steps to follow are:

  1. Deploy ViewResolver.cdc
  2. Deploy NonFungibleToken.cdc, importing ViewResolver.
  3. Deploy ExampleNFT.cdc, importing NonFungibleToken.

Then you can experiment with some of the other transactions and scripts in transactions/ or even write your own. You'll need to replace some of the import address placeholders with addresses that you deploy to, as well as some of the transaction arguments.

Running automated tests

You can find automated tests written in the Cadence testing framework in the tests/ directory. Use flow test tests/test_example_nft.cdc to run these tests.

More tests, written in Go, are in the lib/go/test/ directory. They use the transaction templates package that is contained in the lib/go/templates/ directory. To run the Go tests, you can run make test from the repository root. Contract and transaction assets must be generated before individual tests can be run, so if you are wanting to run the tests individually via go test, you must run make generate from within the lib/go/ directory after every revision you make to the contract or transaction files.

License

The works in these files:

are under the Unlicense.

flow-nft's People

Contributors

10thfloor avatar aishairzay avatar albeethekid avatar alilloig avatar austinkline avatar bartolomej avatar bjartek avatar brodieve avatar bshahid331 avatar codingone21 avatar dependabot[bot] avatar jkan2 avatar joshuahannan avatar jribbink avatar laynelafrance avatar m-peter avatar mastereye-07 avatar michaelgold avatar nasir-ali-shah avatar nialexsan avatar omahs avatar phi-line avatar psiemens avatar satyamakgec avatar sisyphussmiling avatar solipsis avatar timmymmit avatar turbolent avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flow-nft's Issues

Core Views in NFTView

This is a spin-off ticket originating from #74. Please review its comment history for deeper context about what this ticket is for

A central theme of discussion many of us have brought up is what views should be "required" to be implemented in order to say that a collection has implemented Flow's metadata standard. While individual collections can define their own views, there is also a central set of what some of us have called "core" views

What are core views for?

Core views, when all put together, should give a "complete" picture of an NFT on flow. That is.. marketplaces, wallets, and applications should be able to use the NFTView as a central source to obtain information about an item both to transact with and to display.

Current Proposed Core Views

  • Display - "How do I show this NFT?"
  • ExternalURL - "Where did this NFT come from/how do I make backlinks to this NFT's project?"
  • Medias - "What is the full image/animation of this NFT? Are there multiple ways to show it?"
  • Traits (In PR at #97) - "What data exists on this NFT? What is its Body, Head, Background, Hometown, etc? How do I show this data?"

Possible missing pieces

  • NftCollectionData - "How should I store this NFT?"
  • TokenURI - Some collections like TopShot have data that exists off-chain. Ideally we can mark how to obtain that extra data or at least note that what an application has could be incomplete

I'm not sure about NftCollectionData, I've flip-flopped on it a few times. TokenURI I think has its place given that some prominent projects are already split, so we know that we will need to handle that.

If anything else is missing, please chime in! The ideal is that we settle on these core views and then we can create a factory method or some kind of helper on the MetadataStandards contract that builds this for you. Then, a collection can just delegate to the factory for building the NftView and it can be practically for free for collection owners to include.

Fix Go bindata tool so that `contracts` and `templates` generate can run at the same time

Issue To Be Solved

Every time a contract or transaction is changed and we want to run automated tests, we have to rerun make generate in lib/go/contracts/ and lib/go/templates to ensure that those changes are reflected in the templates we use for the tests in lib/go/test.

Suggest A Solution

  • Fix Makefiles so that a make generate from the root of the repo runs make generate in each of the packages.
  • Run a make generate automatically when the automated tests are run.

Consistent ability to pull Set information for a NFT (Set View)

Issue To Be Solved

The ability for NFT's to have sub-categories or groupings that are exposed in a consistent way.

Solution 1: MetadataViews.SetView

Introduce the MetadataViews.SetView view:

// ... MetadataViews Contract ...

pub struct SetView {
pub let id: UInt64
pub let name: String?
pub let description: String?
}

This id, name, and description would be for the set information instead of the individual NFT. name and description are optional as id is the only needed field to differentiate a Set within an NFT. This route makes determining the NFT set information easy for a single NFT but is not great for having a good on-chain index of all the NFT's within a set.

Context

Ideally, this could be implemented in a way so that someone could offer or buy anything within a set then any NFT within that set could fulfill the request.

For example, if I want any NFT from the Ballerz set from Gaia or any NBA Top Shot from a certain Set or Play it would be nice to allow for a Metadata View so that NFT creators can group these logically allowing for Sales and Offers to potentially be grouped as well.

Add new transaction and script templates

Issue To Be Solved

There are many ways non fungible tokens can be used and we want more transaction templates to be defined for them.

Suggest A Solution

Please leave comments in this issue if you think of a transaction that you would like to be added as a template.
This issue will also be updated with ideas as they are added.

When adding a new template:

  1. Create an issue for the template you are adding and assign it to yourself. Leave a comment on this post that you are working on it. Include any relevant questions or discussion about your template in the issue that you create.
  2. Write the template as a .cdc file and save it in the transactions directory.
  3. Save the non fungible token address as 0xNFTADDRESS.
  4. Save the example token address as 0xNFTCONTRACTADDRESS.
  5. Use ExampleNFT as the token name and NFTCollection, etc. as the token and storage name.
  6. Use transaction parameters instead of hard-coded values.
  7. Write a go template getter in lib/go/templates/ and run make generate in that directory.
  8. Write a test for your transaction in lib/go/test/ and make sure the test passes.
  9. Ensure that your template and test are well commented.

Template Suggestions

Feel free to choose a template from this list to work on, or make a comment to add your own idea.

  • Send tokens to multiple addresses. The addresses and ids to send can be configurable parameters to the transaction.
  • Remove the public receiver capability from an account.
  • Create a provider capability and store it in another account's /private/ domain.
  • Use an account's provider capability in your /private/ domain to withdraw tokens from their account and deposit it in your account.

Make `templates` package use the templates in `transactions`

Issue To Be Solved

We have accurate template transactions in the transactions folder but not all of them are included in the lib/go/templates package.

Suggest A Solution

  • Use the go bindata tool and string replacer to get the template from transactions/ and replace the contract names and addresses with the provided arguments, similar to how it is done with GenerateCreateCollectionScript in transaction_templates.go

contract/collection level metadata

Issue To Be Solved

At present, when Flow wallets or DApps integrate an NFT Collection, what the basic information of NFT collections (like display name, description, etc.) needs to be collected case by case.

Have we considered proposing a FLIP that implements a standard for the definition of contract or collection level metadata?
Reference: https://docs.opensea.io/docs/contract-level-metadata

If such an standard exists, the work will be handed over to the NFT contract developers who will implement Views like GeneralDisplay, BloctoDisplay, AlchemyDisplay, NewWalletDisplay with their collection level information(contract name, display name, description, banner image, etc.).

Improvements to the NFT Standard

Issue To Be Solved

We recently had a discussion during Flow Developer Office hours about improvements to the NFT standard. There is some consensus that the current NFT standard is lacking in some areas and could use either:

  • A complete re-design and brand new standard

OR

  • Improvements to the existing standard

The first option would be nice because we could start from scratch and do whatever we want, but getting projects to migrate to the new standard and managing the existence of two standards at the same time would be quite difficult, so there is definitely an incentive to try to stick with the old standard if possible.

We will explore both possibilities within this issue and connected issues.

Notes from the conversation are here. The notes are still very rough and need a lot more detail. I will need help prioritizing and creating issues for each important improvement.

None of these are set in stone, they are simply just ideas for potential improvements.
They all need a lot of discussion before we move forward with any of them.

Suggest A Solution

  • Maybe add a totalMinted field in addition to totalSupply: #11

  • Standard for storage and collection public paths

    • naming of the paths themselves and including the paths, addresses, and potentially types in the interface
    • may require an update to Cadence to allow more sophisticated path names
  • removing the id field and using uuid instead

  • remove total supply field

    • not necessarily needed
  • make ownedNFTs let instead of var

  • creating a transfer method that allows to withdraw and deposit in a single call and emit a transfer event

  • batch withdraw, batch deposit, and batch transfer

  • getName method

    • doesn't require a field, can use a custom function or struct
  • Generics

    • REALLY big change to Cadence, likely not possible any time soon, if at all
  • Default methods

    • we could structure the code to avoid having to write boilerplate code, especially having to force-cast the NFT in the
  • Requiring that a certain event is emitted in a function

    • requires an update to Cadence
  • Using the uuid for the key in the ownedNFTs dictionary could be more useful

  • being able to support multiple NFT types in a single contract

    • How would a single collection handle that, or would it be multiple collections
  • Accounts could all be initialized with a standard NFT collection so that there is always a place to store an NFT even if the one for a specific contract has been unlinked or not created

    • If the link is public, people could spam and flood an account's storage with NFTs (BAD)
    • could have a field in the collection to only allow up to a certain amount of NFTs to be deposited, or require those who deposit to the collection to help pay for the storage required
  • Need an NFTMinted or NFT Destroyed event: #34

  • Capability Index to a specific NFT in a collection to give the capability owner the ability to withdraw a single NFT from a collection : #36

  • Add getDefaultStoragePath() functions to FT+NFT interfaces

  • Add a nonce to NFT standard: #63

Adding an author / minter to the NFT MetadataViews

Instructions

Issue To Be Solved

Currently in the MetadataViews there isn't a clear way of representing the Author or Original Minter of the NFT. However, this is an essential attribute for all NFTs and can commonly be seen in most marketplaces.

Suggest A Solution

Discussion was raised in: https://discord.com/channels/613813861610684416/1007006779135250433/1013671709041233950 where @bjartek suggested two potential solutions:

  1. Adding a new displayType in Traits view that could be called User or Author or Creator
  2. Creating a new semantic view called Author or Creator which could have an address field to specify the user's wallet address (and maybe some other optional fields such as name)

Add a javascript contracts package

Issue To Be Solved

We want to be able to release packages in other language so that apps written in those languages can import them to get the contract code defined in the repo, similar to how it is done in Go.

Suggest A Solution

  • Design and write a package in lib/javascript/ for getting contract code.
  • Use the code in contracts/ and replace the addresses and names with arguments that the caller provides.
  • Write tests to make sure the templates are created correctly.

Identity View

Instructions

Add a Identity view so that resources can Identify who they are

Problem

How do you know that you are buying a flowverse sock from the correct minter? Discovering this progrematically is very hard and almost impossible.

Also the very useful uuid field is hidden from the NFT.

Acceptance Criteria

Implement a View in the new NFT standard that expose some common information about an NFT, most of this can be default implemented in the contract, atleast there could be a method to generate it for you.

The information I can think of is:

  • id: AnyStruct, the id of this resource, the reson this is anyStruct is because the view is not tied to NFT and other resources can have other ids. (like .find names are identified by the name)
  • type: Type, the Type of this resource
  • uuid: the UIn64 uuid field
  • discriminator: This is a text field to discriminate NFTS that are of the same Type but different origin

Adding this view to the Standard will and getting it adopted will make it easer for everybody to uniqely identify resources. The reson id/type is there is really to be able to map from the old pattern to the new pattern.

Collection Index Capability

It would be very nice if it was possible to get a capability to an index in a Collection though. That would actually be HUGE.

In the KittyItems code we store an NFT.Provider and a tokenID (more general purpose code would store a uuid, or an id and a Type) then attempt to fetch that.

Wrapping this up as a capability that any collection can vend would be very interesting.

Update Repo for Secure Cadence

Issue To Be Solved

Secure Cadence is coming. Need to upgrade the dependencies to make sure all contracts are working properly.
Also, do some more cleanup

Suggest A Solution

Nounce View

After talking with @austinkline at Flowty I think having a view for Nounce would be a good adition to the standard.

Basicaly this nounce will change if the NFT has been transfered. So if you implement it you have to make sure to do that internally. This nounce could then be used in listings so that if an NFT is

  1. listed for sale at account A: nounce 1
  2. transfered to acocunt B: nounce 2
  3. wait a good while
  4. transfered to account A: nounce 3

Then the NFTs listing that was made in 1. is not active anymore since the nounce has changed .

MetadataViews over complexify previous design

Instructions

While the MetadataViews proposal strives to add more structure to NFT metadata is actually adds unnecessary complexity.

Issue To Be Solved

Perviously, each contract defined their interface and a list of methods that could be called to get various data from the contract.

In the new proposal, each contract is defining their own custom views.

When a Dapp, needs to setup a new account to be used with a specific contract, that Dapp needs to setup the new account with all the views that were defined in the contract otherwise the metadata exposed by those views will not be available.

Additionally, the main problem, a metadata standard is not solved as the developer still needs to look through the contract code and define custom scripts to use the custom view functions defined in each contract.

(Optional): Suggest A Solution

Abandon MetadataViews and rely on previous design.
Propose new metadata standard.

(Optional): Context

When a user purchases an NFT on a marketplace, the marketplace needs to link all the metadata views defined by the contract that minted the NFT otherwise the views won't be accessible.

Previously the marketplace only needed to link one specific interface per contract.

As I see there are other issues proposing different types of views I suggest taking a pause and re-evaluating if this is not going in the wrong direction.

CONTRACT: Create NFT Forwarding Contract

Issue To Be Solved

Some users may want to forward the NFTs that are sent to them to a different account's collection. Make a contract that defines a resource type that implements the Receiver interface from NonFungibleToken and deposits the NFT into another account.

This is similar to the TokenForwarding contract from the flow-ft repo

(Optional): Suggest A Solution

  • Write the contract
  • Test it with the transfer_nft.cdc transaction

IMPROVEMENT: NFT Metadata

Issue To Be Solved

NFTs always have some sort of metadata associated with them. Historically, most of that metadata has been stored off-chain, but we would like to create a standard for metadata that allows all metadata to be stored on-chain so everything about the NFTs is truly decentralized.

This issue is meant for discussion about the possibilities of the solution. More documentation and examples will be added as we research and discuss more.

I am currently leading the charge on this, but I have a lot on my plate and don't know if I can give this issue the love it deserves, so if someone from the community wants to lead, I would love to speak with you!

Suggest A Solution

  • Ideally, we'd like to try to have some sort of self-describing json format for the metadata, but more research needs to be done on how we could support this in Cadence and the flow sdk.

Context

The Avastars project is an interesting project on Ethereum that that we could potentially take inspiration from for our metadata.

Supporting royalties that live alongside the NFT

Problem

Some projects have complex royalties structures that they want enforced in any plattform that sells or transfers that NFT. In order to support this several solutions have included Royalty data into the NFT resources themselves.

Some examples here are:

  • Versus have Artist Royalty and Minter Royalty stored in the NFT
  • Flovatar has a 1% Minter royalty stored in the NFT
  • NeoCollectibles have a Royalty to the Owner of the main Motorcycle NFT on trades of NFTs in its crews.

Work done to support this thus far

In onflow/flip-fest#16 this was discussed but it was taken out of the final document because more stakeholders wanted a say.

bjartek, dete, rhea had a meeting about this because bjartek (as a proposed) and rhea (as a representative of dapper) had a disagreement about how it should work. In this meetin the following struct was agreed upon

	/// A struct interface for Royalty agreed upon by @dete, @rheaplex, @bjartek
	pub struct interface Royalty {

		/// if nil cannot pay this type
		/// if not nill withdraw that from main vault and put it into distributeRoyalty
		pub fun calculateRoyalty(type:Type, amount:UFix64) : UFix64?

		/// call this with a vault containing the amount given in calculate royalty and it will be distributed accordingly
		pub fun distributeRoyalty(vault: @FungibleToken.Vault)

		/// generate a string that represents all the royalties this NFT has for display purposes
		pub fun displayRoyalty() : String?

	}

The main proposal here came from dete and some subleries of it was discussed and we agreed upon what is stated above.

Here is an implementaion of how that can work for Versus art.
https://github.com/findonflow/find/blob/testing/contracts/Art.cdc#L323

Add getDefaultStoragePath() functions to FT+NFT interfaces

Issue To Be Solved

Currently using (arbitrarily) named value fields is the suggested best practice to obtain the default storage paths used by a contracts a Vaults/Collections etc.

https://docs.onflow.org/cadence/anti-patterns/#named-value-fields-are-preferable

(Optional): Suggest A Solution

Suggest adding a function that returns this path as part of the interface:

getDefaultStoragePath() : StoragePath?

Same could be done for Public and Private paths. This would save referencing the original contracts individually and would allow these default paths to be obtained programatically.

Or could this plausibly be incorporated as part of the metadata standard?

Make ownedNFTs `access(self)` instead of `pub`

Should these member variables:

https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc#L116

https://github.com/onflow/flow-nft/blob/master/contracts/ExampleNFT.cdc#L29

        pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT}

instead be declared like this:

        access(self) let ownedNFTs: @{UInt64: NonFungibleToken.NFT}

As pub access allows the ownedNFTs dictionary to be manipulated without going through the deposit/withdraw functions, and var allows it to be replaced wholesale.

If this is desired behaviour, it is worth documenting the implications of it in the code.

MetadataViews.SerialNumber

Issue To Be Solved

Now that we have MetadataViews.Display, the next piece of data which is present in a significant portion of the NFT's out there is the so-called Serial Number. Unlike name and description, this information is not appliable to all tokens. That said, it's still something people care about.

Solution 1: MetadataViews.SerialNumber

Introduce the MetadataViews.SerialNumber view:

// ... MetadataViews Contract ...

pub struct SerialNumber {
  pub let serialNumber: UInt64
  pub let totalMinted: UInt64? // Not sure about this
}

PS: I'm still unsure if we should include the total number of minted NFT's. E.g: #1/200 (1 out of 200 copies). Mainly because this information is more likely to change.

Solution 2: Serial number as part of the name / description

This is not a solution, just an alternative.

If we don't want the Serial Number as first-class information within MetadataViews we can include it as part of the name/description in the Display view. It would be complex and error-prone if the client wanted to extract this information.

Adding Medias view to MetadataViews.NFTView

Issue To Be Solved

Are there any reasons why the Medias view is not included in the MetadataViews.NFTView?
Can this be included as there are quite a few NFT collections that use video files rather than images and this can only be included in the Medias view.

IMPROVEMENT: Consumable NFTs

The current NonFungibleToken doesn't work well with the concept of consumable NFTs. In order to add this feature, we should add a 'totalMinted' property to track the total minted NFTs, and repurpose 'totalSupply' to track the actual circulating supply (minted - destroyed).

DictView

Issue To Be Solved

A generic platform supporting any resource implementing the NFT standard has no view to use which contains all metadata for a given NFT. For example, TopShot uses the TopShotMomentMetadataView. However, for platforms such as flowty to use it, we must know when to ask for TopShot's metadata view versus another collection's own view should they also implement the nft standard. Additionally, platforms consuming these views would need to know how to read the resulting type which would necessitate importing that type and adding code into our own contracts that interpret them.

As more and more collections come to flow, dapps will need a more flexible view as an option which all collections can support that will return a complete set of metadata from a given NFT. Having this proposed view will let dapps implement features which are dependent on the metadata from a given nft without needing to understand its underlying type. For instance, a marketplace might want to support global offers where a users can offer to buy an item from anyone if and only if its metadata contains certain key/value pairs such as an offer on any Topshot Moment which comes from Play X and has a Serial number less than Y.

Suggested Solution:

@bjartek has mentioned a suggested TagsView which would return a {String:String} mapping, but I think we need a more flexible option in order to support comparison operations. The below view is what I would suggest:

pub struct DictView {
    pub let data: {String: AnyStruct}
}

Make the concept of core views clear at the docs

Issue To Be Solved

Since the concept of core views is used by the NFT catalog it should be crystal clear on the README and even in the NFTView comments which views are considered the core views, and maybe even a reference about the need of implementing NFTView to be displayed on the NFT catalog

Create NPM package

Context:

dApp developers need smart contract access to interact with it, It is hard to keep a copy of the contract and transactions within the frontend codebase and it comes with operation overhead if anything gets changed within the contract or transaction.

Solution
Create an npm package for better interaction with the dApp and easy to maintain.

Listing view

Many solutions on flow today offer an listing for an NFT. This can be:

  • flowty offering a loan
  • schwap offering a schwap
  • nft storefront listing something for sale
  • .find listing a name for auction or sale

This list is not complete obviously. Just some examples.

I think it would be nice to have a common view for all of these cases where you can say that "this item is listed as X".

I do not have a implementation for this but I think it should be possible to specify

  • what FT type if any that is required
  • what item that is listed
  • what price that is required if any
  • a description of the sale
  • a url to where you can see the listing in a web ui

Add way to create an empty NFT collection without needing to create a new contract.

Instructions

Please fill out the template below to the best of your ability and include a label indicating which tool/service you were working with when you encountered the problem.

Issue To Be Solved

In order to create an empty NFT collection, one needs to declare its own contract that conforms to NonFungibleToken.

Example:

pub contract GenericNFT: NonFungibleToken {
    // code ommited
} 

pub contract SomeContract {
    access(self) var collection: @NonFungibleToken.Collection
// code ommited
    self.collection <- GenericNFT.createEmptyCollection() as! @NonFungibleToken.Collection
// code ommited
}

(Optional): Suggest A Solution

Replace the pub contract Dummy {} with a GenericNFT contract that can be used to create an empty NFT collection.
Not sure Generic is the best name for it, could be called NFT, BasicNFT etc.

(Optional): Context

<what are you currently working on that this is blocking?>

Ownership over NFT metadata

Issue To Be Solved

As we know that NFT purpose is to give the ownership of asset data to the user and only user should have authority over his/her owned NFT. If user owned a digital asset then user should have full ownership over it and nobody can change the metadata but some of the data may need to be changed for example, some game asset need to be changed over time.

Suggest A Solution

There should be a concept of mutable and immutable metadata. Mutable metadata can be changed by contract as it is mutable in nature because contract can change some of attributes depend upon the needs and immutable part of data cannot be changed as it represent the full ownership over that data for example in case of digital art, the image link should be immutable.

Also this concept fits perfectly with flow account storage model where user asset data get stored in his/her own storage. My suggestion is to store the immutable data in the user storage and mutable data in the contract storage which will have contract permission to change the data.

Metadata Views: Full License View

Issue To Be Solved

Flow is working with governments to define a standard for how NFT projects can define licensing rights for NFTs that define permissions for what can be done with them and their metadata by the owner.
The current License view does not sufficiently cover the needs for a full license view, so we would like to define a new one that projects can start using.

Suggest A Solution

  • Decide if we want to define a new view, or modify the old one. (probably need to define a new one)
  • Decide which fields are needed
    Options:
    • plain text description
    • ipfs hash
    • file
    • multiple licenses?

We'll post and discuss more in this issue

Question about MetadataView Display

Question

Hi,
I just had a quick question about the MetadataView Display view.
So I assumed that the NFT file path would be stored in the thumbnail field but the comment says:

/// A small thumbnail representation of the object.
///
/// This field should be a web-friendly file (i.e JPEG, PNG)
/// that can be displayed in lists, link previews, etc.
///
pub let thumbnail: AnyStruct{File}

which seems to imply that the thumbnail is an image file?

I was wondering whether this thumbnail field can contain other files such as MP4, MP3, or whether other types of NFT files would need to be stored elsewhere in a different view or field.

MetadataViews.Edition - Add an "Edition Id" to the Edition struct

RE: https://github.com/onflow/flow-nft/blob/master/contracts/MetadataViews.cdc

Issue To Be Solved

MetadataViews.Edition doesn't currently have a concept of an "Edition Id" only a name. Would the FLOW team be open to adding an id onto this struct?

Using name seems semantically wrong, especially since its of type String? and a lot of ids would be UInt64 or UInt32.

Suggest A Solution

  • Add id as a UInt64 identifier
    /// Edition information for a single edition
    pub struct Edition {

        /// The name of the edition
        /// For example, this could be Set, Play, Series,
        /// or any other way a project could classify its editions
        pub let name: String?
        
>>>     pub let id: UInt64

        /// The edition number of the object.
        ///
        /// For an "24 of 100 (#24/100)" item, the number is 24. 
        ///
        pub let number: UInt64

        /// The max edition number of this type of objects.
        /// 
        /// This field should only be provided for limited-editioned objects.
        /// For an "24 of 100 (#24/100)" item, max is 100.
        /// For an item with unlimited edition, max should be set to nil.
        /// 
        pub let max: UInt64?

        init(id: Uint64, name: String?, number: UInt64, max: UInt64?) {
            if max != nil {
                assert(number <= max!, message: "The number cannot be greater than the max number!")
            }
            self.id = id
            self.name = name
            self.number = number
            self.max = max
        }
    }

Context

We are currently exploring adding the ability to create NFT Offers using both nftId and editionId. Ideally we would use a MetaDataView.Edition.id field for storing the unique identifier of the Edition.

Commit reveal Standard to FLOW

Issue To Be Solved

A generic proposal to apply commit reveal to NFT metadata. This approach is used for blind sale where we want to hide the metadata information and only then reveal it, using provenance hash to ensure that there was no manipulation in the metadata.

(Optional): Suggest A Solution

My suggestion is to create an interface with public access and apply it to the Collection, that way it would be possible for the administrator to access the NFT within the collection of a third party. Only the admin can use the interface because it requires Admin resource reference.

The interface receiving NFT Id, admin resource reference and the original metadata with all information

  pub resource interface IRevealNFT {
    pub fun revealNFT(id: UInt64, admin: &Admin, metadata: {String: String})
  }

The standard collection applying the IRevealNFT to call reveal function to a specific NFT

  pub resource Collection: NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection, IRevealNFT { 

    ....

  
    pub fun revealNFT(id: UInt64, admin: &Admin, metadata: {String: String}) {
      if self.ownedNFTs[id] != nil {
        let nft = &self.ownedNFTs[id] as auth &NonFungibleToken.NFT
        let storeFrontNFT = nft as! &NFT
        storeFrontNFT.reveal(metadata: metadata)
      } else {
        panic("can't find nft id")
      }
    }


   ....

  }
    

The HashMetadata struct to save the hash from a specific range of NFTs, considering that we can have multiples hash from one collection/drop

  pub struct HashMetadata {
    pub let hash: String
    pub let start: UInt64
    pub let end: UInt64

    init(hash: String, start: UInt64, end: UInt64) {
      self.hash = hash
      self.start = start
      self.end = end
    }
  }

The NFT resource with reveal function where it update the metadata field - just add here to exemplify, it is not part of suggestion

  pub resource NFT: NonFungibleToken.INFT, MetadataViews.Resolver  {
    pub let id: UInt64
    access(contract) var metadata: {String: String}
    pub let hashMetadata: HashMetadata

    ....

    access(account) fun reveal(metadata: {String: String}) {
      self.metadata = metadata
    }
    
    ....
  }

Add a javascript templates package

Issue To Be Solved

We want to be able to release packages in other language so that apps written in those languages can import them to get the transaction code defined in the repo.

Suggest A Solution

  • Design and write a package in lib/javascript/ for getting template transactions.
  • Use the templates in transactions/ and replace them with arguments that the caller provides.

License view

Some NFTs might contain content that is under a lisence. Haveing a view to show this and some premade builders to create lisences for popular lisences would be a great adition.

How to use views that are wrappers around other views

Instructions

Right now we have a pattern where we have Royalties that contains many Royalty. I think the document should be clear on how a producer is supposed to use these. What should you do if you only have a single Royalty. Should you still expose them boxed in Royalties?

The reason I am askin is that there are really several ways of exposing even multiple Royalties today and I think the standard instruction should be clear on how you are supposed to do this:

All of these types are valid forms of Exposing multiple Royalties

  • Royalties
  • [Royalty]
  • {String:Royalty}
  • Royalty //if you onlye have one

If all marketplaces/consumers have to check all this the code gets a little tedious.

Recommendation:

  • producers should always wrap Royalty in Royalties
  • the same should apply for all other instances of this same pattern. So Editions/Media that is currently merged.

Looking to verify ownership of Moments

Issue To Be Solved

I am looking for a way to verify the ownership of a moment. The ability to link to the identity of the owner of the Moment.

(Optional): Suggest A Solution

Preferrably using the hash of the moment mp4 file, or another of the artifacts linked to the NFT.

Even still, just tell me what I need to know in order to verify the ownership of the Moment.

External Domain view Url

Both .find and alchemy have the concept of a url to your NFT on the web, I think having a single view for this would make it a lot easier to interop between solutions.

I propse the following simple view for this to be added to MetadataViews

pub struct ExternalDomainViewUrl {
  
  pub let url:String

  init(url: String) {
    self.url=url
  }
}

Add `containsNFT` method to CollectionPublic after default implementation is in place

Right now if you want to check if an NFT is in a collection and not panic if it fails you have to get all ids and then check if your id is in that array. With the way that storage is currently implemented this is expensive and inefficient.

This proposal suggests adding a containsNFT method that will return a boolean to signal if an NFT with a given id is here or not.

Note that simply adding this change to the chain might not be enough. Because if the computation of said method will increase as the collection grow it is not a sustainable solution. This issue also touches on the subject onflow/cadence#1938

Media View

I suggest some Media views that add contentType meaning to the File struct interface.

  • Image
  • Video
  • Audio

Feature: NFT Metadata Standard should support bridging to other networks

Issue To Be Solved

There is desire to have NFTs on Flow be bridgable to other platforms, e.g. Ethereum. Secondarily, it is likely that there will also be desire to bridge NFTs from other platforms on to Flow. The NFT Metadata system should have a clear way to take metadata from Flow NFTs and integrate it with other chains and platforms.

Currently, the most popular metadata standard is the OpenSea
"ERC721 Metadata Extension" + “ERC721 Metadata JSON Schema”. In order to integrate with OpenSea on ethereum, any on-chain data would need to somehow be serialized into a JSON format compatible with OpenSea and other platforms, and somehow made available in the actual contract of the NFT that is minted on the target chain.

(Optional): Suggest A Solution

Option 1) We could provide a standard for serializing content from our on-chain formats into JSON formats and even tools for doing so. Then dapp developers could use those tools to generate metadata documents and provide them via an IPFS endpoint or other method, such that when their NFT is bridged the document exists in a known location.

Option 2) We could write a service which looks up on chain data and returns it as a JSON document which works with the JSON spec for opensea on ethereum. This service could be provided as a plugin for the access node API, and any bridge could automatically generate a URL targeting an API endpoint that could return the data.

Other Questions:

Are we at all concerned with state bloat with all this metadata being stored on chain?

NFTView

Issue To Be Solved

A metadata view that encompasses all data of an NFT resource is needed, otherwise we have to rely on hand-made scripts like what's used in Alchemy's NFT endpoint which differs from what folks at .find return. These scripts shouldn't be needed, I should instead be able to ask for a standard view which would contain all information about an NFT that other platforms can then support.

Separately, a complete view is necessary for dapps to support features on their platforms which require on-chain metadata. For instance, suppose there is a marketplace that wants to allow people to make global offers on nfts, allowing any nft to fill the offer so long as it has certain metadata key/value pairs.

(Optional): Suggest A Solution

After some discussion with @bjartek, @bluesign, and @aishairzay, there are a few options for this that I see. First is that we could use the DictView as I have brought up in #73. This would be flexible enough to work, but some concerns were raised about its lack of explanation on the data being shown.

Another option suggested by @aishairzay is to adopt the OpenSea API Metadata Standard as the NftView. Here is what that structure looks like:

{
  "description": "Friendly OpenSea Creature that enjoys long swims in the ocean.", 
  "external_url": "https://openseacreatures.io/3", 
  "image": "https://storage.googleapis.com/opensea-prod.appspot.com/puffs/3.png", 
  "name": "Dave Starbelly",
  "attributes": [ ... ], 
}

And attributes are made up of:

{
  "display_type": "number",  # this one is optional
  "trait_type": "Generation", # this is the key name
  "value": 2
}

Using that as the model, our view would look something like this:

pub struct NftView {
    pub let description: String
    pub let externalUrl: String
    pub let image: String
    pub let name: String
    pub let attributes: [NftViewAttribute]
}

pub struct NftViewAttribute {
    pub let displayType: String?
    pub let traitType: String
    pub let value: AnyStruct
}

I think that we can do away with the things already covered in other views here. I'm just leaving them for reference and consistency with the returned format from OpenSea. You could strip away description, externalUrl, image, and probably name as well. In that case, we are just returning attributes in the format OpenSea returns them. This is a model that folks in the NFT community would be familiar with since that's how much of Ethereum's tokenURI results are formatted. Alignment with the broader NFT ecosystem would be a nice plus there.

Lastly, an option from @bluesign was given to support a generic toDictionary function on structs. In which case, a platform could grab all views an NFT supports and translate them to dictionaries. While this approach would not be a view, I am including it here for the sake of completeness of discussions on the issue at hand.

(Optional): Context

Not having a view like this or something like #73 prevent us from making generic metadata-driven features on flowty and on other platforms. We cannot import all view types that we would like to support on a per-collection basis, so something broader would be a nice value-add.

Rarity View

Many different solutions on flow have the concept of Rarity. I think it would make sense to express this logic as a shared view to interop better between solutions.

My naive implementation looks like this.

// Would this work for rarity? Hoodlums, flovatar, Basicbeasts? comments?
pub struct Rarity{
	pub let rarity: UFix64
	pub let rarityName: String
	pub let parts: {String: RarityPart}

	init(rarity: UFix64, rarityName: String, parts:{String:RarityPart}) {
		//TODO: pre that rarity cannot be above 100.0
		self.rarity=rarity
		self.rarityName=rarityName
		self.parts=parts
	}
}

pub struct RarityPart{

	pub let rarity: UFix64
	pub let rarityName: String
	pub let name: String

	init(rarity: UFix64, rarityName: String, name:String) {

		self.rarity=rarity
		self.rarityName=rarityName
		self.name=name
	}

}

NFTMinted event?

Issue To Be Solved

The NFT standard does not have an event to indicate that a token has been minted.

Rather we must infer that a token has been created by watching for an initial Deposit event to a Collection.

If the NFT is not saved to a collection, its creation may not be visible from events.

(Optional): Suggest A Solution

Add the following event to the NFT standard contract:

pub event Minted(id: UInt64, by: Address?)

Listening for this event would allow off-chain code to establish when to start listening for further events regarding the NFT with that ID.

(Optional): Context

This is not a blocker, and may not be a desirable enhancement:

  • Batch minting of tokens may be better represented by a single bulk event.
  • There may be more useful information that a contract wishes to contain in a token creation event. Requiring a standardized event means that the contract must emit a second, nonstandard, event at increased cost of gas and block event space.
  • A contract may not wish to advertise minting or to use that terminology.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.