Skip to main content

Quickly prototype schemas

This guide provides a hands-on walk-through of the end-to-end workflow for rapid prototyping with static schemas using the SDK. This approach allows you to define, publish, version, and test schemas to iterate on your solution quickly.

Step 1: Define a schema with a UDT

First, define a schema using user-defined types (UDTs) in your code. Use the @VcSchema decorator to define a unique identifier (slug) and a version number of the schema.

// Define a UDT for a "basic profile" credential schema
@VcSchema({ slug: 'basic-profile', version: 1 })
export class BasicProfileClaims {
@VcNotEmptyClaim
firstName!: string;

lastName?: string;
}

Step 2: Publish the schema

Next, publish the schema using the VcDecorator from your UDT. The publishSchema() method sends the schema to the Truvity platform, making it immutable and publicly accessible for verification.

important

Once a schema is published, its definition is permanently frozen and cannot be changed. This is a core principle of Verifiable Credentials. To make changes, you must publish a new version of the schema.

// Create a decorator from your UDT
const basicProfileDecorator = client.createVcDecorator(BasicProfileClaims);

// Publish the schema
try {
await basicProfileDecorator.publishSchema();
console.log('Schema published successfully!');
} catch (error) {
console.error('Failed to publish schema:', error);
}

Step 3: Test interoperability

The published schema can now be used to issue a verifiable credential. Any party can then verify the credential against the public definition of the schema, proving its interoperability.

You can also retrieve the public URL of the schema for discoverability and sharing.

// Create a draft using the published schema
const createdDraft = await basicProfileDecorator.create({
claims: {
firstName: 'John',
lastName: 'Doe'
}
});

// Generate a private key for signing if it doesn't exist
const privateKey = await client.keys.keyGenerate({ data: { type: 'P256' } });

// Issue a credential from the draft
const issuedCredential = await createdDraft.issue(privateKey.id);

// Verify the credential
const isVerified = await issuedCredential.verify();

if (isVerified) {
console.log('Credential verified successfully!');
} else {
console.log('Credential verification failed.');
}

Step 4: Create and publish a new schema version

As part of the credential schema lifecycle, you most likely need to make updates to a published schema to align with new business or regulatory requirements.

To make a change to the schema, you must create a new version. Define a new UDT with an incremented version number and your changes, and then publish it.

// Define an updated UDT for the "basic profile" credential schema to version 2
@VcSchema({ slug: 'basic-profile', version: 2 })
export class BasicProfileClaimsV2 {
@VcNotEmptyClaim
firstName!: string;

lastName?: string;

// Add a new field
birthDate?: Rfc3339Date;
}

// Create a decorator from the new UDT
const basicProfileDecoratorV2 = client.createVcDecorator(BasicProfileClaimsV2);

// Publish the new version
try {
await basicProfileDecoratorV2.publishSchema();
console.log('Schema v2 published successfully!');
} catch (error) {
console.error('Failed to publish schema:', error);
}
Tip

If you want to only add new fields when extending an existing schema definition, you don't need to copy and paste the full UDT definition and can use class extension instead. The following example shows how to do that.


// Define an updated UDT for the "basic profile" credential schema to version 2
@VcSchema({ slug: 'basic-profile', version: 2 })
export class BasicProfileClaimsV2 extends BasicProfileClaims {
// Add a new field
birthDate?: Rfc3339Date;
}

Step 5: Test interoperability of a new schema version

Finally, test the interoperability of the new schema version by creating and verifying a credential.

// Create a draft using the latest published schema (v2)
const createdDraftV2 = await basicProfileDecoratorV2.create({
claims: {
firstName: 'John',
lastName: 'Doe',
birthDate: new Rfc3339Date('1990-01-01')
}
});

// Assume 'privateKey' is the private key generated in a previous step
const issuedCredentialV2 = await createdDraftV2.issue(privateKey.id);

// Verify the credential
const isVerifiedV2 = await issuedCredentialV2.verify();

if (isVerifiedV2) {
console.log('Credential v2 verified successfully!');
} else {
console.log('Credential v2 verification failed.');
}

Further reading