Skip to content

Commit

Permalink
use latest import syntax update readme and use correct borrow syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuahannan committed Mar 5, 2024
1 parent cd2c42e commit 938a91c
Show file tree
Hide file tree
Showing 27 changed files with 293 additions and 241 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
restore-keys: |
${{ runner.os }}-go-
- name: Install Flow CLI
run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.12.0-cadence-v1.0.0-M4-2
run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.sh)"
- name: Flow CLI Version
run: flow version
- name: Update PATH
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
test:
$(MAKE) generate -C lib/go
$(MAKE) test -C lib/go
flow test --cover --covercode="contracts" tests/test_*.cdc
flow-c1 test --cover --covercode="contracts" tests/test_*.cdc

.PHONY: ci
ci:
$(MAKE) ci -C lib/go
flow test --cover --covercode="contracts" tests/test_*.cdc
flow-c1 test --cover --covercode="contracts" tests/test_*.cdc
102 changes: 23 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,60 +56,23 @@ Create a new collection using the `Token.createEmptyCollection()` 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 link the `NonFungibleToken.CollectionPublic` interface as a public capability.

```cadence
let collection <- ExampleNFT.createEmptyCollection()
account.save(<-collection, to: ExampleNFT.CollectionStoragePath)
// create a public capability for the collection
account.link<&{NonFungibleToken.CollectionPublic}>(
ExampleNFT.CollectionPublicPath,
target: ExampleNFT.CollectionStoragePath
)
```
and public a capability to their collection.

### Withdraw an NFT

