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