Coder Social home page Coder Social logo

capability-cache's Introduction

codecov

Capability Cache

Overview

CapabilityCache is a contract that allows the storing and retrieval of capabilities. Private paths are/were removed from Cadence with the launch of Crescendo, which presents a challenge for platforms that want to keep the number of capabilities they issue for their users to a minimum.

These platforms could choose to iterate over all controllers on a storage path they want to have access to and choose one that matches their desired type, but that has a few challengnes:

  • How do you know the capability you are using isn't slated to be removed by another platform when they no longer need it?
  • What if there are so many capabilities issued to an existing storage path that iteration over it isn't possible?
  • How does a platform know which capabilities they issued without having to build complex indexing?

Some of these can be fixed without a contract solution like this one. For instance, a platform could choose to store a controller id or the issued Capability itself into storage in a way that can be looked up as needed. This can work, but is overhead that can be offloaded to a contract.

The @CapabilityCache.Cache resource is given a namespace which it should be stored in (though there is no way to guarantee this), which allows every platform to make their own cache and manage the capabilities that they issue for their users. This also makes it fairly easy to tell what capabilities belong to what platform. If the cache is used, all a user or ecosystem tool would need to do is look at each stored @Cache resource and iterate through the types and capabilities that they've stored.

Usage

Initialize Cache

In order to make a cache, you need to give it a namespace. This is done to encourage each platform to maintain their own cache.

NOTE: There is no way to ensure that someone else won't take a platform's typical cache namespace

import "CapabilityCache"

transaction(namespace: String) {
    prepare(acct: auth(Storage) &Account) {
        let s = CapabilityCache.getPathForCache(namespace)
        if acct.storage.borrow<&CapabilityCache.Cache>(from: s) == nil {
            let c <- CapabilityCache.createCache(namespace: namespace)
            acct.storage.save(<-c, to: s)
        }
    }
}

Add Capability to Cache

import "CapabilityCache"

transaction(namespace: String, type: Type, path: StoragePath) {
    prepare(acct: auth(SaveValue, BorrowValue, IssueStorageCapabilityController) &Account) {
        let s = CapabilityCache.getPathForCache(namespace)
        if acct.storage.borrow<&CapabilityCache.Cache>(from: s) == nil {
            let c <- CapabilityCache.createCache(namespace: namespace)
            acct.storage.save(<-c, to: s)
        }

        let cache = acct.storage.borrow<auth(CapabilityCache.Add) &CapabilityCache.Cache>(from: s)
            ?? panic("capability cache was not found")

        let cap = acct.capabilities.storage.issueWithType(path, type: type)
        cache.addCapability(cap: cap, type: type)
    }
}

Retrieve FT Provider Capability from Cache

import "CapabilityCache"
import "FungibleToken"

transaction(namespace: String) {
    prepare(acct: auth(BorrowValue) &Account) {
        let type = Type<auth(FungibleToken.Withdraw) &{FungibleToken.Provider}>()

        let s = CapabilityCache.getPathForCache(namespace)
        let cache = acct.storage.borrow<auth(CapabilityCache.Get) &CapabilityCache.Cache>(from: s)
            ?? panic("cache not found in storage")
        let cap = cache.getCapabilityByType(type)
            ?? panic("capability not found with provided type")
        let casted = cap as! Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Provider}>
        casted.borrow() ?? panic("failed to borrow provider capability")
    }
}

Remove Capability from Cache

import "CapabilityCache"

transaction(namespace: String, type: Type) {
    prepare(acct: auth(BorrowValue) &Account) {
        let s = CapabilityCache.getPathForCache(namespace)
        let cache = acct.storage.borrow<auth(CapabilityCache.Delete) &CapabilityCache.Cache>(from: s)
            ?? panic("cache not found in storage")

        cache.removeCapabilityByType(type)
    }
}

capability-cache's People

Contributors

austinkline avatar

Stargazers

Greg Santos avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.