Smart Contract

SoulMadeMain

A.9a57dfe5c8ce609c.SoulMadeMain

Deployed

2d ago
Feb 26, 2026, 11:01:58 AM UTC

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import SoulMadeComponent from 0x9a57dfe5c8ce609c
4import FlowToken from 0x1654653399040a61
5import FungibleToken from 0xf233dcee88fe0abe
6
7pub contract SoulMadeMain: NonFungibleToken {
8
9    pub var totalSupply: UInt64
10
11    pub let CollectionStoragePath: StoragePath
12    pub let CollectionPublicPath: PublicPath
13    pub let CollectionPrivatePath: PrivatePath
14
15    pub event ContractInitialized()
16    pub event Withdraw(id: UInt64, from: Address?)
17    pub event Deposit(id: UInt64, to: Address?)
18
19    pub event SoulMadeMainCollectionCreated()
20    pub event SoulMadeMainCreated(id: UInt64, series: String)
21    pub event NameSet(id: UInt64, name: String)
22    pub event DescriptionSet(id: UInt64, description: String)
23    pub event IpfsHashSet(id: UInt64, ipfsHash: String)
24    pub event MainComponentUpdated(mainNftId: UInt64)
25
26    pub struct MainDetail{
27        pub let id: UInt64
28        pub(set) var name: String
29        pub let series: String
30        pub(set) var description: String
31        pub(set) var ipfsHash: String
32        pub(set) var componentDetails: [SoulMadeComponent.ComponentDetail]
33
34        init(id: UInt64,
35                name: String,
36                series: String,
37                description: String,
38                ipfsHash: String,
39                componentDetails: [SoulMadeComponent.ComponentDetail]){
40
41            self.id = id
42            self.name = name
43            self.series = series
44            self.description = description
45            self.ipfsHash = ipfsHash
46            self.componentDetails = componentDetails
47        }
48    }
49
50    pub resource interface MainPublic {
51        pub let id: UInt64
52        pub let mainDetail: MainDetail
53
54        pub fun getAllComponentDetail(): {String : SoulMadeComponent.ComponentDetail} 
55    }
56
57    pub resource interface MainPrivate {
58        pub fun setName(_ name: String)
59        pub fun setDescription(_ description: String)
60        pub fun setIpfsHash(_ ipfsHash: String)
61        pub fun withdrawComponent(category: String): @SoulMadeComponent.NFT?
62        pub fun depositComponent(componentNft: @SoulMadeComponent.NFT): @SoulMadeComponent.NFT?
63    }
64
65    pub resource NFT: MainPublic, MainPrivate, NonFungibleToken.INFT, MetadataViews.Resolver {
66        pub let id: UInt64
67        pub let mainDetail: MainDetail
68
69        access(self) var components: @{String : SoulMadeComponent.NFT}
70
71        init(id: UInt64, series: String) {
72            self.id = id
73            self.mainDetail = MainDetail(id: id, name: "", series: series, description: "", ipfsHash: "", componentDetails: [])
74            self.components <- {}
75        }
76        
77        pub fun getAllComponentDetail(): {String : SoulMadeComponent.ComponentDetail} {
78            var info : {String : SoulMadeComponent.ComponentDetail} = {}
79            for categoryKey in self.components.keys{
80                let componentRef = (&self.components[categoryKey] as! &SoulMadeComponent.NFT?)!
81                let detail = componentRef.componentDetail
82                info[categoryKey] = detail
83            }
84            return info
85        }
86
87        pub fun withdrawComponent(category: String): @SoulMadeComponent.NFT {
88            let componentNft <- self.components.remove(key: category)!
89            self.mainDetail.componentDetails = self.getAllComponentDetail().values
90            emit MainComponentUpdated(mainNftId: self.id)
91            return <- componentNft
92        }
93
94        pub fun depositComponent(componentNft: @SoulMadeComponent.NFT): @SoulMadeComponent.NFT? {
95            let category : String = componentNft.componentDetail.category
96            var old <- self.components[category] <- componentNft
97            self.mainDetail.componentDetails = self.getAllComponentDetail().values
98            emit MainComponentUpdated(mainNftId: self.id)
99            return <- old
100        }
101
102        pub fun setName(_ name: String){
103            pre {
104                name.length > 2 : "The name is too short"
105                name.length < 100 : "The name is too long" 
106            }
107            self.mainDetail.name = name
108            emit NameSet(id: self.id, name: name)
109        }
110
111        pub fun setDescription(_ description: String){
112            pre {
113                description.length > 2 : "The descripton is too short"
114                description.length < 500 : "The description is too long" 
115            }
116            self.mainDetail.description = description
117            emit DescriptionSet(id: self.id, description: description)
118        }
119
120        pub fun setIpfsHash(_ ipfsHash: String){
121            self.mainDetail.ipfsHash = ipfsHash
122            emit IpfsHashSet(id: self.id, ipfsHash: ipfsHash)
123        }
124
125        pub fun getViews(): [Type] {
126            return [
127                Type<MetadataViews.Display>(),
128                Type<MetadataViews.Royalties>(),
129                Type<MetadataViews.ExternalURL>(),
130                Type<MetadataViews.NFTCollectionData>(),
131                Type<MetadataViews.NFTCollectionDisplay>()
132            ]
133        }
134
135        pub fun resolveView(_ view: Type): AnyStruct? {
136            switch view {
137                case Type<MetadataViews.Display>():
138                    return MetadataViews.Display(
139                        name: self.mainDetail.name,
140                        description: self.mainDetail.description,
141                        thumbnail: MetadataViews.IPFSFile(
142                            cid: self.mainDetail.ipfsHash,
143                            path: nil
144                        )
145                    )
146                case Type<MetadataViews.Royalties>():
147                    return MetadataViews.Royalties([
148						MetadataViews.Royalty(
149							recepient: getAccount(0x9a57dfe5c8ce609c).getCapability<&FlowToken.Vault{FungibleToken.Receiver}>(/public/flowTokenReceiver),
150							cut: 0.00, 
151							description: "SoulMade Main Royalties"
152						)
153					])
154                case Type<MetadataViews.ExternalURL>():
155                    return MetadataViews.ExternalURL("https://soulmade.art")
156                case Type<MetadataViews.NFTCollectionData>():
157                    return MetadataViews.NFTCollectionData(
158                        storagePath: SoulMadeMain.CollectionStoragePath,
159                        publicPath: SoulMadeMain.CollectionPublicPath,
160                        providerPath: /private/SoulMadeMainCollection,
161                        publicCollection: Type<&Collection{CollectionPublic}>(),
162                        publicLinkedType: Type<&Collection{CollectionPublic, NonFungibleToken.CollectionPublic, NonFungibleToken.Receiver, MetadataViews.ResolverCollection}>(),
163                        providerLinkedType: Type<&Collection{CollectionPublic, NonFungibleToken.CollectionPublic, NonFungibleToken.Provider, MetadataViews.ResolverCollection}>(),
164                        createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection {
165                            return <- SoulMadeMain.createEmptyCollection()
166                        })
167                    )
168                case Type<MetadataViews.NFTCollectionDisplay>():
169                    let squareMedia = MetadataViews.Media(
170                        file: MetadataViews.HTTPFile(
171                           url: "https://i.imgur.com/XgqDY3s.jpg"
172                        ),
173                        mediaType: "image"
174                    )
175                    let bannerMedia = MetadataViews.Media(
176                        file: MetadataViews.HTTPFile(
177                            url: "https://i.imgur.com/yBw3ktk.png"
178                        ),
179                        mediaType: "image"
180                    )
181                    return MetadataViews.NFTCollectionDisplay(
182                        name: "SoulMadeMain",
183                        description: "SoulMade Main Collection",
184                        externalURL: MetadataViews.ExternalURL("https://soulmade.art"),
185                        squareImage: squareMedia,
186                        bannerImage: bannerMedia,
187                        socials: {
188                            "twitter": MetadataViews.ExternalURL("https://twitter.com/soulmade_nft"),
189                            "discord": MetadataViews.ExternalURL("https://discord.com/invite/xtqqXCKW9B")
190                        }
191                    )
192            }
193
194            return nil
195        }
196
197        destroy() {
198            destroy self.components
199        }
200    }
201
202    pub resource interface CollectionPublic {
203        pub fun deposit(token: @NonFungibleToken.NFT)
204        pub fun getIDs(): [UInt64]
205        pub fun borrowViewResolver(id: UInt64): &{MetadataViews.Resolver}
206        pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT
207        pub fun borrowMain(id: UInt64): &{SoulMadeMain.MainPublic}
208    }
209
210    pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection {
211        pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT}
212
213        init () {
214            self.ownedNFTs <- {}
215        }
216
217        pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT {
218            let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing Main NFT")
219
220            emit Withdraw(id: token.id, from: self.owner?.address)
221
222            return <- token
223        }
224
225        pub fun deposit(token: @NonFungibleToken.NFT) {
226            let token <- token as! @SoulMadeMain.NFT
227            let id: UInt64 = token.id
228            let oldToken <- self.ownedNFTs[id] <- token
229
230            emit Deposit(id: id, to: self.owner?.address)
231
232            destroy oldToken
233        }
234
235        pub fun getIDs(): [UInt64] {
236            return self.ownedNFTs.keys
237        }
238
239        pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
240            return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)!
241        }
242
243        pub fun borrowMain(id: UInt64): &{SoulMadeMain.MainPublic} {
244            pre {
245                self.ownedNFTs[id] != nil: "Main NFT doesn't exist"
246            }
247            let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
248            return ref as! &SoulMadeMain.NFT
249        }
250
251        pub fun borrowMainPrivate(id: UInt64): &{SoulMadeMain.MainPrivate} {
252            pre {
253                self.ownedNFTs[id] != nil: "Main NFT doesn't exist"
254            }
255            let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
256            return ref as! &SoulMadeMain.NFT
257        }
258
259        pub fun borrowViewResolver(id: UInt64): &{MetadataViews.Resolver} {
260            let nft = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
261            let mainNFT = nft as! &SoulMadeMain.NFT
262            return mainNFT as &{MetadataViews.Resolver}
263        }    
264
265        destroy() {
266            destroy self.ownedNFTs
267        }
268    }
269
270    pub fun createEmptyCollection(): @NonFungibleToken.Collection {
271        emit SoulMadeMainCollectionCreated()
272        return <- create Collection()
273    }
274
275    pub fun mintMain(series: String) : @NFT {
276        var new <- create NFT(id : SoulMadeMain.totalSupply, series: series)
277        emit SoulMadeMainCreated(id: SoulMadeMain.totalSupply, series: series)
278        SoulMadeMain.totalSupply = SoulMadeMain.totalSupply + 1
279        return <- new
280    }
281
282    init() {
283        self.totalSupply = 0
284
285        self.CollectionPublicPath = /public/SoulMadeMainCollection
286        self.CollectionStoragePath = /storage/SoulMadeMainCollection
287        self.CollectionPrivatePath = /private/SoulMadeMainCollection
288        
289        emit ContractInitialized()
290    }
291}