LearnCard Developer Docs
  • 🚀Get Started
    • 👋Welcome
    • ⭐Who are you?
      • Learners & Employees
      • Traditional Educator
      • Non-Traditional Educator
      • Assessment Provider
      • Employer
      • App Developer & EdTech
      • DAO & Communities
      • Content Creators
      • Research Institutions
      • NGOs & Governments
      • Plugfest Partner
        • Guide for Interop Issuers
          • 🤽Creating an Interop Issuer
        • Guide for Interop Wallets
    • Protocol Overview
      • The Internet of Education
      • The Learning Economy
      • Learner & Employee Privacy
      • 22nd Century Education
      • The Open Credential Network
      • PVCs
  • 🔰LearnCard SDK
    • What is LearnCard?
      • Why a Universal Wallet?
      • Architectural Patterns
      • Production Deployment Guide
      • Troubleshooting Guide
    • LearnCard Core
      • Quick Start
        • Create New Credentials
          • Creating Verifiable Credentials for LearnCard
          • Achievement Types and Categories
          • Custom Types
          • Understanding Boosts
          • Creating Boost Credentials
        • Sign & Send Credentials
        • Accept & Verify Credentials
        • Share & Present Credentials
      • Construction
        • Managing Seed Phrases
        • initLearnCard
        • DIDKit
        • learnCardFromSeed
        • emptyLearnCard
        • IDX Config
      • Control Planes
        • ID
        • Read
        • Store
        • Index
        • Cache
        • Context
      • Plugins
        • Adding Plugins
        • Official Plugins
          • Dynamic Loader
          • Crypto
          • DIDKit
          • DID Key
          • VC
            • Expiration Sub-Plugin
          • VC Resolution
          • VC-Templates
          • VC-API
          • Ceramic
          • IDX
          • VPQR
          • Ethereum
          • CHAPI
          • LearnCard Network
          • LearnCloud
          • LearnCard
          • Claimable Boosts
        • Writing Plugins
          • The Simplest Plugin
          • The Plugin Type
          • The LearnCard Type
          • Implementing Control Planes
          • Implementing Methods
          • The Implicit LearnCard
          • Depending on Plugins
          • Private Fields
          • Publishing a Plugin to NPM
      • URIs
      • CHAPI
        • ⭐CHAPI Wallet Setup Guide
        • ↔️Translating to CHAPI documentation
        • 🖥️Demo Application
        • 🔰Using LearnCard to Interact with a CHAPI Wallet
        • 📝Cheat Sheets
          • Issuers
          • Wallets
      • LearnCard UX
        • Quick Start
        • Components
          • Verifiable Credentials
            • VC Thumbnail
            • VC Thumbnail, Mini
          • LearnCards
            • LearnCard Front
            • LearnCard Back
        • API
      • LearnCard Bridge
      • API
      • Migration Guide
    • LearnCard Network
      • LearnCard Network API
        • Authentication
        • Auth Grants and API Tokens
        • Profile
        • Credentials
        • Boosts
        • Presentations
        • Storage
        • Signing Authorities
        • Notifications
        • API Docs
        • Launch Your Own Network
      • 🔌Connect Your Application
    • ConsentFlow
      • Setting Up ConsentFlow with an Independent Network
    • GameFlow
      • Sending xAPI Statements
        • xAPI URIs
      • Reading xAPI Statements
        • Advanced xAPI Statement Queries
      • Consentful "Claim Later" Flow
  • 🚀Applications
    • LearnCard
    • SuperSkills!
      • SuperSkills! SDK
        • Digital Wallets
        • Issuing into SuperSkills!
        • 🦸Creating a SuperSkills! Issuer
    • Metaversity
    • Admin Dashboard
  • 🔗Resources
    • Github
    • Community
    • 💅Custom Development
    • Contact Our Team
    • Learning Economy
  • 🤖LearnCard Services
    • LearnCard CLI
    • Discord Bot
    • Metamask Snap
  • 💸LearnBank SDK
    • Why LearnBank?
  • 📊LearnGraph SDK
    • Why LearnGraph?
Powered by GitBook
On this page
  • LearnCard URI
  • ResolveCredential
  • ResolutionExtension
  • Dissecting the Ceramic Plugin
  • Defining Types
  • CeramicURI
  • The resolveCredential Method

Was this helpful?

  1. LearnCard SDK
  2. LearnCard Core
  3. Plugins
  4. Official Plugins

