[TOC] # Setup DAF can be used by using Typescript API directly, or by using remote GraphQL api ## Typescript ```typescript= // We will be using 'did:ethr' identities import { IdentityProvider } from 'daf-ethr-did' // Storing key pairs in the database import { KeyStore } from 'daf-core' const keyStore = new KeyStore() // KeyManagementSystem is responsible for managing encryption and signing keys import { KeyManagementSystem } from 'daf-libsodium' const kms = new KeyManagementSystem(keyStore) // Storing managed identities in the database import { IdentityStore } from 'daf-core' const identityStore = new IdentityStore('unique-store-name') // Infura is being used to access Ethereum blockchain. https://infura.io const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c' // Injecting required dependencies, and specifying which blockchain to use and how to access it const rinkebyIdentityProvider = new IdentityProvider({ kms, identityStore, network: 'rinkeby', rpcUrl: 'https://rinkeby.infura.io/v3/' + infuraProjectId, }) // Using local DID Document resolver. It is being used internally to // validate messages and to get information about service endpoints import { DafResolver } from 'daf-resolver' const didResolver = new DafResolver({ infuraProjectId }) // Setting up Message Handler Chain import { UrlMessageHandler } from 'daf-url' import { DIDCommMessageHandler } from 'daf-did-comm' import { JwtMessageHandler } from 'daf-did-jwt' import { W3cMessageHandler } from 'daf-w3c' import { SdrMessageHandler } from 'daf-selective-disclosure' const messageHandler = new UrlMessageHandler() messageHandler .setNext(new DIDCommMessageHandler()) .setNext(new JwtMessageHandler()) .setNext(new W3cMessageHandler()) .setNext(new SdrMessageHandler()) // Setting up Action Handler Chain import { DIDCommActionHandler } from 'daf-did-comm' import { W3cActionHandler } from 'daf-w3c' import { SdrActionHandler } from 'daf-selective-disclosure' const actionHandler = new W3cActionHandler() actionHandler .setNext(new SdrActionHandler()) .setNext(new DIDCommActionHandler()) // Initializing the Core import { Agent } from 'daf-core' // we need defaultIdentityProvider = 'rinkeby-ethr-did' const agent = new Agent({ didResolver, identityProviders: [rinkebyIdentityProvider], actionHandler, messageHandler, }) // Setting up the database connection import { Entities } from 'daf-core' import { createConnection } from 'typeorm' // https://typeorm.io/#/connection-options await createConnection({ type: 'sqlite', database: 'database.sqlite', synchronize: true, entities: [...Entities], }) ``` ## GraphQL Server ```typescript= import { ApolloServer } from 'apollo-server' import { CoreGql, Message, EventTypes } from 'daf-core' import { W3cGql } from 'daf-w3c' import { SdrGql } from 'daf-selective-disclosure' import merge from 'lodash.merge' const server = new ApolloServer({ typeDefs: [ CoreGql.baseTypeDefs, CoreGql.typeDefs, CoreGql.IdentityManager.typeDefs, W3cGql.typeDefs, SdrGql.typeDefs, ], resolvers: merge( CoreGql.resolvers, CoreGql.IdentityManager.resolvers, W3cGql.resolvers, SdrGql.resolvers, ), context: () => ({ agent }), introspection: true, }) agent.on(EventTypes.savedMessage, async (message: Message) => { // Add your business logic here console.log(message) }) const info = await server.listen() console.log(`🚀 Server ready at ${info.url}`) ``` # Create identity ## Typescript ```typescript const providers = await core.identityManager.getIdentityProviders() const identity = await core.identityManager.createIdentity(providers[0].type) ``` ## GraphQL ```graphql query { identityProviders { type } } mutation createIdentity($type: String!) { createIdentity(type: $type) { did } } ``` # Selective Disclosure Request ## Sign JWT ``` typescript= const data = { issuer: 'did:example:123', replyUrl: 'https://example.com/didcomm', tag: 'session-123', claims: [ { reason: 'We are required by law to collect this information', claimType: 'name', essential: true }, { reason: 'You can get %30 discount if you are a member of the club', credentialContext: 'https://www.w3.org/2018/credentials/v1', credentialType: 'ClubMembership', claimType: 'status', claimValue: 'member', issuers: [ { did: 'did:ethr:567', url: 'https://join-the-club.partner1.com' }, { did: 'did:ethr:659', url: 'https://ecosystem.io' } ] } ], credentials: ['JWT-public-profile...'] } ``` ### Typescript ```typescript const sdrJwt = await core.handleAction({ type: 'sign.sdr.jwt', data }) ``` ### GraphQL ```graphql mutation signSdrJwt($data: SDRInput!){ signSdr(data: $data) } ``` ## Show as QR Code ```typescript const url = encodeURI('https://example.com/ssi?c_i=') + sdrJwt ``` ``` html <img src="https://chart.googleapis.com/chart?chs=540x540&cht=qr&chl={{url}}&choe=UTF-8" width="540" height="540" /> ``` ## Send DIDComm message ```typescript const data = { from: 'did:example:1234', to: 'did:example:3456', type: 'jwt', // this is a "subprotocol" body: sdrJwt, } ``` ### Typescript ```typescript const message: Message = await core.handleAction({ type: 'send.message.didcomm-alpha-1', save: true, data }) console.log(message.id) // 443230-234234-123123 console.log(message.type) // sdr ``` ### GraphQL ```graphql mutation sendMessageDidCommAlpha1($data: SendMessageInput!, $save: Boolean = true){ sendMessageDidCommAlpha1(data: $data, save: $save){ id } } ``` # Handle incoming message ```typescript const raw = 'https://example.com/ssi?c_i=JWT...' const meta = [ // this is optional { type: 'qrcode' }, { type: 'foo', value: 'bar'} ] ``` ## Typescript ``` typescript const sdrMessage: Message = await core.handleMessage({ raw, meta, save: true, // default = true }) console.log(message.type) // 'sdr' console.log(message.credentials) // public profile ``` ## GraphQL ```graphql mutation handleMessage($raw: String!, $meta: [MetaDataInput]) { handleMessage(raw: $raw, meta: $meta, save: true){ id type } } ``` # Sign and save Verifiable Credential ```typescript const data = { '@context': ['https://www.w3.org/2018/credentials/v1'], type: ['VerifiableCredential'], issuer: 'did:example:1234', credentialSubject: { id: 'did:example:1234', name: 'Alice', } } ``` ## Typescript ```typescript const nameVc: Credential = await core.handleAction({ type: 'sign.w3c.vc.jwt', save: true, data }) console.log(nameVc.raw) // JWT.... console.log(nameVc.claims) // [Claim({type: 'name', value: 'Alice', ...})] ``` ## GraphQL ```graphql mutation signCredentialJwt($data: SignCredentialInput!){ signCredentialJwt(data: $data, save: true) { hash } } ``` # Find Verifiable Credential ## "Manually" ### Typescript ```typescript= import { In } from 'typeorm' const nameClaims = await Claim.find({ where: { subject: 'did:example:1234', type: 'name', }, relations: ['credential'] }) const nameVc = nameClaims[0]?.credential const memberClaims = await Claim.find({ where: { issuer: In(['did:ethr:567', 'did:ethr:659']), subject: 'did:example:1234', type: 'status', value: 'member', }, relations: ['credential'] }) const memberVc = memberClaims[0]?.credential ``` ### GraphQL ```typescript const input = { issuer: ['did:ethr:567', 'did:ethr:659'], subject: 'did:example:1234', type: 'member', value: 'status' } ``` ```graphql query claims($input: ClaimsInput) { claims(input: $input) { credential { raw } } } ``` ## Using the helper ### Typescript ```typescript import { findCredentialsForSdr } from 'daf-selective-disclosure' const result = await findCredentialsForSdr(sdr, 'did:example:1234') console.log(result) ``` ```javascript [ { reason: 'We are required by law to collect this information', type: 'name', essential: true, credentials: [ Credential(...), // name: 'Alice' Credential(...), // name: 'Alisa' ] }, { reason: 'You can get %30 discount if you are a member of the club', type: 'status', value: 'member', iss: [ { did: 'did:ethr:567', url: 'https://join-the-club.partner1.com' }, { did: 'did:ethr:659', url: 'https://ecosystem.io' } ], credentials: [ Credential(...), // status: 'member', iss: 'did:ethr:567' Credential(...), // status: 'member', iss: 'did:ethr:659' ] } ] ``` ### GraphQL ```typescript const messageId = 'message-id-12345' const activeDid = 'did:example:1234' ``` ```graphql query message($messageId: ID!, $activeDid: ID!) { message(id: $messageId) { type sdr(did: $activeDid) { reason type value essential credentials { issuer { did } claims { type value } raw } } } } ``` # Sign and save Verifiable Presentation ```typescript const data = { issuer: 'did:example:1234', subject: 'did:example:3456', tag: sdrMessage.data.tag, '@context': ['https://www.w3.org/2018/credentials/v1'], type: ['VerifiablePresentation'], verifiableCredential: [nameVc.raw, memberVc.raw] } ``` ## Typescript ```typescript const vp: Presentation = await core.handleAction({ type: 'sign.w3c.vp.jwt', save: true, data }) console.log(vp.raw) // JWT.... ``` ## GraphQL ```graphql mutation signPresentationJwt($data: SignPresentationInput!){ signPresentationJwt(data: $data, save: true) { hash } } ``` # Reply to Selective Disclosure Request (Send VP) ```typescript const url = sdrMessage.replyUrl const data = { from: 'did:example:1234', to: 'did:example:3456', type: 'jwt', body: vp.raw, } ``` ## Typescript ```typescript const message: Message = await core.handleAction({ type: 'send.message.didcomm-alpha-1', save: true, url, data }) console.log(message.id) // 443230-234234-123123 console.log(message.type) // w3c.vp ``` ## GraphQL ```graphql mutation sendMessageDidCommAlpha1($data: SendMessageInput!, $url: String){ sendMessageDidCommAlpha1(data: $data, url: $url, save: true) { id } } ``` # Checking if VP has all requested VCs ```typescript= const sdr = { issuer: 'did:example:123', replyUrl: 'https://example.com/didcomm', tag: 'session-123', claims: [ { reason: 'We are required by law to collect this information', claimType: 'name', essential: true }, { reason: 'You can get %30 discount if you are a member of the club', credentialContext: 'https://www.w3.org/2018/credentials/v1', credentialType: 'ClubMembership', claimType: 'status', claimValue: 'member', issuers: [ { did: 'did:ethr:567', url: 'https://join-the-club.partner1.com' }, { did: 'did:ethr:659', url: 'https://ecosystem.io' } ] } ], credentials: ['JWT-public-profile...'] } ``` ### Typescript ```typescript import { validatePresentationAgainstSdr } from 'daf-selective-disclosure' //... const result = await validatePresentationAgainstSdr(presentation, sdr) console.log(result) ``` ```javascript { valid: true, claims: [ { reason: 'We are required by law to collect this information', type: 'name', essential: true, credentials: [ Credential(...), // name: 'Alice' Credential(...), // name: 'Alisa' ] }, { reason: 'You can get %30 discount if you are a member of the club', type: 'status', value: 'member', iss: [ { did: 'did:ethr:567', url: 'https://join-the-club.partner1.com' }, { did: 'did:ethr:659', url: 'https://ecosystem.io' } ], credentials: [ Credential(...), // status: 'member', iss: 'did:ethr:567' Credential(...), // status: 'member', iss: 'did:ethr:659' ] } ] } ``` ### GraphQL ```typescript const hash = 'presentation-hash-12345' ``` ```graphql query presentation($hash: ID!, $sdr: SDRInput!) { presentation(hash: $hash) { validateAgainstSdr(data: $sdr){ valid } } } ``` # Querying data ## Entities * Identity * Message * Presentation * Credential * Claim There are too many ways of querying data to fit into this documentation. What follows are couple of examples https://typeorm.io/#/find-options ## Identity Fields * did * provider * sentMessages * receivedMessages * issuedPresentations * receivedPresentations * issuedCredentials * receivedCredentials * issuedClaims * receivedClaims ### Typescript ```typescript import { Identity } from 'daf-core' const identity = await Identity.findOne('did:example:123', { relations: ['receivedClaims'] }) console.log(identity.receivedClaims) // [Claim(type: 'name', value: 'Alice'), ...] ``` ### GraphQL ```graphql query { identity(did: "did:example:123") { receivedClaims { type value } } } ``` ## Message Fields * id * saveDate * updateDate * createdAt * expiresAt * threadId * type * raw * data * replyTo * replyUrl * from * to * metaData * presentations * credentials ### Typescript ```typescript import { Message } from 'daf-core' const messages = await Message.find({ take: 5, where: { type: 'sdr' } }) ``` ### GraphQL ```graphql query { messages(input: { type: "sdr", options: { take: 5 } }) { id from { did } to { did } } } ``` ## Presentation Fields * hash * issuer * audience * issuanceDate * expirationDate * data * context * type * credentials * messages ### Typescript ```typescript import { Presentation } from 'daf-core' const presentations = await Presentation.find({ where: { issuer: 'did:web:example.com', type: 'VerifiablePresentation,KYC' }, relations: ['credentials'] }) ``` ### GraphQL ```graphql query { presentations(input: { type: "VerifiablePresentation,KYC", issuer: "did:web:example.com" }) { audience { did } issuanceDate expirationDate credentials { raw claims { type value } } } } ``` ## Credentials Fields * hash * issuer * subject * issuanceDate * expirationDate * context * type - e.x. 'VerifiableCredential,KYC' * data * claims * presentations * messages ### Typescript ```typescript import { Credential } from 'daf-core' import { LessThan } from 'typeorm' const credentials = await Credential.find({ where: { subject: 'did:web:example.com', expirationDate: LessThan(new Date()) }, relations: ['messages'] }) // This would also return messages where these credentials were used at ``` ### GraphQL ```graphql query { credentials(input: { subject: "did:web:example.com", expirationDateLessThan: "2020-12-12T10:00:00Z" }) { issuer { did } expirationDate raw messages { id type } } } ``` ## Claims Fields * hash * issuer * subject * credential * issuanceDate * expirationDate * context * credentialType - e.x. 'VerifiableCredential,KYC' * type * value * isObj ### Typescript ```typescript import { Claim } from 'daf-core' const claims = await Claim.find({ where: { type: 'address', }, relations: ['credential'] }) console.log(claims) ``` ``` [ Claim( ... type: 'address', value: { street: 'Some', houseNr: 4 }, isObj: true ), Claim( ... type: 'address', value: 'Other str, 5', isObj: false ) ] ``` ### GraphQL ```graphql query { claims(input: { type: "address" }) { type value isObj } } ``` ## Managed identities ### Typescript ```typescript const identities = await core.identityManager.getIdentities() ``` ### GraphQL ```graphql query { managedIdentities { did provider } } ```