TransactionSEALED

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

Transaction ID

Timestamp

Sep 03, 2025, 03:15:47 AM UTC
6mo ago

Block Height

125,021,643

Computation

0

Execution Fee

0.00002199 FLOW

Transaction Summary

Contract Call

Called Swap, Utils, MetadataViews +4 more

Script Arguments

Copy:

Cadence Script

1import Swap from 0x15f55a75d7843780
2import Utils from 0x15f55a75d7843780
3import MetadataViews from 0x1d7e57aa55817448
4import NonFungibleToken from 0x1d7e57aa55817448
5import FungibleToken from 0xf233dcee88fe0abe
6import ViewResolver from 0x1d7e57aa55817448
7import DapperWalletRestrictions from 0x2d4cebdb9eca6f49
8
9access(all) fun getStorageCapability(
10    _ signer: auth(Storage, Capabilities) &Account,
11    storagePath: StoragePath,
12    capabilityType: Type
13): Capability? {
14    var capability: Capability? = nil
15    signer.capabilities.storage.forEachController(forPath: storagePath, fun (controller: &StorageCapabilityController): Bool {
16        if (!controller.capability.isInstance(capabilityType)) {
17            return true
18        }
19        capability = controller.capability
20        return false
21    })
22    return capability
23}
24
25access(all) fun getVaultCapabilities(_ signer: auth(Storage, Capabilities) &Account, vaultIdentifier: String): {String: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Provider, FungibleToken.Balance}>} {
26    let unsupportedVaultError = "unsupported vault for "
27    let missingVaultError = "missing vault for "
28    let capabilities: {String: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Provider, FungibleToken.Balance}>} = { }
29    let unsupportedError = unsupportedVaultError.concat(vaultIdentifier)
30    let vaultType = CompositeType(vaultIdentifier) ?? panic(unsupportedError)
31    let dataMap = Utils.getTypeFTVaultData([vaultType])
32    let data = dataMap[vaultType] ?? panic(unsupportedError)
33    var capability = getStorageCapability(signer, storagePath: data.storagePath, capabilityType: Type<Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>>()) as! Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>?
34    if (capability == nil) {
35        assert(signer.storage.type(at: Swap.SwapCollectionStoragePath) == Type<&{FungibleToken.Vault}>(), message: missingVaultError.concat(vaultType.identifier))
36        capability = signer.capabilities.storage.issue<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>(data.storagePath)
37    }
38    capabilities.insert(key: vaultType.identifier, capability!)
39    return capabilities
40}
41
42access(all) fun getNftCapabilities(_ signer: auth(Storage, Capabilities) &Account, nfts: [Swap.ProposedTradeAsset]): {String: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>} {
43    let missingError = "missing or invalid capability for "
44    let capabilities: {String: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>} = { }
45    for nft in nfts {
46        if (capabilities.containsKey(nft.type.identifier)){
47            continue
48        }
49        let capablity = getStorageCapability(signer, storagePath: nft.collectionData.storagePath, capabilityType: Type<Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>>()) as! Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>?
50        assert(capablity != nil && capablity!.check(), message: missingError.concat(nft.type.identifier))
51        capabilities.insert(key: nft.type.identifier, capablity!)
52    }
53    return capabilities
54}
55
56access(all) fun initializeCollections(
57    _ signer: auth(Storage, Capabilities) &Account,
58    collectionDataMap: { Type: MetadataViews.NFTCollectionData },
59    proposedNfts: [[Swap.ProposedTradeAsset]]
60): Void {
61    let initializedTypes: [Type] = []
62    for nfts in proposedNfts {
63        for nft in nfts {
64            if (initializedTypes.contains(nft.type)) {
65                continue
66            }
67            let restriction = DapperWalletRestrictions.getConfig(nft.collectionData.publicCollection)
68            assert(restriction == nil || restriction!.flags["CAN_INIT"] != false, message: "NFT type not allowed: ".concat(nft.type.identifier))
69            let collectionData = collectionDataMap[nft.type] ?? panic("collection data lookup failed for: ".concat(nft.type.identifier))
70            if (signer.storage.type(at: collectionData.storagePath) == nil) {
71                signer.storage.save(<-collectionData.createEmptyCollection(), to: collectionData.storagePath)
72            }
73            let hasPrivilegedCapability = getStorageCapability(signer, storagePath: collectionData.storagePath, capabilityType: Type<Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>>()) != nil
74            if (!hasPrivilegedCapability) {
75                signer.capabilities.storage.issue<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Collection}>(collectionData.storagePath)
76            }
77            if (signer.capabilities.borrow<&{NonFungibleToken.Collection}>(collectionData.publicPath) == nil) {
78                let capability = signer.capabilities.storage.issue<&{NonFungibleToken.Collection}>(collectionData.storagePath)
79                signer.capabilities.unpublish(collectionData.publicPath)
80                signer.capabilities.publish(capability, at: collectionData.publicPath)
81            }
82            initializedTypes.append(nft.type)
83        }
84    }
85}
86
87access(all) fun getSwapManager(_ signer: auth(Storage, Capabilities) &Account): auth(Swap.CreateProposal, Swap.DeleteProposal) &Swap.SwapCollection {
88    let storedType = signer.storage.type(at: Swap.SwapCollectionStoragePath)
89    if (storedType != nil && storedType != Type<@Swap.SwapCollection>()) {
90        let oldCollection <- signer.storage.load<@AnyResource>(from: Swap.SwapCollectionStoragePath)
91        destroy oldCollection
92    }
93    if (signer.storage.type(at: Swap.SwapCollectionStoragePath) == nil) {
94        let newCollection <- Swap.createEmptySwapCollection()
95        signer.storage.save(<-newCollection, to: Swap.SwapCollectionStoragePath)
96    }
97    let hasPrivilegedCapability = getStorageCapability(signer, storagePath: Swap.SwapCollectionStoragePath, capabilityType: Type<Capability<auth(Swap.CreateProposal, Swap.DeleteProposal) &Swap.SwapCollection>>()) != nil
98    if (!hasPrivilegedCapability) {
99        signer.capabilities.storage.issue<auth(Swap.CreateProposal, Swap.DeleteProposal) &Swap.SwapCollection>(Swap.SwapCollectionStoragePath)
100    }
101    if (signer.capabilities.borrow<&Swap.SwapCollection>(Swap.SwapCollectionPublicPath) == nil) {
102        let capability = signer.capabilities.storage.issue<&Swap.SwapCollection>(Swap.SwapCollectionStoragePath)
103        signer.capabilities.unpublish(Swap.SwapCollectionPublicPath)
104        signer.capabilities.publish(capability, at: Swap.SwapCollectionPublicPath)
105    }
106    return signer.storage.borrow<auth(Swap.CreateProposal, Swap.DeleteProposal) &Swap.SwapCollection>(from: Swap.SwapCollectionStoragePath) ?? panic("invalid manager reference")
107}
108
109// v1
110transaction() {
111    let leftUserNfts: {String: [UInt64]}
112    let rightUserNfts: {String: [UInt64]}
113    let leftUserOffer: Swap.UserOffer
114    let rightUserOffer: Swap.UserOffer
115    let leftCollectionReceiverCapabilities: {String: Capability<&{NonFungibleToken.Receiver}>}
116    let leftCollectionProviderCapabilities: {String: Capability<auth(NonFungibleToken.Withdraw) &{NonFungibleToken.Provider}>}
117    var leftFeeProviderCapabilities: {String: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Provider, FungibleToken.Balance}>}
118    let signer: auth(Storage, Capabilities) &Account
119
120    prepare(signer: auth(Storage, Capabilities) &Account) {
121        self.leftUserNfts = {"A.edf9df96c92f4595.Pinnacle.NFT": [219902326534548]}
122        self.rightUserNfts = {"A.edf9df96c92f4595.Pinnacle.NFT": [162727721883462]}
123        self.signer = signer
124        self.leftFeeProviderCapabilities = { }
125        let collectionDataMap = Utils.getIdentifierNFTCollectionData(self.leftUserNfts.keys.concat(self.rightUserNfts.keys))
126        let toProposedNfts = fun (ownerAddress: Address, _ nfts: { String: [UInt64] }): [Swap.ProposedTradeAsset] {
127            let proposedNfts: [Swap.ProposedTradeAsset] = []
128            nfts.forEachKey(fun (identifier: String): Bool {
129                for nftID in nfts[identifier]! {
130                    let compositeType = CompositeType(identifier) ?? panic("unable to cast type; must be a valid NFT type reference")
131                    proposedNfts.append(Swap.ProposedTradeAsset(
132                        nftID: nftID,
133                        type: compositeType,
134                        collectionData: collectionDataMap[compositeType] ?? panic("no collection data for ".concat(compositeType.identifier))
135                    ))
136                }
137                return true
138            })
139            return proposedNfts
140        }
141        let leftProposedNfts = toProposedNfts(ownerAddress: signer.address, self.leftUserNfts)
142        let rightProposedNfts = toProposedNfts(ownerAddress: 0x854edd1c03c2cf50, self.rightUserNfts)
143        initializeCollections(
144            signer,
145            collectionDataMap: collectionDataMap,
146            proposedNfts: [leftProposedNfts, rightProposedNfts]
147        )
148        Swap.assertProposedNftRestrictions(leftProposedNfts, rightProposedNfts)
149
150        if false {
151            self.leftFeeProviderCapabilities = getVaultCapabilities(signer, vaultIdentifier: ""!)
152        }
153
154        self.leftUserOffer = Swap.UserOffer(userAddress: signer.address, proposedNfts: leftProposedNfts, metadata: nil)
155        self.rightUserOffer = Swap.UserOffer(userAddress: 0x854edd1c03c2cf50, proposedNfts: rightProposedNfts, metadata: nil)
156        self.leftCollectionReceiverCapabilities = getNftCapabilities(signer, nfts: self.rightUserOffer.proposedNfts)
157        self.leftCollectionProviderCapabilities = getNftCapabilities(signer, nfts: self.leftUserOffer.proposedNfts)
158    }
159
160    execute {
161        getSwapManager(self.signer).createProposal(
162            leftUserOffer: self.leftUserOffer,
163            rightUserOffer: self.rightUserOffer,
164            leftUserCapabilities: Swap.UserCapabilities(
165                collectionReceiverCapabilities: self.leftCollectionReceiverCapabilities,
166                collectionProviderCapabilities: self.leftCollectionProviderCapabilities,
167                feeProviderCapabilities: self.leftFeeProviderCapabilities,
168                extraCapabilities: nil
169            ),
170            expirationOffsetMinutes: 1440.00000000,
171            metadata: {"environmentId": "disney"}
172        )
173    }
174}