VC Resolution

The (Deprecated) building block of the LearnCard URI

PreviousExpiration Sub-PluginNextVC-Templates

Last updated 1 year ago

Was this helpful?

Removed

As of @learncard/core@9.0.0, this plugin has been removed. Please use the Read and Store Control Planes instead!

Deprecated

This plugin is now deprecated in favor of using the Read and Store Control Planes! It will be removed in the future

The VC Resolution plugin doesn't do much on its own, but rather lays the groundwork for the LearnCard URI!

LearnCard URI

The LearnCard URI is a that allows a Universal Wallet to resolve a credential. It is freely extensible and any plugin can add to it in any way. However standard plugins will adhere to a format of lc:${method}:${location}. For example, the IDX plugin adds lc:ceramic:${streamID} URI support.

ResolveCredential

LearnCard URIs act as an alias to a credential, much like a URL acts as an alias to an IP Address. In order to get to that credential, we must resolve the URI. This is done via the resolveCredential method exposed by this plugin. If a wallet is instantiated with only the VC Resolution plugin, the resolveCredential method will simply error with a message saying that there are no plugins able to resolve the URI.

ResolutionExtension

In order to become useful, resolveCredential must be re-exposed by another plugin. This is made easier with the ResolutionExtension type exposed by this plugin.

The ResolutionExtension type can be used by plugins to implement a new LearnCard URI. In order to do this, the plugin will need to define its URI scheme, then intersect the ResolutionExtension type with the type of its methods.

Dissecting the Ceramic Plugin

Let's look at an example: the Ceramic Plugin!

Defining Types

The Ceramic plugin exposes lots of methods via the CeramicPluginMethods type, but we can mostly ignore them. With that in mind, the CeramicPluginMethods type looks something like this:

export type CeramicPluginMethods = {
//-- snip
} & ResolutionExtension<CeramicURI>;

This type is then used in the function signature of getCeramicPlugin like this:

export const getCeramicPlugin = async (
    wallet: Wallet<any, any, CeramicPluginDependentMethods>,
    //-- snip
): Promise<Plugin<'Ceramic', any, CeramicPluginMethods>> => {

The presence of ResolutionExtension in the CeramicPluginMethods type signature forces the return value of getCeramicPlugin to include a resolveCredential method that takes in a CeramicURI and returns a VC.

CeramicURI

A Ceramic URI is a URI of the form lc:ceramic:${streamID}. In TypeScript, we can (and do) capture this with the type `lc:ceramic:${string}` though in practice, it is quite a bit easier to just treat it as a string.

export const CeramicURIValidator = z
    .string()
    .refine(
        string => string.split(':').length === 3 && string.split(':')[0] === 'lc',
        'URI must be of the form lc:${storage}:${url}'
    )
    .refine(
        string => string.split(':')[1] === 'ceramic',
        'URI must use storage type ceramic (i.e. must be lc:ceramic:${streamID})'
    );

The resolveCredential Method

With the above information in mind, let's take a quick look at how the Ceramic Plugin implements the resolveCredential method:

export const getCeramicPlugin = async (
    wallet: Wallet<any, CeramicPluginDependentMethods>,
    //-- snip
): Promise<Plugin<'Ceramic', any, CeramicPluginMethods>> => {
    //-- snip

    return {
        methods: {
            //-- snip
            resolveCredential: async (_wallet, uri) => {
                const verificationResult = await CeramicURIValidator.spa(uri);
                
                if (!verificationResult.success) return wallet.pluginMethods.resolveCredential(uri);
                
                //-- Resolve Credential via Ceramic
            },
        }
    };
};

Essentially, what this code is doing is validating the incoming URI to see if it is a Ceramic URI using the CeramicURIValidator. If it is not a Ceramic URI, this plugin that passes it down to the existing wallet's resolveCredential method, giving other plugins the chance to take a crack at resolving this URI. If is is a Ceramic URI, it goes about it's business resolving it!

This pattern is extremely important when writing plugins that implement ResolutionExtension. If a plugin does not delegate resolution to the existing wallet when resolving a credential, it will effectively make all previous resolution extensions worthless!

What is useful, however, is to be able to validate and parse these URIs. The Ceramic Plugin makes use of the validation library to easily validate strings and ensure that they are Ceramic URIs:

🔰
URI
zod