Smart Contract
FindForgeOrder
A.097bafa4e0b48eef.FindForgeOrder
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