TransactionSEALED

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

Transaction ID

Timestamp

Oct 27, 2025, 10:03:28 PM UTC
4mo ago

Block Height

130,843,537

Computation

0

Transaction Summary

Contract Call

Called NonFungibleToken, FungibleToken, OffersV2 +7 more

Script Arguments

0amountUFix64
0.29000000
1royalties{Address
{
  "0x6590f8918060ef13": "0.00725000"
}
2offerParamsString{String
{
  "expiry": "1764198197"
}
3nftIdUInt64
49030647
4collectionAddressAddress
5collectionNameString
TopShot
6publicPathIdentifierString
MomentCollection
7storagePathIdentifierString
MomentCollection
8proxyAddressAddress
9expiryUInt64
1764198197
10nftTypeIdentifierString
A.0b2a3299cc857e29.TopShot.NFT

Cadence Script

1import NonFungibleToken from 0x1d7e57aa55817448
2import FungibleToken from 0xf233dcee88fe0abe
3import OffersV2 from 0xb8ea91944fd51c43
4import DapperOffersV2 from 0xb8ea91944fd51c43
5import DapperUtilityCoin from 0xead892083b3e2c6c
6import Resolver from 0xb8ea91944fd51c43
7import FlowtyOffersResolver from 0x322d96c958eb8c46
8import StringUtils from 0xa340dc0a4ec828ab
9import NFTStorefrontV2 from 0x3cdbb3d569211ff3
10import FlowtyUtils from 0x3cdbb3d569211ff3
11
12transaction(
13    amount: UFix64,
14    royalties: {Address: UFix64},
15    offerParamsString: {String: String},
16    nftId: UInt64,
17    collectionAddress: Address,
18    collectionName: String,
19    publicPathIdentifier: String,
20    storagePathIdentifier: String,
21    proxyAddress: Address,
22    expiry: UInt64,
23    nftTypeIdentifier: String
24) {
25    var nftReceiver: Capability<&{NonFungibleToken.CollectionPublic}>
26    let dapperOffer: auth(DapperOffersV2.Manager) &DapperOffersV2.DapperOffer
27    let ducVaultRef: Capability<auth(FungibleToken.Withdraw) &DapperUtilityCoin.Vault>
28    let resolverCapability: Capability<&{Resolver.ResolverPublic}>
29    let tokenAdminCollection: Capability<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>
30
31    prepare(signer: auth(Storage, Capabilities) &Account, dapper: auth(Storage, Capabilities) &Account) {
32        let contractAcct = getAccount(collectionAddress)
33        let borrowedContract = contractAcct.contracts.borrow<&{NonFungibleToken}>(name: collectionName) ?? panic("collection not found")
34        let nftType = CompositeType(nftTypeIdentifier) ?? panic("invalid nftTypeIdentifier")
35
36        let storagePath = StoragePath(identifier: storagePathIdentifier)!
37        let publicPath = PublicPath(identifier: publicPathIdentifier)!
38        if signer.storage.borrow<&{NonFungibleToken.CollectionPublic}>(from: storagePath) == nil {
39            let c <- borrowedContract.createEmptyCollection(nftType: nftType)
40            signer.storage.save(<-c, to: storagePath)
41            signer.capabilities.unpublish(publicPath)
42            signer.capabilities.publish(
43                signer.capabilities.storage.issue<&{NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic}>(storagePath),
44                at: publicPath
45            )
46        }
47
48        self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(publicPath)
49        if !self.nftReceiver.check() {
50            signer.capabilities.unpublish(publicPath)
51            signer.capabilities.publish(
52                signer.capabilities.storage.issue<&{NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic}>(storagePath),
53                at: publicPath
54            )
55            self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(publicPath)
56        }
57
58        let dapperOfferType = Type<@DapperOffersV2.DapperOffer>()
59
60        // Link the DapperOffer resource
61        if signer.storage.borrow<&DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath) == nil {
62            let dapperOffer <- DapperOffersV2.createDapperOffer()
63            signer.storage.save(<-dapperOffer, to: DapperOffersV2.DapperOffersStoragePath)
64            signer.capabilities.publish(
65                signer.capabilities.storage.issue<&{DapperOffersV2.DapperOfferPublic}>(DapperOffersV2.DapperOffersStoragePath),
66                at: DapperOffersV2.DapperOffersPublicPath
67            )
68
69            let managerStoragePath = /storage/flowtyDapperOfferManager
70            let cap = signer.storage.copy<Capability<auth(DapperOffersV2.Manager) &{DapperOffersV2.DapperOfferManager}>>(from: managerStoragePath)
71            if cap?.check() != true {
72                let managerCap = signer.capabilities.storage.issue<auth(DapperOffersV2.Manager) &{DapperOffersV2.DapperOfferManager}>(DapperOffersV2.DapperOffersStoragePath)
73                signer.storage.save(managerCap, to: managerStoragePath)
74            }
75        }
76
77        // DapperOfferProxyManager Setup
78        let proxyStoragePath = /storage/flowtyDapperOfferProxy
79        let copiedProxy = signer.storage.copy<Capability<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>>(from: proxyStoragePath)
80        if copiedProxy?.check() == true {
81            self.tokenAdminCollection = copiedProxy!
82        } else {
83            self.tokenAdminCollection = signer.capabilities.storage.issue<auth(DapperOffersV2.ProxyManager) &DapperOffersV2.DapperOffer>(DapperOffersV2.DapperOffersStoragePath)
84            signer.storage.load<AnyStruct>(from: proxyStoragePath)
85            signer.storage.save(self.tokenAdminCollection, to: proxyStoragePath)
86        }
87
88        if dapper.storage.borrow<&DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath) == nil {
89            let dapperOffer <- DapperOffersV2.createDapperOffer()
90            dapper.storage.save(<-dapperOffer, to: DapperOffersV2.DapperOffersStoragePath)
91            dapper.capabilities.publish(
92                dapper.capabilities.storage.issue<&{DapperOffersV2.DapperOfferPublic}>(DapperOffersV2.DapperOffersStoragePath),
93                at: DapperOffersV2.DapperOffersPublicPath
94            )
95
96            let proxyManagerStoragePath = /storage/dapperProxyManager
97            let proxyCap = dapper.capabilities.storage.issue<auth(DapperOffersV2.ProxyManager) &{DapperOffersV2.DapperOfferManager, DapperOffersV2.DapperOfferProxyManager}>(DapperOffersV2.DapperOffersStoragePath)
98            dapper.storage.save(proxyCap, to: proxyManagerStoragePath)
99        }
100
101        // Setup Proxy Cancel for Dapper
102        let capabilityReceiver = dapper.capabilities.get<&{DapperOffersV2.DapperOfferPublic}>(/public/DapperOffersV2).borrow()
103            ?? panic("Could not borrow capability receiver reference")
104        capabilityReceiver.addProxyCapability(account: signer.address, cap: self.tokenAdminCollection)
105
106        // Get the capability to the offer creators NFT collection
107        self.nftReceiver = signer.capabilities.get<&{NonFungibleToken.CollectionPublic}>(publicPath)
108        assert(self.nftReceiver.check(), message: "Missing or mis-typed collection receiver")
109
110        self.dapperOffer = signer.storage.borrow<auth(DapperOffersV2.Manager) &DapperOffersV2.DapperOffer>(from: DapperOffersV2.DapperOffersStoragePath)
111            ?? panic("Missing or mis-typed DapperOffersV2.DapperOffer")
112        // Get the capability to the DUC vault
113
114        let ducCapStoragePath = /storage/flowtyDucProvider
115        let copiedDucProvider = dapper.storage.copy<Capability<auth(FungibleToken.Withdraw) &DapperUtilityCoin.Vault>>(from: ducCapStoragePath)
116        if copiedDucProvider?.check() == true {
117            self.ducVaultRef = copiedDucProvider!
118        } else {
119            self.ducVaultRef = dapper.capabilities.storage.issue<auth(FungibleToken.Withdraw) &DapperUtilityCoin.Vault>(/storage/dapperUtilityCoinVault)
120            dapper.storage.save(self.ducVaultRef, to: ducCapStoragePath)
121        }
122
123        assert(self.ducVaultRef.check() != nil, message: "Missing or mis-typed DapperUtilityCoin provider")
124        self.resolverCapability = FlowtyOffersResolver.getResolverCap()
125    }
126
127    execute {
128        var royaltysList: [OffersV2.Royalty] = []
129        for k in royalties.keys {
130            royaltysList.append(OffersV2.Royalty(
131                receiver: getAccount(k).capabilities.get<&{FungibleToken.Receiver}>(/public/dapperUtilityCoinReceiver),
132                amount: royalties[k]!
133            ))
134        }
135
136        let str = collectionAddress.toString()
137        let typeId = StringUtils.join(["A", str.slice(from: 2, upTo: str.length), collectionName, "NFT"], ".")
138
139        offerParamsString.insert(key: "nftId", nftId.toString())
140        offerParamsString.insert(key: "resolver", FlowtyOffersResolver.ResolverType.NFT.rawValue.toString())
141        offerParamsString.insert(key: "_type", "NFT")
142        offerParamsString.insert(key: "typeId", typeId)
143
144        let offerParamsUInt64: {String: UInt64} = { "expiry": expiry }
145
146        self.dapperOffer.createOffer(
147            vaultRefCapability: self.ducVaultRef,
148            nftReceiverCapability: self.nftReceiver,
149            nftType: CompositeType(typeId)!,
150            amount: amount,
151            royalties: royaltysList,
152            offerParamsString: offerParamsString,
153            offerParamsUFix64: {},
154            offerParamsUInt64: offerParamsUInt64,
155            resolverCapability: self.resolverCapability
156        )
157    }
158}