MarketplaceSEALED

╱^◇~◆?╳●&○*#▓░░▓@?■╳#█^~╲!╱□?▪◆!$$□▫▪╲*!●!!▪%$░&??▒╱$▪■▪#■#◇▓&○○

Transaction ID

Timestamp

Aug 19, 2024, 06:25:49 PM UTC
1y ago

Block Height

84,896,173

Computation

0

Execution Fee

0.00004277 FLOW

Transaction Summary

Marketplace

Called FlowToken, FiatToken, REVV +6 more

Script Arguments

1collectionIdentifiers[String]
[
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow",
  "HeroesOfTheFlow"
]
2saleItemIDs[UInt64]
[
  "9410",
  "9411",
  "9907",
  "9908",
  "9909",
  "4065",
  "4532",
  "6215",
  "6216",
  "6709",
  "6711",
  "6799",
  "6801",
  "7369",
  "7370",
  "7371",
  "7641",
  "7762",
  "7763",
  "7764",
  "8005",
  "8007",
  "8128"
]
3saleItemPrices[UFix64]
[
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000",
  "0.74000000"
]
4salePaymentVaultTypeIdentifiers[String]
[
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault",
  "A.1654653399040a61.FlowToken.Vault"
]
5royaltiesCuts[[UFix64]]
[
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ],
  [
    "0.05000000"
  ]
]
6royaltiesReceivers[[Address]]
[
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ],
  [
    "0xc5857663ca37efbf"
  ]
]
7privatePathOverrides[String?]
[
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null
]
8customIDString?
flowverse-nft-marketplace
9commissionAmounts[UFix64]
[
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000",
  "0.00000000"
]
10expiries[UInt64]
[
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304",
  "1726770304"
]

Cadence Script

