github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/grc/grc721/grc721_royalty.gno (about) 1 package grc721 2 3 import ( 4 "std" 5 6 "gno.land/p/demo/avl" 7 ) 8 9 // royaltyNFT represents a non-fungible token (NFT) with royalty functionality. 10 type royaltyNFT struct { 11 *metadataNFT // Embedding metadataNFT for NFT functionality 12 tokenRoyaltyInfo *avl.Tree // AVL tree to store royalty information for each token 13 maxRoyaltyPercentage uint64 // maxRoyaltyPercentage represents the maximum royalty percentage that can be charged every sale 14 } 15 16 // Ensure that royaltyNFT implements the IGRC2981 interface. 17 var _ IGRC2981 = (*royaltyNFT)(nil) 18 19 // NewNFTWithRoyalty creates a new royalty NFT with the specified name, symbol, and royalty calculator. 20 func NewNFTWithRoyalty(name string, symbol string) *royaltyNFT { 21 // Create a new NFT with metadata 22 nft := NewNFTWithMetadata(name, symbol) 23 24 return &royaltyNFT{ 25 metadataNFT: nft, 26 tokenRoyaltyInfo: avl.NewTree(), 27 maxRoyaltyPercentage: 100, 28 } 29 } 30 31 // SetTokenRoyalty sets the royalty information for a specific token ID. 32 func (r *royaltyNFT) SetTokenRoyalty(tid TokenID, royaltyInfo RoyaltyInfo) error { 33 // Validate the payment address 34 if err := isValidAddress(royaltyInfo.PaymentAddress); err != nil { 35 return ErrInvalidRoyaltyPaymentAddress 36 } 37 38 // Check if royalty percentage exceeds maxRoyaltyPercentage 39 if royaltyInfo.Percentage > r.maxRoyaltyPercentage { 40 return ErrInvalidRoyaltyPercentage 41 } 42 43 // Check if the caller is the owner of the token 44 owner, err := r.metadataNFT.OwnerOf(tid) 45 if err != nil { 46 return err 47 } 48 caller := std.PrevRealm().Addr() 49 if caller != owner { 50 return ErrCallerIsNotOwner 51 } 52 53 // Set royalty information for the token 54 r.tokenRoyaltyInfo.Set(string(tid), royaltyInfo) 55 56 return nil 57 } 58 59 // RoyaltyInfo returns the royalty information for the given token ID and sale price. 60 func (r *royaltyNFT) RoyaltyInfo(tid TokenID, salePrice uint64) (std.Address, uint64, error) { 61 // Retrieve royalty information for the token 62 val, found := r.tokenRoyaltyInfo.Get(string(tid)) 63 if !found { 64 return "", 0, ErrInvalidTokenId 65 } 66 67 royaltyInfo := val.(RoyaltyInfo) 68 69 // Calculate royalty amount 70 royaltyAmount, _ := r.calculateRoyaltyAmount(salePrice, royaltyInfo.Percentage) 71 72 return royaltyInfo.PaymentAddress, royaltyAmount, nil 73 } 74 75 func (r *royaltyNFT) calculateRoyaltyAmount(salePrice, percentage uint64) (uint64, error) { 76 royaltyAmount := (salePrice * percentage) / 100 77 return royaltyAmount, nil 78 }