Ana içeriğe geç

Attestation Request 🎉

In this section, we will create a Claim and a Credential. However, the Credential we create is just like a piece of paper for now. 📜 Why? Because for it to be reliable for Validators, it must be attested by an Attester! 🤝

🌟 Star Tip 🌟

Think of KILT as a party that everyone can join! 🎉 Anyone or anything can create a claim and attest to it. But there's something to keep in mind: If a Validator doesn't trust an Attester, then that credential is just a piece of paper! 🙅‍♀️

alternative text

📝 Creating a Claim 📝

With the light DID we created earlier, the ctype, and the information provided by the Claimer, we will create a Claim object as if creating a recipe. 🍲

🤔 What is a Claim? Let's Dive into the Details 🤔
  • As mentioned, you can think of CTypes as a recipe; it tells us what to do. 📑🍲

  • So, what happens after we follow the recipe? Does it remain as a recipe? No, of course not! 🙅‍♂️ It becomes a dish! 🍲

  • Similarly, when we fill the CType with the information we want, it becomes a Claim. Claims are similar to Credentials but have yet to be attested by an Attester. 📝🔐

  • Attesters play a critical role in this process, just like judges in a cooking competition! 🤩 They decide whether to approve or reject the Credential. ✅

  • KILT is an open system where anyone can claim anything, even about themselves. 🌍 However, a Claim can only be trusted if it has been attested by an Attester. So, Verifiers might trust different Attesters for different situations. 🔍🔒

Adding Packages

claimer/createClaim.ts
import * as Kilt from '@kiltprotocol/sdk-js'

When adding packages to our file, we can first notice that the only required package is the KILT-SDK. Since claims have a simpler structure compared to other formats, this will be sufficient on its own.

createClaim Function

claimer/createClaim.ts
export function createClaim(
lightDid: Kilt.DidUri,
ctype: Kilt.ICType,
content: Kilt.IClaim['contents']
): Kilt.IClaim {

We can set up the function required to create the Claim inside the file. This function takes in 3 parameters. These parameters are:

  1. lightDid: Kilt.DidUri: The URI of the Light DID. This specifies who created the claim.
  2. ctype: Kilt.ICType: Specifies which CType (Claim Type) the claim adheres to. In other words, which "form template" is this claim using?
  3. content: Kilt.IClaim['contents']: The content of the claim, i.e., the information in the filled-out form.

Creating the Claim

Entering the function, we can create our operation, which will be the claim creation action.

claimer/createClaim.ts
const claim = Kilt.Claim.fromCTypeAndClaimContents(ctype, content, lightDid)

When creating the claim, the Kilt.Claim.fromCTypeAndClaimContents() function is called, and a variable named claim is created by entering the parameters into it.

Returning the Claim

claimer/createClaim.ts
return claim

Finally, the created claim object is returned.

Full Code

If we need to see the entire code together:

claimer/createClaim.ts
import * as Kilt from '@kiltprotocol/sdk-js'

// Create a Claim object from light DID, CType, and given content.
export function createClaim(
lightDid: Kilt.DidUri,
ctype: Kilt.ICType,
content: Kilt.IClaim['contents']
): Kilt.IClaim {
const claim = Kilt.Claim.fromCTypeAndClaimContents(ctype, content, lightDid)

return claim
}

This piece of code lays the foundation for creating a claim. Once a claim is created, it can be attested by an "Attester" and later verified by a "Verifier."

Creating a Credential

alternative text

After creating our Claim, we can construct a Credential if we want it to be attested. We can utilize the generateCredential function for this purpose. This Credential will encompass all the necessary information, allowing the Attester to attest the document.

Adding Packages

claimer/generateCredential.ts
import { config as envConfig } from 'dotenv'
import * as Kilt from '@kiltprotocol/sdk-js'
import { createClaim } from './createClaim'
import { generateLightDid } from './generateLightDid'
import { getCtypeSchema } from '../attester/ctypeSchema'

Looking at the content of the packages:

  • dotenv: Used to load environment variables.
  • Kilt: The KILT protocol SDK.
  • createClaim, generateLightDid, getCtypeSchema: Helper functions defined in previous code snippets.

generateCredential Function

claimer/generateCredential.ts
export function generateCredential(
claimerDid: Kilt.DidUri,
claimAttributes: Kilt.IClaim['contents']
): Kilt.ICredential {

We can start by writing the necessary function to create a Credential. This function will take in 2 parameters and return an output of type Kilt.ICredential. Looking at the parameters one by one:

  • claimerDid: Takes in the Light DID created by the Claimer.
  • claimAttributes: Contains a list of claimed attributes.

Creating the Claim and CType

claimer/generateCredential.ts
const ctype = getCtypeSchema()
const claim = createClaim(claimerDid, ctype, claimAttributes)

We had written the code to create both the ctype and the claim and imported them into our file. We can use these functions first to retrieve the CType schema and then call the claim creation function. So, in order:

  • getCtypeSchema(): Retrieves a previously defined CType schema.
  • createClaim(): Creates a claim (Claim) using the specified CType and attributes.

Creating the Credential

claimer/generateCredential.ts
console.log('Claimer -> create request')
return Kilt.Credential.fromClaim(claim)

With our beautiful little Credential.fromClaim() code, we can create a Credential from the Claim.

Main Code Block

This section provides the operations performed if the file is run independently.

claimer/generateCredential.ts
if (require.main === module) {
.
.
.
})()
}

