diff --git a/transactions/example-nft/mint_nft.cdc b/transactions/example-nft/mint_nft.cdc new file mode 100644 index 0000000..51f41a6 --- /dev/null +++ b/transactions/example-nft/mint_nft.cdc @@ -0,0 +1,90 @@ +/// This script uses the NFTMinter resource to mint a new NFT +/// It must be run with the account that has the minter resource +/// stored in /storage/NFTMinter + +import "NonFungibleToken" +import "ExampleNFT" +import "MetadataViews" +import "FungibleToken" + +transaction( + recipient: Address, + name: String, + description: String, + thumbnail: String, + cuts: [UFix64], + royaltyDescriptions: [String], + royaltyBeneficiaries: [Address] +) { + + /// local variable for storing the minter reference + let minter: &ExampleNFT.NFTMinter + + /// Reference to the receiver's collection + let recipientCollectionRef: &{NonFungibleToken.CollectionPublic} + + /// Previous NFT ID before the transaction executes + let mintingIDBefore: UInt64 + + prepare(signer: AuthAccount) { + self.mintingIDBefore = ExampleNFT.totalSupply + + // borrow a reference to the NFTMinter resource in storage + self.minter = signer.borrow<&ExampleNFT.NFTMinter>(from: ExampleNFT.MinterStoragePath) + ?? panic("Account does not store an object at the specified path") + + // Borrow the recipient's public NFT collection reference + self.recipientCollectionRef = getAccount(recipient).getCapability<&{NonFungibleToken.CollectionPublic}>( + ExampleNFT.CollectionPublicPath + ).borrow() + ?? panic("Could not get receiver reference to the NFT Collection") + } + + pre { + cuts.length == royaltyDescriptions.length && cuts.length == royaltyBeneficiaries.length: + "Array length should be equal for royalty related details" + } + + execute { + + // Create the royalty details + var count = 0 + var royalties: [MetadataViews.Royalty] = [] + while royaltyBeneficiaries.length > count { + let beneficiary = royaltyBeneficiaries[count] + let beneficiaryCapability = getAccount(beneficiary).getCapability<&{FungibleToken.Receiver}>( + MetadataViews.getRoyaltyReceiverPublicPath() + ) + + // Make sure the royalty capability is valid before minting the NFT + assert(beneficiaryCapability.check(), message: "Beneficiary capability is not valid!") + + royalties.append( + MetadataViews.Royalty( + receiver: beneficiaryCapability, + cut: cuts[count], + description: royaltyDescriptions[count] + ) + ) + count = count + 1 + } + + + + // Mint the NFT and deposit it to the recipient's collection + self.minter.mintNFT( + recipient: self.recipientCollectionRef, + name: name, + description: description, + thumbnail: thumbnail, + royalties: royalties + ) + } + + post { + self.recipientCollectionRef.getIDs().contains(self.mintingIDBefore): + "The next NFT ID should have been minted and delivered" + ExampleNFT.totalSupply == self.mintingIDBefore + 1: + "The total supply should have been increased by 1" + } +} diff --git a/transactions/example-nft/setup_account.cdc b/transactions/example-nft/setup_account.cdc new file mode 100644 index 0000000..f56bf2f --- /dev/null +++ b/transactions/example-nft/setup_account.cdc @@ -0,0 +1,40 @@ +/// This transaction is what an account would run +/// to set itself up to receive NFTs + +import "NonFungibleToken" +import "ExampleNFT" +import "MetadataViews" + +transaction { + + prepare(signer: AuthAccount) { + // Return early if the account already has a collection + if signer.borrow<&ExampleNFT.Collection>(from: ExampleNFT.CollectionStoragePath) == nil { + // Create a new empty collection + let collection <- ExampleNFT.createEmptyCollection() + + // save it to the account + signer.save(<-collection, to: ExampleNFT.CollectionStoragePath) + } + + // create a public capability for the collection + if signer.getCapability<&{NonFungibleToken.CollectionPublic, ExampleNFT.ExampleNFTCollectionPublic, MetadataViews.ResolverCollection}>( + ExampleNFT.CollectionPublicPath + ).check() == false { + signer.unlink(ExampleNFT.CollectionPublicPath) + signer.link<&{NonFungibleToken.CollectionPublic, ExampleNFT.ExampleNFTCollectionPublic, MetadataViews.ResolverCollection}>( + ExampleNFT.CollectionPublicPath, + target: ExampleNFT.CollectionStoragePath + ) + } + + let providerPath: PrivatePath = /private/exampleNFTProvider + if signer.getCapability<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>(providerPath).check() == false { + signer.unlink(/private/exampleNFTProvider) + signer.link<&{NonFungibleToken.Provider, NonFungibleToken.CollectionPublic}>( + providerPath, + target: ExampleNFT.CollectionStoragePath + ) + } + } +} diff --git a/transactions/example-nft/transfer_nft.cdc b/transactions/example-nft/transfer_nft.cdc new file mode 100644 index 0000000..80bb712 --- /dev/null +++ b/transactions/example-nft/transfer_nft.cdc @@ -0,0 +1,44 @@ +/// This transaction is for transferring and NFT from +/// one account to another + +import "NonFungibleToken" +import "ExampleNFT" + +transaction(recipient: Address, withdrawID: UInt64) { + + /// Reference to the withdrawer's collection + let withdrawRef: &ExampleNFT.Collection + + /// Reference of the collection to deposit the NFT to + let depositRef: &{NonFungibleToken.CollectionPublic} + + 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 receivers collection + self.depositRef = recipient.getCapability<&{NonFungibleToken.CollectionPublic}>( + ExampleNFT.CollectionPublicPath + ).borrow() + ?? panic("Could not borrow a reference to the receiver's collection") + + } + + execute { + + // withdraw the NFT from the owner's collection + let nft <- self.withdrawRef.withdraw(withdrawID: withdrawID) + + // Deposit the NFT in the recipient's collection + self.depositRef.deposit(token: <-nft) + } + + post { + !self.withdrawRef.getIDs().contains(withdrawID): "Original owner should not have the NFT anymore" + self.depositRef.getIDs().contains(withdrawID): "The reciever should now own the NFT" + } +}