Search Apps Documentation Source Content File Folder Download Copy Actions Download

utils.gno

2.78 Kb ยท 97 lines
 1package gnft
 2
 3import (
 4	"chain/runtime"
 5	"math/rand"
 6	"time"
 7
 8	"gno.land/p/demo/tokens/grc721"
 9	"gno.land/p/nt/ufmt"
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, from, to address, tid grc721.TokenID) {
30	if err == nil {
31		return
32	}
33
34	caller := runtime.PreviousRealm().Address()
35
36	// Check if token exists
37	owner, ownerErr := nft.OwnerOf(tid)
38	if ownerErr != nil {
39		panic(ownerErr)
40	}
41
42	switch err {
43	case grc721.ErrCallerIsNotOwnerOrApproved:
44		// Check if caller is the owner
45		if caller == owner {
46			panic(makeErrorWithDetails(grc721.ErrTransferFromIncorrectOwner, ufmt.Sprintf("owner mismatch - from: %s, actual owner: %s, token: %s", from, owner, string(tid))))
47		}
48
49		// Check if caller is approved for this specific token
50		approved, _ := nft.GetApproved(tid)
51		if approved != caller {
52			// Check if caller is approved for all tokens
53			if !nft.IsApprovedForAll(owner, caller) {
54				panic(makeErrorWithDetails(grc721.ErrCallerIsNotOwnerOrApproved, ufmt.Sprintf("caller %s is not owner %s or approved for token %s", caller, owner, string(tid))))
55			}
56		}
57
58	case grc721.ErrInvalidAddress:
59		panic(makeErrorWithDetails(grc721.ErrInvalidAddress, ufmt.Sprintf("to address (%s)", to)))
60
61	case grc721.ErrTransferFromIncorrectOwner:
62		panic(makeErrorWithDetails(grc721.ErrTransferFromIncorrectOwner, ufmt.Sprintf("from %s is not the owner %s of token %s", from, owner, string(tid))))
63
64	case grc721.ErrInvalidTokenId:
65		panic(makeErrorWithDetails(grc721.ErrInvalidTokenId, ufmt.Sprintf("token %s", string(tid))))
66
67	default:
68		panic(err.Error())
69	}
70}
71
72// checkApproveErr wraps approve errors with more specific context.
73func checkApproveErr(err error, approved address, tid grc721.TokenID) {
74	if err == nil {
75		return
76	}
77
78	errMsg := err.Error()
79	caller := runtime.PreviousRealm().Address()
80
81	// Check if token exists
82	owner, ownerErr := nft.OwnerOf(tid)
83	if ownerErr != nil {
84		panic(makeErrorWithDetails(errTokenNotExists, ufmt.Sprintf("token %s", string(tid))))
85	}
86
87	switch {
88	case errMsg == "caller is not token owner or approved":
89		panic(makeErrorWithDetails(errNotOwnerOrApproved, ufmt.Sprintf("caller %s cannot approve for token %s owned by %s", caller, string(tid), owner)))
90
91	case errMsg == "approval to current owner":
92		panic(makeErrorWithDetails(errTransferToSelf, ufmt.Sprintf("cannot approve to current owner %s for token %s", approved, string(tid))))
93
94	default:
95		panic(err.Error())
96	}
97}