MarketplaceSEALED
◇^#~$█▪&●◆$▓◆■◇&!●▫▒▫╱▓?░░▪#▫^&◇@█%░╳╲#◇□╳╲~~^▓^▒◆◇●╲▫*$╲□░^?!~&
Transaction ID
Execution Fee
0.00009072 FLOWTransaction Summary
MarketplaceCalled FungibleToken, NonFungibleToken, ViewResolver +6 more
Script Arguments
0saleRequests[TransactionTypes.StorefrontListingRequest]
[
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "50141334",
"price": "1.95000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "50087226",
"price": "0.72000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "50140765",
"price": "1.85000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "50149677",
"price": "1.80000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "49950027",
"price": "0.65000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "48997807",
"price": "0.59000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "49004876",
"price": "0.59000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "48711795",
"price": "0.86000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "49377006",
"price": "0.99000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "49374708",
"price": "0.65000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
},
{
"nftProviderAddress": "0x01229f466b9e1af2",
"nftProviderControllerID": "0",
"nftStoragePath": "storage/MomentCollection",
"nftTypeIdentifier": "A.0b2a3299cc857e29.TopShot.NFT",
"nftID": "48966989",
"price": "0.75000000",
"customID": null,
"expiry": "15552000",
"buyerAddress": null,
"catalogCollection": true
}
]Cadence Script
1// Flowty - List multiple items for sale at the same time
2import FungibleToken from 0xf233dcee88fe0abe
3import NonFungibleToken from 0x1d7e57aa55817448
4import ViewResolver from 0x1d7e57aa55817448
5import NFTStorefrontV2 from 0x3cdbb3d569211ff3
6import FlowtyUtils from 0x3cdbb3d569211ff3
7import TransactionTypes from 0x26836b2113af9115
8import DapperUtilityCoin from 0xead892083b3e2c6c
9import TokenForwarding from 0xe544175ee0461c4b
10import HybridCustody from 0xd8a7e05a7ac670c0
11
12transaction(saleRequests: [TransactionTypes.StorefrontListingRequest]) {
13 prepare(seller: auth(Storage, Capabilities) &Account) {
14 if seller.storage.borrow<&NFTStorefrontV2.Storefront>(from: NFTStorefrontV2.StorefrontStoragePath) == nil {
15 let storefront <- NFTStorefrontV2.createStorefront()
16 seller.storage.save(<-storefront, to: NFTStorefrontV2.StorefrontStoragePath)
17
18 seller.capabilities.unpublish(NFTStorefrontV2.StorefrontPublicPath)
19 seller.capabilities.publish(
20 seller.capabilities.storage.issue<&NFTStorefrontV2.Storefront>(NFTStorefrontV2.StorefrontStoragePath),
21 at: NFTStorefrontV2.StorefrontPublicPath
22 )
23 }
24
25 let paymentReceiver = seller.capabilities.get<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
26 assert(paymentReceiver.check() != nil, message: "Missing or mis-typed DapperUtilityCoin receiver")
27
28 let nftCache: {String: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>} = {}
29 let nftRef: auth(Mutate) &{String: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>} = &nftCache
30
31 let typeCache: {String: Type} = {}
32 let typeRef: auth(Mutate) &{String: Type} = &typeCache
33
34 let storefront = seller.storage.borrow<auth(NFTStorefrontV2.List, NFTStorefrontV2.Cancel) &NFTStorefrontV2.Storefront>(from: NFTStorefrontV2.StorefrontStoragePath)!
35 for request in saleRequests {
36 createListing(seller, storefront, request, paymentReceiver, nftRef, typeRef)
37 }
38 }
39}
40
41access(all) fun createListing(
42 _ seller: auth(Storage, Capabilities) &Account,
43 _ storefront: auth(NFTStorefrontV2.List, NFTStorefrontV2.Cancel) &NFTStorefrontV2.Storefront,
44 _ r: TransactionTypes.StorefrontListingRequest,
45 _ paymentReceiver: Capability<&{FungibleToken.Receiver}>,
46 _ nftCache: auth(Mutate) &{String: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>},
47 _ typeCache: auth(Mutate) &{String: Type}
48) {
49 if typeCache[r.nftTypeIdentifier] == nil {
50 typeCache[r.nftTypeIdentifier] = CompositeType(r.nftTypeIdentifier) ?? panic("invalid nft type identifier")
51 }
52
53 let collectionCap = getCollectionCap(seller, r, nftCache, typeCache[r.nftTypeIdentifier]!)
54
55 // check for existing listings of the NFT
56 var existingListingIDs = storefront.getExistingListingIDs(
57 nftType: typeCache[r.nftTypeIdentifier]!,
58 nftID: r.nftID
59 )
60 // remove existing listings
61 for listingID in existingListingIDs {
62 storefront.removeListing(listingResourceID: listingID)
63 }
64
65 // Create listing
66 storefront.createListing(
67 nftProviderCapability: collectionCap,
68 paymentReceiver: paymentReceiver,
69 nftType: typeCache[r.nftTypeIdentifier]!,
70 nftID: r.nftID,
71 salePaymentVaultType: Type<@DapperUtilityCoin.Vault>(),
72 price: r.price,
73 customID: r.customID,
74 expiry: UInt64(getCurrentBlock().timestamp) + r.expiry,
75 buyer: r.buyerAddress
76 )
77}
78
79access(all) fun getCollectionCap(
80 _ seller: auth(Storage, Capabilities) &Account,
81 _ r: TransactionTypes.StorefrontListingRequest,
82 _ nftCache: auth(Mutate) &{String: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>},
83 _ nftType: Type
84): Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}> {
85 let key = r.nftProviderAddress.toString().concat(r.nftTypeIdentifier)
86 if nftCache[key] != nil {
87 return nftCache[key]!
88 }
89
90 if r.nftProviderAddress == seller.address {
91 let storagePath = FlowtyUtils.getCapabilityStoragePath(type: nftType, suffix: "CollectionProviderForFlowty")
92
93 let copiedCap = seller.storage.copy<Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>>(from: storagePath)
94 if copiedCap != nil && copiedCap!.check() {
95 nftCache[key] = copiedCap!
96 return copiedCap!
97 } else {
98 // clean this storage slot in case something is there already
99 seller.storage.load<AnyStruct>(from: storagePath)
100 let cap = seller.capabilities.storage.issue<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(r.nftStoragePath)
101 assert(cap.check(), message: "invalid issued provider capability")
102 seller.storage.save(cap, to: storagePath)
103 nftCache[key] = cap
104
105 return cap
106 }
107 }
108
109 let manager = seller.storage.borrow<auth(HybridCustody.Manage) &HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath)
110 ?? panic("Missing or mis-typed HybridCustody Manager")
111
112 let child = manager.borrowAccount(addr: r.nftProviderAddress) ?? panic("no child account with that address")
113 let providerCap = child.getCapability(controllerID: r.nftProviderControllerID, type: Type<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>())
114 ?? panic("no nft provider found")
115 let cap = providerCap as! Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>
116 nftCache[key] = cap
117
118 return cap
119}