Skip to content

Commit

Permalink
Merge pull request #214 from onflow/giovanni/add-evm-metadata-impl
Browse files Browse the repository at this point in the history
Add EVMBridgedMetadata view implementation
  • Loading branch information
sisyphusSmiling authored May 2, 2024
2 parents 694a05c + da65ccf commit d8db9b2
Show file tree
Hide file tree
Showing 14 changed files with 233 additions and 27 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.5.0
run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)"
- name: Flow CLI Version
run: flow version
- name: Update PATH
Expand Down
43 changes: 41 additions & 2 deletions contracts/ExampleNFT.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ pub contract ExampleNFT: NonFungibleToken, ViewResolver {
Type<MetadataViews.NFTCollectionData>(),
Type<MetadataViews.NFTCollectionDisplay>(),
Type<MetadataViews.Serial>(),
Type<MetadataViews.Traits>()
Type<MetadataViews.Traits>(),
Type<MetadataViews.EVMBridgedMetadata>()
]
}

Expand Down Expand Up @@ -159,6 +160,29 @@ pub contract ExampleNFT: NonFungibleToken, ViewResolver {
traitsView.addTrait(fooTrait)

return traitsView
case Type<MetadataViews.EVMBridgedMetadata>():
// Implementing this view gives the project control over how the bridged NFT is represented as an
// ERC721 when bridged to EVM on Flow via the public infrastructure bridge.
// Get the contract-level name and symbol values
let contractLevel = ExampleNFT.resolveView(
Type<MetadataViews.EVMBridgedMetadata>()
) as! MetadataViews.EVMBridgedMetadata?
?? panic("Could not resolve contract-level EVMBridgedMetadata")
// Compose the token-level URI based on a base URI and the token ID, pointing to a JSON file. This
// would be a file you've uploaded and are hosting somewhere - in this case HTTP, but this could be
// IPFS, S3, a data URL containing the JSON directly, etc.
let baseURI = "https://example-nft.onflow.org/token-metadata/"
let uriValue = self.id.toString().concat(".json")

return MetadataViews.EVMBridgedMetadata(
name: contractLevel.name,
symbol: contractLevel.symbol,
uri: MetadataViews.URI(
baseURI: baseURI, // defining baseURI results in a concatenation of baseURI and value
value: self.id.toString().concat(".json")
)
)

}
return nil
Expand Down Expand Up @@ -365,6 +389,20 @@ pub contract ExampleNFT: NonFungibleToken, ViewResolver {
"twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain")
}
)
case Type<MetadataViews.EVMBridgedMetadata>():
// Implementing this view gives the project control over how the bridged NFT is represented as an ERC721
// when bridged to EVM on Flow via the public infrastructure bridge.
// Compose the contract-level URI. In this case, the contract metadata is located on some HTTP host,
// but it could be IPFS, S3, a data URL containing the JSON directly, etc.
return MetadataViews.EVMBridgedMetadata(
name: "ExampleNFT",
symbol: "XMPL",
uri: MetadataViews.URI(
baseURI: nil, // setting baseURI as nil sets the given value as the uri field value
value: "https://example-nft.onflow.org/contract-metadata.json"
)
)
}
return nil
}
Expand All @@ -377,7 +415,8 @@ pub contract ExampleNFT: NonFungibleToken, ViewResolver {
pub fun getViews(): [Type] {
return [
Type<MetadataViews.NFTCollectionData>(),
Type<MetadataViews.NFTCollectionDisplay>()
Type<MetadataViews.NFTCollectionDisplay>(),
Type<MetadataViews.EVMBridgedMetadata>()
]
}

Expand Down
9 changes: 9 additions & 0 deletions contracts/MetadataViews.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -803,4 +803,13 @@ pub contract MetadataViews {
}
}

pub fun getEVMBridgedMetadata(_ viewResolver: &{Resolver}) : EVMBridgedMetadata? {
if let view = viewResolver.resolveView(Type<EVMBridgedMetadata>()) {
if let v = view as? EVMBridgedMetadata {
return v
}
}
return nil
}

}
42 changes: 42 additions & 0 deletions docs/MetdataViews/MetadataViews.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,24 @@ to find and load the image via an IPFS gateway.

---

### `URI`

```cadence
pub struct URI {
pub let baseURI: String?
access(self) let value: String
}
```
View to represent a generic URI. May be used to represent the URI of
the NFT where the type of URI is not able to be determined (i.e. HTTP,
IPFS, etc.).

[More...](MetadataViews_URI.md)

---

### `Edition`

```cadence
Expand Down Expand Up @@ -398,6 +416,30 @@ some contextualized data about each trait.

[More...](MetadataViews_Traits.md)

---

### `EVMBridgedMetadata`

```cadence
pub struct EVMBridgedMetadata {
pub let name: String
pub let symbol: String
pub let uri: {File}
}
```
This view may be used by Cadence-native projects to define their
contract- and token-level metadata according to EVM-compatible
formats. Several ERC standards (e.g. ERC20, ERC721, etc.) expose name
and symbol values to define assets as well as contract- & token-level
metadata view `tokenURI(uint256)` and `contractURI()` methods. This
view enables Cadence projects to define in their own contracts how
they would like their metadata to be defined when bridged to EVM.

[More...](MetadataViews_EVMBridgedMetadata.md)

---
## Functions

Expand Down
28 changes: 28 additions & 0 deletions docs/MetdataViews/MetadataViews_EVMBridgedMetadata.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Struct `EVMBridgedMetadata`

```cadence
pub struct EVMBridgedMetadata {
pub let name: String
pub let symbol: String
pub let uri: {File}
}
```

This view may be used by Cadence-native projects to define contract-
and token-level metadata according to EVM-compatible formats. Several
ERC standards (e.g. ERC20, ERC721, etc.) expose name and symbol values
to define assets as well as contract- & token-level metadata view
`tokenURI(uint256)` and `contractURI()` methods. This view enables
Cadence projects to define in their own contracts how they would like
their metadata to be defined when bridged to EVM.

### Initializer

```cadence
init(name: String, symbol: String, uri: {File})
```

---
40 changes: 40 additions & 0 deletions docs/MetdataViews/MetadataViews_URI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Struct `URI`

```cadence
pub struct URI {
pub let baseURI: String?
access(self) let value: String
}
```

View to represent a generic URI. May be used to represent the URI of
the NFT where the type of URI is not able to be determined (i.e. HTTP,
IPFS, etc.)

Implemented Interfaces:
- `File`


### Initializer

```cadence
init(baseURI: String?, value: String?)
```


## Functions

### `uri()`

```cadence
view fun uri(): String
```
This function returns the uri for this file. If the `baseURI` is set,
this will be a concatenation of the `baseURI` and the `value`. If the
`baseURI` is not set, this will return the `value`.

Returns: The string containing the file uri

---
2 changes: 1 addition & 1 deletion flow.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"MetadataViews": {
"source": "./contracts/MetadataViews.cdc",
"aliases": {
"testing": "0x0000000000000001"
"testing": "0x0000000000000007"
}
},
"ViewResolver": {
Expand Down
Loading

0 comments on commit d8db9b2

Please sign in to comment.