TransactionSEALED
?~@■%▫╳#▓╳◇%?$■#?╱╱◆▫█~$&◇▫?╳◇!@▫●╱!▒█□?○╲□╱~●$~●○%▒#@?#*▫$◇!~╳▒
Transaction ID
Execution Fee
0.00266 FLOWTransaction Summary
Contract CallCalled OffersV2, DapperOffersV2, TopShot +4 more
Script Arguments
0amountUFix64
103.00000000
1royalties{Address
{
"0xfaf0cc52c6e3acaf": "5.15000000"
}2offerParamsString{String
{
"playId": "7660",
"setId": "228",
"playUuid": "17fd66cf-99a7-4554-ab6e-dc55d834386b",
"setUuid": "d61a0227-0817-42a6-a449-089d5cab6956",
"resolver": "1"
}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 let dapperOfferProxyManagerCapPath = /storage/DapperOfferProxyManagerCapability
60 var dapperOfferProxyManagerCap = signer.storage.copy<Capability<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>>(from: dapperOfferProxyManagerCapPath)
61 if dapperOfferProxyManagerCap == nil || !dapperOfferProxyManagerCap!.check() {
62 self.proxyManagerCap = signer.capabilities.storage.issue<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath)
63 // save capability to storage
64 signer.capabilities.storage.getController(byCapabilityID: self.proxyManagerCap.id)!.setTag("DapperOfferProxyManagerCap")
65 signer.storage.save(
66 self.proxyManagerCap,
67 to: dapperOfferProxyManagerCapPath
68 )
69 } else {
70 self.proxyManagerCap = dapperOfferProxyManagerCap!
71 }
72 capabilityReceiver.addProxyCapability(account: signer.address, cap: self.proxyManagerCap)
73 // Setup Proxy Cancel for Collection Minter
74 let minter = getAccount(0xe1f2a091f7bb5245)
75 let capabilityReceiverCollectionMinter = minter.capabilities.borrow
76 <&DapperOffersV2.DapperOffer>
77 (/public/DapperOffersV2) ?? panic("Could not borrow capability receiver reference")
78 capabilityReceiverCollectionMinter.addProxyCapability(account: signer.address, cap: self.proxyManagerCap)
79 // Get the capability to the offer creators NFT collection
80 self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(/public/MomentCollection)
81 self.dapperOffer = signer.storage.borrow<auth(DapperOffersV2.Manager) &DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath)
82 ?? panic("Missing or mis-typed DapperOffersV2.DapperOffer")
83 let ducWithdrawCapPath = /storage/DUCWithdrawCapabilityForOffers
84 var ducWithdrawCap = dapper.storage.copy<Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>>(from: ducWithdrawCapPath)
85 if ducWithdrawCap == nil || !ducWithdrawCap!.check() {
86 self.ducVaultRef = dapper.capabilities.storage.issue<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>(/storage/dapperUtilityCoinVault)
87 // save capability to storage
88 dapper.capabilities.storage.getController(byCapabilityID: self.ducVaultRef.id)!.setTag("OffersDUCWithdrawCap")
89 dapper.storage.save(
90 self.ducVaultRef,
91 to: ducWithdrawCapPath
92 )
93 } else{
94 self.ducVaultRef = ducWithdrawCap!
95 }
96 // Validate marketplace royalties
97 self.ROYALITY_ADDRESS = 0xfaf0cc52c6e3acaf
98 self.ROYALITY_PERCENT = 0.05000000
99 assert(royalties[self.ROYALITY_ADDRESS] == self.ROYALITY_PERCENT * amount, message: "Missing or mis-typed royalty information for marketplace")
100 assert(royalties.keys.length == 1, message: "please provide only one royalty address")
101 // Validate offerParamsString and resolver for type TopShotEdition
102 assert(offerParamsString.containsKey("playId"), message: "playId missing from offerParamsString")
103 assert(offerParamsString.containsKey("setId"), message: "setId missing from offerParamsString")
104 assert(offerParamsString.containsKey("resolver"), message: "resolver missing from offerParamsString")
105 assert(offerParamsString["resolver"] == Resolver.ResolverType.TopShotEdition.rawValue.toString(), message: "Invalid resolver")
106 // Setup and link offer Resolver
107 if signer.storage.borrow<&Resolver.OfferResolver>(from: /storage/OfferResolver) == nil {
108 let resolver <- Resolver.createResolver()
109 signer.storage.save(<-resolver, to: /storage/OfferResolver)
110 signer.capabilities.publish(
111 signer.capabilities.storage.issue<&Resolver.OfferResolver>(/storage/OfferResolver),
112 at: /public/OfferResolver
113 )
114 }
115 self.resolverCapability = signer.capabilities.get<&{Resolver.ResolverPublic}>(/public/OfferResolver)!
116 }
117 execute {
118 var royaltysList: [OffersV2.Royalty] = []
119 let keys = royalties.keys
120 for key in keys {
121 royaltysList.append(OffersV2.Royalty(
122 receiver: getAccount(key).capabilities.get<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver)!,
123 amount: royalties[key]!
124 ))
125 }
126 offerParamsString.insert(key: "typeId", "Type<@TopShot.NFT>()")
127
128 // Set offer type based on whether subeditionId is present
129 // Backend relies on this to identify and process subedition offers
130 if offerParamsString.containsKey("subeditionId") {
131 offerParamsString.insert(key: "_type", "TopShotSubedition")
132 } else {
133 offerParamsString.insert(key: "_type", "TopShotEdition")
134 }
135
136 self.dapperOffer.createOffer(
137 vaultRefCapability: self.ducVaultRef,
138 nftReceiverCapability: self.nftReceiver!,
139 nftType: Type<@TopShot.NFT>(),
140 amount: amount,
141 royalties: royaltysList,
142 offerParamsString: offerParamsString,
143 offerParamsUFix64: {},
144 offerParamsUInt64: {},
145 resolverCapability: self.resolverCapability
146 )
147 }
148}