From d9ef40e75182157c8fd9dc1d3f890450506758ab Mon Sep 17 00:00:00 2001 From: Giovanni Sanchez <108043524+sisyphusSmiling@users.noreply.github.com> Date: Fri, 20 Oct 2023 18:50:50 -0500 Subject: [PATCH] update NFTForwarding transactions for new implementation --- .../change_forwarder_recipient.cdc | 35 ----------- .../NFTForwarding/create_forwarder.cdc | 63 ------------------- .../transfer_nft_to_receiver.cdc | 44 ------------- .../unlink_forwarder_link_collection.cdc | 29 --------- .../change_forwarder_recipient.cdc | 30 +++++++++ .../nft-forwarding/create_forwarder.cdc | 29 +++++++++ .../transfer_nft_to_receiver.cdc | 50 +++++++++++++++ .../unlink_forwarder_link_collection.cdc | 26 ++++++++ 8 files changed, 135 insertions(+), 171 deletions(-) delete mode 100644 transactions/NFTForwarding/change_forwarder_recipient.cdc delete mode 100644 transactions/NFTForwarding/create_forwarder.cdc delete mode 100644 transactions/NFTForwarding/transfer_nft_to_receiver.cdc delete mode 100644 transactions/NFTForwarding/unlink_forwarder_link_collection.cdc create mode 100644 transactions/nft-forwarding/change_forwarder_recipient.cdc create mode 100644 transactions/nft-forwarding/create_forwarder.cdc create mode 100644 transactions/nft-forwarding/transfer_nft_to_receiver.cdc create mode 100644 transactions/nft-forwarding/unlink_forwarder_link_collection.cdc diff --git a/transactions/NFTForwarding/change_forwarder_recipient.cdc b/transactions/NFTForwarding/change_forwarder_recipient.cdc deleted file mode 100644 index 7bce00ee..00000000 --- a/transactions/NFTForwarding/change_forwarder_recipient.cdc +++ /dev/null @@ -1,35 +0,0 @@ -/// This transaction is what an account would run -/// to change the NFTForwarder recipient - -import NonFungibleToken from "NonFungibleToken" -import ExampleNFT from "ExampleNFT" -import NFTForwarding from "NFTForwarding" - -transaction(newRecipientAddress: Address) { - - /// Reference to the NFTFowarder Resource - let forwarderRef: &NFTForwarding.NFTForwarder - /// Collection we will designate as forwarding recipient - let newRecipientCollection: Capability<&{NonFungibleToken.CollectionPublic}> - - prepare(signer: AuthAccount) { - // Borrow reference to NFTForwarder resource - self.forwarderRef = signer - .borrow<&NFTForwarding.NFTForwarder>(from: NFTForwarding.StoragePath) - ?? panic("Could not borrow reference to NFTForwarder") - - // Get Receiver Capability from the recipientAddress account - self.newRecipientCollection = getAccount(newRecipientAddress) - .getCapability<&{NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath) - - // Make sure the CollectionPublic capability is valid before minting the NFT - if !self.newRecipientCollection.check() { - panic("CollectionPublic capability is not valid!") - } - } - - execute { - // Set new recipient - self.forwarderRef.changeRecipient(newRecipient: self.newRecipientCollection) - } -} diff --git a/transactions/NFTForwarding/create_forwarder.cdc b/transactions/NFTForwarding/create_forwarder.cdc deleted file mode 100644 index 349011ce..00000000 --- a/transactions/NFTForwarding/create_forwarder.cdc +++ /dev/null @@ -1,63 +0,0 @@ -/// This transaction is what an account would run -/// to set itself up to forward NFTs to a designated -/// recipient's collection - -import NonFungibleToken from "NonFungibleToken" -import MetadataViews from "MetadataViews" -import ExampleNFT from "ExampleNFT" -import NFTForwarding from "NFTForwarding" - -transaction(recipientAddress: Address) { - - prepare(signer: AuthAccount) { - // Change recipient and return if the account already has an NFTForwarder - if signer.borrow<&NFTForwarding.NFTForwarder>(from: NFTForwarding.StoragePath) != nil { - - let forwarderRef = signer.borrow<&NFTForwarding.NFTForwarder>(from: NFTForwarding.StoragePath)! - let newRecipientCollection = getAccount(recipientAddress) - .getCapability<&{NonFungibleToken.CollectionPublic}>(ExampleNFT.CollectionPublicPath) - - // Make sure the CollectionPublic capability is valid before minting the NFT - if !newRecipientCollection.check() { - panic("Recipient's CollectionPublic capability is not valid!") - } - - // Set new recipient - forwarderRef.changeRecipient(newRecipient: newRecipientCollection) - return - } - - // Get Receiver Capability from the recipientAddress account - let recipientCollectionCap = getAccount(recipientAddress) - .getCapability< - &{NonFungibleToken.CollectionPublic} - >( - ExampleNFT.CollectionPublicPath - ) - - // Make sure the CollectionPublic capability is valid before minting the NFT - if !recipientCollectionCap.check() { panic("CollectionPublic capability is not valid!") } - - // Create a new NFTForwarder resource - let forwarder <- NFTForwarding.createNewNFTForwarder(recipient: recipientCollectionCap) - - // save it to the account - signer.save(<-forwarder, to: NFTForwarding.StoragePath) - - // unlink existing Collection capabilities from PublicPath - if signer.getCapability(ExampleNFT.CollectionPublicPath) - .check<&{ - NonFungibleToken.CollectionPublic, - ExampleNFT.ExampleNFTCollectionPublic, - MetadataViews.ResolverCollection - }>() { - signer.unlink(ExampleNFT.CollectionPublicPath) - } - - // create a public capability for the forwarder where the collection would be - signer.link<&{NonFungibleToken.Receiver}>( - ExampleNFT.CollectionPublicPath, - target: NFTForwarding.StoragePath - ) - } -} diff --git a/transactions/NFTForwarding/transfer_nft_to_receiver.cdc b/transactions/NFTForwarding/transfer_nft_to_receiver.cdc deleted file mode 100644 index e4316dc2..00000000 --- a/transactions/NFTForwarding/transfer_nft_to_receiver.cdc +++ /dev/null @@ -1,44 +0,0 @@ -/// This transaction is for transferring an NFT from -/// one account to another using the recipient's Receiver resource -/// which is more limited than a CollectionPublic Resource - -import NonFungibleToken from "NonFungibleToken" -import ExampleNFT from "ExampleNFT" - -transaction(recipient: Address, withdrawID: UInt64) { - - /// Reference to the withdrawer's collection - let withdrawRef: &ExampleNFT.Collection - - /// Reference of the Receiver to deposit the NFT to - let depositRef: &{NonFungibleToken.Receiver} - - prepare(signer: AuthAccount) { - // borrow a reference to the signer's NFT collection - self.withdrawRef = signer - .borrow<&ExampleNFT.Collection>(from: ExampleNFT.CollectionStoragePath) - ?? panic("Account does not store an object at the specified path") - - // get the recipients public account object - let recipient = getAccount(recipient) - - // borrow a public reference to the recipient's Receiver - self.depositRef = recipient - .getCapability(ExampleNFT.CollectionPublicPath) - .borrow<&{NonFungibleToken.Receiver}>() - ?? panic("Could not borrow a reference to the recipient's Receiver") - } - - execute { - - // withdraw the NFT from the owner's collection - let nft <- self.withdrawRef.withdraw(withdrawID: withdrawID) - - // Deposit the NFT in the recipient - self.depositRef.deposit(token: <-nft) - } - - post { - !self.withdrawRef.getIDs().contains(withdrawID): "Original owner should not have the NFT anymore" - } -} diff --git a/transactions/NFTForwarding/unlink_forwarder_link_collection.cdc b/transactions/NFTForwarding/unlink_forwarder_link_collection.cdc deleted file mode 100644 index 2beeb218..00000000 --- a/transactions/NFTForwarding/unlink_forwarder_link_collection.cdc +++ /dev/null @@ -1,29 +0,0 @@ -/// This transaction is what an account would run -/// to link a collection to its public storage -/// after having configured its NFTForwarder - -import NonFungibleToken from "NonFungibleToken" -import MetadataViews from "MetadataViews" -import ExampleNFT from "ExampleNFT" -import NFTForwarding from "NFTForwarding" - -transaction { - - prepare(signer: AuthAccount) { - if signer.getCapability(ExampleNFT.CollectionPublicPath).check<&{ExampleNFT.ExampleNFTCollectionPublic}>() { - log("Collection already configured for PublicPath") - return - } - - if signer.getCapability(ExampleNFT.CollectionPublicPath).check<&{NonFungibleToken.Receiver}>() { - log("Unlinking NFTForwarder from PublicPath") - signer.unlink(ExampleNFT.CollectionPublicPath) - } - - // create a public capability for the collection - signer.link<&{NonFungibleToken.CollectionPublic, ExampleNFT.ExampleNFTCollectionPublic, MetadataViews.ResolverCollection}>( - ExampleNFT.CollectionPublicPath, - target: ExampleNFT.CollectionStoragePath - ) - } -} diff --git a/transactions/nft-forwarding/change_forwarder_recipient.cdc b/transactions/nft-forwarding/change_forwarder_recipient.cdc new file mode 100644 index 00000000..6b2cb0ca --- /dev/null +++ b/transactions/nft-forwarding/change_forwarder_recipient.cdc @@ -0,0 +1,30 @@ +import NonFungibleToken from "NonFungibleToken" +import NFTForwarding from "NFTForwarding" + +/// This transaction updates the NFTForwarder recipient to the one given at the specified PublicPath +/// +transaction(newRecipientAddress: Address, collectionPublicPath: PublicPath) { + + // reference to the NFTFowarder Resource + let forwarderRef: auth(NFTForwarding.Mutable) &NFTForwarding.NFTForwarder + // Collection we will designate as forwarding recipient + let newRecipientCollection: Capability<&{NonFungibleToken.Collection}> + + prepare(signer: auth(BorrowValue) &Account) { + // borrow reference to NFTForwarder resource + self.forwarderRef = signer.storage.borrow( + from: NFTForwarding.StoragePath + ) ?? panic("Could not borrow reference to NFTForwarder") + + // get Collection Capability from the recipientAddress account + self.newRecipientCollection = getAccount(newRecipientAddress).capabilities.get<&{NonFungibleToken.Collection}>( + collectionPublicPath + ) ?? panic("Could not get Collection capability from recipient") + + } + + execute { + // set new recipient + self.forwarderRef.changeRecipient(self.newRecipientCollection) + } +} diff --git a/transactions/nft-forwarding/create_forwarder.cdc b/transactions/nft-forwarding/create_forwarder.cdc new file mode 100644 index 00000000..b98a4615 --- /dev/null +++ b/transactions/nft-forwarding/create_forwarder.cdc @@ -0,0 +1,29 @@ +import NonFungibleToken from "NonFungibleToken" +import MetadataViews from "MetadataViews" +import NFTForwarding from "NFTForwarding" + +/// This transaction is what an account would run to set itself up to forward NFTs to a designated recipient's +/// NFT.Collection assuming the recipient is configured for the given NFT Collection +/// +transaction(recipientAddress: Address, collectionPublicPath: PublicPath) { + + prepare(signer: auth(BorrowValue, IssueStorageCapabilityController, PublishCapability, SaveValue) &Account) { + + // get Collection Capability from the recipientAddress account + let recipientCollectionCap = getAccount(recipientAddress).capabilities.get<&{NonFungibleToken.Collection}>( + collectionPublicPath + ) ?? panic("Recipient is not configured with NFT Collection at the given path") + + // create a new NFTForwarder resource & save in storage, forwarding to the recipient's Collection + let forwarder <- NFTForwarding.createNewNFTForwarder(recipient: recipientCollectionCap) + signer.storage.save(<-forwarder, to: NFTForwarding.StoragePath) + + // unpublish existing Collection capabilities from PublicPath + signer.capabilities.unpublish(collectionPublicPath) + + // create & publish a capability for the forwarder where the collection would normally be + let forwarderReceiverCap = signer.capabilities.storage.issue<&{NonFungibleToken.Receiver}>(NFTForwarding.StoragePath) + signer.capabilities.publish(forwarderReceiverCap, at: collectionPublicPath) + + } +} diff --git a/transactions/nft-forwarding/transfer_nft_to_receiver.cdc b/transactions/nft-forwarding/transfer_nft_to_receiver.cdc new file mode 100644 index 00000000..ad9cec64 --- /dev/null +++ b/transactions/nft-forwarding/transfer_nft_to_receiver.cdc @@ -0,0 +1,50 @@ +import NonFungibleToken from "NonFungibleToken" +import ViewResolver from "ViewResolver" +import MetadataViews from "MetadataViews" + +/// This transaction is for transferring an NFT from one account to the recipient's Receiver +/// +transaction( + contractAddress: Address, + contractName: String, + recipient: Address, + withdrawID: UInt64 +) { + + // reference to the withdrawer's collection + let withdrawRef: auth(Withdrawable) &{NonFungibleToken.Collection} + // reference of the Receiver to deposit the NFT to + let depositRef: &{NonFungibleToken.Receiver} + + prepare(signer: auth(BorrowValue) &Account) { + + // get the collection data from the NFT contract + let nftContract = getAccount(contractAddress).contracts.borrow<&ViewResolver>(name: contractName) + ?? panic("Could not borrow ViewResolver reference to the contract") + let collectionData = nftContract.resolveView(Type()) as MetadataViews.NFTCollectionData? + ?? panic("Could not resolve NFTCollectionData view") + + // borrow a reference to the signer's NFT collection + self.withdrawRef = signer.storage.borrow( + from: collectionData.storagePath + ) ?? panic("Account does not store an object at the specified path") + + // borrow a public reference to the recipient's Receiver + self.depositRef = getAccount(recipient).capabilities.borrow<&{NonFungibleToken.Receiver}>( + collectionData.publicPath + ) ?? panic("Could not borrow a reference to the recipient's Receiver") + } + + execute { + + // withdraw the NFT from the owner's collection + let nft <- self.withdrawRef.withdraw(withdrawID: withdrawID) + + // Deposit the NFT in the recipient + self.depositRef.deposit(token: <-nft) + } + + post { + !self.withdrawRef.getIDs().contains(withdrawID): "Original owner should not have the NFT anymore" + } +} diff --git a/transactions/nft-forwarding/unlink_forwarder_link_collection.cdc b/transactions/nft-forwarding/unlink_forwarder_link_collection.cdc new file mode 100644 index 00000000..46a5fd6d --- /dev/null +++ b/transactions/nft-forwarding/unlink_forwarder_link_collection.cdc @@ -0,0 +1,26 @@ + +import NonFungibleToken from "NonFungibleToken" +import MetadataViews from "MetadataViews" +import NFTForwarding from "NFTForwarding" + +// This transaction replaces NFTForwarder Receiver Capabilities with a collection to its public storage after having configured +// its NFTForwarder +/// +transaction(collectionStoragePath: StoragePath, receiverPublicPath: PublicPath) { + + prepare(signer: AuthAccount) { + + // a collection is already published, do nothing - remember .NFTForwarder only conforms to NFT.Receiver + if signer.capabilities.get<&{NonFungibleToken.Collection}>(receiverPublicPath) != nil { + return + } + + // otherwise, unpublish the published Capability + signer.capabilities.unpublish(receiverPublicPath) + + // create & publish a capability for the collection + let collectionCap = signer.capabilities.storage.issue<&{NonFungibleToken.Collection}>(collectionStoragePath) + signer.capabilities.publish(collectionCap, receiverPublicPath) + + } +}