As mentioned above, the if structure checks if the code runs independently.

claimer/generateCredential.ts
envConfig()

With this function, we add the environment variables from the .env file into the code.

claimer/generateCredential.ts
    try {
.
.
.
} catch (e) {
console.log('Error while building credential')
throw e
}

A try-catch structure is set up for the function to run. If there's an error in the operations, the error is printed to the screen using the log structure.

Within the try structure, the credential form can be set up.

claimer/generateCredential.ts
await Kilt.init()

Upon entering the try structure, we can add the KILT SDK to the project with the Kilt.init structure.

Retrieving the Mnemonic Key

claimer/generateCredential.ts
const claimerDidMnemonic = process.env.CLAIMER_DID_MNEMONIC as string

It retrieves the CLAIMER_DID_MNEMONIC from the environment variables and stores it as a string.

Creating the Light DID

claimer/generateCredential.ts
const claimerDid = generateLightDid(claimerDidMnemonic)

Using the generateLightDid function, we defined in another code file earlier, it creates a light DID from the mnemonic.

Creating the Credential

claimer/generateCredential.ts
const request = generateCredential(claimerDid.uri, 
{ age: 21,
name: 'Aybars Göktuğ Ayan'
})

console.log('⚠️ Save to ./claimer/_credential.json file ⚠️\n\n')
console.log(JSON.stringify(request, null, 2))

Finally, with the generateCredential function, we fill in the claim and convert it to the credential format. This function creates a credential using the generated DID and specified attributes (age and name). Then, it prints the created identity information in JSON format to the console.

Overview

If we look at the entire code:

claimer/generateCredential.ts
import { config as envConfig } from 'dotenv'

import * as Kilt from '@kiltprotocol/sdk-js'

import { createClaim } from './createClaim'
import { generateLightDid } from './generateLightDid'
import { getCtypeSchema } from '../attester/ctypeSchema'

export function generateCredential(
claimerDid: Kilt.DidUri,
claimAttributes: Kilt.IClaim['contents']
): Kilt.ICredential {
// Create claim.
const ctype = getCtypeSchema()
const claim = createClaim(claimerDid, ctype, claimAttributes)

// Create credential and request attestation.
console.log('Claimer -> create request')
return Kilt.Credential.fromClaim(claim)
}

// Don't execute if this is imported by another file.
if (require.main === module) {
;(async () => {
envConfig()

try {
await Kilt.init()

const claimerDidMnemonic = process.env.CLAIMER_DID_MNEMONIC as string
const claimerDid = generateLightDid(claimerDidMnemonic)

const request = generateCredential(claimerDid.uri, {
age: 21,
name: 'Aybars Göktuğ Ayan'
})
console.log(
'⚠️ save this to ./claimer/_credential.json for testing ⚠️\n\n'
)
console.log(JSON.stringify(request, null, 2))
} catch (e) {
console.log('Error while building credential')
throw e
}
})()
}

If we examine it step by step:

  • We added the packages.
  • We create a Claim.
  • We create a Credential with the Claim and register it on the chain.

Running the Program

To run the 2 interconnected codes we wrote, make sure you are in the kilt-rocks folder and then you can run the code below.

yarn ts-node claimer/generateCredential.ts

uyarı

Attestations are recorded on the chain after they are approved by the Attesters. This process requires a deposit. Each Credential is unique. Generally, by storing and reusing credentials during testing, we prevent multiple attestation processes.

To save this document, you can create a file at ./claimer/_credential.json and write the information inside. You can even share this credential with your friends and let them use it.

Well done to us

Yes, now as a Claimer, we have created a Claim and generated a credential from this Claim. Let's complete the attester and get the credential attested.