grc721_royalty.gno

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