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}