Skip to content

Commit

Permalink
-add getter to basic nft and igrc721 interface
Browse files Browse the repository at this point in the history
-change tokenhub to be a hub for nfts rather than a hub for fungible tokens
  • Loading branch information
matijamarjanovic committed Jan 10, 2025
1 parent 6b9ceb7 commit 7ec4dc7
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 65 deletions.
7 changes: 7 additions & 0 deletions examples/gno.land/p/demo/grc/grc721/basic_nft.gno
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,10 @@ func (s *basicNFT) RenderHome() (str string) {

return
}

// Then add the Getter method to your NFT types
func (n *basicNFT) Getter() NFTGetter {
return func() IGRC721 {
return n
}
}
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/grc/grc721/igrc721.gno
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ const (
ApprovalEvent = "Approval"
ApprovalForAllEvent = "ApprovalForAll"
)

type NFTGetter func() IGRC721

72 changes: 36 additions & 36 deletions examples/gno.land/r/matijamarjanovic/tokenhub/test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,51 @@ package tokenhub
import (
"std"

"gno.land/p/demo/grc/grc20"
"gno.land/p/demo/grc/grc721"
"gno.land/p/demo/ufmt"
)

var (
tokenA *grc20.Token
tokenB *grc20.Token
tokenC *grc20.Token
tokenD *grc20.Token
tokenE *grc20.Token
// Initialize basic NFTs using the public constructor
nftA = grc721.NewBasicNFT("Collection A", "NFTA")
nftB = grc721.NewBasicNFT("Collection B", "NFTB")
nftC = grc721.NewBasicNFT("Collection C", "NFTC")
)

func init() {
tokenA = grc20.NewToken("Token A", "TKNA", 6)
tokenB = grc20.NewToken("Token B", "TKNB", 6)
tokenC = grc20.NewToken("Token C", "TKNC", 6)
tokenD = grc20.NewToken("Token D", "TKND", 6)
tokenE = grc20.NewToken("Token E", "TKNE", 6)

Send5OfEach("g1ej0qca5ptsw9kfr64ey8jvfy9eacga6mpj2z0y")
RegisterToken(tokenA)
RegisterToken(tokenB)
RegisterToken(tokenC)
RegisterToken(tokenD)
RegisterToken(tokenE)

// Test address to receive NFTs
testAddr := std.Address("g1ej0qca5ptsw9kfr64ey8jvfy9eacga6mpj2z0y")

// Mint test NFTs
MintTestNFTs(testAddr)

// Register all NFT collections using the Getter method
RegisterNFT(func() grc721.IGRC721 { return nftA })
RegisterNFT(func() grc721.IGRC721 { return nftB })
RegisterNFT(func() grc721.IGRC721 { return nftC })
}

