Plugin System
What is a plugin?
initLearnCard() gives you an object with methods like issueCredential, send, and read.get. None of those live in the core. Each comes from a plugin, and the core's only job is to load plugins in order and merge what they expose.
That matters to you in three ways:
You only carry what you use. A server that just verifies credentials needs three plugins; a full network client needs a dozen.
initLearnCardpicks the right stack from the options you pass (seed,network,didWebβ¦), so you rarely assemble it by hand.Plugins can be swapped. Anything that implements the same interface can stand in β a different storage backend, a different DID method, a test double. Plugins that implement a control plane stack: three storage plugins all answer
store.upload, and you pick which by name.You can add your own. A plugin is a plain object with a name and some methods; it can depend on the methods of plugins loaded before it. See Build a Plugin (GitHub) for a 10-minute walkthrough.
The rest of this page is how that works underneath.
Plugin Interface
A LearnCard plugin follows a standard interface structure which includes:
name: A unique identifier string
displayName: A human-readable name for UI display
description: A description of the plugin's functionality
methods: An object containing the functions provided by the plugin
The type system uses generics to track which plugins are added to a LearnCard instance, ensuring type safety when accessing plugin methods.
Adding Plugins
In order to create a fully functioning LearnCard, you will need to add some plugins. Specifically, you will (probably) want to add at least one plugin that implements each Control Plane.
In code, constructing a LearnCard completely from scratch looks like this:
Install @learncard/init, @learncard/didkit-plugin, and @learncard/didkey-plugin. Use a 32-byte (64-hex) seed; this example generates one if SECURE_SEED is unset.
However, you don't have to start from scratch! Each instantiation function is completely able to add bespoke plugins to it:
Example: Expiration Plugin
Let's examine how the Expiration Plugin is implemented to understand a typical plugin structure:
The Expiration Plugin extends the credential verification process to check expiration dates:
It depends on the VC Plugin's
verifyCredentialmethodIt calls the original method to perform base verification
It adds additional checks for credential expiration
It returns an enhanced verification result
This demonstrates how plugins can build upon each other's functionality in a composable manner.
Interacting with Plugins
After initialization, applications interact with plugins through the LearnCard instance's invoke property. The method calls follow this pattern:
This unified interface allows applications to access all plugin functionality through a single entry point, abstracting away the details of which plugin provides which method.
Plugin Data Types
Plugins often work with specific data types, particularly for credential operations. The core types used across plugins include:
UnsignedVC
Unsigned Verifiable Credential data structure
VC
Signed Verifiable Credential with proof
UnsignedVP
Unsigned Verifiable Presentation
VP
Signed Verifiable Presentation with proof
Proof
Cryptographic proof structure
Profile
Entity profile information
These types are defined in the @learncard/types package and used consistently across all plugins to ensure interoperability.
Graph of Plugins
Last updated
Was this helpful?