CType 🎯
CTYPE
, yani Claim Type, KILT protokolü için özel bir terimdir. Aslında, bu oldukça basit bir konsept: CTYPE
bir claim
ya da Türkçe'de iddia
nın veri modelidir. 📊
KILT, işletmeler ve tüketiciler için öz-yönetimli, doğrulanabilir kimlik bilgileri ve DID'ler sağlar. 🛡️ Ama hangi tür kimlik bilgilerinden bahsediyoruz? 🤔🔐
Kimlik bilgilerimizi nasıl saklayabiliriz? 🗂️ Doldurmamız gereken belirli bir form var mı? 📝 Tüm bu soruları yanıtlayacağız! 😎👍
Diyelim ki bazı verileri onaylatmak istiyorsunuz. 📋 Bu verilerin içinde adınız, konumunuz gibi daha küçük parçalar var. Peki, bu verileri bir onaylayıcıya nasıl sunacaksınız? 🤷♂️ Hangi şablonda? 📑
CTypes'ı tanıyalım! 🎉 CTypes, kimlik bilgilerinin şemalarıdır. 📋 İhtiyacınız olan "form oluşturma araçları" olarak hizmet edebilirler. 🛠️
CTypes, bir iddianın yapısını, veri modeli dahil, tanımlayan KILT'a özgü veri tipleridir. 📊✅ JSON Şeması'na dayanmaktadırlar, bu da JSON belgelerini açıklamak ve doğrulamak için kullanılan bir standarttır. 📜
Kendi CTypes'ınızı oluşturabilir 🛠️ ve bunları zincirde saklayabilir veya ihtiyacınızı karşılamak için zincirde zaten var olan CTypes'ı kullanabilirsiniz. 💡🔗
Attesterlar, bir attest
yani onay
işlemi yapmadan önce, hangi Ctype
formatını destekleyeceklerini belirlemelidir. 🎯 Örneğin, sürücü kursları sadece ehliyetle alakalı onaylama yapabilirler, evin mesken alanı ile alakalı bir onaylama yapamazlar. 🚗🏠
CTYPE'lar standartlaşması hedeflenen öğelerdir. 🎯 Yeni bir Ctype oluşturmadan önce olanları kullanmak büyük ölçüde önerilir. 👍
Workshop'ta süreci öğrenmek için kendi CTYPE'ımızı yaratacağız! 🛠️🎉
CType, bir credential
'ın içerisinde gerekli tüm bilgilerin var olmasını teyit eder. 🛡️ Örneğin, bir ehliyette doğum tarihi, isim ve hangi tür aracın kullanılma izninin olduğu yer alır. 🚗📅 Bu bilgiler, ehliyetimizi kontrol eden polis memurunun bizi onaylaması için gerekli olan bilgilerdir. 🚓👮♂️
CType oluşturmak için zincir üzerinde bir full DID
gereklidir. 🆔 Ayrıca, bu hesabın içerisinde PILT
coinlerinin olduğundan emin olmalıyız, çünkü CType oluşturma işlemi bizden bir miktar ödeme alacak. 💰
Örnek bir CTYPE'a bakalım
Hadi kafamızda tam oturması için örnek bir CType incelelim, bu işlem için de yine ehliyeti örnek gösterebiliriz:
{
"$id": "kilt:ctype:0x4f1d68ac46daf4613181b33b16faaf10cf94879dc2246d7485dc2ccbb843641d",
"$schema": "ipfs://bafybeiah66wbkhqbqn7idkostj2iqyan2tstc4tpqt65udlhimd7hcxjyq/",
"additionalProperties": false,
"properties": {
"age": {
"type": "integer"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
}
},
"title": "Drivers License by did:kilt:4t9FPVbcN42UMxt3Z2Y4Wx38qPL8bLduAB11gLZSwn5hVEfH",
"type": "object"
}
Yukarıdaki kod yapısını inceleyecek olursak ilk olarak bu yapının JSON
formatına benzediğini görebiliriz ki bu durumda haklı oluruz. CType'lar temellerinde JavaScript Objeleri olarak tasarlanmıştır.
Satır satır bu niteliklere bakacak olursak:
Anahtar | Değer |
---|---|
$id | Bu CType'ın KILT kimliği. CType'ın dijital izi'ni temsil ettiği için en önemli özelliğidir. |
$schema | Bir CType'ın nasıl görünebileceğini tanımlayan meta-şemaya bir referans. İki versiyonu vardır. |
title | CType'ın başlığı. |
properties | Bu CType'a uygun bir iddianın sahip olabileceği özellikler. |
type | Tüm CType'lar için type bir nesnedir. |
additionalProperties | Varsayılan olarak false olarak ayarlanmıştır. Bu, bir iddiada istenmeyen özelliklerin sınırlanmasını sağlar. |
Ctypelar KILT Blokzinciri üzerinde depolanmaktadır.
Gerçek hayatta CType'ları var olan bir depodan veya zincirden çekmemiz gerekmektedir.
Bu workshop içerisinde Attester
bireyimiz kendi bir CType oluşturup test zincirine yükleyecektir.
CType Oluşturma
Ctype oluşturmak için alt kısımdaki gibi bir yapı oluşturabiliriz:
import * as Kilt from '@kiltprotocol/sdk-js'
// Return CType with the properties matching a given schema.
export function getCtypeSchema(): Kilt.ICType {
return Kilt.CType.fromProperties('Drivers License', {
name: {
type: 'string'
},
age: {
type: 'integer'
}
})
}
Bu kodun nasıl çalıştığına satır satır bakacak olursak:
- İlk olarak KILT-SDK'yi kodumuzun içerisine eklemekle başlayabiliriz.
- Sonrasında
getCtypeSchema
adın da bir fonksiyon tanımlanırız. - Son olarak gerekli bilgileri alarak
CType.fromProperties
fonksiyonu ile Ctype'a çevirmeye hazır hale getiririz.
CType'ı Elde Etme
Şimdi CTYPE'ların olup olmadığını kontrol ederek olmaması durumunda oluşturacak kodumuzu yazabiliriz.
Kütüphane Ekleme
import { config as envConfig } from 'dotenv'
import * as Kilt from '@kiltprotocol/sdk-js'
import { generateAccount } from './generateAccount'
import { generateKeypairs } from './generateKeypairs'
import { getCtypeSchema } from './ctypeSchema'
Bu kısımda eklediğimiz paketleri incelediğimizde daha önceden de eklediğimiz paketlerin yer aldığını görüntüleyebiliriz. Bu paketlerden daha önce kullanmadığımız getCtypeSchema
gözümüze çarpabilir. Bu paket daha öncesinde yazdığımız ctypeSchema.ts
dosyasından getCtypeSchema
methoduna erişmektedir.
ensureStoredCtype
Fonksiyonu
export async function ensureStoredCtype(
attesterAccount: Kilt.KiltKeyringPair,
attesterDid: Kilt.DidUri,
signCallback: Kilt.SignExtrinsicCallback
): Promise<Kilt.ICType> {
// ...
}
Tabii, ensureStoredCtype
fonksiyonu üç parametre alıyor ve bir Promise
döndürüyor. Fonksiyonun amacı, bir CType'ın (Claim Type) zaten KILT blockchain'de kayıtlı olup olmadığını kontrol etmek ve eğer değilse, onu oluşturmaktır. Bu parametrelere bakacak olursak:
attesterAccount: Kilt.KiltKeyringPair
: Bu, işlemleri imzalamak için kullanılacak olan KILT hesabının anahtar çiftini temsil eder.attesterDid: Kilt.DidUri
: Bu, işlemleri yetkilendirmek için kullanılacak olan Decentralized Identifier (DID) URI'yi temsil eder.signCallback: Kilt.SignExtrinsicCallback
: Bu, işlemi imzalamak için kullanılacak olan callback fonksiyonudur.
Promise<Kilt.ICType>
: Fonksiyon, oluşturulan veya zaten var olan CType'ı döndüren bir Promise
döndürür.
KILT API'sini Almak
const api = Kilt.ConfigService.get('api');
KILT API'sini alır, bu API üzerinden blockchain ile etkileşime geçilecektir.
CType Şemasını Almak
const ctype = getCtypeSchema();
Önceden tanımlanmış bir CType şemasını alır. Bu şemayı daha önce yazdığımız ctypeSchema.ts
dosyasından elde etmektedir. Bu dosya içerisinden CType'ı alarak projemiz içerisine ekler.
CType'ın Olup Olmadığını Kontrol Etmek
try {
await Kilt.CType.verifyStored(ctype)
console.log('Ctype already stored. Skipping creation')
return ctype
} catch {
// ...
}
Oluşturacağımız CType'lar zincirde aynı şekilde var olabilir. Bu durumlarda yeniden bir CType'ı zincire eklemek bizlere gereksiz bir ücrete malolacaktır. Bu durumu önlemek için try
yapısı içerisinde CType.verifyStored()
methodu ile şemamızın var olup olmadığını kontrol edebiliriz. Eğer hali hazırda depolanmış ise bu durum kullanıcıya söylenir ve ctype
'ı döndürerek devam eder.
Ctype'ın kayıtlı olmaması durumunda catch
yapısı çalışacaktır.
CType Oluşturmak ve Kaydetmek
Zincirde CType'ın bulunmadığına emin olduğumuzda zincire oluşturduğumuz CType'ı ekleyebiliriz.
console.log('Ctype not present. Creating it now...');
const encodedCtype = Kilt.CType.toChain(ctype);
const tx = api.tx.ctype.add(encodedCtype);
const extrinsic = await Kilt.Did.authorizeTx(
attesterDid,
tx,
signCallback,
attesterAccount.address
);
await Kilt.Blockchain.signAndSubmitTx(extrinsic, attesterAccount);
return ctype;
Üst Kısımda CType'ı oluşturup zincire eklememiz için gerekli kod ifade edilmiştir. Bu kodu sırasıyla inceleyecek olursak:
encodedCtype
: Ctype'ı şema olarak oluşturduk ancak zincirin içerisine ekleyebileceğimiz şekilde şifrelememiz gerekmektedir. Bu işlemiCType.toChain()
ile gerçekleştirebiliriz.tx
: CType'ı zincire eklememiz için bu CType'ın transferini gerçekleştirmemiz gerekmektedir. Bu transfer için de Ctype'ıtx.ctype.add
fonksiyonu ile hazırlayabiliriz.extrinsic
: Zincire ekleyeceğimiz transferi uygun formata getirmek için kullanırız. Bu transfer sayesinde zincir ile etkileşime geçeceğimiz içinattesterDid
değerini kullanmamız gerekmektedir.signAndSubmitTx
: Son olarak işlemi zincire imzalayarak göndereririz.
Ana Kod Bloğu
Bu kısım yine diğer kodlarda olduğu gibi generateCtype.ts
dosyası direkt olarak çağırılırsa nasıl çalışacağını ifade etmektedir.
if (require.main === module) {
;(async () => {
// ...
})()
}
Kodun direkt olarak çalıştırılıp çalıştırılmadığına bir if
yapısı ile bakarız. Eğer direkt olarak çalıştırılıyorsa altında bulunan kodlar çalışır.
Çevre Değişkenleri ve Bağlantı
envConfig()
await Kilt.connect(process.env.WSS_ADDRESS as string)
Çevre değişkenleri yüklenir ve KILT blockchain'ine bağlanılır.
Hesap ve DID Oluşturma
const accountMnemonic = process.env.ATTESTER_ACCOUNT_MNEMONIC as string
const { account } = generateAccount(accountMnemonic)
const didMnemonic = process.env.ATTESTER_DID_MNEMONIC as string
const { authentication, assertionMethod } = generateKeypairs(didMnemonic)
const attesterDidUri = Kilt.Did.getFullDidUriFromKey(authentication)
Mnemonic kullanarak bir hesap ve DID (Decentralized Identifier) oluşturulur.
ensureStoredCtype
Fonksiyonunun Çağrılması
await ensureStoredCtype(account, attesterDidUri, async ({ data }) => ({
signature: assertionMethod.sign(data),
keyType: assertionMethod.type
}))
ensureStoredCtype
fonksiyonu çağrılır ve gerekli işlemler yapılır.
Hadi birlikte yazdığımız generateCtype.ts
dosyasının nasıl çalıştığına tüm kodu bir arada görerek bakalım.
import { config as envConfig } from 'dotenv'
import * as Kilt from '@kiltprotocol/sdk-js'
import { generateAccount } from './generateAccount'
import { generateKeypairs } from './generateKeypairs'
import { getCtypeSchema } from './ctypeSchema'
export async function ensureStoredCtype(
attesterAccount: Kilt.KiltKeyringPair,
attesterDid: Kilt.DidUri,
signCallback: Kilt.SignExtrinsicCallback
): Promise<Kilt.ICType> {
const api = Kilt.ConfigService.get('api')
// Get the CTYPE and see if it's stored, if yes return it.
const ctype = getCtypeSchema()
try {
await Kilt.CType.verifyStored(ctype)
console.log('Ctype already stored. Skipping creation')
return ctype
} catch {
console.log('Ctype not present. Creating it now...')
// Authorize the tx.
const encodedCtype = Kilt.CType.toChain(ctype)
const tx = api.tx.ctype.add(encodedCtype)
const extrinsic = await Kilt.Did.authorizeTx(
attesterDid,
tx,
signCallback,
attesterAccount.address
)
// Write to chain then return the CType.
await Kilt.Blockchain.signAndSubmitTx(extrinsic, attesterAccount)
return ctype
}
}
// Don't execute if this is imported by another file.
if (require.main === module) {
;(async () => {
envConfig()
try {
await Kilt.connect(process.env.WSS_ADDRESS as string)
const accountMnemonic = process.env.ATTESTER_ACCOUNT_MNEMONIC as string
const { account } = generateAccount(accountMnemonic)
const didMnemonic = process.env.ATTESTER_DID_MNEMONIC as string
const { authentication, assertionMethod } = generateKeypairs(didMnemonic)
const attesterDidUri = Kilt.Did.getFullDidUriFromKey(authentication)
await ensureStoredCtype(account, attesterDidUri, async ({ data }) => ({
signature: assertionMethod.sign(data),
keyType: assertionMethod.type
}))
} catch (e) {
console.log('Error while checking on chain ctype')
throw e
}
})()
}
Sırasıyla kodu inceleyecek olursak:
- İlk olarak paketleri yükleriz.
ctypeSchema.ts
dosyasından şemamızı çekerek kodumuzun içerisine ekleriz.- Zincir üzerinde oluşturmak istediğimiz CType'ın olup olmadığını kontrol ederiz.
- Zincirde yoksa nasıl ekleyebileceğimizin kodunu yazarız.
- Dosya tek başına çalıştırılacak olursa yapılacak Ctype işlemlerini yazarız.
Bu şekilde zincirin içerisinde oluşturacağımız CType'ın olup olmadığını inceleyen ve yoksa oluşturan bir kod yazdık.
Zincir üzerine eklemek için bir deposito ödememiz gerekmektedir. Bu nedenle PILT Coinlere ihtiyacımız var unutmayalım.
Çalıştırma
Kodumuzu çalıştırmak için terminalde kilt-rocks
klasöründe olduğumuzdan emin olduktan sonra şu kodu çalıştırabiliriz:
yarn ts-node attester/generateCtype.ts
Eveeeet şimdi, artık Ctype'ı da oluşturduğumuza göre bizden bir attestation
isteyecek Claimer
bireyine ihtiyacımız var.