Smart Contract
KARATZPJLKNSBT
A.857211bc2b7a1e94.KARATZPJLKNSBT
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3import FungibleToken from 0xf233dcee88fe0abe
4import ViewResolver from 0x1d7e57aa55817448
5
6
7access(all) contract KARATZPJLKNSBT: NonFungibleToken {
8
9 access(all) let CollectionStoragePath: StoragePath
10 access(all) let CollectionPublicPath: PublicPath
11 access(all) let AdminStoragePath: StoragePath
12
13 access(all) var totalSupply: UInt64
14
15 access(all) event ContractInitialized()
16 access(all) event Withdraw(id: UInt64, from: Address?)
17 access(all) event Deposit(id: UInt64, to: Address?)
18 access(all) event Minted(id: UInt64, metadata: Metadata)
19
20 access(all) resource NFT: NonFungibleToken.NFT {
21 access(all) let id: UInt64
22 access(all) let metadata: Metadata
23
24 init(initID: UInt64, initMetadata: Metadata) {
25 self.id = initID
26 self.metadata = initMetadata
27 }
28
29 access(all) view fun getMetadata(): Metadata {
30 return self.metadata
31 }
32
33 /// createEmptyCollection creates an empty Collection
34 /// and returns it to the caller so that they can own NFTs
35 /// @{NonFungibleToken.Collection}
36 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
37 return <-KARATZPJLKNSBT.createEmptyCollection(nftType: Type<@KARATZPJLKNSBT.NFT>())
38 }
39
40 access(all) view fun getViews(): [Type] {
41 return [
42 Type<MetadataViews.Display>(),
43 Type<MetadataViews.Royalties>(),
44 Type<MetadataViews.Editions>(),
45 Type<MetadataViews.ExternalURL>(),
46 Type<MetadataViews.NFTCollectionData>(),
47 Type<MetadataViews.NFTCollectionDisplay>(),
48 Type<MetadataViews.Serial>(),
49 Type<MetadataViews.Traits>(),
50 Type<MetadataViews.EVMBridgedMetadata>()
51 ]
52 }
53
54 access(all) fun resolveView(_ view: Type): AnyStruct? {
55 switch view {
56 case Type<MetadataViews.Display>():
57 return MetadataViews.Display(
58 name: self.metadata.name,
59 description: self.metadata.description,
60 thumbnail: MetadataViews.HTTPFile(
61 url: "https://apps.24karat.io/collections/KARATZPJLKNSBT/nfts/".concat(self.id.toString()).concat("/thumbnail.png")
62 )
63 )
64 case Type<MetadataViews.Editions>():
65 // There is no max number of NFTs that can be minted from this contract
66 // so the max edition field value is set to nil
67 let editionInfo = MetadataViews.Edition(name: "認定証 Edition", number: self.id, max: nil)
68 let editionList: [MetadataViews.Edition] = [editionInfo]
69 return MetadataViews.Editions(
70 editionList
71 )
72 case Type<MetadataViews.Serial>():
73 return MetadataViews.Serial(
74 self.id
75 )
76 case Type<MetadataViews.Royalties>():
77 return MetadataViews.Royalties(
78 [MetadataViews.Royalty(
79 receiver: getAccount(self.metadata.artistAddress).capabilities.get<&{FungibleToken.Receiver}>(MetadataViews.getRoyaltyReceiverPublicPath())!,
80 cut: self.metadata.royalty,
81 description: "The Royalty of 認定証"
82 )]
83 )
84 case Type<MetadataViews.ExternalURL>():
85 return MetadataViews.ExternalURL("https://24karat.io")
86 case Type<MetadataViews.NFTCollectionData>():
87 return MetadataViews.NFTCollectionData(
88 storagePath: KARATZPJLKNSBT.CollectionStoragePath,
89 publicPath: KARATZPJLKNSBT.CollectionPublicPath,
90 publicCollection: Type<&KARATZPJLKNSBT.Collection>(),
91 publicLinkedType: Type<&KARATZPJLKNSBT.Collection>(),
92 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
93 return <-KARATZPJLKNSBT.createEmptyCollection(nftType: Type<@KARATZPJLKNSBT.NFT>())
94 })
95 )
96 case Type<MetadataViews.NFTCollectionDisplay>():
97 let media = MetadataViews.Media(
98 file: MetadataViews.HTTPFile(
99 url: "https://apps.24karat.io/collections/KARATZPJLKNSBT/thumbnail.png"
100 ),
101 mediaType: "image/png"
102 )
103 return MetadataViews.NFTCollectionDisplay(
104 name: "認定証",
105 description: "",
106 externalURL: MetadataViews.ExternalURL("https://24karat.io"),
107 squareImage: media,
108 bannerImage: media,
109 socials: {}
110 )
111 case Type<MetadataViews.Traits>():
112 let excludedTraits: [String] = []
113 let traitsView = MetadataViews.dictToTraits(dict: {}, excludedNames: excludedTraits)
114 return traitsView
115 case Type<MetadataViews.EVMBridgedMetadata>():
116 // Project-defined ERC721 EVM contract stores baseURI, name, and symbol in its own contract storage
117 return MetadataViews.EVMBridgedMetadata(
118 name: "認定証",
119 symbol: "KARATZPJLKNSBT",
120 uri: MetadataViews.URI(
121 baseURI: "",
122 value: "https://apps.24karat.io/collections/KARATZPJLKNSBT/nfts/".concat(self.id.toString()).concat("/metadata")
123 )
124 )
125
126 }
127 return nil
128 }
129 }
130
131 access(all) struct Metadata {
132 access(all) let name: String
133 access(all) let artist: String
134 access(all) let artistAddress: Address
135 access(all) let description: String
136 access(all) let type: String
137 access(all) let serialId: UInt64
138 access(all) let royalty: UFix64
139
140 init(
141 name: String,
142 artist: String,
143 artistAddress: Address,
144 description: String,
145 type: String,
146 serialId: UInt64,
147 royalty: UFix64
148 ) {
149 self.name = name
150 self.artist = artist
151 self.artistAddress = artistAddress
152 self.description = description
153 self.type = type
154 self.serialId = serialId
155 self.royalty = royalty
156 }
157 }
158
159 // Deprecated: Only here for backward compatibility.
160 access(all) resource interface KARATZPJLKNSBTCollectionPublic {}
161
162 access(all) resource Collection: NonFungibleToken.Collection, KARATZPJLKNSBTCollectionPublic {
163 access(all) var ownedNFTs: @{UInt64: {NonFungibleToken.NFT}}
164
165 init () {
166 self.ownedNFTs <- {}
167 }
168
169 /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts
170 access(all) view fun getSupportedNFTTypes(): {Type: Bool} {
171 let supportedTypes: {Type: Bool} = {}
172 supportedTypes[Type<@KARATZPJLKNSBT.NFT>()] = true
173 return supportedTypes
174 }
175
176 /// Returns whether or not the given type is accepted by the collection
177 /// A collection that can accept any type should just return true by default
178 access(all) view fun isSupportedNFTType(type: Type): Bool {
179 return type == Type<@KARATZPJLKNSBT.NFT>()
180 }
181
182 /// withdraw removes an NFT from the collection and moves it to the caller
183 access(NonFungibleToken.Withdraw) fun withdraw(withdrawID: UInt64): @{NonFungibleToken.NFT} {
184 let token <- self.ownedNFTs.remove(key: withdrawID)
185 ?? panic("Could not withdraw an NFT with the provided ID from the collection")
186
187 return <-token
188 }
189
190 access(all) fun deposit(token: @{NonFungibleToken.NFT}) {
191 let id: UInt64 = token.id
192 let oldToken <- self.ownedNFTs[id] <- token
193 emit Deposit(id: id, to: self.owner?.address)
194 destroy oldToken
195 }
196
197 access(all) view fun getIDs(): [UInt64] {
198 return self.ownedNFTs.keys
199 }
200
201 /// Gets the amount of NFTs stored in the collection
202 access(all) view fun getLength(): Int {
203 return self.ownedNFTs.keys.length
204 }
205
206 access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? {
207 return (&self.ownedNFTs[id] as &{NonFungibleToken.NFT}?)
208 }
209
210 /// Borrow the view resolver for the specified NFT ID
211 access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}? {
212 if let nft = &self.ownedNFTs[id] as &{NonFungibleToken.NFT}? {
213 return nft as &{ViewResolver.Resolver}
214 }
215 return nil
216 }
217
218 /// createEmptyCollection creates an empty Collection of the same type
219 /// and returns it to the caller
220 /// @return A an empty collection of the same type
221 access(all) fun createEmptyCollection(): @{NonFungibleToken.Collection} {
222 return <-KARATZPJLKNSBT.createEmptyCollection(nftType: Type<@KARATZPJLKNSBT.NFT>())
223 }
224 }
225
226 access(all) fun createEmptyCollection(nftType: Type): @{NonFungibleToken.Collection} {
227 return <- create Collection()
228 }
229
230 access(all) view fun getContractViews(resourceType: Type?): [Type] {
231 return [
232 Type<MetadataViews.NFTCollectionData>(),
233 Type<MetadataViews.NFTCollectionDisplay>()
234 ]
235 }
236
237 /// Function that resolves a metadata view for this contract.
238 ///
239 /// @param view: The Type of the desired view.
240 /// @return A structure representing the requested view.
241 ///
242 access(all) fun resolveContractView(resourceType: Type?, viewType: Type): AnyStruct? {
243 switch viewType {
244 case Type<MetadataViews.NFTCollectionData>():
245 let collectionData = MetadataViews.NFTCollectionData(
246 storagePath: self.CollectionStoragePath,
247 publicPath: self.CollectionPublicPath,
248 publicCollection: Type<&KARATZPJLKNSBT.Collection>(),
249 publicLinkedType: Type<&KARATZPJLKNSBT.Collection>(),
250 createEmptyCollectionFunction: (fun(): @{NonFungibleToken.Collection} {
251 return <-KARATZPJLKNSBT.createEmptyCollection(nftType: Type<@KARATZPJLKNSBT.NFT>())
252 })
253 )
254 return collectionData
255 case Type<MetadataViews.NFTCollectionDisplay>():
256 let media = MetadataViews.Media(
257 file: MetadataViews.HTTPFile(
258 url: "https://apps.24karat.io/collections/KARATZPJLKNSBT/thumbnail.png"
259 ),
260 mediaType: "image/png"
261 )
262 return MetadataViews.NFTCollectionDisplay(
263 name: "認定証",
264 description: "",
265 externalURL: MetadataViews.ExternalURL("https://24karat.io"),
266 squareImage: media,
267 bannerImage: media,
268 socials: {
269 "twitter": MetadataViews.ExternalURL("https://twitter.com/24karat_io")
270 }
271 )
272 }
273 return nil
274 }
275
276 access(all) resource NFTMinter {
277 access(all) fun mintNFT(recipient: &{NonFungibleToken.Receiver}, metadata: KARATZPJLKNSBT.Metadata) {
278 pre {
279 metadata.royalty <= 0.1: "royalty must lower than 0.1"
280 }
281
282 let tokenId = KARATZPJLKNSBT.totalSupply + (1 as UInt64)
283 var newNFT <- create NFT(initID: tokenId, initMetadata: metadata)
284 recipient.deposit(token: <-newNFT)
285 emit Minted(id: tokenId, metadata: metadata)
286 KARATZPJLKNSBT.totalSupply = tokenId
287 }
288 }
289
290 init() {
291 self.CollectionStoragePath = /storage/KARATZPJLKNSBTCollection
292 self.CollectionPublicPath = /public/KARATZPJLKNSBTCollection
293 self.AdminStoragePath = /storage/KARATZPJLKNSBTAdmin
294
295 self.totalSupply = 0
296
297 let minter: @KARATZPJLKNSBT.NFTMinter <- create NFTMinter()
298 self.account.storage.save(<-minter, to: self.AdminStoragePath)
299
300 emit ContractInitialized()
301 }
302}