TransactionSEALED
!●▫▫~●■^▫*^%▒█?▫░@●@◇▪◆╳&░@?░%░@○^◆╳!░▫▪█%*~░#?◆◇╱~~░~?□○!@~○▓@■
Transaction ID
Execution Fee
0.00274 FLOWTransaction Summary
Contract CallCalled OffersV2, DapperOffersV2, TopShot +4 more
Script Arguments
0amountUFix64
45.00000000
1royalties{Address
{
"0xfaf0cc52c6e3acaf": "2.25000000"
}2offerParamsString{String
{
"resolver": "1",
"setId": "135",
"playId": "4706",
"setUuid": "5f9848cf-e024-447a-a4c9-9bf0490ca299",
"playUuid": "d910d6cc-a8a1-46cd-ab1d-c8ee6a88bf65"
}Cadence Script
1import OffersV2 from 0xb8ea91944fd51c43
2import DapperOffersV2 from 0xb8ea91944fd51c43
3import TopShot from 0x0b2a3299cc857e29
4import NonFungibleToken from 0x1d7e57aa55817448
5import FungibleToken from 0xf233dcee88fe0abe
6import DapperUtilityCoin from 0xead892083b3e2c6c
7import Resolver from 0xb8ea91944fd51c43
8transaction(amount: UFix64, royalties: {Address:UFix64}, offerParamsString: {String:String}) {
9 var nftReceiver: Capability<&{NonFungibleToken.CollectionPublic}>?
10 let dapperOffer: auth(DapperOffersV2.Manager) &DapperOffersV2.DapperOffer
11 var ducVaultRef: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>
12 let resolverCapability: Capability<&{Resolver.ResolverPublic}>
13 var proxyManagerCap: Capability<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>
14 var ROYALITY_ADDRESS: Address
15 var ROYALITY_PERCENT: UFix64
16 prepare(signer: auth(Storage, Capabilities) &Account, dapper: auth(Storage, Capabilities) &Account) {
17 // Link the NFT collection
18 if signer.storage.borrow<&TopShot.Collection>(from: /storage/MomentCollection) == nil {
19 let collection <- TopShot.createEmptyCollection(nftType: Type<@TopShot.NFT>())
20 signer.storage.save(<-collection, to: /storage/MomentCollection)
21 signer.capabilities.unpublish(/public/MomentCollection)
22 signer.capabilities.publish(
23 signer.capabilities.storage.issue<&TopShot.Collection>(/storage/MomentCollection),
24 at: /public/MomentCollection
25 )
26 }
27 self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(/public/MomentCollection)
28 if self.nftReceiver == nil || !self.nftReceiver!.check() {
29 signer.capabilities.unpublish(/public/MomentCollection)
30 signer.capabilities.publish(
31 signer.capabilities.storage.issue<&{NonFungibleToken.CollectionPublic}>(/storage/MomentCollection),
32 at: /public/MomentCollection
33 )
34 self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(/public/MomentCollection)
35 }
36 // Link the DapperOffer resource
37 if signer.storage.borrow<&DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath) == nil {
38 let dapperOffer <- DapperOffersV2.createDapperOffer() as! @DapperOffersV2.DapperOffer
39 signer.storage.save(<-dapperOffer, to: DapperOffersV2.DapperOffersStoragePath)
40 signer.capabilities.publish(
41 signer.capabilities.storage.issue<&DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath),
42 at: DapperOffersV2.DapperOffersPublicPath
43 )
44 }
45 // DapperOfferProxyManager Setup
46 if dapper.storage.borrow<&DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath) == nil {
47 let dapperOffer <- DapperOffersV2.createDapperOffer() as! @DapperOffersV2.DapperOffer
48 dapper.storage.save(<-dapperOffer, to: DapperOffersV2.DapperOffersStoragePath)
49 dapper.capabilities.publish(
50 dapper.capabilities.storage.issue<&DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath),
51 at: DapperOffersV2.DapperOffersPublicPath
52 )
53 }
54 // Setup Proxy Cancel for Dapper
55 let capabilityReceiver = dapper.capabilities.borrow
56 <&DapperOffersV2.DapperOffer>
57 (/public/DapperOffersV2) ?? panic("Could not borrow capability receiver reference")
58
59
60 let dapperOfferProxyManagerCapPath = /storage/DapperOfferProxyManagerCapability
61 var dapperOfferProxyManagerCap = signer.storage.copy<Capability<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>>(from: dapperOfferProxyManagerCapPath)
62 if dapperOfferProxyManagerCap == nil || !dapperOfferProxyManagerCap!.check() {
63 self.proxyManagerCap = signer.capabilities.storage.issue<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath)
64 // save capability to storage
65 signer.capabilities.storage.getController(byCapabilityID: self.proxyManagerCap.id)!.setTag("DapperOfferProxyManagerCap")
66 signer.storage.save(
67 self.proxyManagerCap,
68 to: dapperOfferProxyManagerCapPath
69 )
70 } else {
71 self.proxyManagerCap = dapperOfferProxyManagerCap!
72 }
73
74
75 capabilityReceiver.addProxyCapability(account: signer.address, cap: self.proxyManagerCap)
76 // Setup Proxy Cancel for Collection Minter
77 let minter = getAccount(0xe1f2a091f7bb5245)
78 let capabilityReceiverCollectionMinter = minter.capabilities.borrow
79 <&DapperOffersV2.DapperOffer>
80 (/public/DapperOffersV2) ?? panic("Could not borrow capability receiver reference")
81 capabilityReceiverCollectionMinter.addProxyCapability(account: signer.address, cap: self.proxyManagerCap)
82 // Get the capability to the offer creators NFT collection
83 self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(/public/MomentCollection)
84 self.dapperOffer = signer.storage.borrow<auth(DapperOffersV2.Manager) &DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath)
85 ?? panic("Missing or mis-typed DapperOffersV2.DapperOffer")
86
87 let ducWithdrawCapPath = /storage/DUCWithdrawCapabilityForOffers
88 var ducWithdrawCap = dapper.storage.copy<Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>>(from: ducWithdrawCapPath)
89 if ducWithdrawCap == nil || !ducWithdrawCap!.check() {
90 self.ducVaultRef = dapper.capabilities.storage.issue<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>(/storage/dapperUtilityCoinVault)
91 // save capability to storage
92 dapper.capabilities.storage.getController(byCapabilityID: self.ducVaultRef.id)!.setTag("OffersDUCWithdrawCap")
93 dapper.storage.save(
94 self.ducVaultRef,
95 to: ducWithdrawCapPath
96 )
97 } else{
98 self.ducVaultRef = ducWithdrawCap!
99 }
100
101 // Validate marketplace royalties
102 self.ROYALITY_ADDRESS = 0xfaf0cc52c6e3acaf
103 self.ROYALITY_PERCENT = 0.05000000
104 assert(royalties[self.ROYALITY_ADDRESS] == self.ROYALITY_PERCENT * amount, message: "Missing or mis-typed royalty information for marketplace")
105 assert(royalties.keys.length == 1, message: "please provide only one royalty address")
106 // Validate offerParamsString and resolver for type TopShotEdition
107 assert(offerParamsString.containsKey("playId"), message: "playId missing from offerParamsString")
108 assert(offerParamsString.containsKey("setId"), message: "setId missing from offerParamsString")
109 assert(offerParamsString.containsKey("resolver"), message: "resolver missing from offerParamsString")
110 assert(offerParamsString["resolver"] == Resolver.ResolverType.TopShotEdition.rawValue.toString(), message: "Invalid resolver")
111 // Setup and link offer Resolver
112 if signer.storage.borrow<&Resolver.OfferResolver>(from: /storage/OfferResolver) == nil {
113 let resolver <- Resolver.createResolver()
114 signer.storage.save(<-resolver, to: /storage/OfferResolver)
115 signer.capabilities.publish(
116 signer.capabilities.storage.issue<&Resolver.OfferResolver>(/storage/OfferResolver),
117 at: /public/OfferResolver
118 )
119 }
120 self.resolverCapability = signer.capabilities.get<&{Resolver.ResolverPublic}>(/public/OfferResolver)!
121 }
122 execute {
123 var royaltysList: [OffersV2.Royalty] = []
124 let keys = royalties.keys
125 for key in keys {
126 royaltysList.append(OffersV2.Royalty(
127 receiver: getAccount(key).capabilities.get<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)!,
128 amount: royalties[key]!
129 ))
130 }
131 offerParamsString.insert(key: "typeId", "Type<@TopShot.NFT>()")
132
133 // Set offer type based on whether subeditionId is present
134 // Backend relies on this to identify and process subedition offers
135 if offerParamsString.containsKey("subeditionId") {
136 offerParamsString.insert(key: "_type", "TopShotSubedition")
137 } else {
138 offerParamsString.insert(key: "_type", "TopShotEdition")
139 }
140
141 self.dapperOffer.createOffer(
142 vaultRefCapability: self.ducVaultRef,
143 nftReceiverCapability: self.nftReceiver!,
144 nftType: Type<@TopShot.NFT>(),
145 amount: amount,
146 royalties: royaltysList,
147 offerParamsString: offerParamsString,
148 offerParamsUFix64: {},
149 offerParamsUInt64: {},
150 resolverCapability: self.resolverCapability
151 )
152 }
153}