Smart Contract

GenerativeNFTV3

A.0b80e42aaab305f0.GenerativeNFTV3

Deployed

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

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import MetadataViews from 0x1d7e57aa55817448
3
4pub contract GenerativeNFTV3: NonFungibleToken {
5
6  pub var totalSupply: UInt64
7  pub var maxSupply: UInt64
8  pub let nftData: {UInt64: {String:String}}
9
10  //------------------------------------------------------------
11  // Events
12  //------------------------------------------------------------
13  pub event ContractInitialized()
14  pub event Withdraw(id: UInt64, from: Address?)
15  pub event Deposit(id: UInt64, to: Address?)
16  pub event Minted(id: UInt64, initMeta: {String: String})
17
18  //------------------------------------------------------------
19  // Storage Path
20  //------------------------------------------------------------
21  pub let CollectionStoragePath: StoragePath
22  pub let CollectionPublicPath: PublicPath
23  pub let MinterStoragePath: StoragePath
24
25  // idToAddress
26  // Maps each item ID to its current owner
27  access(self) let idToAddress: {UInt64: Address}
28
29
30  //------------------------------------------------------------
31  // NFT Resource
32  //------------------------------------------------------------
33  pub resource NFT: NonFungibleToken.INFT, MetadataViews.Resolver {
34    pub let id: UInt64
35    access(self) let metadata: {String: String}
36
37    init(initID: UInt64, initMeta: {String: String}) {
38      self.id = initID
39      self.metadata = initMeta
40    }
41
42    pub fun getMetadata(): {String: String} {
43        return self.metadata
44    }
45
46    pub fun getImage() : String {
47        return self.getMetadata()["image"] ?? ""
48    }
49
50    pub fun getTitle() : String {
51        return self.getMetadata()["title"] ?? ""
52    }
53
54    pub fun getDescription() : String {
55        return self.getMetadata()["description"] ?? ""
56    }
57
58    // receiver: Capability<&AnyResource{FungibleToken.Receiver}>, cut: UFix64, description: String
59    pub fun getRoyalties():MetadataViews.Royalties {
60      return MetadataViews.Royalties([
61
62      ])
63    }
64
65    /// Function that returns all the Metadata Views implemented by a Non Fungible Token
66    ///
67    /// @return An array of Types defining the implemented views. This value will be used by
68    ///         developers to know which parameter to pass to the resolveView() method.
69    ///
70    pub fun getViews(): [Type] {
71        return [
72            Type<MetadataViews.Display>(),
73            Type<MetadataViews.Royalties>(),
74            Type<MetadataViews.ExternalURL>(),
75            Type<MetadataViews.NFTCollectionData>(),
76            Type<MetadataViews.NFTCollectionDisplay>(),
77            Type<MetadataViews.Serial>()
78        ]
79    }
80
81    pub fun resolveView(_ view: Type): AnyStruct? {
82            switch view {
83                case Type<MetadataViews.Display>():
84                    return MetadataViews.Display(
85                        name: self.getTitle(),
86                        description: self.getDescription(),
87                        thumbnail: MetadataViews.HTTPFile(
88                            url: self.getImage()
89                        )
90                  )
91                case Type<MetadataViews.Serial>():
92                    return MetadataViews.Serial(
93                        self.id
94                )
95                case Type<MetadataViews.Royalties>():
96                    return self.getRoyalties()
97                case Type<MetadataViews.ExternalURL>():
98                    return MetadataViews.ExternalURL("https://mikosea.io/")
99                case Type<MetadataViews.NFTCollectionData>():
100                    return MetadataViews.NFTCollectionData(
101                        storagePath: GenerativeNFTV3.CollectionStoragePath,
102                        publicPath: GenerativeNFTV3.CollectionPublicPath,
103                        providerPath: /private/MiKoSeaNFTCollection,
104                        publicCollection: Type<&GenerativeNFTV3.Collection{GenerativeNFTV3.GenerativeNFTCollectionPublic}>(),
105                        publicLinkedType: Type<&GenerativeNFTV3.Collection{GenerativeNFTV3.GenerativeNFTCollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Receiver,MetadataViews.ResolverCollection}>(),
106                        providerLinkedType: Type<&GenerativeNFTV3.Collection{GenerativeNFTV3.GenerativeNFTCollectionPublic,NonFungibleToken.CollectionPublic,NonFungibleToken.Provider,MetadataViews.ResolverCollection}>(),
107                        createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection {
108                            return <-GenerativeNFTV3.createEmptyCollection()
109                        })
110                    )
111                case Type<MetadataViews.NFTCollectionDisplay>():
112                    let bannerImage = MetadataViews.Media(
113                        file: MetadataViews.HTTPFile(
114                            url: "https://storage.googleapis.com/studio-design-asset-files/projects/1pqD36e6Oj/s-300x50_aa59a692-741b-408b-aea3-bcd25d29c6bd.svg"
115                        ),
116                        mediaType: "image/svg+xml"
117                    )
118                    let squareImage = MetadataViews.Media(
119                        file: MetadataViews.HTTPFile(
120                            url: "https://app.mikosea.io/mikosea_1.png"
121                        ),
122                        mediaType: "image/png"
123                    )
124                    return MetadataViews.NFTCollectionDisplay(
125                        name: "あらゆる事業者の思いを載せて神輿を担ぐNFTクラウドファンディングマーケット",
126                        description: "MikoSeaはアーティスト、企業、インフルエンサーといったクリエイターや、あたらしく何かを始めたい人のためのクラウドファンディングサービスです。プロジェクトの発起人は、NFTを販売することで商品を販売するという一方向の取引を超え、プロジェクトの想いに共感した”熱狂的なファン”から資金を調達し、夢の実現へと近づけます。プロジェクト支援者は、プロジェクトを支援する目的でNFTを購入し、共創・協働のプロセスに参加することで、プロジェクトから特別な体験価値やメリットを得ることができます。",
127                        externalURL: MetadataViews.ExternalURL("https://app.mikosea.io/"),
128                        squareImage: squareImage,
129                        bannerImage: bannerImage,
130                        socials: {
131                            "twitter": MetadataViews.ExternalURL("https://twitter.com/MikoSea_io")
132                        }
133                    )
134            }
135            return nil
136        }
137  }
138
139  //------------------------------------------------------------
140  // Collection Public Interface
141  //------------------------------------------------------------
142
143  pub resource interface GenerativeNFTCollectionPublic {
144    pub fun deposit(token: @NonFungibleToken.NFT)
145    pub fun getIDs(): [UInt64]
146    pub fun borrowViewResolver(id: UInt64): &{MetadataViews.Resolver}
147    pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT
148    pub fun borrowItem(id: UInt64): &GenerativeNFTV3.NFT? {
149      post {
150        (result == nil) || (result?.id == id):
151          "Cannot borrow reference: The ID of the returned reference is incorrect"
152      }
153    }
154  }
155
156  //------------------------------------------------------------
157  // Collection Resource
158  //------------------------------------------------------------
159
160  pub resource Collection: GenerativeNFTCollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic, MetadataViews.ResolverCollection {
161
162    pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT}
163
164    init () {
165      self.ownedNFTs <- {}
166    }
167
168    pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT {
169      let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT")
170      emit Withdraw(id: token.id, from: self.owner!.address)
171      return <-token
172    }
173
174    pub fun deposit(token: @NonFungibleToken.NFT) {
175      let token <- token as! @GenerativeNFTV3.NFT
176      let id: UInt64 = token.id
177      let oldToken <- self.ownedNFTs[id] <- token
178      // update owner
179
180      if self.owner?.address != nil {
181        GenerativeNFTV3.idToAddress[id] = self.owner!.address
182        emit Deposit(id: id, to: self.owner!.address)
183      }
184      destroy oldToken
185    }
186
187    pub fun transfer(id: UInt64, recipient: &{NonFungibleToken.CollectionPublic}) {
188      post {
189        self.ownedNFTs[id] == nil: "The specified NFT was not transferred"
190        recipient.borrowNFT(id: id) != nil: "Recipient did not receive the intended NFT"
191      }
192      let nft <- self.withdraw(withdrawID: id)
193      recipient.deposit(token: <- nft)
194    }
195
196    pub fun burn(id: UInt64) {
197      post {
198        self.ownedNFTs[id] == nil: "The specified NFT was not burned"
199      }
200      destroy <- self.withdraw(withdrawID: id)
201    }
202
203    pub fun getIDs(): [UInt64] {
204      return self.ownedNFTs.keys
205    }
206
207    pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT {
208      if self.ownedNFTs[id] != nil {
209        return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)!
210      }
211      panic("NFT not found in collection.")
212    }
213
214    pub fun borrowItem(id: UInt64): &GenerativeNFTV3.NFT? {
215      if self.ownedNFTs[id] != nil {
216        let ref = &self.ownedNFTs[id] as auth &NonFungibleToken.NFT?
217        if ref != nil {
218          return ref! as! &GenerativeNFTV3.NFT
219        }
220      }
221      return nil
222    }
223
224    pub fun borrowViewResolver(id: UInt64): &AnyResource{MetadataViews.Resolver} {
225            let nft = (&self.ownedNFTs[id] as auth &NonFungibleToken.NFT?)!
226            let mikoseaNFT = nft as! &GenerativeNFTV3.NFT
227            return mikoseaNFT as &AnyResource{MetadataViews.Resolver}
228        }
229
230    /// Safe way to borrow a reference to an NFT that does not panic
231    ///
232    /// @param id: The ID of the NFT that want to be borrowed
233    /// @return An optional reference to the desired NFT, will be nil if the passed id does not exist
234    ///
235    pub fun borrowNFTSafe(id: UInt64): &GenerativeNFTV3.NFT? {
236      return self.borrowItem(id: id)
237    }
238
239    destroy() {
240      destroy self.ownedNFTs
241    }
242  }
243
244  // createEmptyCollection
245  pub fun createEmptyCollection(): @NonFungibleToken.Collection {
246      return <- create Collection()
247  }
248
249  //------------------------------------------------------------
250  // NFT Minter
251  //------------------------------------------------------------
252	pub resource NFTMinter {
253
254    pub fun mintNFTs(initMetadata: {String: String}): @GenerativeNFTV3.NFT{
255      pre{
256        GenerativeNFTV3.totalSupply < GenerativeNFTV3.maxSupply : "NFT Sold Out!!!"
257      }
258      GenerativeNFTV3.totalSupply = GenerativeNFTV3.totalSupply  + 1
259      let nftID = GenerativeNFTV3.totalSupply
260      var newNFT <- create GenerativeNFTV3.NFT(
261                initID: nftID, initMeta: initMetadata
262            )
263      GenerativeNFTV3.nftData[nftID] = initMetadata
264      emit Minted(id: nftID, initMeta: initMetadata)
265      return <- newNFT
266    }
267
268    pub fun mintNFT(initMetadata: {String: String}, address: Address): @GenerativeNFTV3.NFT {
269      let newNFT <- self.mintNFTs(initMetadata: initMetadata)
270      GenerativeNFTV3.idToAddress[newNFT.id] = address
271      return <- newNFT
272    }
273
274    pub fun addSuply(num: UInt64) {
275      GenerativeNFTV3.maxSupply = GenerativeNFTV3.maxSupply + num
276    }
277	}
278
279  // getOwner
280  // Gets the current owner of the given item
281  //
282  pub fun getOwner(itemID: UInt64): Address? {
283    if itemID >= 0 && itemID < self.maxSupply {
284      if (itemID < GenerativeNFTV3.totalSupply) {
285        return GenerativeNFTV3.idToAddress[itemID]
286      } else {
287        return nil
288      }
289    }
290    return nil
291  }
292
293  //------------------------------------------------------------
294  // Initializer
295  //------------------------------------------------------------
296	init() {
297    // Set our named paths
298    self.CollectionStoragePath = /storage/GenerativeNFTV3Collections
299    self.CollectionPublicPath = /public/GenerativeNFTV3Collections
300    self.MinterStoragePath = /storage/GenerativeNFTV3Minters
301
302    // Initialize the total supply
303    self.totalSupply = 0
304
305    // Initialize the max supply
306    self.maxSupply = 10000
307
308    // Initalize mapping from ID to address
309    self.idToAddress = {}
310
311    self.nftData = {}
312
313    // Create a Minter resource and save it to storage
314    let minter <- create NFTMinter()
315    self.account.save(<-minter, to: self.MinterStoragePath)
316    emit ContractInitialized()
317	}
318}
319