Smart Contract

FindForgeOrder

A.097bafa4e0b48eef.FindForgeOrder

Deployed

2d ago
Feb 26, 2026, 03:12:51 AM UTC

Dependents

0 imports
1import NonFungibleToken from 0x1d7e57aa55817448
2import FungibleToken from 0xf233dcee88fe0abe
3import MetadataViews from 0x1d7e57aa55817448
4import ViewResolver from 0x1d7e57aa55817448
5import FIND from 0x097bafa4e0b48eef
6import FindUtils from 0x097bafa4e0b48eef
7
8access(all) contract FindForgeOrder {
9
10    access(all) event ContractInitialized()
11    access(all) event Withdraw(id: UInt64, from: Address?)
12    access(all) event Deposit(id: UInt64, to: Address?)
13    access(all) event ForgeOrdered(lease: String, mintType: String, collectionDescription: String, collectionExternalURL: String, collectionSquareImage: String , collectionBannerImage: String, collectionSocials: {String : String})
14    access(all) event ForgeOrderCompleted(lease: String, mintType: String, collectionDescription: String, collectionExternalURL: String, collectionSquareImage: String , collectionBannerImage: String, collectionSocials: {String : String}, contractName: String)
15    access(all) event ForgeOrderCancelled(lease: String, mintType: String, collectionDescription: String, collectionExternalURL: String, collectionSquareImage: String , collectionBannerImage: String, collectionSocials: {String : String}, contractName: String)
16
17    access(all) let QueuedCollectionStoragePath: StoragePath
18    access(all) let QueuedCollectionPublicPath: PublicPath
19    access(all) let CompletedCollectionStoragePath: StoragePath
20    access(all) let CompletedCollectionPublicPath: PublicPath
21
22    access(all) let mintTypes : [String]
23    // contractName : Resource UUID
24    access(all) let contractNames : {String : UInt64}
25
26    access(all) resource interface OrderPublic {
27        access(all) fun getID(): UInt64
28        access(all) fun getLeaseName(): String
29        access(all) fun getMintType(): String
30        access(all) fun getContractName(): String
31        access(all) fun getMinterCut(): UFix64?
32        access(all) fun getCollectionDisplay(): MetadataViews.NFTCollectionDisplay
33    }
34
35    access(all) resource Order: OrderPublic, ViewResolver.Resolver {
36        access(all) let id: UInt64
37        access(all) let leaseName: String 
38        access(all) let mintType: String 
39        access(all) let contractName: String
40        access(all) let minterCut: UFix64?
41        access(all) let collectionDisplay : MetadataViews.NFTCollectionDisplay 
42
43        init(
44            lease: String,
45            mintType: String, 
46            minterCut: UFix64?,
47            collectionDisplay : MetadataViews.NFTCollectionDisplay 
48        ) {
49            pre{
50                collectionDisplay.name.toLower() == lease : "Collection Display Name must equal to lease Name"
51                FindForgeOrder.mintTypes.contains(mintType) : "MintType is not supported at the moment"
52            }
53            self.id = self.uuid
54            self.leaseName=lease
55            self.mintType=mintType
56            self.contractName="Find".concat(FindUtils.firstUpperLetter(self.leaseName)).concat(mintType)
57            self.minterCut=minterCut
58            self.collectionDisplay = collectionDisplay
59        }
60
61        access(all) view fun getViews(): [Type] {
62            return [
63            Type<MetadataViews.Display>()
64            ]
65        }
66
67        access(all) fun resolveView(_ view: Type): AnyStruct? {
68            switch view {
69            case Type<MetadataViews.Display>():
70                return MetadataViews.Display(
71                    name: self.collectionDisplay.name,
72                    description: self.collectionDisplay.description,
73                    thumbnail: self.collectionDisplay.squareImage.file
74                )
75
76                // This can be implemented when borrow contract is implemented 
77                //case Type<MetadataViews.NFTCollectionData>():
78                //	return MetadataViews.NFTCollectionData(
79                //		storagePath: NFGv3.CollectionStoragePath,
80                //		publicPath: NFGv3.CollectionPublicPath,
81                //		providerPath: NFGv3.CollectionPrivatePath,
82                //		publicCollection: Type<&NFGv3.Collection>(),
83                //		publicLinkedType: Type<&NFGv3.Collection>(),
84                //		providerLinkedType: Type<&NFGv3.Collection{NonFungibleToken.Collection,NonFungibleToken.Provider,ViewResolver.ResolverCollection}>(),
85                //		createEmptyCollectionFunction: (fun (): @NonFungibleToken.Collection {
86                //			return <-NFGv3.createEmptyCollection()
87                //		})
88                //	)
89            case Type<MetadataViews.NFTCollectionDisplay>():
90                return self.collectionDisplay
91            }
92            return nil
93        }
94
95        access(all) fun getID(): UInt64 {
96            return self.id
97        }
98        access(all) fun getLeaseName(): String {
99            return self.leaseName
100        }
101        access(all) fun getMintType(): String {
102            return self.mintType
103        }
104        access(all) fun getContractName(): String {
105            return self.contractName
106        }
107        access(all) fun getMinterCut(): UFix64? {
108            return self.minterCut
109        }
110        access(all) fun getCollectionDisplay(): MetadataViews.NFTCollectionDisplay {
111            return self.collectionDisplay
112        }
113    }
114
115    access(all) resource interface OrderCollection {
116        access(all) fun borrow(_ id: UInt64): &FindForgeOrder.Order?
117        access(all) fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver}
118        access(all) view fun getIDs(): [UInt64]
119        access(all) fun deposit(token: @FindForgeOrder.Order)
120    }
121
122    access(all) entitlement Owner
123
124    access(all) resource Collection : OrderCollection, ViewResolver.ResolverCollection {
125        access(all) let orders: @{UInt64: FindForgeOrder.Order}
126
127        init () {
128            self.orders <- {}
129        }
130
131        // withdraw removes an NFT from the collection and moves it to the caller
132        access(Owner) fun withdraw(withdrawID: UInt64): @FindForgeOrder.Order {
133            let token <- self.orders.remove(key: withdrawID) ?? panic("missing Order : ".concat(withdrawID.toString()))
134
135            emit Withdraw(id: token.getID(), from: self.owner?.address)
136
137            return <-token
138        }
139
140        // deposit takes a NFT and adds it to the collections dictionary
141        // and adds the ID to the id array
142        access(all) fun deposit(token: @FindForgeOrder.Order) {
143
144            emit Deposit(id: token.getID(), to: self.owner?.address)
145
146            self.orders[token.getID()] <-! token
147        }
148
149        // getIDs returns an array of the IDs that are in the collection
150        access(all) view fun getIDs(): [UInt64] {
151            return self.orders.keys
152        }
153
154        // borrowNFT gets a reference to an NFT in the collection
155        // so that the caller can read its metadata and call its methods
156        access(all) fun borrow(_ id: UInt64): &FindForgeOrder.Order? {
157            return &self.orders[id]
158        }
159
160        access(all) view fun borrowViewResolver(id: UInt64): &{ViewResolver.Resolver} {
161            let nft = &self.orders[id] as &{ViewResolver.Resolver}?
162            return nft!
163        }
164
165    }
166
167    access(account) fun orderForge(leaseName: String, mintType: String, minterCut: UFix64?, collectionDisplay: MetadataViews.NFTCollectionDisplay) {
168        let order <- create FindForgeOrder.Order(lease: leaseName, mintType: mintType, minterCut: minterCut, collectionDisplay: collectionDisplay)
169        let c = collectionDisplay
170        let s : {String : String} = {}
171        for social in c.socials.keys {
172            s[social] = c.socials[social]!.url
173        } 
174        emit ForgeOrdered(lease: leaseName, mintType: mintType, collectionDescription: c.description, collectionExternalURL: c.externalURL.url, collectionSquareImage: c.squareImage.file.uri() , collectionBannerImage: c.bannerImage.file.uri(), collectionSocials: s)
175        FindForgeOrder.contractNames[order.contractName] = order.id
176        let col = FindForgeOrder.account.storage.borrow<auth(Owner) &FindForgeOrder.Collection>(from: FindForgeOrder.QueuedCollectionStoragePath)!
177        col.deposit(token: <- order)
178    }
179
180    access(account) fun cancelForgeOrder(leaseName: String, mintType: String) {
181        let contractName = "Find".concat(FindUtils.firstUpperLetter(leaseName)).concat(mintType)
182        let id = FindForgeOrder.contractNames[contractName] ?? panic("Forge is not ordered. identifier : ".concat(contractName))
183        let queuedCol = FindForgeOrder.account.storage.borrow<auth(Owner) &FindForgeOrder.Collection>(from: FindForgeOrder.QueuedCollectionStoragePath)!
184        let order <- queuedCol.withdraw(withdrawID: id) 
185        let c = order.getCollectionDisplay()
186        let s : {String : String} = {}
187        for social in c.socials.keys {
188            s[social] = c.socials[social]!.url
189        } 
190        emit ForgeOrderCancelled(lease: order.getLeaseName(), mintType: order.getMintType(), collectionDescription: c.description, collectionExternalURL: c.externalURL.url, collectionSquareImage: c.squareImage.file.uri() , collectionBannerImage: c.bannerImage.file.uri(), collectionSocials: s, contractName : contractName)
191        destroy order
192    }
193
194    access(account) fun fulfillForgeOrder(_ contractName: String, forgeType: Type) : &FindForgeOrder.Order {
195        let id = FindForgeOrder.contractNames[contractName] ?? panic("Forge is not ordered. identifier : ".concat(contractName))
196        let queuedCol = FindForgeOrder.account.storage.borrow<auth(Owner) &FindForgeOrder.Collection>(from: FindForgeOrder.QueuedCollectionStoragePath)!
197        let order <- queuedCol.withdraw(withdrawID: id) 
198        let c = order.getCollectionDisplay()
199        let s : {String : String} = {}
200        for social in c.socials.keys {
201            s[social] = c.socials[social]!.url
202        } 
203        emit ForgeOrderCompleted(lease: order.getLeaseName(), mintType: order.getMintType(), collectionDescription: c.description, collectionExternalURL: c.externalURL.url, collectionSquareImage: c.squareImage.file.uri() , collectionBannerImage: c.bannerImage.file.uri(), collectionSocials: s, contractName : contractName)
204
205        let completedCol = FindForgeOrder.account.storage.borrow<auth(Owner) &FindForgeOrder.Collection>(from: FindForgeOrder.CompletedCollectionStoragePath)!
206        completedCol.deposit(token: <- order)
207        let ref = completedCol.borrow(id)
208        return ref!
209    }
210
211    access(account) fun addMintType(_ mintType: String) {
212        pre{
213            !self.mintTypes.contains(mintType) : "Mint type is already there : ".concat(mintType)
214        }
215        self.mintTypes.append(mintType)
216    }
217
218    access(account) fun removeMintType(_ mintType: String) {
219        pre{
220            self.mintTypes.contains(mintType) : "Mint type not there : ".concat(mintType)
221        }
222        self.mintTypes.remove(at: self.mintTypes.firstIndex(of: mintType)!)
223    }
224
225
226    // public function that anyone can call to create a new empty collection
227    access(all) fun createEmptyCollection(): @{FindForgeOrder.OrderCollection} {
228        return <- create Collection()
229    }
230
231    init() {
232        // Initialize the total supply
233        self.mintTypes = []
234        self.contractNames = {}
235
236        // Set the named paths
237        self.QueuedCollectionStoragePath = /storage/queuedFindForgeOrder
238        self.QueuedCollectionPublicPath = /public/queuedFindForgeOrder
239        self.CompletedCollectionStoragePath = /storage/completedFindForgeOrder
240        self.CompletedCollectionPublicPath = /public/completedFindForgeOrder
241
242        // Create a Collection resource and save it to storage
243        let queuedCollection <- create Collection()
244        self.account.storage.save(<-queuedCollection, to: self.QueuedCollectionStoragePath)
245
246        // create a public capability for the collection
247        let cap = self.account.capabilities.storage.issue<&{FindForgeOrder.OrderCollection}>(self.QueuedCollectionStoragePath)
248        self.account.capabilities.publish(cap, at: self.QueuedCollectionPublicPath)
249
250        // Create a Collection resource and save it to storage
251        let completedCollection <- create Collection()
252        self.account.storage.save(<-completedCollection, to: self.CompletedCollectionStoragePath)
253
254        // create a public capability for the collection
255        let cap2 = self.account.capabilities.storage.issue<&{FindForgeOrder.OrderCollection}>(self.CompletedCollectionStoragePath)
256        self.account.capabilities.publish(cap2, at: self.CompletedCollectionPublicPath)
257    }
258}
259
260
261