Capacidades

Quando armazenamos dados em uma conta em um caminho de armazenamento, esses dados só são acessíveis pelo proprietário da conta.

Podemos “vincular” (usando a função link) dados armazenados em um caminho de armazenamento a um caminho público, o que cria uma capacidade. A capacidade então atua como uma chave para outras pessoas acessarem esses dados públicos.

Podemos restringir capacidades publicadas em seu tipo, para que compartilhemos apenas certos dados/funções que queremos que o acessor de nossa capacidade tenha.

cadence
		
			// Contract file: Test.cdc
// Deployed to 0x01
pub contract Test {

   pub resource interface INFT {
      pub let id: UInt64
      pub let rarity: String
      pub var name: String
   }

   pub resource NFT: INFT {
      pub let id: UInt64
      pub let rarity: String
      pub var name: String

      pub fun changeName(newName: String) {
         self.name = newName
      }
      
      init(rarity: String, name: String) {
         self.id = self.uuid
         self.rarity = rarity
         self.name = name
      }
   }

   pub fun createNFT(rarity: String, name: String): @NFT {
      let nft <- create NFT(rarity: rarity, name: name)
      return <- nft
   }

}
		 
	
cadence
		
			// Transaction file: store_nft.cdc
import Test from 0x01

transaction(rarity: String, name: String) {

   prepare(signer: AuthAccount) {
      let nft <- Test.createNFT(rarity: rarity, name: name)
      // moves the NFT resource into storage at `/storage/MyNFT`
      signer.save(<- nft, to: /storage/MyNFT)

      // Creates a capability at `/public/MyPublicNFT` for anyone to borrow.
      // 
      // Notice we restrict the linked type to `&NFT{INFT}`, so the public
      // won't be able to call our `changeName` function since it's not in the
      // `INFT` interface.
      signer.link<&Test.NFT{Test.INFT}>(/public/MyPublicNFT, target:/storage/MyNFT)
   }

   execute {
      
   }
}
		 
	
cadence
		
			// Script file: read_nft.cdc
import Test from 0x01

pub fun main(owner: Address): NFTData {
   // PublicAccount is a type that lets us borrow public
   // capabilities on that account's storage
   let ownerPublicAccount: PublicAccount = getAccount(owner)

   let nftCapability: Capability<&Test.NFT{Test.INFT}> = ownerPublicAccount.getCapability<&Test.NFT{Test.INFT}>(/public/MyPublicNFT)

   let nftRef: &Test.NFT{Test.INFT} = nftCapability.borrow() ?? panic("Not a valid NFT capability.")

   /*
    INVALID: `changeName` is not accessible on the restricted type.
    NOTE: Calling changeName in this script wouldn't do anything
    because scripts don't modify data. But you can imagine
    allowing this to be called in a transaction would be a problem.
   
    nftRef.changeName(newName: "Jacob")
   */

   return NFTData(nftRef.id, nftRef.rarity, nftRef.name)
}

pub struct NFTData {
   pub let id: UInt64
   pub let rarity: String
   pub let name: String

   init(_ i: UInt64, _ r: String, _ n: String) {
      self.id = i
      self.rarity = r
      self.name = n
   }
}