Smart Contract
FindLeaseMarketDirectOfferSoft
A.097bafa4e0b48eef.FindLeaseMarketDirectOfferSoft
1import FungibleToken from 0xf233dcee88fe0abe
2import FlowToken from 0x1654653399040a61
3import NonFungibleToken from 0x1d7e57aa55817448
4import MetadataViews from 0x1d7e57aa55817448
5import FindViews from 0x097bafa4e0b48eef
6import Clock from 0x097bafa4e0b48eef
7import Debug from 0x097bafa4e0b48eef
8import FIND from 0x097bafa4e0b48eef
9import FindMarket from 0x097bafa4e0b48eef
10import FindLeaseMarket from 0x097bafa4e0b48eef
11
12access(all) contract FindLeaseMarketDirectOfferSoft {
13
14 access(all) entitlement Seller
15
16 access(all) event DirectOffer(tenant: String, id: UInt64, saleID: UInt64, seller: Address, sellerName: String?, amount: UFix64, status: String, vaultType:String, leaseInfo: FindLeaseMarket.LeaseInfo?, buyer:Address?, buyerName:String?, buyerAvatar:String?, endsAt: UFix64?, previousBuyer:Address?, previousBuyerName:String?)
17
18 access(all) resource SaleItem : FindLeaseMarket.SaleItem {
19
20 access(contract) var pointer: {FindLeaseMarket.LeasePointer}
21 access(contract) var offerCallback: Capability<&MarketBidCollection>
22
23 access(contract) var directOfferAccepted:Bool
24 access(contract) var validUntil: UFix64?
25 access(contract) var saleItemExtraField: {String : AnyStruct}
26
27 init(pointer: FindLeaseMarket.ReadLeasePointer, callback: Capability<&MarketBidCollection>, validUntil: UFix64?, saleItemExtraField: {String : AnyStruct}) {
28 self.offerCallback=callback
29 self.directOfferAccepted=false
30 self.validUntil=validUntil
31 self.saleItemExtraField=saleItemExtraField
32 self.pointer=pointer
33 }
34
35 access(all) fun getName() : String {
36 return self.pointer.name
37 }
38
39 access(contract) fun acceptDirectOffer() {
40 self.directOfferAccepted=true
41 }
42
43 //Here we do not get a vault back, it is sent in to the method itself
44 access(contract) fun acceptNonEscrowedBid() {
45 pre{
46 self.offerCallback.check() : "Bidder unlinked the bid collection capability."
47 self.pointer != nil : "Please accept offer"
48 }
49 self.offerCallback.borrow()!.acceptNonEscrowed(self.getLeaseName())
50 let pointer = self.pointer as! FindLeaseMarket.AuthLeasePointer
51 pointer.move(to: self.offerCallback.address)
52 }
53
54 access(all) fun getFtType() : Type {
55 pre{
56 self.offerCallback.check() : "Bidder unlinked the bid collection capability."
57 }
58 return self.offerCallback.borrow()!.getVaultType(self.getLeaseName())
59 }
60
61 access(all) fun getLeaseName() : String {
62 return self.pointer.name
63 }
64
65 access(all) fun getItemType() : Type {
66 return Type<@FIND.Lease>()
67 }
68
69 access(all) fun getAuction(): FindLeaseMarket.AuctionItem? {
70 return nil
71 }
72
73 access(all) fun getId() : UInt64 {
74 return self.pointer.getUUID()
75 }
76
77 access(all) fun getSaleType() : String {
78 if self.directOfferAccepted {
79 return "active_finished"
80 }
81 return "active_ongoing"
82 }
83
84 access(all) fun getListingType() : Type {
85 return Type<@SaleItem>()
86 }
87
88 access(all) fun getListingTypeIdentifier() : String {
89 return Type<@SaleItem>().identifier
90 }
91
92 access(all) fun getBalance() : UFix64 {
93 pre{
94 self.offerCallback.check() : "Bidder unlinked the bid collection capability."
95 }
96 return self.offerCallback.borrow()!.getBalance(self.getLeaseName())
97 }
98
99 access(all) fun getSeller() : Address {
100 return self.pointer.owner()
101 }
102
103 access(all) fun getSellerName() : String? {
104 let address = self.pointer.owner()
105 return FIND.reverseLookup(address)
106 }
107
108 access(all) fun getBuyer() : Address? {
109 return self.offerCallback.address
110 }
111
112 access(all) fun getBuyerName() : String? {
113 if let name = FIND.reverseLookup(self.offerCallback.address) {
114 return name
115 }
116 return nil
117 }
118
119 access(all) fun toLeaseInfo() : FindLeaseMarket.LeaseInfo{
120 return FindLeaseMarket.LeaseInfo(self.pointer)
121 }
122
123 access(contract) fun setValidUntil(_ time: UFix64?) {
124 self.validUntil=time
125 }
126
127 access(all) fun getValidUntil() : UFix64? {
128 return self.validUntil
129 }
130
131 access(contract) fun setPointer(_ pointer: FindLeaseMarket.AuthLeasePointer) {
132 self.pointer=pointer
133 }
134
135 access(contract) fun setCallback(_ callback: Capability<&MarketBidCollection>) {
136 self.offerCallback=callback
137 }
138
139 access(all) fun checkPointer() : Bool {
140 return self.pointer.valid()
141 }
142
143 access(all) fun getSaleItemExtraField() : {String : AnyStruct} {
144 return self.saleItemExtraField
145 }
146
147 access(contract) fun setSaleItemExtraField(_ field: {String : AnyStruct}) {
148 self.saleItemExtraField = field
149 }
150
151 }
152
153 access(all) resource interface SaleItemCollectionPublic {
154 //fetch all the tokens in the collection
155 access(all) fun getNameSales(): [String]
156 access(all) fun containsNameSale(_ name: String): Bool
157 access(contract) fun cancelBid(_ name: String)
158 access(contract) fun registerIncreasedBid(_ name: String)
159
160 //place a bid on a token
161 access(contract) fun registerBid(name: String, callback: Capability<&MarketBidCollection>, validUntil: UFix64?, saleItemExtraField: {String : AnyStruct})
162
163 access(contract) fun isAcceptedDirectOffer(_ name:String) : Bool
164
165 access(contract) fun fulfillDirectOfferNonEscrowed(name:String, vault: @{FungibleToken.Vault})
166
167 }
168
169 access(all) resource SaleItemCollection: SaleItemCollectionPublic, FindLeaseMarket.SaleItemCollectionPublic {
170 //is this the best approach now or just put the NFT inside the saleItem?
171 access(contract) var items: @{String: SaleItem}
172
173 access(contract) let tenantCapability: Capability<&FindMarket.Tenant>
174
175 init (_ tenantCapability: Capability<&FindMarket.Tenant>) {
176 self.items <- {}
177 self.tenantCapability=tenantCapability
178 }
179
180 access(self) fun getTenant() : &FindMarket.Tenant {
181 pre{
182 self.tenantCapability.check() : "Tenant client is not linked anymore"
183 }
184 return self.tenantCapability.borrow()!
185 }
186
187 access(contract) fun isAcceptedDirectOffer(_ name:String) : Bool{
188 pre {
189 self.items.containsKey(name) : "Invalid name sale=".concat(name)
190 }
191 let saleItem = self.borrow(name)
192
193 return saleItem.directOfferAccepted
194 }
195
196 access(all) fun getListingType() : Type {
197 return Type<@SaleItem>()
198 }
199
200 //this is called when a buyer cancel a direct offer
201 access(contract) fun cancelBid(_ name: String) {
202 pre {
203 self.items.containsKey(name) : "Invalid name sale=".concat(name)
204 }
205 let saleItem=self.borrow(name)
206
207 let actionResult=self.getTenant().allowedAction(listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType(), action: FindMarket.MarketAction(listing:false, name:"cancel bid in direct offer soft"), seller: nil, buyer: nil)
208
209 if !actionResult.allowed {
210 panic(actionResult.message)
211 }
212
213 self.emitEvent(saleItem: saleItem, status: "cancel", previousBuyer: nil)
214 destroy <- self.items.remove(key: name)
215 }
216
217
218 access(self) fun emitEvent(saleItem: &SaleItem, status: String, previousBuyer:Address?) {
219 let owner=saleItem.getSeller()
220 let ftType=saleItem.getFtType()
221 let balance=saleItem.getBalance()
222 let buyer=saleItem.getBuyer()!
223 let buyerName=FIND.reverseLookup(buyer)
224 let profile = FIND.lookup(buyer.toString())
225
226 var leaseInfo:FindLeaseMarket.LeaseInfo?=nil
227 if saleItem.checkPointer() {
228 leaseInfo=saleItem.toLeaseInfo()
229 }
230
231 var previousBuyerName : String?=nil
232 if let pb= previousBuyer {
233 previousBuyerName = FIND.reverseLookup(pb)
234 }
235
236 emit DirectOffer(tenant:self.getTenant().name, id: saleItem.getId(), saleID: saleItem.uuid, seller:owner, sellerName: FIND.reverseLookup(owner), amount: balance, status:status, vaultType: ftType.identifier, leaseInfo:leaseInfo, buyer: buyer, buyerName: buyerName, buyerAvatar: profile?.getAvatar(), endsAt: saleItem.validUntil, previousBuyer:previousBuyer, previousBuyerName:previousBuyerName)
237 }
238
239
240 //The only thing we do here is basically register an event
241 access(contract) fun registerIncreasedBid(_ name: String) {
242 pre {
243 self.items.containsKey(name) : "Invalid name sale=".concat(name)
244 }
245 let saleItem=self.borrowAuth(name)
246
247 let actionResult=self.getTenant().allowedAction(listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType(), action: FindMarket.MarketAction(listing:true, name:"increase bid in direct offer soft"), seller: self.owner!.address, buyer: saleItem.offerCallback.address)
248
249 if !actionResult.allowed {
250 panic(actionResult.message)
251 }
252
253 self.emitEvent(saleItem: saleItem, status: "active_offered", previousBuyer:nil)
254 }
255
256
257 //This is a function that buyer will call (via his bid collection) to register the bicCallback with the seller
258 access(contract) fun registerBid(name: String, callback: Capability<&MarketBidCollection>, validUntil: UFix64?, saleItemExtraField: {String : AnyStruct}) {
259
260 //If there are no bids from anybody else before we need to make the item
261 if !self.items.containsKey(name) {
262 let item = FindLeaseMarket.ReadLeasePointer(name: name)
263 let saleItem <- create SaleItem(pointer: item, callback: callback, validUntil: validUntil, saleItemExtraField: saleItemExtraField)
264 let actionResult=self.getTenant().allowedAction(listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType(), action: FindMarket.MarketAction(listing:true, name:"bid in direct offer soft"), seller: self.owner!.address, buyer: callback.address)
265
266 if !actionResult.allowed {
267 panic(actionResult.message)
268 }
269 self.items[name] <-! saleItem
270 let saleItemRef=self.borrow(name)
271 self.emitEvent(saleItem: saleItemRef, status: "active_offered", previousBuyer:nil)
272 return
273 }
274
275
276 let saleItem=self.borrowAuth(name)
277 if self.borrow(name).getBuyer()! == callback.address {
278 panic("You already have the latest bid on this item, use the incraseBid transaction")
279 }
280
281 let actionResult=self.getTenant().allowedAction(listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType(), action: FindMarket.MarketAction(listing:true, name:"bid in direct offer soft"), seller: self.owner!.address, buyer: callback.address)
282
283 if !actionResult.allowed {
284 panic(actionResult.message)
285 }
286
287 let balance=callback.borrow()?.getBalance(name) ?? panic("Bidder unlinked the bid collection capability. bidder address : ".concat(callback.address.toString()))
288
289 let currentBalance=saleItem.getBalance()
290 Debug.log("currentBalance=".concat(currentBalance.toString()).concat(" new bid is at=").concat(balance.toString()))
291 if currentBalance >= balance {
292 panic("There is already a higher bid on this item. Current bid : ".concat(currentBalance.toString()).concat(" . New bid is at : ").concat(balance.toString()))
293 }
294 let previousBuyer=saleItem.offerCallback.address
295 //somebody else has the highest item so we cancel it
296 saleItem.offerCallback.borrow()!.cancelBidFromSaleItem(name)
297 saleItem.setValidUntil(validUntil)
298 saleItem.setSaleItemExtraField(saleItemExtraField)
299 saleItem.setCallback(callback)
300
301 self.emitEvent(saleItem: saleItem, status: "active_offered", previousBuyer:previousBuyer)
302
303 }
304
305
306 //cancel will reject a direct offer
307 access(Seller) fun cancel(_ name: String) {
308 pre {
309 self.items.containsKey(name) : "Invalid name sale=".concat(name)
310 }
311
312 let saleItem=self.borrowAuth(name)
313
314 let actionResult=self.getTenant().allowedAction(listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType(), action: FindMarket.MarketAction(listing:false, name:"reject offer in direct offer soft"), seller: nil, buyer: nil)
315
316 if !actionResult.allowed {
317 panic(actionResult.message)
318 }
319
320 self.emitEvent(saleItem: saleItem, status: "cancel_rejected", previousBuyer:nil)
321 if !saleItem.offerCallback.check() {
322 panic("Seller unlinked the SaleItem collection capability. seller address : ".concat(saleItem.offerCallback.address.toString()))
323 }
324 saleItem.offerCallback.borrow()!.cancelBidFromSaleItem(name)
325 destroy <- self.items.remove(key: name)
326 }
327
328 access(Seller) fun acceptOffer(_ pointer: FindLeaseMarket.AuthLeasePointer) {
329 pre {
330 self.items.containsKey(pointer.name) : "Invalid name sale=".concat(pointer.name)
331 }
332
333 let saleItem = self.borrowAuth(pointer.name)
334
335 if saleItem.validUntil != nil && saleItem.validUntil! < Clock.time() {
336 panic("This direct offer is already expired")
337 }
338
339 let actionResult=self.getTenant().allowedAction(listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType(), action: FindMarket.MarketAction(listing:false, name:"accept offer in direct offer soft"), seller: self.owner!.address, buyer: saleItem.offerCallback.address)
340
341 if !actionResult.allowed {
342 panic(actionResult.message)
343 }
344
345 //Set the auth pointer in the saleItem so that it now can be fulfilled
346 saleItem.setPointer(pointer)
347 saleItem.acceptDirectOffer()
348
349 self.emitEvent(saleItem: saleItem, status: "active_accepted", previousBuyer:nil)
350 }
351
352 /// this is called from a bid when a seller accepts
353 access(contract) fun fulfillDirectOfferNonEscrowed(name:String, vault: @{FungibleToken.Vault}) {
354 pre {
355 self.items.containsKey(name) : "Invalid name sale=".concat(name)
356 }
357
358 let saleItem = self.borrowAuth(name)
359 if !saleItem.directOfferAccepted {
360 panic("cannot fulfill a direct offer that is not accepted yet")
361 }
362
363 if vault.getType() != saleItem.getFtType() {
364 panic("The FT vault sent in to fulfill does not match the required type. Required Type : ".concat(saleItem.getFtType().identifier).concat(" . Sent-in vault type : ".concat(vault.getType().identifier)))
365 }
366 let actionResult=self.getTenant().allowedAction(listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType(), action: FindMarket.MarketAction(listing:false, name:"fulfill directOffer"), seller: self.owner!.address, buyer: saleItem.offerCallback.address)
367
368 if !actionResult.allowed {
369 panic(actionResult.message)
370 }
371
372 let cuts= self.getTenant().getCuts(name: actionResult.name, listingType: self.getListingType(), nftType: saleItem.getItemType(), ftType: saleItem.getFtType())
373
374 self.emitEvent(saleItem: saleItem, status: "sold", previousBuyer:nil)
375 let leaseInfo=saleItem.toLeaseInfo()
376 saleItem.acceptNonEscrowedBid()
377 FindLeaseMarket.pay(tenant: self.getTenant().name, leaseName:name, saleItem: saleItem, vault: <- vault, leaseInfo: leaseInfo, cuts:cuts)
378
379 destroy <- self.items.remove(key: name)
380 }
381
382 access(all) fun getNameSales(): [String] {
383 return self.items.keys
384 }
385
386 access(all) fun containsNameSale(_ name: String): Bool {
387 return self.items.containsKey(name)
388 }
389
390 access(all) fun borrow(_ name: String): &SaleItem {
391 pre{
392 self.items.containsKey(name) : "This name sale does not exist.".concat(name)
393 }
394 return (&self.items[name])!
395 }
396
397 access(Seller) fun borrowAuth(_ name: String): auth(Seller) &SaleItem {
398 pre{
399 self.items.containsKey(name) : "This name sale does not exist.".concat(name)
400 }
401 return (&self.items[name])!
402 }
403
404 access(all) fun borrowSaleItem(_ name: String) : &{FindLeaseMarket.SaleItem} {
405 pre{
406 self.items.containsKey(name) : "This name sale does not exist.".concat(name)
407 }
408 return (&self.items[name])!
409 }
410 }
411
412 /*
413 ==========================================================================
414 Bids are a collection/resource for storing the bids bidder made on leases
415 ==========================================================================
416 */
417
418 access(all) resource Bid : FindLeaseMarket.Bid {
419 access(contract) let from: Capability<&SaleItemCollection>
420 access(contract) let leaseName: String
421
422 //this should reflect on what the above uuid is for
423 access(contract) let vaultType: Type
424 access(contract) var bidAt: UFix64
425 access(contract) var balance: UFix64 //This is what you bid for non escrowed bids
426 access(contract) let bidExtraField: {String : AnyStruct}
427
428 init(from: Capability<&SaleItemCollection>, leaseName: String, vaultType:Type, nonEscrowedBalance:UFix64, bidExtraField: {String : AnyStruct}){
429 self.vaultType= vaultType
430 self.balance=nonEscrowedBalance
431 self.leaseName=leaseName
432 self.from=from
433 self.bidAt=Clock.time()
434 self.bidExtraField=bidExtraField
435 }
436
437 access(contract) fun setBidAt(_ time: UFix64) {
438 self.bidAt=time
439 }
440
441 access(contract) fun increaseBid(_ amount:UFix64) {
442 self.balance=self.balance+amount
443 }
444
445 access(all) fun getBalance() : UFix64 {
446 return self.balance
447 }
448
449 access(all) fun getSellerAddress() : Address {
450 return self.from.address
451 }
452
453 access(all) fun getBidExtraField() : {String : AnyStruct} {
454 return self.bidExtraField
455 }
456 }
457
458 access(all) resource interface MarketBidCollectionPublic {
459 access(all) fun getBalance(_ name: String) : UFix64
460 access(all) fun getVaultType(_ name: String) : Type
461 access(all) fun containsNameBid(_ name: String): Bool
462 access(all) fun getNameBids() : [String]
463 access(contract) fun acceptNonEscrowed(_ name: String)
464 access(contract) fun cancelBidFromSaleItem(_ name: String)
465 }
466
467 access(all) entitlement Buyer
468
469 //A collection stored for bidders/buyers
470 access(all) resource MarketBidCollection: MarketBidCollectionPublic, FindLeaseMarket.MarketBidCollectionPublic {
471
472 access(contract) var bids : @{String: Bid}
473 access(contract) let receiver: Capability<&{FungibleToken.Receiver}>
474 access(contract) let tenantCapability: Capability<&FindMarket.Tenant>
475
476 //not sure we can store this here anymore. think it needs to be in every bid
477 init(receiver: Capability<&{FungibleToken.Receiver}>, tenantCapability: Capability<&FindMarket.Tenant>) {
478 self.bids <- {}
479 self.receiver=receiver
480 self.tenantCapability=tenantCapability
481 }
482
483 access(self) fun getTenant() : &FindMarket.Tenant {
484 pre{
485 self.tenantCapability.check() : "Tenant client is not linked anymore"
486 }
487 return self.tenantCapability.borrow()!
488 }
489
490 //called from lease when auction is ended
491 access(contract) fun acceptNonEscrowed(_ name: String) {
492 let bid <- self.bids.remove(key: name) ?? panic("missing bid")
493 destroy bid
494 }
495
496 access(all) fun getVaultType(_ name:String) : Type {
497 return self.borrowBid(name).vaultType
498 }
499
500 access(all) fun getNameBids() : [String] {
501 return self.bids.keys
502 }
503
504 access(all) fun containsNameBid(_ name: String) : Bool {
505 return self.bids.containsKey(name)
506 }
507
508 access(all) fun getBidType() : Type {
509 return Type<@Bid>()
510 }
511
512
513 access(Buyer) fun bid(name: String, amount:UFix64, vaultType:Type, validUntil: UFix64?, saleItemExtraField: {String : AnyStruct}, bidExtraField: {String : AnyStruct}) {
514 if self.owner!.address == FIND.status(name).owner! {
515 panic("You cannot bid on your own resource")
516 }
517
518 if self.bids[name] !=nil{
519 panic("You already have an bid for this item, use increaseBid on that bid")
520 }
521
522 // ensure it is not a 0 dollar listing
523 if amount <= 0.0 {
524 panic("Offer price should be greater than 0")
525 }
526
527 // ensure validUntil is valid
528 if validUntil != nil && validUntil! < Clock.time() {
529 panic("Valid until is before current time")
530 }
531
532 let from=getAccount(FIND.status(name).owner!).capabilities.get<&SaleItemCollection>(self.getTenant().getPublicPath(Type<@SaleItemCollection>()))
533
534 let bid <- create Bid(from: from, leaseName: name, vaultType: vaultType, nonEscrowedBalance:amount, bidExtraField: bidExtraField)
535 let saleItemCollection= from.borrow() ?? panic("Could not borrow sale item for name=".concat(name))
536 let callbackCapability =self.owner!.capabilities.get<&MarketBidCollection>(self.getTenant().getPublicPath(Type<@MarketBidCollection>()))
537
538 let oldToken <- self.bids[name] <- bid
539 saleItemCollection.registerBid(name: name, callback: callbackCapability, validUntil: validUntil, saleItemExtraField: saleItemExtraField)
540 destroy oldToken
541 }
542
543 access(all) fun fulfillDirectOffer(name:String, vault: @{FungibleToken.Vault}) {
544 pre {
545 self.bids[name] != nil : "You need to have a bid here already"
546 }
547
548 let bid =self.borrowBid(name)
549 let saleItem=bid.from.borrow()!
550
551 if !saleItem.isAcceptedDirectOffer(name) {
552 panic("offer is not accepted yet")
553 }
554
555 saleItem.fulfillDirectOfferNonEscrowed(name:name, vault: <- vault)
556 }
557
558 access(Buyer) fun increaseBid(name: String, increaseBy: UFix64) {
559 let bid =self.borrowBid(name)
560 bid.setBidAt(Clock.time())
561 bid.increaseBid(increaseBy)
562 if !bid.from.check() {
563 panic("Seller unlinked the SaleItem collection capability. seller address : ".concat(bid.from.address.toString()))
564 }
565 bid.from.borrow()!.registerIncreasedBid(name)
566 }
567
568 /// The users cancel a bid himself
569 access(Buyer) fun cancelBid(_ name: String) {
570 let bid= self.borrowBid(name)
571 if !bid.from.check() {
572 panic("Seller unlinked the SaleItem collection capability. seller address : ".concat(bid.from.address.toString()))
573 }
574 bid.from.borrow()!.cancelBid(name)
575 self.cancelBidFromSaleItem(name)
576 }
577
578 //called from saleItem when things are cancelled
579 //if the bid is canceled from seller then we move the vault tokens back into your vault
580 access(contract) fun cancelBidFromSaleItem(_ name: String) {
581 let bid <- self.bids.remove(key: name) ?? panic("missing bid")
582 destroy bid
583 }
584
585 access(all) fun borrowBid(_ name: String): &Bid {
586 pre{
587 self.bids.containsKey(name) : "This name bid does not exist.".concat(name)
588 }
589 return (&self.bids[name])!
590 }
591
592 access(all) fun borrowBidItem(_ name: String): &{FindLeaseMarket.Bid} {
593 pre{
594 self.bids.containsKey(name) : "This name bid does not exist.".concat(name)
595 }
596 return (&self.bids[name])!
597 }
598
599 access(all) fun getBalance(_ name: String) : UFix64 {
600 let bid= self.borrowBid(name)
601 return bid.balance
602 }
603 }
604
605 //Create an empty lease collection that store your leases to a name
606 access(all) fun createEmptySaleItemCollection(_ tenantCapability: Capability<&FindMarket.Tenant>) : @SaleItemCollection {
607 return <- create SaleItemCollection(tenantCapability)
608 }
609
610 access(all) fun createEmptyMarketBidCollection(receiver: Capability<&{FungibleToken.Receiver}>, tenantCapability: Capability<&FindMarket.Tenant>) : @MarketBidCollection {
611 return <- create MarketBidCollection(receiver: receiver, tenantCapability:tenantCapability)
612 }
613
614 access(all) fun getSaleItemCapability(marketplace:Address, user:Address) : Capability<&{SaleItemCollectionPublic, FindLeaseMarket.SaleItemCollectionPublic}>? {
615 if FindMarket.getTenantCapability(marketplace) == nil {
616 panic("Invalid tenant")
617 }
618 if let tenant=FindMarket.getTenantCapability(marketplace)!.borrow() {
619
620 return getAccount(user).capabilities.get<&{SaleItemCollectionPublic, FindLeaseMarket.SaleItemCollectionPublic}>(tenant.getPublicPath(Type<@SaleItemCollection>()))
621 }
622 return nil
623 }
624
625 access(all) fun getBidCapability( marketplace:Address, user:Address) : Capability<&{MarketBidCollectionPublic, FindLeaseMarket.MarketBidCollectionPublic}>? {
626 if FindMarket.getTenantCapability(marketplace) == nil {
627 panic("Invalid tenant")
628 }
629 if let tenant=FindMarket.getTenantCapability(marketplace)!.borrow() {
630 return getAccount(user).capabilities.get<&{MarketBidCollectionPublic, FindLeaseMarket.MarketBidCollectionPublic}>(tenant.getPublicPath(Type<@MarketBidCollection>()))
631 }
632 return nil
633 }
634
635 init() {
636 FindLeaseMarket.addSaleItemType(Type<@SaleItem>())
637 FindLeaseMarket.addSaleItemCollectionType(Type<@SaleItemCollection>())
638 FindLeaseMarket.addMarketBidType(Type<@Bid>())
639 FindLeaseMarket.addMarketBidCollectionType(Type<@MarketBidCollection>())
640 }
641}
642