Overview
The Verifiable Credentials SDK provides tools for working with blockchain-based verifiable credentials (VCs), including:
Retrieving credentials from NFTs
Verifying credential signatures and validity
Decrypting encrypted credentials
Managing credential collections
Installation
npm install @crossmint/client-sdk-verifiable-credentials
Setup
Configure the SDK with your Crossmint API key:
import { crossmintAPI } from '@crossmint/client-sdk-verifiable-credentials' ;
crossmintAPI . init ({
apiKey: 'your-api-key'
});
CredentialService
Service for retrieving verifiable credentials from different sources.
Creating an Instance
import { CredentialService } from '@crossmint/client-sdk-verifiable-credentials' ;
const credentialService = new CredentialService ();
The service includes default retrieval procedures for:
IPFS : Credentials stored on IPFS
Crossmint : Credentials stored in Crossmint’s API
getById
Retrieve a credential by its ID from Crossmint.
const credential = await credentialService . getById (
'cred_123456789'
);
if ( credential ) {
console . log ( 'Credential:' , credential );
console . log ( 'Subject:' , credential . credentialSubject );
}
The unique identifier of the credential
Returns: Promise<VerifiableCredentialType | null>
Throws: Error if retrieval fails
getCredential
Retrieve a credential from an NFT’s metadata.
const collection : CredentialsCollection = {
contract: {
address: '0x123...abc' ,
chain: 'ethereum'
},
credentials: [
{
tokenId: '1' ,
credentialSubject: { id: 'did:example:123' }
}
]
};
const credential = await credentialService . getCredential (
collection ,
'1' // tokenId
);
collection
CredentialsCollection
required
Credential collection containing contract and credential metadata
Token ID of the NFT containing the credential
Returns: Promise<VerifiableCredentialType>
getCredentialNfts
Retrieve all NFTs that are verifiable credentials for a given wallet.
import {
getCredentialNfts ,
type VCChain ,
type CredentialFilter
} from '@crossmint/client-sdk-verifiable-credentials' ;
const collections = await getCredentialNfts (
'ethereum' as VCChain ,
'0x1234...5678' ,
{
credentialType: 'VerifiableCredential' ,
issuer: 'did:web:issuer.example.com'
}
);
collections . forEach ( collection => {
console . log ( 'Contract:' , collection . contract . address );
console . log ( 'Credentials:' , collection . credentials . length );
});
Blockchain to query type VCChain =
| 'ethereum'
| 'polygon'
| 'base'
| 'arbitrum'
| 'optimism'
filters
CredentialFilter
default: "{}"
Optional filters to select specific credentials Show CredentialFilter properties
Filter by credential type
Filter credentials valid from this date (ISO 8601)
Filter credentials valid until this date (ISO 8601)
Returns: Promise<CredentialsCollection[]>
Requires: API key with credentials.read scope
verifyCredential
Verify the cryptographic signature and validity of a credential.
import { verifyCredential } from '@crossmint/client-sdk-verifiable-credentials' ;
const isValid = await verifyCredential ( credential );
if ( isValid ) {
console . log ( 'Credential is valid and signed correctly' );
} else {
console . error ( 'Credential verification failed' );
}
credential
VerifiableCredential
required
The credential to verify
Returns: Promise<boolean> - true if the credential is valid and signature is correct
Lit
Class for decrypting verifiable credentials encrypted with Lit Protocol.
Creating an Instance
import { Lit , type LitNetwork } from '@crossmint/client-sdk-verifiable-credentials' ;
const lit = new Lit (
'cayenne' as LitNetwork , // or 'habanero', 'manzano'
undefined , // optional custom auth sig
false // debug mode
);
Lit Protocol network type LitNetwork = 'cayenne' | 'habanero' | 'manzano' | 'datil-dev' | 'datil-test' ;
capacityDelegationAuthSig
Custom capacity delegation signature. If not provided, uses Crossmint’s signature (requires credentials.decrypt scope).
decrypt
Decrypt an encrypted verifiable credential.
import {
Lit ,
type EncryptedVerifiableCredential
} from '@crossmint/client-sdk-verifiable-credentials' ;
const encryptedCredential : EncryptedVerifiableCredential = {
id: 'cred_encrypted_123' ,
payload: 'encrypted_data_here'
};
const lit = new Lit ( 'cayenne' );
const decryptedCredential = await lit . decrypt ( encryptedCredential );
console . log ( 'Decrypted credential:' , decryptedCredential . credentialSubject );
credential
EncryptedVerifiableCredential
required
The encrypted credential to decrypt
Returns: Promise<VerifiableCredential> - The decrypted credential
Note: User will be prompted to sign a message to decrypt the credential
CrossmintDecrypt
Decrypt credentials using Crossmint’s decryption service.
import { CrossmintDecrypt } from '@crossmint/client-sdk-verifiable-credentials' ;
const decryptedCredential = await CrossmintDecrypt ({
encryptedCredential ,
secret: 'decryption_secret_from_api'
});
encryptedCredential
EncryptedVerifiableCredential
required
The encrypted credential
Decryption secret obtained from Crossmint API
Returns: Promise<VerifiableCredential>
Types
VerifiableCredential
interface VerifiableCredential {
id : string ;
credentialSubject : any ;
validUntil ?: string ;
name ?: string ;
description ?: string ;
nft : Nft ;
issuer : { id : string };
type : string [];
validFrom : string ;
'@context' : string [];
proof ?: {
proofValue : string ;
[ key : string ] : any ;
};
}
EncryptedVerifiableCredential
interface EncryptedVerifiableCredential {
id : string ;
payload : string ; // Encrypted data
}
VerifiableCredentialType
type VerifiableCredentialType =
| VerifiableCredential
| EncryptedVerifiableCredential ;
CredentialsCollection
interface CredentialsCollection {
contract : {
address : string ;
chain : string ;
};
credentials : Array <{
tokenId : string ;
credentialSubject : any ;
// ... other credential fields
}>;
}
CredentialFilter
interface CredentialFilter {
credentialType ?: string ;
issuer ?: string ;
validFrom ?: string ;
validUntil ?: string ;
}
Utility Functions
isVerifiableCredential
Type guard to check if an object is a VerifiableCredential.
import { isVerifiableCredential } from '@crossmint/client-sdk-verifiable-credentials' ;
if ( isVerifiableCredential ( credential )) {
console . log ( 'Type:' , credential . type );
console . log ( 'Subject:' , credential . credentialSubject );
}
isEncryptedVerifiableCredential
Type guard to check if an object is an EncryptedVerifiableCredential.
import { isEncryptedVerifiableCredential } from '@crossmint/client-sdk-verifiable-credentials' ;
if ( isEncryptedVerifiableCredential ( credential )) {
console . log ( 'Credential is encrypted, needs decryption' );
const decrypted = await lit . decrypt ( credential );
}
isCredentialType
Check if a credential matches a specific type.
import { isCredentialType } from '@crossmint/client-sdk-verifiable-credentials' ;
if ( isCredentialType ( credential , 'VerifiableCredential' )) {
console . log ( 'This is a standard verifiable credential' );
}
Complete Example
import {
crossmintAPI ,
CredentialService ,
getCredentialNfts ,
verifyCredential ,
Lit ,
isEncryptedVerifiableCredential
} from '@crossmint/client-sdk-verifiable-credentials' ;
// Initialize
crossmintAPI . init ({ apiKey: 'your-api-key' });
// Get all credential NFTs for a wallet
const collections = await getCredentialNfts (
'ethereum' ,
'0x1234...5678' ,
{ credentialType: 'EducationCredential' }
);
console . log ( `Found ${ collections . length } collections` );
// Get a specific credential
const credentialService = new CredentialService ();
const credential = await credentialService . getById ( 'cred_123' );
if ( ! credential ) {
console . error ( 'Credential not found' );
return ;
}
// Check if encrypted
if ( isEncryptedVerifiableCredential ( credential )) {
console . log ( 'Credential is encrypted, decrypting...' );
const lit = new Lit ( 'cayenne' );
const decrypted = await lit . decrypt ( credential );
// Verify the decrypted credential
const isValid = await verifyCredential ( decrypted );
if ( isValid ) {
console . log ( 'Valid credential!' );
console . log ( 'Subject:' , decrypted . credentialSubject );
console . log ( 'Issuer:' , decrypted . issuer . id );
console . log ( 'Valid from:' , decrypted . validFrom );
console . log ( 'Valid until:' , decrypted . validUntil );
} else {
console . error ( 'Credential verification failed' );
}
} else {
// Verify unencrypted credential
const isValid = await verifyCredential ( credential );
console . log ( 'Credential is valid:' , isValid );
}
Best Practices
API Key Scope : Ensure your API key has the required scopes:
credentials.read for retrieving credentials
credentials.decrypt for using Crossmint’s Lit delegation signature
Verification : Always verify credentials before trusting their contents:
const isValid = await verifyCredential ( credential );
if ( ! isValid ) throw new Error ( 'Invalid credential' );
Error Handling : Handle encryption/decryption errors gracefully:
try {
const decrypted = await lit . decrypt ( encryptedCredential );
} catch ( error ) {
console . error ( 'Decryption failed:' , error . message );
}
Filtering : Use filters to reduce API calls and improve performance:
const collections = await getCredentialNfts (
'ethereum' ,
walletAddress ,
{
issuer: 'did:web:trusted-issuer.com' ,
credentialType: 'EducationCredential'
}
);
Type Checking : Use type guards to handle both encrypted and unencrypted credentials:
if ( isEncryptedVerifiableCredential ( credential )) {
// Handle encrypted credential
} else {
// Handle unencrypted credential
}