MarketplaceSEALED
◇█▒?!■□▫▓╲@▒○@◆%╳█@*▪░╱▓!~~▒^▫░%▫╳◆○^%◆╲╳╱#◇╳%#*#*◆█▒□╱▪█▓□●?▪*▫
Transaction ID
Payer
Proposerseq:0 key:0
Authorizers
2Transaction Summary
MarketplaceCalled FungibleToken, NonFungibleToken, DapperUtilityCoin +2 more
Script Arguments
0saleItemIDUInt64
185129
1saleItemPriceUFix64
4.00000000
2royaltyPercentUFix64
0.05000000
Cadence Script
1import FungibleToken from 0xf233dcee88fe0abe
2import NonFungibleToken from 0x1d7e57aa55817448
3import DapperUtilityCoin from 0xead892083b3e2c6c
4import MFLPlayer from 0x8ebcbfd516b1da27
5import NFTStorefront from 0x4eb8a10cb9f87357
6
7/**
8 This transaction can be used to place a Player NFT for sale on a marketplace such that a specified percentage of the proceeds of the sale
9 go to the dapp as a royalty.
10**/
11
12transaction(saleItemID: UInt64, saleItemPrice: UFix64, royaltyPercent: UFix64) {
13 let sellerPaymentReceiver: Capability<&{FungibleToken.Receiver}>
14 let nftProviderCap: Capability<auth(NonFungibleToken.Withdraw) &MFLPlayer.Collection>
15 let storefront: auth(NFTStorefront.CreateListing, NFTStorefront.RemoveListing) &NFTStorefront.Storefront
16 let dappAddress: Address
17
18 // It's important that the dapp account authorize this transaction so the dapp as the ability
19 // to validate and approve the royalty included in the sale.
20 prepare(dapp: &Account, seller: auth(BorrowValue, IssueStorageCapabilityController, PublishCapability, UnpublishCapability, LoadValue, SaveValue, CopyValue) &Account) {
21 self.dappAddress = dapp.address
22
23 // If the account doesn't already have a Storefront
24 if seller.storage.borrow<&NFTStorefront.Storefront>(from: NFTStorefront.StorefrontStoragePath) == nil {
25 // Save a new .Storefront to account storage
26 seller.storage.save(
27 <- NFTStorefront.createStorefront(),
28 to: NFTStorefront.StorefrontStoragePath
29 )
30 // create a public capability for the .Storefront & publish
31 let storefrontPublicCap = seller.capabilities.storage.issue<&{NFTStorefront.StorefrontPublic}>(
32 NFTStorefront.StorefrontStoragePath
33 )
34 seller.capabilities.publish(storefrontPublicCap, at: NFTStorefront.StorefrontPublicPath)
35 }
36
37 // Get a reference to the receiver that will receive the fungible tokens if the sale executes.
38 self.sellerPaymentReceiver = seller.capabilities.get<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
39 assert(self.sellerPaymentReceiver.check(), message: "Missing or mis-typed DapperUtilityCoin receiver")
40
41 // If the user does not have their collection set up
42 if seller.storage.borrow<&MFLPlayer.Collection>(from: MFLPlayer.CollectionStoragePath) == nil {
43 let collection <- MFLPlayer.createEmptyCollection(nftType: Type<@MFLPlayer.NFT>())
44 seller.storage.save(<-collection, to: MFLPlayer.CollectionStoragePath)
45
46 seller.capabilities.unpublish(MFLPlayer.CollectionPublicPath)
47 let collectionCap = seller.capabilities.storage.issue<&MFLPlayer.Collection>(MFLPlayer.CollectionStoragePath)
48 seller.capabilities.publish(collectionCap, at: MFLPlayer.CollectionPublicPath)
49 }
50
51 // Get a capability to access the user's NFT collection.
52 let nftProviderCapStoragePath: StoragePath = /storage/MFLPlayerCollectionCap
53 let cap = seller.storage.copy<Capability<auth(NonFungibleToken.Withdraw) &MFLPlayer.Collection>>(from: nftProviderCapStoragePath)
54 if cap != nil && cap!.check() {
55 self.nftProviderCap = cap!
56 } else {
57 // clean this storage slot in case something is there already
58 seller.storage.load<AnyStruct>(from: nftProviderCapStoragePath)
59 self.nftProviderCap = seller.capabilities.storage.issue<auth(NonFungibleToken.Withdraw) &MFLPlayer.Collection>(MFLPlayer.CollectionStoragePath)
60 seller.storage.save(self.nftProviderCap, to: nftProviderCapStoragePath)
61 }
62 assert(self.nftProviderCap.check(), message: "Missing or mis-typed collection provider")
63
64 // Get a reference to the user's NFT storefront
65 self.storefront = seller.storage.borrow<auth(NFTStorefront.CreateListing, NFTStorefront.RemoveListing) &NFTStorefront.Storefront>(
66 from: NFTStorefront.StorefrontStoragePath
67 ) ?? panic("Missing or mis-typed NFTStorefront Storefront")
68
69 // Make sure this NFT is not already listed for sale in this storefront.
70 let existingOffers = self.storefront.getListingIDs()
71 if existingOffers.length > 0 {
72 for listingResourceID in existingOffers {
73 let listing: &{NFTStorefront.ListingPublic}? = self.storefront.borrowListing(listingResourceID: listingResourceID)
74 if listing != nil && listing!.getDetails().nftID == saleItemID && listing!.getDetails().nftType == Type<@MFLPlayer.NFT>(){
75 self.storefront.removeListing(listingResourceID: listingResourceID)
76 }
77 }
78 }
79 }
80
81 // Make sure dapp is actually the dapp and not some random account
82 pre {
83 self.dappAddress == 0x15e71a9f7fe7d53d : "Requires valid authorizing signature"
84 }
85
86 execute {
87 // Calculate the amout the seller should receive if the sale executes, and the amount
88 // that should be sent to the dapp as a royalty.
89 let amountSeller = saleItemPrice * (1.0 - royaltyPercent)
90 let amountRoyalty = saleItemPrice - amountSeller
91
92 // Get the royalty recipient's public account object
93 let royaltyRecipient = getAccount(0x15e71a9f7fe7d53d)
94
95 // Get a reference to the royalty recipient's Receiver
96 let royaltyReceiverRef = royaltyRecipient.capabilities.get<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)
97 assert(royaltyReceiverRef.borrow() != nil, message: "Missing or mis-typed DapperUtilityCoin royalty receiver")
98
99 let saleCutSeller = NFTStorefront.SaleCut(
100 receiver: self.sellerPaymentReceiver,
101 amount: amountSeller
102 )
103
104 let saleCutRoyalty = NFTStorefront.SaleCut(
105 receiver: royaltyReceiverRef,
106 amount: amountRoyalty
107 )
108
109 self.storefront.createListing(
110 nftProviderCapability: self.nftProviderCap,
111 nftType: Type<@MFLPlayer.NFT>(),
112 nftID: saleItemID,
113 salePaymentVaultType: Type<@DapperUtilityCoin.Vault>(),
114 saleCuts: [saleCutSeller, saleCutRoyalty]
115 )
116 }
117}