Skip to main content
Version: v0.4.x

Registering a schema and credential definition on an AnonCreds Registry

In this tutorial we will register a schema and credential definition on an AnonCredsRegistry e.g. Hyperledger Indy ledger indy-vdr, cheqd.

info

This section assumes that

  1. You have set-up your development environment.
  2. You have basic knowledge of the required fields in the Agent Config

1. Setting up the agent

First, an agent must be setup with a wallet and an indy-vdr or cheqd module. For these code examples, we will use a Node.js environment.

📄issuer
import { Agent } from '@aries-framework/core'
import { agentDependencies } from '@aries-framework/node'
import { AskarModule } from '@aries-framework/askar'
import { ariesAskar } from '@hyperledger/aries-askar-nodejs'
import {
IndyVdrAnonCredsRegistry,
IndyVdrIndyDidRegistrar,
IndyVdrIndyDidResolver,
IndyVdrModule,
} from '@aries-framework/indy-vdr'
import { indyVdr } from '@hyperledger/indy-vdr-nodejs'
import { AnonCredsModule } from '@aries-framework/anoncreds'
import { AnonCredsRsModule } from '@aries-framework/anoncreds-rs'
import { anoncreds } from '@hyperledger/anoncreds-nodejs'
import {
CheqdAnonCredsRegistry,
CheqdDidRegistrar,
CheqdDidResolver,
CheqdModule,
CheqdModuleConfig,
} from '@aries-framework/cheqd'

const agent = new Agent({
config,
dependencies: agentDependencies,
modules: {
// Register the Askar module on the agent
// We do this to have access to a wallet
askar: new AskarModule({
ariesAskar,
}),
anoncredsRs: new AnonCredsRsModule({
anoncreds,
}),
indyVdr: new IndyVdrModule({
indyVdr,
networks: [
{
isProduction: false,
indyNamespace: 'bcovrin:test',
genesisTransactions: '<genesis transactions>',
connectOnStartup: true,
},
],
}),
cheqd: new CheqdModule(
new CheqdModuleConfig({
networks: [
{
network: '<mainnet or testnet>',
cosmosPayerSeed: '<cosmos payer seed or mnemonic>',
},
],
})
),
anoncreds: new AnonCredsModule({
registries: [new IndyVdrAnonCredsRegistry(), new CheqdAnonCredsRegistry()],
}),
dids: new DidsModule({
registrars: [new IndyVdrIndyDidRegistrar(), new CheqdDidRegistrar()],
resolvers: [new IndyVdrIndyDidResolver(), new CheqdDidResolver()],
}),
},
})

2. Importing a DID (optional)

info

There are many ledgers which can be used to register DIDs on for development.

Indy VDR

We recommend bcovrin test net. This network allows very easily to register a DID from a seed which can then be used as the privateKey in the snippet below. The seed is used as the private key for legacy compatibility with the Hyperledger Indy-SDK. The genesis transactions can also be retrieved for easy integration.

Cheqd

Follow the cheqd setup and cheqd DID module to setup the network and create a DID. Cheqd supports a mainnet for production and a testnet for development purposes.

In order to register a schema and credential definition, a DID must be added to the agent first. This can be done by calling agent.dids.create(), but this does require an endorser DID to be present as the submitterDid. For this tutorial a DID will already be registered on the ledger, but it will be imported, with the associated private key, to be used later when registering the schema and credential definition.

This section can be omitted if your agent already has a DID in its wallet.

📄issuer
const seed = TypedArrayEncoder.fromString(`<seed>`) // What you input on bcovrin. Should be kept secure in production!
const unqualifiedIndyDid = `<unqualifiedIndyDid>` // will be returned after registering seed on bcovrin
const indyDid = `did:indy:bcovrin:test:${unqualifiedIndyDid}`

const cheqdDid = await agent.dids.create({
method: 'cheqd',
secret: {
verificationMethod: {
id: 'key-1',
type: 'Ed25519VerificationKey2020',
},
},
options: {
network: 'testnet',
methodSpecificIdAlgo: 'uuid',
},
})

await agent.dids.import({
did: '<did>',
overwrite: true,
privateKeys: [
{
privateKey: seed,
keyType: KeyType.Ed25519,
},
],
})

3. Registering a schema

When you have a registered DID on a network and in your wallet, you can register a schema. Registering a schema requires four fields: issuerId, name, version and attrNames. It is important to note that the issuerId must be the same as a DID in your wallet.

📄issuer
const schemaResult = await agent.modules.anoncreds.registerSchema({
schema: {
attrNames: ['name'],
issuerId: '<did>',
name: 'Example Schema to register',
version: '1.0.0',
},
options: {},
})

if (schemaResult.schemaState.state === 'failed') {
throw new Error(`Error creating schema: ${schemaResult.schemaState.reason}`)
}

3. Registering a credential definition

After registering a schema, a credential definition can be registered based on the schema. The credential definition, amongst more things, binds the schema to a specific issuer. Schemas can be reused between issuers, but a credential definition is specific to an issuer. In a credential definition revocation can also be specified. This section will not go in-depth about revocation.

📄issuer
const credentialDefinitionResult = await agent.modules.anoncreds.registerCredentialDefinition({
credentialDefinition: {
tag: 'default',
issuerId: '<did>',
schemaId: schemaResult.schemaState.schemaId,
},
options: {},
})

if (credentialDefinitionResult.credentialDefinitionState.state === 'failed') {
throw new Error(
`Error creating credential definition: ${credentialDefinitionResult.credentialDefinitionState.reason}`
)
}

Using it

After everything is registered on a AnonCredsRegistry, we can use it to issue credentials. The next tutorial is all about issuing an AnonCreds credential with this setup.

Useful Resources