TransactionSEALED
◆~▓~░*╱□█?▪╲█╳▫?^◇&▫&@!▪●%$▒╲■^░*░~◆╱◇@▒$◇▫▪▫◆▓@●@▒^^$□■▪▫◆○╱%╲░
Transaction ID
Execution Fee
0.00002199 FLOWTransaction 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}