func Send5OfEach(to std.Address) error {
func MintTestNFTs(to std.Address) error {
if !to.IsValid() {
return grc20.ErrInvalidAddress
return grc721.ErrInvalidAddress
}

if err := adminA.Mint(to, 5); err != nil {
return err
}
if err := adminB.Mint(to, 5); err != nil {
return err
}
if err := adminC.Mint(to, 5); err != nil {
return err
}
if err := adminD.Mint(to, 5); err != nil {
return err
}
if err := adminE.Mint(to, 5); err != nil {
return err
// Mint NFTs for each collection
for i := 1; i <= 2; i++ {
// Create TokenID for each NFT
tokenIDA := grc721.TokenID(ufmt.Sprintf("NFTA_%d", i))
if err := nftA.Mint(to, tokenIDA); err != nil {
return err
}

tokenIDB := grc721.TokenID(ufmt.Sprintf("NFTB_%d", i))
if err := nftB.Mint(to, tokenIDB); err != nil {
return err
}

tokenIDC := grc721.TokenID(ufmt.Sprintf("NFTC_%d", i))
if err := nftC.Mint(to, tokenIDC); err != nil {
return err
}
}

return nil
Expand Down
69 changes: 40 additions & 29 deletions examples/gno.land/r/matijamarjanovic/tokenhub/tokenhub.gno
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,50 @@ package tokenhub
import (
"std"
"errors"
"strings"
"strings"
"gno.land/p/demo/avl"
"gno.land/p/demo/grc/grc20"
"gno.land/p/moul/md"
"gno.land/p/demo/ufmt"
"gno.land/p/demo/grc/grc721"
"gno.land/p/moul/md"
"gno.land/p/demo/ufmt"
)

var (
registeredTokens = avl.NewTree() // symbol -> *grc20.Token
registeredNFTs = avl.NewTree() // symbol -> NFTGetter

ErrTokenAlreadyRegistered = errors.New("token already registered")
ErrTokenNotFound = errors.New("token not found")
ErrNFTAlreadyRegistered = errors.New("NFT already registered")
ErrNFTNotFound = errors.New("NFT not found")
)

func RegisterToken(token *grc20.Token) error {
symbol := token.GetSymbol()
func RegisterNFT(nftGetter grc721.NFTGetter) error {
nft := nftGetter()
metadata, ok := nft.(grc721.IGRC721CollectionMetadata)
if !ok {
return errors.New("NFT must implement IGRC721CollectionMetadata")
}

symbol := metadata.Symbol()

if registeredTokens.Has(symbol) {
return ErrTokenAlreadyRegistered
if registeredNFTs.Has(symbol) {
return ErrNFTAlreadyRegistered
}

registeredTokens.Set(symbol, token)
registeredNFTs.Set(symbol, nftGetter)
return nil
}

func getBalances(addr std.Address) string {
balances := avl.NewTree()
var sb strings.Builder

registeredTokens.Iterate("", "", func(key string, value interface{}) bool {
token := value.(*grc20.Token)
balance := token.BalanceOf(addr)
registeredNFTs.Iterate("", "", func(key string, value interface{}) bool {
nftGetter := value.(grc721.NFTGetter)
nft := nftGetter()
balance, _ := nft.BalanceOf(addr)
balances.Set(key, balance)
return false
})

sb.WriteString("Balances: ")
sb.WriteString("NFT Balances: ")
balances.Iterate("", "", func(key string, value interface{}) bool {
balance := value.(uint64)
sb.WriteString(ufmt.Sprintf("%s: %d ", key, balance))
Expand All @@ -56,25 +63,29 @@ func GetMyBalances() string {
func Render(path string) string {
var sb strings.Builder

sb.WriteString(md.H1("TokenHub"))
sb.WriteString(md.Paragraph("A central registry for GRC20 tokens on gno.land"))
sb.WriteString(md.H1("NFT Hub"))
sb.WriteString(md.Paragraph("A central registry for GRC721 NFTs on gno.land"))

sb.WriteString(md.H2("Registered Tokens"))
sb.WriteString(md.H2("Registered NFTs"))

var tokenItems []string
registeredTokens.Iterate("", "", func(key string, value interface{}) bool {
token := value.(*grc20.Token)
tokenItems = append(tokenItems, ufmt.Sprintf("%s (%s) - %d decimals",
token.GetName(),
token.GetSymbol(),
token.GetDecimals()))
var nftItems []string
registeredNFTs.Iterate("", "", func(key string, value interface{}) bool {
nftGetter := value.(grc721.NFTGetter)
nft := nftGetter()
metadata, ok := nft.(grc721.IGRC721CollectionMetadata)
if !ok {
return false
}
nftItems = append(nftItems, ufmt.Sprintf("%s (%s)",
metadata.Name(),
metadata.Symbol()))
return false
})

if len(tokenItems) > 0 {
sb.WriteString(md.BulletList(tokenItems))
if len(nftItems) > 0 {
sb.WriteString(md.BulletList(nftItems))
} else {
sb.WriteString(md.Italic("No tokens registered yet"))
sb.WriteString(md.Italic("No NFTs registered yet"))
sb.WriteString("\n")
}

Expand Down

0 comments on commit 7ec4dc7

Please sign in to comment.