Skip to content

Commit

Permalink
Merge pull request #3406 from dessaya/tokenuri-hack
Browse files Browse the repository at this point in the history
erc721 tokenURI(): return NFT uri+name+description
  • Loading branch information
dessaya authored May 17, 2024
2 parents 083907b + 75e5a40 commit 13fe876
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 6 deletions.
15 changes: 10 additions & 5 deletions packages/isc/irc27nft.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import "encoding/json"
// IRC27NFTMetadata represents an NFT metadata according to IRC27.
// See: https://github.com/iotaledger/tips/blob/main/tips/TIP-0027/tip-0027.md
type IRC27NFTMetadata struct {
Standard string `json:"standard"`
Version string `json:"version"`
MIMEType string `json:"type"`
URI string `json:"uri"`
Name string `json:"name"`
Standard string `json:"standard"`
Version string `json:"version"`
MIMEType string `json:"type"`
URI string `json:"uri"`
Name string `json:"name"`
CollectionName string `json:"collectionName,omitempty"`
Royalties map[string]float32 `json:"royalties,omitempty"`
IssuerName string `json:"issuerName,omitempty"`
Description string `json:"description,omitempty"`
Attributes *json.RawMessage `json:"attributes,omitempty"`
}

func NewIRC27NFTMetadata(mimeType, uri, name string) *IRC27NFTMetadata {
Expand Down
4 changes: 4 additions & 0 deletions packages/vm/core/evm/evmimpl/iscmagic_sandbox_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/iotaledger/wasp/packages/parameters"
"github.com/iotaledger/wasp/packages/vm/core/accounts"
"github.com/iotaledger/wasp/packages/vm/core/errors/coreerrors"
"github.com/iotaledger/wasp/packages/vm/core/evm"
"github.com/iotaledger/wasp/packages/vm/core/evm/iscmagic"
)

Expand All @@ -39,6 +40,9 @@ func (h *magicContractHandler) GetNFTData(nftID iscmagic.NFTID) iscmagic.ISCNFT
func (h *magicContractHandler) GetIRC27NFTData(nftID iscmagic.NFTID) iscmagic.IRC27NFT {
nft := h.ctx.GetNFTData(nftID.Unwrap())
metadata, err := isc.IRC27NFTMetadataFromBytes(nft.Metadata)
// This hack is so that the ERC721 tokenURI view function returns the NFT name and description
// for explorers
metadata.URI = evm.EncodePackedNFTURI(metadata)
h.ctx.RequireNoError(err)
return iscmagic.IRC27NFT{
Nft: iscmagic.WrapISCNFT(nft),
Expand Down
6 changes: 5 additions & 1 deletion packages/vm/core/evm/evmtest/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,11 @@ func TestERC721NFTCollection(t *testing.T) {
{
var uri string
erc721.callView("tokenURI", []any{iscmagic.WrapNFTID(nft.ID).TokenID()}, &uri)
require.EqualValues(t, nftMetadatas[0].URI, uri)
p, err := evm.DecodePackedNFTURI(uri)
require.NoError(t, err)
require.EqualValues(t, nftMetadatas[0].URI, p.Image)
require.EqualValues(t, nftMetadatas[0].Name, p.Name)
require.EqualValues(t, nftMetadatas[0].Description, p.Description)
}
}

Expand Down
6 changes: 6 additions & 0 deletions packages/vm/core/evm/iscmagic/ISCSandbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ interface ISCSandbox {
function getNFTData(NFTID id) external view returns (ISCNFT memory);

// Get information about an on-chain IRC27 NFT
// Note: the metadata.uri field is encoded as a data URL with:
// base64(jsonEncode({
// "name": NFT.name,
// "description": NFT.description,
// "image": NFT.URI
// }))
function getIRC27NFTData(NFTID id) external view returns (IRC27NFT memory);

// Get the address of an ERC20NativeTokens contract for the given foundry serial number
Expand Down
6 changes: 6 additions & 0 deletions packages/vm/core/evm/iscmagic/ISCTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ struct IRC27NFTMetadata {
string standard;
string version;
string mimeType;
// Note: uri field is encoded as a data URL with:
// base64(jsonEncode({
// "name": NFT.name,
// "description": NFT.description,
// "image": NFT.URI
// }))
string uri;
string name;
}
Expand Down
48 changes: 48 additions & 0 deletions packages/vm/core/evm/nfthack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package evm

import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/samber/lo"

"github.com/iotaledger/wasp/packages/isc"
)

// This hack is so that the ERC721 tokenURI view function returns the NFT name and description
// for explorers
type PackedNFTURI struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Image string `json:"image"`
}

const dataURLPrefix = "data:application/json;base64"

func EncodePackedNFTURI(metadata *isc.IRC27NFTMetadata) string {
return dataURLPrefix + "," + base64.StdEncoding.EncodeToString(lo.Must(json.Marshal(PackedNFTURI{
Name: metadata.Name,
Description: metadata.Description,
Image: metadata.URI,
})))
}

func DecodePackedNFTURI(uri string) (*PackedNFTURI, error) {
parts := strings.Split(uri, ",")
if len(parts) != 2 {
return nil, errors.New("cannot decode packed NFT URI: expected valid data URL")
}
if parts[0] != dataURLPrefix {
return nil, errors.New("cannot decode packed NFT URI: expected valid data URL")
}
b, err := base64.StdEncoding.DecodeString(parts[1])
if err != nil {
return nil, fmt.Errorf("cannot decode packed NFT URI: %w", err)
}
var p *PackedNFTURI
err = json.Unmarshal(b, &p)
return p, err
}

0 comments on commit 13fe876

Please sign in to comment.