1package grc721
2
3import (
4 "std"
5
6 "gno.land/p/demo/avl"
7)
8
9// royaltyNFT represents a non-fungible token (NFT) with royalty functionality.
10type 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.
17var _ IGRC2981 = (*royaltyNFT)(nil)
18
19// NewNFTWithRoyalty creates a new royalty NFT with the specified name, symbol, and royalty calculator.
20func 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.
32func (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.
60func (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
75func (r *royaltyNFT) calculateRoyaltyAmount(salePrice, percentage uint64) (uint64, error) {
76 royaltyAmount := (salePrice * percentage) / 100
77 return royaltyAmount, nil
78}
grc721_royalty.gno
2.36 Kb ยท 78 lines