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
! 🤝
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! 🙅♀️
📝 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. 🍲
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 toCredentials
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 theCredential
. ✅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 anAttester
. So,Verifiers
might trust differentAttesters
for different situations. 🔍🔒
Adding Packages
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
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:
lightDid: Kilt.DidUri
: The URI of the Light DID. This specifies who created the claim.ctype: Kilt.ICType
: Specifies which CType (Claim Type) the claim adheres to. In other words, which "form template" is this claim using?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.
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
return claim
Finally, the created claim object is returned.
If we need to see the entire code together:
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
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
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
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
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
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.
if (require.main === module) {
.
.
.
})()
}
As mentioned above, the if
structure checks if the code runs independently.
envConfig()
With this function, we add the environment variables from the .env
file into the code.
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.
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
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
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
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.
If we look at the entire code:
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
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.
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.