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}