Smart Contract

Giefts

A.097bafa4e0b48eef.Giefts

Deployed

2d ago
Feb 26, 2026, 03:12:51 AM UTC

Dependents

0 imports
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