Smart Contract
Giefts
A.097bafa4e0b48eef.Giefts
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import ViewResolver from 0x1d7e57aa55817448
4
5// ___ __
6// __ /'___\/\ \__
7// __ /\_\ __ /\ \__/\ \ ,_\ ____
8// /'_ `\/\ \ /'__`\ \ ,__\\ \ \/ /',__\
9// /\ \L\ \ \ \/\ __/\ \ \_/ \ \ \_/\__, `\
10// \ \____ \ \_\ \____\\ \_\ \ \__\/\____/
11// \/___L\ \/_/\/____/ \/_/ \/__/\/___/
12// /\____/
13// \_/__/
14//
15// Giefts - wrap NFT gifts in a box and send them to your friends.
16// The gifts can be claimed by passing the correct password.
17//
18access(all)
19contract Giefts{
20
21 access(all) entitlement Owner
22 /**/
23 /////////////////////////////////////////////////////////////
24
25 // PATHS //
26 /////////////////////////////////////////////////////////////**/
27 access(all)
28 let GieftsStoragePath: StoragePath
29
30 access(all)
31 let GieftsPublicPath: PublicPath
32
33 // EVENTS //
34 /////////////////////////////////////////////////////////////**/
35 access(all)
36 event Packed(gieft: UInt64, nfts: [UInt64])
37
38 access(all)
39 event Added(gieft: UInt64, nft: UInt64, type: String, name: String, thumbnail: String)
40
41 access(all)
42 event Removed(gieft: UInt64, nft: UInt64, type: String, name: String, thumbnail: String)
43
44 access(all)
45 event Claimed(
46 gieft: UInt64,
47 nft: UInt64,
48 type: String,
49 name: String,
50 thumbnail: String,
51 gifter: Address?,
52 giftee: Address?
53 ) /**/
54 /////////////////////////////////////////////////////////////
55
56
57 // INTERFACES //
58 /////////////////////////////////////////////////////////////**/
59 /// Gieft
60 access(all)
61 resource interface GieftPublic{
62 access(all)
63 let password: [UInt8]
64
65 access(all)
66 fun borrowClaimableNFT(): &{NonFungibleToken.NFT}?
67
68 access(all)
69 fun claimNft(
70 password: String,
71 collection: &{NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection}
72 )
73
74 access(all)
75 fun getNftIDs(): [UInt64]
76 }
77
78 /// GieftCollection
79 access(all)
80 resource interface GieftCollectionPublic{
81 access(all)
82 fun borrowGieft(_ gieft: UInt64): &Giefts.Gieft?
83
84 access(all)
85 fun getGieftIDs(): [UInt64]
86 }
87
88 access(all)
89 resource interface GieftCollectionPrivate{
90 access(Owner)
91 fun packGieft(
92 name: String,
93 password: [
94 UInt8
95 ],
96 nfts: @{
97 UInt64:{ NonFungibleToken.NFT}
98 }
99 ): Void
100
101 access(Owner)
102 fun addNftToGieft(gieft: UInt64, nft: @{NonFungibleToken.NFT})
103
104 access(Owner)
105 fun unpackGieft(gieft: UInt64): @{UInt64:{ NonFungibleToken.NFT}}
106 } /**/
107 /////////////////////////////////////////////////////////////
108
109
110 // RESOURCES //
111 /////////////////////////////////////////////////////////////**/
112 /// Gieft
113 /// A collection of NFTs that can be claimed by passing the correct password
114 access(all)
115 resource Gieft: GieftPublic{
116 /// The name of the gieft
117 access(all)
118 let name: String
119
120 /// A collection of NFTs
121 /// nfts are stored as a map of uuids to NFTs
122 access(contract)
123 var nfts: @{UInt64:{ NonFungibleToken.NFT}}
124
125 /// The hashed password to claim an nft
126 access(all)
127 let password: [UInt8]
128
129 /// add an NFT to the gieft
130 access(contract)
131 fun addNft(nft: @{NonFungibleToken.NFT}){
132 pre{
133 !self.nfts.keys.contains(nft.uuid):
134 "NFT uuid already added"
135 }
136 let display: MetadataViews.Display = nft.resolveView(Type<MetadataViews.Display>())! as! MetadataViews.Display
137 emit Added(gieft: self.uuid, nft: nft.uuid, type: nft.getType().identifier, name: display.name, thumbnail: display.thumbnail.uri())
138 let oldNft <- self.nfts[nft.uuid] <- nft
139 destroy oldNft
140 }
141
142 /// borrwClaimableNFT
143 /// get a reference to the first NFT that can be claimed
144 /// @returns the first NFT that can be claimed
145 access(all)
146 fun borrowClaimableNFT(): &{NonFungibleToken.NFT}?{
147 if self.nfts.length > 0{
148 return &self.nfts[self.nfts.keys[0]]
149 } else{
150 return nil
151 }
152 }
153
154 /// claim an NFT from the gieft
155 /// @params password: the password to claim the NFT
156 access(all)
157 fun claimNft(password: String, collection: &{NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection}){
158 pre{
159 self.password == HashAlgorithm.KECCAK_256.hash(password.utf8):
160 "Incorrect password"
161 self.nfts.length > 0:
162 "No NFTs to claim"
163 }
164 let nft <- self.nfts.remove(key: self.nfts.keys[0])!
165 let display: MetadataViews.Display = nft.resolveView(Type<MetadataViews.Display>())! as! MetadataViews.Display
166 emit Claimed(gieft: self.uuid, nft: nft.uuid, type: nft.getType().identifier, name: display.name, thumbnail: display.thumbnail.uri(), gifter: self.owner?.address, giftee: collection.owner?.address)
167 collection.deposit(token: <-nft)
168 }
169
170 /// unpack, a function to unpack an NFT from the gieft, this function is only callable by the owner
171 /// @params nft: the uuid of the NFT to claim
172 access(contract)
173 fun unpack(nft: UInt64): @{NonFungibleToken.NFT}{
174 pre{
175 self.nfts.keys.contains(nft):
176 "NFT does not exist"
177 }
178 let nft <- self.nfts.remove(key: nft)!
179 let display: MetadataViews.Display = nft.resolveView(Type<MetadataViews.Display>())! as! MetadataViews.Display
180 emit Removed(gieft: self.uuid, nft: nft.uuid, type: nft.getType().identifier, name: display.name, thumbnail: display.thumbnail.uri())
181 return <-nft
182 }
183
184 /// get all NFT ids
185 access(all)
186 fun getNftIDs(): [UInt64]{
187 return self.nfts.keys
188 }
189
190 init(name: String, password: [UInt8], nfts: @{UInt64:{ NonFungibleToken.NFT}}){
191 self.name = name
192 self.nfts <- nfts
193 self.password = password
194 emit Packed(gieft: self.uuid, nfts: self.nfts.keys)
195 }
196 }
197
198 /// GieftCollection
199 /// A collection of giefts
200 access(all)
201 resource GieftCollection: GieftCollectionPublic, GieftCollectionPrivate{
202 /// a collection of giefts
203 access(all)
204 var giefts: @{UInt64: Gieft}
205
206 /// create a new gieft
207 /// @params password: the hashed password to claim an NFT from the Gieft
208 /// @params nfts: the NFTs to add to the gieft
209 access(Owner)
210 fun packGieft(name: String, password: [UInt8], nfts: @{UInt64:{ NonFungibleToken.NFT}}){
211 let gieft <- create Gieft(name: name, password: password, nfts: <-nfts)
212 let oldGieft <- self.giefts[gieft.uuid] <- gieft
213 destroy oldGieft
214 }
215
216 /// add an NFT to a gieft
217 /// @params gieft: the uuid of the gieft to add the NFT to
218 /// @params nft: the NFT to add to the gieft
219 access(Owner)
220 fun addNftToGieft(gieft: UInt64, nft: @{NonFungibleToken.NFT}){
221 pre{
222 self.giefts.keys.contains(gieft):
223 "Gieft does not exist"
224 }
225 (self.borrowGieft(gieft)!).addNft(nft: <-nft)
226 }
227
228 /// unpack a gieft
229 /// @params gieft: the uuid of the gieft to unpack
230 access(Owner)
231 fun unpackGieft(gieft: UInt64): @{UInt64:{ NonFungibleToken.NFT}}{
232 pre{
233 self.giefts.keys.contains(gieft):
234 "Gieft does not exist"
235 }
236 var nfts: @{UInt64:{ NonFungibleToken.NFT}} <-{}
237 let gieft = self.borrowGieft(gieft)!
238 let nftIDs = gieft.getNftIDs()
239 for nftID in nftIDs{
240 let nft <- gieft.unpack(nft: nftID)
241 let oldNft <- nfts[nftID] <- nft
242 destroy oldNft
243 }
244 return <-nfts
245 }
246
247 /// borrow a gieft reference
248 /// @params gieft: the uuid of the gieft to borrow
249 access(all)
250 fun borrowGieft(_ gieft: UInt64): &Gieft?{
251 return &self.giefts[gieft]
252 }
253
254 /// get all gieft ids
255 access(all)
256 fun getGieftIDs(): [UInt64]{
257 return self.giefts.keys
258 }
259
260 init(){
261 self.giefts <-{}
262 }
263 } /**/
264 /////////////////////////////////////////////////////////////
265
266
267 // FUNCTIONS //
268 /////////////////////////////////////////////////////////////**/
269 /// create a new gieft collection resource
270 access(all)
271 fun createGieftCollection(): @GieftCollection{
272 return <-create GieftCollection()
273 }
274
275 init(){
276 /// paths
277 self.GieftsStoragePath = /storage/Giefts
278 self.GieftsPublicPath = /public/Giefts
279 }
280}
281