Smart Contract

SimpleFlunksWithTraits

A.bfffec679fff3a94.SimpleFlunksWithTraits

Deployed

14h ago
Feb 28, 2026, 02:29:07 AM UTC

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import ViewResolver from 0x1d7e57aa55817448
4
5access(all)
6contract SimpleFlunksWithTraits: NonFungibleToken {
7    
8    access(all) event ContractInitialized()
9    access(all) event Withdraw(id: UInt64, from: Address?)
10    access(all) event Deposit(id: UInt64, to: Address?)
11    access(all) event Minted(id: UInt64, to: Address?)
12    
13    access(all) var totalSupply: UInt64
14    
15    access(all) let CollectionStoragePath: StoragePath
16    access(all) let CollectionPublicPath: PublicPath
17    access(all) let AdminStoragePath: StoragePath
18    
19    // Trait structure for NFT attributes
20    access(all) struct Trait {
21        access(all) let name: String
22        access(all) let value: AnyStruct
23        access(all) let displayType: String?
24        access(all) let rarity: String?
25        
26        init(name: String, value: AnyStruct, displayType: String?, rarity: String?) {
27            self.name = name
28            self.value = value
29            self.displayType = displayType
30            self.rarity = rarity
31        }
32    }
33    
34    access(all) resource NFT: NonFungibleToken.NFT, ViewResolver.Resolver {
35        
36        access(all) let id: UInt64
37        access(all) let name: String
38        access(all) let description: String
39        access(all) let image: String
40        access(all) let traits: [Trait]
41        access(all) let externalURL: String?
42        access(all) let animationURL: String?
43        access(all) let edition: UInt64?
44        access(all) let maxEdition: UInt64?
45        
46        init(
47            id: UInt64, 
48            name: String, 
49            description: String, 
50            image: String,
51            traits: [Trait],
52            externalURL: String?,
53            animationURL: String?,
54            edition: UInt64?,
55            maxEdition: UInt64?
56        ) {
57            self.id = id
58            self.name = name
59            self.description = description
60            self.image = image
61            self.traits = traits
62            self.externalURL = externalURL
63            self.animationURL = animationURL
64            self.edition = edition
65            self.maxEdition = maxEdition
66        }
67        
68        access(all) view fun getViews(): [Type] {
69            return [
70                Type<MetadataViews.Display>(),
71                Type<MetadataViews.Traits>(),
72                Type<MetadataViews.Editions>(),
73                Type<MetadataViews.ExternalURL>(),
74                Type<MetadataViews.NFTCollectionData>(),
75                Type<MetadataViews.NFTCollectionDisplay>(),
76                Type<MetadataViews.Serial>(),
77                Type<MetadataViews.Royalties>()
78            ]
79        }
80        
81        access(all) fun resolveView(_ view: Type): AnyStruct? {
82            switch view {
83                case Type<MetadataViews.Display>():
84                    return MetadataViews.Display(
85                        name: self.name,
86                        description: self.description,
87                        thumbnail: MetadataViews.HTTPFile(url: self.image)
88                    )
89                
90                case Type<MetadataViews.Traits>():
91                    let traitsView: [MetadataViews.Trait] = []
92                    for trait in self.traits {
93                        traitsView.append(MetadataViews.Trait(
94                            name: trait.name,
95                            value: trait.value,
96                            displayType: trait.displayType,
97                            rarity: trait.rarity != nil ? MetadataViews.Rarity(
98                                score: nil,
99                                max: nil,
100                                description: trait.rarity!
101                            ) : nil
102                        ))
103                    }
104                    return MetadataViews.Traits(traitsView)
105                
106                case Type<MetadataViews.Editions>():
107                    if self.edition != nil && self.maxEdition != nil {
108                        return MetadataViews.Editions([
109                            MetadataViews.Edition(
110                                name: "SimpleFlunks Edition",
111                                number: self.edition!,
112                                max: self.maxEdition
113                            )
114                        ])
115                    }
116                    return nil
117                
118                case Type<MetadataViews.ExternalURL>():
119                    if self.externalURL != nil {
120                        return MetadataViews.ExternalURL(self.externalURL!)
121                    }
122                    return nil
123                
124                case Type<MetadataViews.Serial>():
125                    return MetadataViews.Serial(self.id)
126                
127                case Type<MetadataViews.Royalties>():
128                    return MetadataViews.Royalties([])
129            }
130            return nil
131        }
132        
133        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
134            return <-create Collection()
135        }
136    }
137    
138    access(all) resource Collection: NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.Collection, NonFungibleToken.CollectionPublic, ViewResolver.ResolverCollection {
139        
140        access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
141        
142        init() {
143            self.ownedNFTs <- {}
144        }
145        
146        access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
147            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
148            emit Withdraw(id: token.id, from: self.owner?.address)
149            return <-token
150        }
151        
152        access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
153            let token <- token as! @SimpleFlunksWithTraits.NFT
154            let id: UInt64 = token.id
155            let oldToken <- self.ownedNFTs[id] <- token
156            emit Deposit(id: id, to: self.owner?.address)
157            destroy oldToken
158        }
159        
160        access(all) view fun getIDs(): [UInt64] {
161            return self.ownedNFTs.keys
162        }
163        
164        access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
165            return &self.ownedNFTs[id]
166        }
167        
168        access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
169            if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
170                return nft as &{ViewResolver.Resolver}
171            }
172            return nil
173        }
174        
175        access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
176            return <-create Collection()
177        }
178        
179        access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
180            return {Type<@SimpleFlunksWithTraits.NFT>(): true}
181        }
182        
183        access(all) view fun isSupportedNFTType(type: Type): Bool {
184            return type == Type<@SimpleFlunksWithTraits.NFT>()
185        }
186    }
187    
188    access(all) resource Admin {
189        
190        access(all) fun mintNFT(
191            recipient: &{NonFungibleToken.CollectionPublic},
192            name: String,
193            description: String,
194            image: String,
195            traits: [Trait],
196            externalURL: String?,
197            animationURL: String?,
198            edition: UInt64?,
199            maxEdition: UInt64?
200        ) {
201            let newNFT <- create NFT(
202                id: SimpleFlunksWithTraits.totalSupply,
203                name: name,
204                description: description,
205                image: image,
206                traits: traits,
207                externalURL: externalURL,
208                animationURL: animationURL,
209                edition: edition,
210                maxEdition: maxEdition
211            )
212            
213            let recipientAddress = recipient.owner!.address
214            
215            recipient.deposit(token: <-newNFT)
216            
217            emit Minted(id: SimpleFlunksWithTraits.totalSupply, to: recipientAddress)
218            
219            SimpleFlunksWithTraits.totalSupply = SimpleFlunksWithTraits.totalSupply + 1
220        }
221    }
222    
223    access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
224        return <-create Collection()
225    }
226    
227    access(all) view fun getContractViews(resourceType: Type?): [Type] {
228        return [Type<MetadataViews.NFTCollectionData>()]
229    }
230    
231    access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
232        switch viewType {
233            case Type<MetadataViews.NFTCollectionData>():
234                return MetadataViews.NFTCollectionData(
235                    storagePath: SimpleFlunksWithTraits.CollectionStoragePath,
236                    publicPath: SimpleFlunksWithTraits.CollectionPublicPath,
237                    publicCollection: Type<&SimpleFlunksWithTraits.Collection>(),
238                    publicLinkedType: Type<&SimpleFlunksWithTraits.Collection>(),
239                    createEmptyCollectionFunction: (fun (): @{NonFungibleToken.Collection} {
240                        return <-SimpleFlunksWithTraits.createEmptyCollection(nftType: Type<@SimpleFlunksWithTraits.Collection>())
241                    })
242                )
243        }
244        return nil
245    }
246    
247    init() {
248        self.totalSupply = 0
249        
250        self.CollectionStoragePath = /storage/SimpleFlunksWithTraitsCollection
251        self.CollectionPublicPath = /public/SimpleFlunksWithTraitsCollection
252        self.AdminStoragePath = /storage/SimpleFlunksWithTraitsAdmin
253        
254        let admin <- create Admin()
255        self.account.storage.save(<-admin, to: self.AdminStoragePath)
256        
257        emit ContractInitialized()
258    }
259}
260