Smart Contract
DisruptArt
A.cd946ef9b13804c6.DisruptArt
1// DisruptArt NFT Marketplace
2// NFT smart contract
3// NFT Marketplace : www.disrupt.art
4// Owner : Disrupt Art, INC.
5// Developer : www.blaze.ws
6// Version : 0.0.8
7// Blockchain : Flow www.onFlow.org
8
9import NonFungibleToken from 0x1d7e57aa55817448
10import MetadataViews from 0x1d7e57aa55817448
11import FungibleToken from 0xf233dcee88fe0abe
12
13pub contract DisruptArt: NonFungibleToken {
14
15 // Total number of token supply
16 pub var totalSupply: UInt64
17
18 // NFT No of Editions(Multiple copies) limit
19 pub var editionLimit: UInt
20
21 /// Path where the `Collection` is stored
22 pub let disruptArtStoragePath: StoragePath
23
24 /// Path where the public capability for the `Collection` is
25 pub let disruptArtPublicPath: PublicPath
26
27 /// NFT Minter
28 pub let disruptArtMinterPath: StoragePath
29
30 // Contract Events
31 pub event ContractInitialized()
32 pub event Withdraw(id: UInt64, from: Address?)
33 pub event Deposit(id: UInt64, to: Address?)
34 pub event Mint(id: UInt64, content:String, owner: Address?, name:String)
35 pub event GroupMint(id: UInt64, content:String, owner: Address?, name:String, tokenGroupId: UInt64 )
36
37
38 // TOKEN RESOURCE
39 pub resource NFT: NonFungibleToken.INFT, MetadataViews.Resolver {
40
41 // Unique identifier for NFT Token
42 pub let id :UInt64
43
44 // Meta data to store token data (use dict for data)
45 access(self) let metaData: {String : String}
46
47 pub fun getMetadata():{String: String} {
48 return self.metaData
49 }
50
51 // NFT token name
52 pub let name:String
53
54 // NFT token creator address
55 pub let creator:Address?
56
57 // In current store static dict in meta data
58 init( id : UInt64, content : String, name:String, description:String , creator:Address?,previewContent:String,mimeType:String) {
59 self.id = id
60 self.metaData = {"content" : content, "description": description, "previewContent":previewContent, "mimeType":mimeType }
61 self.creator = creator
62 self.name = name
63 }
64
65 access(self) fun getFlowRoyaltyReceiverPublicPath(): PublicPath {
66 return /public/flowTokenReceiver
67 }
68
69
70 // fn to get the royality details
71 access(self) fun genRoyalities():[MetadataViews.Royalty] {
72
73 var royalties:[MetadataViews.Royalty] = []
74
75 // Creator Royalty
76 royalties.append(
77 MetadataViews.Royalty(
78 receiver: getAccount(self.creator!).getCapability<&FungibleToken.Vault{FungibleToken.Receiver}>(self.getFlowRoyaltyReceiverPublicPath()),
79 cut: UFix64(0.1),
80 description: "Creator Royalty"
81 )
82 )
83
84 return royalties
85 }
86
87 pub fun getViews(): [Type] {
88 return [
89 Type<MetadataViews.Display>(),
90 Type<MetadataViews.Royalties>(),
91 Type<MetadataViews.ExternalURL>(),
92 Type<MetadataViews.NFTCollectionData>(),
93 Type<MetadataViews.NFTCollectionDisplay>(),
94 Type<MetadataViews.Serial>(),
95 Type<MetadataViews.Traits>()
96 ]
97 }
98
99 pub fun resolveView(_ view: Type): AnyStruct? {
100 switch view {
101 case Type<MetadataViews.Display>():
102 return MetadataViews.Display(
103 name: self.name,
104 description: self.metaData["description"]!,
105 thumbnail: MetadataViews.HTTPFile(
106 url: self.metaData["previewContent"]!
107 )
108 )
109 case Type<MetadataViews.Serial>():
110 return MetadataViews.Serial(
111 self.id
112 )
113 case Type<MetadataViews.Royalties>():
114 return MetadataViews.Royalties(
115 self.genRoyalities()
116 )
117 case Type<MetadataViews.ExternalURL>():
118 return MetadataViews.ExternalURL("https://disrupt.art")
119 case Type<MetadataViews.NFTCollectionData>():
120 return MetadataViews.NFTCollectionData(
121 storagePath: DisruptArt.disruptArtStoragePath,
122 publicPath: DisruptArt.disruptArtPublicPath,
123 providerPath: /private/DisruptArtNFTCollection,
124 publicCollection: Type<&DisruptArt.Collection{DisruptArt.DisruptArtCollectionPublic}>(),
125 publicLinkedType: Type<&DisruptArt.Collection{DisruptArt.DisruptArtCollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Receiver,MetadataViews.ResolverCollection}>(),
126 providerLinkedType: Type<&DisruptArt.Collection{DisruptArt.DisruptArtCollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Provider,MetadataViews.ResolverCollection}>(),
127 createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection {
128 return <-DisruptArt.createEmptyCollection()
129 })
130 )
131 case Type<MetadataViews.NFTCollectionDisplay>():
132 let media = MetadataViews.Media(
133 file: MetadataViews.HTTPFile(
134 url: "https://disrupt.art/nft/assets/images/logoicon.png"
135 ),
136 mediaType: "image/png"
137 )
138 return MetadataViews.NFTCollectionDisplay(
139 name: "DisruptArt Collection",
140 description: "Discover amazing NFT collections from various disruptor creators. Disrupt.art Marketplace's featured and spotlight NFTs",
141 externalURL: MetadataViews.ExternalURL("https://disrupt.art"),
142 squareImage: media,
143 bannerImage: media,
144 socials: {
145 "twitter": MetadataViews.ExternalURL("https://twitter.com/DisruptArt"),
146 "instagram": MetadataViews.ExternalURL("https://www.instagram.com/disrupt.art/"),
147 "discord" : MetadataViews.ExternalURL("https://discord.io/disruptart")
148 }
149 )
150 case Type<MetadataViews.Traits>():
151 return []
152 }
153 return nil
154 }
155
156 }
157
158 // Account's public collection
159 pub resource interface DisruptArtCollectionPublic {
160
161 pub fun deposit(token:@NonFungibleToken.NFT)
162
163 pub fun getIDs(): [UInt64]
164
165 pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT
166
167 pub fun borrowDisruptArt(id: UInt64): &DisruptArt.NFT? {
168 // If the result isn't nil, the id of the returned reference
169 // should be the same as the argument to the function
170 post {
171 (result == nil) || (result?.id == id):
172 "Cannot borrow CaaPass reference: The ID of the returned reference is incorrect"
173 }
174 }
175
176 }
177
178 // NFT Collection resource
179 pub resource Collection : DisruptArtCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection {
180
181 // Contains caller's list of NFTs
182 pub var ownedNFTs: @{UInt64 : NonFungibleToken.NFT}
183
184 init() {
185 self.ownedNFTs <- {}
186 }
187
188 pub fun deposit(token: @NonFungibleToken.NFT) {
189
190 let token <- token as! @DisruptArt.NFT
191
192 let id: UInt64 = token.id
193
194 // add the new token to the dictionary which removes the old one
195 let oldToken <- self.ownedNFTs[id] <- token
196
197 emit Deposit(id: id, to: self.owner?.address)
198
199 destroy oldToken
200 }
201
202 // function returns token keys of owner
203 pub fun getIDs():[UInt64] {
204 return self.ownedNFTs.keys
205 }
206
207 // function returns token data of token id
208 pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
209 return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)!
210 }
211
212 // Gets a reference to an NFT in the collection as a DisruptArt
213 pub fun borrowDisruptArt(id: UInt64): &DisruptArt.NFT? {
214 if self.ownedNFTs[id] != nil {
215 let ref = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
216 return ref as! &DisruptArt.NFT
217 } else {
218 return nil
219 }
220 }
221
222 // function to check wether the owner have token or not
223 pub fun tokenExists(id:UInt64) : Bool {
224 return self.ownedNFTs[id] != nil
225 }
226
227 pub fun withdraw(withdrawID:UInt64) : @NonFungibleToken.NFT {
228
229 let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
230
231 emit Withdraw(id: token.id, from: self.owner?.address)
232
233 return <-token
234 }
235
236 pub fun borrowViewResolver(id: UInt64): &AnyResource{MetadataViews.Resolver} {
237 let nft = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
238 let DisruptArtNFT = nft as! &DisruptArt.NFT
239 return DisruptArtNFT as &AnyResource{MetadataViews.Resolver}
240 }
241
242 destroy(){
243 destroy self.ownedNFTs
244 }
245
246 }
247
248 // NFT MINTER
249 pub resource NFTMinter {
250
251 // Function to mint group of tokens
252 pub fun GroupMint(recipient: &{DisruptArtCollectionPublic},content:String, description:String, name:String, edition:UInt, tokenGroupId:UInt64, previewContent:String, mimeType:String) {
253 pre {
254 DisruptArt.editionLimit >= edition : "Edition count exceeds the limit"
255 edition >=2 : "Edition count should be greater than or equal to 2"
256 }
257 var count = 0 as UInt
258
259 while count < edition {
260 let token <- create NFT(id: DisruptArt.totalSupply, content:content, name:name, description:description, creator: recipient.owner?.address,previewContent:previewContent,mimeType:mimeType)
261 emit GroupMint(id:DisruptArt.totalSupply,content:content,owner: recipient.owner?.address, name:name, tokenGroupId:tokenGroupId)
262 recipient.deposit(token: <- token)
263 DisruptArt.totalSupply = DisruptArt.totalSupply + 1 as UInt64
264 count = count + 1
265 }
266 }
267
268 pub fun Mint(recipient: &{DisruptArtCollectionPublic},content:String, name:String, description:String,previewContent:String,mimeType:String ) {
269 let token <- create NFT(id: DisruptArt.totalSupply, content:content, name:name, description:description, creator: recipient.owner?.address,previewContent:previewContent, mimeType:mimeType)
270 emit Mint(id:DisruptArt.totalSupply,content:content,owner: recipient.owner?.address, name:name)
271 recipient.deposit(token: <- token)
272 DisruptArt.totalSupply = DisruptArt.totalSupply + 1 as UInt64
273 }
274 }
275
276 // This is used to create the empty collection. without this address cannot access our NFT token
277 pub fun createEmptyCollection(): @NonFungibleToken.Collection {
278 return <- create DisruptArt.Collection()
279 }
280 // Admin can change the maximum supported group minting count limit for the platform. Currently it is 50
281 pub resource Admin {
282 pub fun changeLimit(limit:UInt) {
283 DisruptArt.editionLimit = limit
284 }
285 }
286
287 // Contract init
288 init() {
289
290 // total supply is zero at the time of contract deployment
291 self.totalSupply = 0
292
293 self.editionLimit = 10000
294
295 self.disruptArtStoragePath = /storage/DisruptArtNFTCollection
296
297 self.disruptArtPublicPath = /public/DisruptArtNFTPublicCollection
298
299 self.disruptArtMinterPath = /storage/DisruptArtNFTMinter
300
301 self.account.save(<-self.createEmptyCollection(), to: self.disruptArtStoragePath)
302
303 self.account.link<&{DisruptArtCollectionPublic}>(self.disruptArtPublicPath, target:self.disruptArtStoragePath)
304
305 self.account.save(<-create self.Admin(), to: /storage/DirsuptArtAdmin)
306
307 // store a minter resource in account storage
308 self.account.save(<-create NFTMinter(), to: self.disruptArtMinterPath)
309
310 emit ContractInitialized()
311
312 }
313
314}
315
316