FT TransferMarketplaceSEALED
▪!!◇●◇╳^◇!○◇@#░◇█╱╳*^▫▫^□█?$□░!■^▒*╳◇&█◇^□&■◇█░$*╲◇█▓*■~●▪!▫╱▫□*
Transaction ID
Execution Fee
0.00834 FLOWTransaction Summary
FT TransferMarketplace
Called FungibleToken, NonFungibleToken, DapperUtilityCoin +2 more
Script Arguments
Copy:
0saleItemIDUInt64
241197
1saleItemPriceUFix64
17.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}