Withdraw an `NFT` from a `Collection` using the [`withdraw()`](contracts/ExampleNFT.cdc#L36-L42) function.
This function emits the [`Withdraw`](contracts/ExampleNFT.cdc#L12) event.

```cadence
let collectionRef = account.borrow<&ExampleNFT.Collection>(from: ExampleNFT.CollectionStoragePath)
?? panic("Could not borrow a reference to the owner's collection")
// withdraw the NFT from the owner's collection
let nft <- collectionRef.withdraw(withdrawID: 42)
```
Withdraw an `NFT` from a `Collection` using the [`withdraw()`](contracts/ExampleNFT.cdc#L160-L165) function.
This function emits the [`NonFungibleToken.Withdrawn`](contracts/NonFungibleToken.cdc#L78) event automatically.

### Deposit an NFT

Deposit an `NFT` into a `Collection` using the [`deposit()`](contracts/ExampleNFT.cdc#L46-L57) function.
This function emits the [`Deposit`](contracts/ExampleNFT.cdc#L13) event.

This function is available on the `NonFungibleToken.CollectionPublic` interface,
which accounts publish as public capability.
This capability allows anybody to deposit an NFT into a collection
without accessing the entire collection.

```cadence
let nft: ExampleNFT.NFT
// ...
let collection = account.getCapability(ExampleNFT.CollectionPublicPath)
.borrow<&{NonFungibleToken.CollectionPublic}>()
?? panic("Could not borrow a reference to the receiver's collection")
collection.deposit(token: <-nft)
```
Deposit an `NFT` into a `Collection` using the [`deposit()`](contracts/ExampleNFT.cdc#L169-L176) function.
This function emits the [`NonFungibleToken.Deposited`](contracts/NonFungibleToken.cdc#L86) 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.
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:

Expand All @@ -120,18 +83,17 @@ let token <- token as! @ExampleNFT.NFT

### List NFTs in an account

Return a list of NFTs in a `Collection` using the [`getIDs`](contracts/ExampleNFT.cdc#L59-L62) function.
Return a list of NFTs in a `Collection` using the [`getIDs`](contracts/ExampleNFT.cdc#L179) function.

This function is available on the `NonFungibleToken.CollectionPublic` interface,
which accounts publish as public capability.
### Return the NFT type that a collection can accept in a deposit

```cadence
let collection = account.getCapability(ExampleNFT.CollectionPublicPath)
.borrow<&{NonFungibleToken.CollectionPublic}>()
?? panic("Could not borrow a reference to the receiver's collection")
Return types of NFTs that a `Collection` can accept in a deposit
using the [`getSupportedNFTTypes`](contracts/ExampleNFT.cdc#L143-L157) functions.

let ids = collection.getIDs()
```
### Get Available SubNFTs, if any

Some NFTs can own other NFTs, the standard provides a [function](contracts/NonFungibleToken.cdc#L111-L131) that
projects can optionally implement to return information the owned NFTs.

## NFT Metadata

Expand All @@ -157,29 +119,6 @@ including the name, description, image and owner.

**Source: [get_nft_metadata.cdc](scripts/get_nft_metadata.cdc)**

```cadence
// Get the regular public capability
let collection = account.getCapability(ExampleNFT.CollectionPublicPath)
.borrow<&{ExampleNFT.ExampleNFTCollectionPublic}>()
?? panic("Could not borrow a reference to the collection")
// Borrow a reference to the NFT as usual
let nft = collection.borrowExampleNFT(id: 42)
?? panic("Could not borrow a reference to the NFT")
// Call the resolveView method
// Provide the type of the view that you want to resolve
// View types are defined in the MetadataViews contract
// You can see if an NFT supports a specific view type by using the `getViews()` method
if let view = nft.resolveView(Type<MetadataViews.Display>()) {
let display = view as! MetadataViews.Display
log(display.name)
log(display.description)
log(display.thumbnail)
}
```

### How to implement metadata

The [example NFT contract](contracts/ExampleNFT.cdc) shows a basic example
Expand Down Expand Up @@ -245,13 +184,18 @@ but without most of the downsides.
## How to test the standard

If you want to test out these contracts, we recommend either testing them
with the [Flow Playground](https://play.onflow.org)
with the [Flow Playground](https://play.flow.com)
or with the [Visual Studio Code Extension](https://github.com/onflow/flow/blob/master/docs/vscode-extension.md#cadence-visual-studio-code-extension).

The steps to follow are:

1. Deploy `NonFungibleToken.cdc`
2. Deploy `ExampleNFT.cdc`, importing `NonFungibleToken` from the address you deployed it to.
1. Deploy `ViewResolver.cdc`
2. Deploy `NonFungibleToken.cdc`, importing `ViewResolver`.
3. Deploy `ExampleNFT.cdc`, importing `NonFungibleToken`.

If you are not making 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.

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.
Expand Down
8 changes: 4 additions & 4 deletions contracts/BasicNFT.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
*
*/

import NonFungibleToken from "NonFungibleToken"
import MetadataViews from "MetadataViews"
import ViewResolver from "ViewResolver"
import UniversalCollection from "UniversalCollection"
import "NonFungibleToken"
import "MetadataViews"
import "ViewResolver"
import "UniversalCollection"

access(all) contract BasicNFT: NonFungibleToken {

Expand Down
6 changes: 3 additions & 3 deletions contracts/ExampleNFT.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
*
*/

import NonFungibleToken from "NonFungibleToken"
import ViewResolver from "ViewResolver"
import MetadataViews from "MetadataViews"
import "NonFungibleToken"
import "ViewResolver"
import "MetadataViews"

access(all) contract ExampleNFT: NonFungibleToken {

Expand Down
8 changes: 4 additions & 4 deletions contracts/MetadataViews.cdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import FungibleToken from "FungibleToken"
import NonFungibleToken from "NonFungibleToken"
import ViewResolver from "ViewResolver"
import "FungibleToken"
import "NonFungibleToken"
import "ViewResolver"

/// This contract implements the metadata standard proposed
/// in FLIP-0636.
Expand Down Expand Up @@ -665,7 +665,7 @@ access(all) contract MetadataViews {
// Square-sized image to represent this collection.
access(all) let squareImage: MetadataViews.Media

// Banner-sized image for this collection, recommended to have a size near 1200x630.
// Banner-sized image for this collection, recommended to have a size near 1400x350.
access(all) let bannerImage: MetadataViews.Media

// Social links to reach this collection's social homepages.
Expand Down
2 changes: 1 addition & 1 deletion contracts/NonFungibleToken.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Collection to complete the transfer.
*/

import ViewResolver from "ViewResolver"
import "ViewResolver"

/// The main NFT contract. Other NFT contracts will
/// import and implement the interfaces defined in this contract
Expand Down
5 changes: 3 additions & 2 deletions contracts/utility/FungibleToken.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ to the Provider interface.
*/

import ViewResolver from "ViewResolver"
//import Burner from "Burner"
import "ViewResolver"
//import "Burner"
/// FungibleToken
///
Expand Down Expand Up @@ -150,6 +150,7 @@ access(all) contract interface FungibleToken: ViewResolver {
post {
self.balance == 0.0: "The balance must be set to zero during the burnCallback method so that it cannot be spammed"
}
self.balance = 0.0
}

/// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts
Expand Down
2 changes: 1 addition & 1 deletion contracts/utility/NFTForwarding.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
/// To create an NFTForwarder resource, an account calls the createNewNFTForwarder()
/// function, passing the Collection Capability to which NFTs will be forwarded.
///
import NonFungibleToken from "NonFungibleToken"
import "NonFungibleToken"

access(all) contract NFTForwarding {

Expand Down
34 changes: 19 additions & 15 deletions lib/go/contracts/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ import (

var (
placeholderNonFungibleToken = regexp.MustCompile(`"NonFungibleToken"`)
nonFungibleTokenImport = "NonFungibleToken from "
placeholderMetadataViews = regexp.MustCompile(`"MetadataViews"`)
metadataViewsImport = "MetadataViews from "
placeholderFungibleToken = regexp.MustCompile(`"FungibleToken"`)
fungibleTokenImport = "FungibleToken from "
placeholderResolver = regexp.MustCompile(`"ViewResolver"`)
placeholderNFTMetadataViews = regexp.MustCompile(`"NFTMetadataViews"`)
viewResolverImport = "ViewResolver from "
placeholderUniversalCollection = regexp.MustCompile(`"UniversalCollection"`)
universalCollectionImport = "UniversalCollection from "
)

const (
Expand Down Expand Up @@ -48,7 +52,7 @@ func withHexPrefix(address string) string {
// NonFungibleToken returns the NonFungibleToken contract interface.
func NonFungibleToken(resolverAddress string) []byte {
code := assets.MustAssetString(filenameNonFungibleToken)
code = placeholderResolver.ReplaceAllString(code, withHexPrefix(resolverAddress))
code = placeholderResolver.ReplaceAllString(code, viewResolverImport+withHexPrefix(resolverAddress))
return []byte(code)
}

Expand All @@ -58,19 +62,19 @@ func NonFungibleToken(resolverAddress string) []byte {
func ExampleNFT(nftAddress, metadataAddress, resolverAddress flow.Address) []byte {
code := assets.MustAssetString(filenameExampleNFT)

code = placeholderNonFungibleToken.ReplaceAllString(code, withHexPrefix(nftAddress.String()))
code = placeholderMetadataViews.ReplaceAllString(code, withHexPrefix(metadataAddress.String()))
code = placeholderResolver.ReplaceAllString(code, withHexPrefix(resolverAddress.String()))
code = placeholderNonFungibleToken.ReplaceAllString(code, nonFungibleTokenImport+withHexPrefix(nftAddress.String()))
code = placeholderMetadataViews.ReplaceAllString(code, metadataViewsImport+withHexPrefix(metadataAddress.String()))
code = placeholderResolver.ReplaceAllString(code, viewResolverImport+withHexPrefix(resolverAddress.String()))

return []byte(code)
}

func MetadataViews(ftAddress, nftAddress, resolverAddress string) []byte {
code := assets.MustAssetString(filenameMetadataViews)

code = placeholderFungibleToken.ReplaceAllString(code, withHexPrefix(ftAddress))
code = placeholderNonFungibleToken.ReplaceAllString(code, withHexPrefix(nftAddress))
code = placeholderResolver.ReplaceAllString(code, withHexPrefix(resolverAddress))
code = placeholderFungibleToken.ReplaceAllString(code, fungibleTokenImport+withHexPrefix(ftAddress))
code = placeholderNonFungibleToken.ReplaceAllString(code, nonFungibleTokenImport+withHexPrefix(nftAddress))
code = placeholderResolver.ReplaceAllString(code, viewResolverImport+withHexPrefix(resolverAddress))

return []byte(code)
}
Expand All @@ -82,18 +86,18 @@ func ViewResolver() []byte {

func UniversalCollection(nftAddress, resolverAddress, metadataAddress flow.Address) []byte {
code := assets.MustAssetString(filenameUniversalCollection)
code = placeholderMetadataViews.ReplaceAllString(code, withHexPrefix(metadataAddress.String()))
code = placeholderNonFungibleToken.ReplaceAllString(code, withHexPrefix(nftAddress.String()))
code = placeholderResolver.ReplaceAllString(code, withHexPrefix(resolverAddress.String()))
code = placeholderMetadataViews.ReplaceAllString(code, metadataViewsImport+withHexPrefix(metadataAddress.String()))
code = placeholderNonFungibleToken.ReplaceAllString(code, nonFungibleTokenImport+withHexPrefix(nftAddress.String()))
code = placeholderResolver.ReplaceAllString(code, viewResolverImport+withHexPrefix(resolverAddress.String()))
return []byte(code)
}

func BasicNFT(nftAddress, resolverAddress, metadataAddress, universalCollectionAddress flow.Address) []byte {
code := assets.MustAssetString(filenameBasicNFT)
code = placeholderMetadataViews.ReplaceAllString(code, withHexPrefix(metadataAddress.String()))
code = placeholderNonFungibleToken.ReplaceAllString(code, withHexPrefix(nftAddress.String()))
code = placeholderResolver.ReplaceAllString(code, withHexPrefix(resolverAddress.String()))
code = placeholderUniversalCollection.ReplaceAllString(code, withHexPrefix(universalCollectionAddress.String()))
code = placeholderMetadataViews.ReplaceAllString(code, metadataViewsImport+withHexPrefix(metadataAddress.String()))
code = placeholderNonFungibleToken.ReplaceAllString(code, nonFungibleTokenImport+withHexPrefix(nftAddress.String()))
code = placeholderResolver.ReplaceAllString(code, viewResolverImport+withHexPrefix(resolverAddress.String()))
code = placeholderUniversalCollection.ReplaceAllString(code, universalCollectionImport+withHexPrefix(universalCollectionAddress.String()))
return []byte(code)
}

Expand Down
Loading

0 comments on commit 938a91c

Please sign in to comment.