Search Apps Documentation Source Content File Folder Download Copy Actions Download

grc721_royalty.gno

2.46 Kb · 76 lines
 1package grc721
 2
 3import (
 4	"math/overflow"
 5
 6	"gno.land/p/nt/avl/v0"
 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 int64     // 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(_ int, rlm realm, name, symbol string) *royaltyNFT {
21	return &royaltyNFT{
22		metadataNFT:          NewNFTWithMetadata(0, rlm, name, symbol),
23		tokenRoyaltyInfo:     avl.NewTree(),
24		maxRoyaltyPercentage: 100,
25	}
26}
27
28// SetTokenRoyalty sets the royalty information for a specific token ID.
29// caller must equal the token's owner; the owning realm's wrapper
30// derives caller from rlm.Previous().Address() under IsCurrent.
31func (r *royaltyNFT) SetTokenRoyalty(caller address, tid TokenID, royaltyInfo RoyaltyInfo) error {
32	// Validate the payment address
33	if err := isValidAddress(royaltyInfo.PaymentAddress); err != nil {
34		return ErrInvalidRoyaltyPaymentAddress
35	}
36
37	// Check if royalty percentage exceeds maxRoyaltyPercentage
38	if royaltyInfo.Percentage > r.maxRoyaltyPercentage {
39		return ErrInvalidRoyaltyPercentage
40	}
41
42	// Check if the caller is the owner of the token
43	owner, err := r.metadataNFT.OwnerOf(tid)
44	if err != nil {
45		return err
46	}
47	if caller != owner {
48		return ErrCallerIsNotOwner
49	}
50
51	// Set royalty information for the token
52	r.tokenRoyaltyInfo.Set(tid.String(), royaltyInfo)
53
54	return nil
55}
56
57// RoyaltyInfo returns the royalty information for the given token ID and sale price.
58func (r *royaltyNFT) RoyaltyInfo(tid TokenID, salePrice int64) (address, int64, error) {
59	// Retrieve royalty information for the token
60	val, found := r.tokenRoyaltyInfo.Get(tid.String())
61	if !found {
62		return "", 0, ErrInvalidTokenId
63	}
64
65	royaltyInfo := val.(RoyaltyInfo)
66
67	// Calculate royalty amount
68	royaltyAmount, _ := r.calculateRoyaltyAmount(salePrice, royaltyInfo.Percentage)
69
70	return royaltyInfo.PaymentAddress, royaltyAmount, nil
71}
72
73func (r *royaltyNFT) calculateRoyaltyAmount(salePrice, percentage int64) (int64, error) {
74	royaltyAmount := overflow.Mul64p(salePrice, percentage) / 100
75	return royaltyAmount, nil
76}