Smart Contract
SoulMadeMain
A.9a57dfe5c8ce609c.SoulMadeMain
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}