Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

utils.gno

2.76 Kb · 91 lines
 1package gnft
 2
 3import (
 4	"errors"
 5	"math/rand"
 6	"time"
 7
 8	"gno.land/p/gnoswap/deps/tokens/grc721"
 9	ufmt "gno.land/p/nt/ufmt/v0"
10)
11
12// generateRandInstance generates a new random instance.
13func generateRandInstance() *rand.Rand {
14	now := time.Now()
15	seed1 := now.Unix() + TotalSupply()
16	seed2 := now.UnixNano() + TotalSupply()
17	pcg := rand.NewPCG(uint64(seed1), uint64(seed2))
18	return rand.New(pcg)
19}
20
21// checkErr panics if an error occurs.
22func checkErr(err error) {
23	if err != nil {
24		panic(err.Error())
25	}
26}
27
28// checkTransferErr wraps transfer errors with more specific context.
29func checkTransferErr(err error, caller, from, to address, tid grc721.TokenID) {
30	if err == nil {
31		return
32	}
33
34	// Check if token exists
35	owner, ownerErr := nft.OwnerOf(tid)
36	if ownerErr != nil {
37		panic(ownerErr)
38	}
39
40	switch err {
41	case grc721.ErrCallerIsNotOwnerOrApproved:
42		// Check if caller is the owner
43		if caller == owner {
44			panic(makeErrorWithDetails(grc721.ErrTransferFromIncorrectOwner.Error(), ufmt.Sprintf("owner mismatch - from: %s, actual owner: %s, token: %s", from, owner, string(tid))))
45		}
46
47		// Check if caller is approved for this specific token
48		approved, _ := nft.GetApproved(tid)
49		if approved != caller {
50			// Check if caller is approved for all tokens
51			if !nft.IsApprovedForAll(owner, caller) {
52				panic(makeErrorWithDetails(grc721.ErrCallerIsNotOwnerOrApproved.Error(), ufmt.Sprintf("caller %s is not owner %s or approved for token %s", caller, owner, string(tid))))
53			}
54		}
55
56	case grc721.ErrInvalidAddress:
57		panic(makeErrorWithDetails(grc721.ErrInvalidAddress.Error(), ufmt.Sprintf("to address (%s)", to)))
58
59	case grc721.ErrTransferFromIncorrectOwner:
60		panic(makeErrorWithDetails(grc721.ErrTransferFromIncorrectOwner.Error(), ufmt.Sprintf("from %s is not the owner %s of token %s", from, owner, string(tid))))
61
62	case grc721.ErrInvalidTokenId:
63		panic(makeErrorWithDetails(grc721.ErrInvalidTokenId.Error(), ufmt.Sprintf("token %s", string(tid))))
64
65	default:
66		panic(err.Error())
67	}
68}
69
70// checkApproveErr wraps approve errors with more specific context.
71func checkApproveErr(err error, caller, approved address, tid grc721.TokenID) {
72	if err == nil {
73		return
74	}
75
76	switch {
77	case errors.Is(err, grc721.ErrInvalidTokenId):
78		panic(makeErrorWithDetails(errTokenNotExists, ufmt.Sprintf("token %s", string(tid))))
79
80	case errors.Is(err, grc721.ErrCallerIsNotOwnerOrApproved):
81		owner, ownerErr := nft.OwnerOf(tid)
82		checkErr(ownerErr)
83		panic(makeErrorWithDetails(errNotOwnerOrApproved, ufmt.Sprintf("caller %s cannot approve for token %s owned by %s", caller, string(tid), owner)))
84
85	case errors.Is(err, grc721.ErrApprovalToCurrentOwner):
86		panic(makeErrorWithDetails(errTransferToSelf, ufmt.Sprintf("cannot approve to current owner %s for token %s", approved, string(tid))))
87
88	default:
89		panic(err.Error())
90	}
91}