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}