TransactionSEALED

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

Transaction ID

Timestamp

Oct 09, 2025, 12:27:22 AM UTC
4mo ago

Block Height

128,833,673

Computation

0

Execution Fee

0.00004123 FLOW

Transaction Summary

Contract Call

Called OffersV2, DapperOffersV2, TopShot +4 more

Script Arguments

0amountUFix64
9.00000000
1royalties{Address
{
  "0xfaf0cc52c6e3acaf": "0.45000000"
}
2offerParamsString{String
{
  "resolver": "0",
  "nftId": "50230553"
}

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
8
9transaction(amount: UFix64, royalties: {Address:UFix64}, offerParamsString: {String:String}) {
10    var nftReceiver: Capability<&{NonFungibleToken.CollectionPublic}>?
11    let dapperOffer: auth(DapperOffersV2.Manager) &DapperOffersV2.DapperOffer
12    var ducVaultRef: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>
13    let resolverCapability: Capability<&{Resolver.ResolverPublic}>
14    var proxyManagerCap: Capability<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>
15    var ROYALITY_ADDRESS: Address
16    var ROYALITY_PERCENT: UFix64
17    prepare(signer: auth(Storage, Capabilities) &Account, dapper: auth(Storage, Capabilities) &Account) {
18        // Link the NFT collection
19        if signer.storage.borrow<&TopShot.Collection>(from: /storage/MomentCollection) == nil {
20            let collection <- TopShot.createEmptyCollection(nftType: Type<@TopShot.NFT>())
21            signer.storage.save(<-collection, to: /storage/MomentCollection)
22            signer.capabilities.unpublish(/public/MomentCollection)
23            signer.capabilities.publish(
24                signer.capabilities.storage.issue<&TopShot.Collection>(/storage/MomentCollection),
25                at: /public/MomentCollection
26            )
27        }
28        self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(/public/MomentCollection)
29        if self.nftReceiver == nil || !self.nftReceiver!.check() {
30            signer.capabilities.unpublish(/public/MomentCollection)
31            signer.capabilities.publish(
32                signer.capabilities.storage.issue<&{NonFungibleToken.CollectionPublic}>(/storage/MomentCollection),
33                at: /public/MomentCollection
34            )
35            self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(/public/MomentCollection)
36        }        
37        // Link the DapperOffer resource
38        if signer.storage.borrow<&DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath) == nil {
39            let dapperOffer <- DapperOffersV2.createDapperOffer() as! @DapperOffersV2.DapperOffer
40            signer.storage.save(<-dapperOffer, to: DapperOffersV2.DapperOffersStoragePath)
41            signer.capabilities.publish(
42                signer.capabilities.storage.issue<&DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath),
43                at: DapperOffersV2.DapperOffersPublicPath
44            )
45        }
46        // DapperOfferProxyManager Setup
47        if dapper.storage.borrow<&DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath) == nil {
48            let dapperOffer <- DapperOffersV2.createDapperOffer() as! @DapperOffersV2.DapperOffer
49            dapper.storage.save(<-dapperOffer, to: DapperOffersV2.DapperOffersStoragePath)
50            dapper.capabilities.publish(
51                dapper.capabilities.storage.issue<&DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath),
52                at: DapperOffersV2.DapperOffersPublicPath
53            )
54        }
55        // Setup Proxy Cancel for Dapper
56        let capabilityReceiver = dapper.capabilities.borrow
57            <&DapperOffersV2.DapperOffer>
58            (DapperOffersV2.DapperOffersPublicPath) ?? panic("Could not borrow capability receiver reference")
59    
60
61        let dapperOfferProxyManagerCapPath = /storage/DapperOfferProxyManagerCapability
62        var dapperOfferProxyManagerCap = signer.storage.copy<Capability<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>>(from: dapperOfferProxyManagerCapPath)
63        if dapperOfferProxyManagerCap == nil || !dapperOfferProxyManagerCap!.check() {
64            self.proxyManagerCap = signer.capabilities.storage.issue<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath)
65            // save capability to storage
66            signer.capabilities.storage.getController(byCapabilityID: self.proxyManagerCap.id)!.setTag("DapperOfferProxyManagerCap")
67            signer.storage.save(
68                self.proxyManagerCap,
69                to: dapperOfferProxyManagerCapPath
70            )
71        } else {
72            self.proxyManagerCap = dapperOfferProxyManagerCap!
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            (DapperOffersV2.DapperOffersPublicPath) ?? 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        // Get the capability to the DUC vault
88        let ducWithdrawCapPath = /storage/DUCWithdrawCapabilityForOffers
89        var ducWithdrawCap = dapper.storage.copy<Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>>(from: ducWithdrawCapPath)
90        if ducWithdrawCap == nil || !ducWithdrawCap!.check() {
91            self.ducVaultRef = dapper.capabilities.storage.issue<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>(/storage/dapperUtilityCoinVault)
92            // save capability to storage
93            dapper.capabilities.storage.getController(byCapabilityID: self.ducVaultRef.id)!.setTag("OffersDUCWithdrawCap")
94            dapper.storage.save(
95                self.ducVaultRef,
96                to: ducWithdrawCapPath
97            )
98        } else{
99            self.ducVaultRef = ducWithdrawCap!
100        }
101
102        // Validate marketplace royalties
103        self.ROYALITY_ADDRESS = 0xfaf0cc52c6e3acaf
104        self.ROYALITY_PERCENT = 0.05000000
105        assert(royalties[self.ROYALITY_ADDRESS] == self.ROYALITY_PERCENT * amount, message: "Missing or mis-typed royalty information for marketplace")
106        assert(royalties.keys.length == 1, message: "please provide only one royalty address")
107        // Validate offerParamsString and resolver for type NFT
108        assert(offerParamsString.containsKey("nftId"), message: "nftId missing from offerParamsString")
109        assert(offerParamsString.containsKey("resolver"), message: "resolver missing from offerParamsString")
110        assert(offerParamsString["resolver"] ==  Resolver.ResolverType.NFT.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        offerParamsString.insert(key: "_type", "NFT")
133        self.dapperOffer.createOffer(
134            vaultRefCapability: self.ducVaultRef,
135            nftReceiverCapability: self.nftReceiver!,
136            nftType: Type<@TopShot.NFT>(),
137            amount: amount,
138            royalties: royaltysList,
139            offerParamsString: offerParamsString,
140            offerParamsUFix64: {},
141            offerParamsUInt64: {},
142            resolverCapability: self.resolverCapability
143        )
144    }
145}