1import FlowToken from 0x1654653399040a61
2import FiatToken from 0xb19436aae4d94622
3import REVV from 0xd01e482eb680ec9f
4import FungibleToken from 0xf233dcee88fe0abe
5import NonFungibleToken from 0x1d7e57aa55817448
6import NFTCatalog from 0x49a7cda3a1eecc29
7import MetadataViews from 0x1d7e57aa55817448
8import NFTStorefrontV2 from 0x4eb8a10cb9f87357
9import HybridCustody from 0xd8a7e05a7ac670c0
10
11transaction(
12    ownerAddresses: [Address],
13    collectionIdentifiers: [String],
14    saleItemIDs: [UInt64],
15    saleItemPrices: [UFix64],
16    salePaymentVaultTypeIdentifiers: [String],
17    royaltiesCuts: [[UFix64]],
18    royaltiesReceivers: [[Address]],
19    privatePathOverrides: [String?],
20    customID: String?,
21    commissionAmounts: [UFix64],
22    expiries: [UInt64]
23) {
24    let collectionCaps: [Capability<&AnyResource{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>]
25    let storefront: &NFTStorefrontV2.Storefront
26    var saleCuts: [[NFTStorefrontV2.SaleCut]]
27    var salePaymentVaultTypes: [Type]
28    let nftTypes: [Type]
29
30    prepare(acct: AuthAccount) {
31        assert(ownerAddresses.length == saleItemIDs.length, message: "ownerAddresses and saleItemIDs must be the same length")
32        assert(saleItemIDs.length == saleItemPrices.length, message: "saleItemIDs and saleItemPrices must be the same length")
33        assert(saleItemIDs.length == salePaymentVaultTypeIdentifiers.length, message: "saleItemIDs and salePaymentVaultTypeIdentifiers must be the same length")
34        assert(saleItemIDs.length == collectionIdentifiers.length, message: "saleItemIDs and collectionIdentifiers must be the same length")
35        assert(saleItemIDs.length == commissionAmounts.length, message: "saleItemIDs and commissionAmounts must be the same length")
36        assert(saleItemIDs.length == expiries.length, message: "saleItemIDs and expiries must be the same length")
37
38        self.collectionCaps = []
39        self.saleCuts = []
40        self.salePaymentVaultTypes = []
41        self.nftTypes = []
42        
43        // If the account doesn't already have a storefront, create one and add it to the account
44        if acct.borrow<&NFTStorefrontV2.Storefront>(from: NFTStorefrontV2.StorefrontStoragePath) == nil {
45            let storefront <- NFTStorefrontV2.createStorefront() as! @NFTStorefrontV2.Storefront
46            acct.save(<-storefront, to: NFTStorefrontV2.StorefrontStoragePath)
47            acct.link<&NFTStorefrontV2.Storefront{NFTStorefrontV2.StorefrontPublic}>(NFTStorefrontV2.StorefrontPublicPath, target: NFTStorefrontV2.StorefrontStoragePath)
48        }
49
50        self.storefront = acct.borrow<&NFTStorefrontV2.Storefront>(from: NFTStorefrontV2.StorefrontStoragePath)
51            ?? panic("Missing or mis-typed NFTStorefront Storefront")
52        
53        var i = 0
54        while i < saleItemIDs.length {
55            var ftReceiverPath: PublicPath? = nil
56            var ftReceiver: Capability<&AnyResource{FungibleToken.Receiver}>? = nil
57
58            switch salePaymentVaultTypeIdentifiers[i] {
59                case Type<@FlowToken.Vault>().identifier:
60                    self.salePaymentVaultTypes.append(Type<@FlowToken.Vault>())
61                    ftReceiverPath = PublicPath(identifier: "flowTokenReceiver")!
62                    ftReceiver = acct.getCapability<&{FungibleToken.Receiver}>(ftReceiverPath!)!
63                case Type<@FiatToken.Vault>().identifier:
64                    self.salePaymentVaultTypes.append(Type<@FiatToken.Vault>())
65                    
66                    // Initialise USDC vault if it doesn't exist
67                    if acct.borrow<&FungibleToken.Vault>(from: /storage/USDCVault) == nil {
68                        acct.save(<- FiatToken.createEmptyVault(), to: /storage/USDCVault)
69                        acct.link<&FiatToken.Vault{FungibleToken.Balance}>(/public/USDCVaultBalance, target: /storage/USDCVault)
70                        acct.link<&FiatToken.Vault{FungibleToken.Receiver}>(/public/USDCVaultReceiver, target: /storage/USDCVault)
71                    }
72
73                    ftReceiverPath = PublicPath(identifier: "USDCVaultReceiver")!
74                    ftReceiver = acct.getCapability<&{FungibleToken.Receiver}>(ftReceiverPath!)!
75                case Type<@REVV.Vault>().identifier:
76                    self.salePaymentVaultTypes.append(Type<@REVV.Vault>())
77                    
78                    // Initialise REVV vault if it doesn't exist
79                    if acct.borrow<&FungibleToken.Vault>(from: REVV.RevvVaultStoragePath) == nil {
80                        acct.save(<- REVV.createEmptyVault(), to: REVV.RevvVaultStoragePath)
81                        acct.link<&REVV.Vault{FungibleToken.Balance}>(REVV.RevvBalancePublicPath, target: REVV.RevvVaultStoragePath)
82                        acct.link<&REVV.Vault{FungibleToken.Receiver}>(REVV.RevvReceiverPublicPath, target: REVV.RevvVaultStoragePath)
83                    }
84
85                    ftReceiverPath = PublicPath(identifier: "revvReceiver")!
86                    ftReceiver = acct.getCapability<&{FungibleToken.Receiver}>(ftReceiverPath!)!
87                default:
88                    panic("Unsupported sale payment vault type identifier")
89            }
90
91            assert(ftReceiver!.borrow() != nil, message: "Missing or mis-typed FungibleToken receiver")
92            
93            let value = NFTCatalog.getCatalogEntry(collectionIdentifier: collectionIdentifiers[i]) ?? panic("Collection does not exist in the NFT Catalog.")
94            
95            // We need a provider capability, but one is not provided by default so we create one if needed.
96            let nftCollectionProviderPrivatePath = PrivatePath(identifier: collectionIdentifiers[i].concat("CollectionProviderForFlowverseNFT"))!
97            
98            let ownerAddress = ownerAddresses[i]
99            let privatePathOverride = privatePathOverrides[i]
100
101            // Check if the owner is a child account
102            if ownerAddress != acct.address {
103                let manager = acct.borrow<&HybridCustody.Manager>(from: HybridCustody.ManagerStoragePath)
104                    ?? panic("Missing or mis-typed HybridCustody Manager")
105                let child = manager.borrowAccount(addr: ownerAddress) ?? panic("no child account with that address")
106                let catalogPrivatePath = value.collectionData.privatePath
107                let flowverseProviderCap = child.getCapability(path: nftCollectionProviderPrivatePath, type: Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>())
108                let catalogProviderCap = child.getCapability(path: catalogPrivatePath, type: Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>())
109                if flowverseProviderCap != nil && (flowverseProviderCap! as! Capability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>).borrow() != nil {
110                    let cap = flowverseProviderCap! as! Capability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>
111                    self.collectionCaps.append(cap)
112                } else if catalogProviderCap != nil && (catalogProviderCap! as! Capability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>).borrow() != nil {
113                    let cap = catalogProviderCap! as! Capability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>
114                    self.collectionCaps.append(cap)
115                } else if privatePathOverride != nil {
116                    let privatePath = PrivatePath(identifier: privatePathOverride!)!
117                    let providerCap = child.getCapability(path: privatePath, type: Type<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>())
118                    if providerCap != nil && (providerCap! as! Capability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>).borrow() != nil {
119                        let cap = providerCap! as! Capability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>
120                        self.collectionCaps.append(cap)
121                    }
122                } else {
123                    panic("The NFT: ".concat(collectionIdentifiers[i]).concat(" cannot be listed by the parent account"))
124                }
125            } else {
126                self.collectionCaps.append(acct.getCapability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(nftCollectionProviderPrivatePath))
127                if !self.collectionCaps[i].check() {
128                    acct.unlink(nftCollectionProviderPrivatePath)
129                    acct.link<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(nftCollectionProviderPrivatePath, target: value.collectionData.storagePath)
130                }
131            }
132
133            let collection = self.collectionCaps[i].borrow()
134            ?? panic("Could not borrow a reference to the collection")
135    
136            let nft = collection.borrowNFT(id: saleItemIDs[i])
137            self.nftTypes.append(nft.getType())
138            
139            let saleCutArr: [NFTStorefrontV2.SaleCut] = []
140            var totalRoyaltyCut: UFix64 = 0.0
141            let saleItemPrice = saleItemPrices[i]
142            let royaltyCuts = royaltiesCuts[i]
143            let royaltyReceivers = royaltiesReceivers[i]
144
145            // Append cuts for the royalties.
146            for index, royaltyCut in royaltyCuts {
147                let receiver = getAccount(royaltyReceivers[index]).getCapability<&AnyResource{FungibleToken.Receiver}>(ftReceiverPath!)
148                let royaltySaleCut = NFTStorefrontV2.SaleCut(receiver: receiver, amount: UFix64(royaltyCut * saleItemPrice))
149                saleCutArr.append(royaltySaleCut)
150                totalRoyaltyCut = totalRoyaltyCut + royaltySaleCut.amount
151            }
152
153            // Append the cut for the seller.
154            saleCutArr.append(NFTStorefrontV2.SaleCut(
155                receiver: ftReceiver!,
156                amount: saleItemPrice - totalRoyaltyCut - commissionAmounts[i]
157            ))
158
159            self.saleCuts.append(saleCutArr)
160            
161            i = i + 1
162        }
163    }
164
165    execute {
166        // Create listings
167        var i = 0
168        while i < saleItemIDs.length {
169            self.storefront.createListing(
170                nftProviderCapability: self.collectionCaps[i],
171                nftType: self.nftTypes[i],
172                nftID: saleItemIDs[i],
173                salePaymentVaultType: self.salePaymentVaultTypes[i],
174                saleCuts: self.saleCuts[i],
175                marketplacesCapability: nil,
176                customID: customID,
177                commissionAmount: commissionAmounts[i],
178                expiry: expiries[i]
179            )
180            i = i + 1
181        }
182    }
183}