77 * found in the LICENSE file in the root directory of this source tree.
88 */
99
10- import { Credential , Did , connect , disconnect } from '@kiltprotocol/sdk-js'
11- import { DidResourceUri , DidUri , ICredentialPresentation , SignCallback } from '@kiltprotocol/types'
10+ import { DataIntegrity } from '@kiltprotocol/credentials'
11+ import { multibaseKeyToDidKey , validateDid } from '@kiltprotocol/did'
12+ import { DidResolver , connect , disconnect } from '@kiltprotocol/sdk-js'
13+ import { Did , DidUrl } from '@kiltprotocol/types'
14+ import { Signers } from '@kiltprotocol/utils'
1215
1316import { Keyring } from '@polkadot/keyring'
1417import { u8aEq } from '@polkadot/util'
1518
1619import { readFile , writeFile } from 'fs/promises'
1720import yargs from 'yargs/yargs'
1821
19- import { didConfigResourceFromCredential , createCredential } from '../wellKnownDidConfiguration/index.js'
20- import type { DidConfigResource } from '../types/index.js'
22+ import { DidConfigResource , DomainLinkageCredential } from '../types/Credential.js'
23+ import {
24+ KILT_SELF_SIGNED_PROOF_TYPE ,
25+ createCredential ,
26+ didConfigResourceFromCredentials ,
27+ } from '../wellKnownDidConfiguration/index.js'
2128
2229type KeyType = 'sr25519' | 'ed25519' | 'ecdsa'
2330
@@ -41,22 +48,39 @@ const createCredentialOpts = {
4148 wsAddress : { alias : 'w' , type : 'string' , demandOption : true , default : 'wss://spiritnet.kilt.io' } ,
4249} as const
4350
44- async function issueCredential ( did : DidUri , origin : string , seed : string , keyType : KeyType , nodeAddress : string ) {
45- await connect ( nodeAddress )
46- const didDocument = await Did . resolve ( did )
47- const assertionMethod = didDocument ?. document ?. assertionMethod ?. [ 0 ]
51+ async function issueCredential ( {
52+ did,
53+ origin,
54+ seed,
55+ keyType,
56+ proofType,
57+ } : {
58+ did : Did
59+ origin : string
60+ seed : string
61+ keyType : KeyType
62+ proofType : string
63+ } ) {
64+ const { didDocument } = await DidResolver . resolve ( did , { } )
65+ const assertionMethodId = didDocument ?. assertionMethod ?. [ 0 ]
66+ const assertionMethod = didDocument ?. verificationMethod ?. find ( ( { id } ) => id === assertionMethodId )
4867 if ( ! assertionMethod ) {
4968 throw new Error (
5069 `Could not resolve assertionMethod of ${ did } . Make sure the DID is registered to this chain and has an assertionMethod key.`
5170 )
5271 }
72+ const keyUri : DidUrl = `${ didDocument ! . id } ${ assertionMethod . id } `
73+
5374 const keypair = new Keyring ( { type : keyType } ) . addFromUri ( seed )
54- if ( assertionMethod . type !== keypair . type || ! u8aEq ( assertionMethod . publicKey , keypair . publicKey ) ) {
75+ const signers = await Signers . getSignersForKeypair ( { keypair, id : keyUri } )
76+
77+ const { keyType : vmType , publicKey } = multibaseKeyToDidKey ( assertionMethod . publicKeyMultibase )
78+ if ( vmType !== keypair . type || ! u8aEq ( publicKey , keypair . publicKey ) ) {
5579 throw new Error ( 'public key and/or key type of the DIDs assertionMethod does not match the supplied signing key' )
5680 }
57- const keyUri : DidResourceUri = ` ${ didDocument ! . document ! . uri } ${ assertionMethod . id } `
58- const signCallback : SignCallback = async ( { data } ) => ( { signature : keypair . sign ( data ) , keyUri , keyType } )
59- const credential = await createCredential ( signCallback , origin , did )
81+
82+ const credential = await createCredential ( signers , origin , didDocument ! , { proofType } as any )
83+
6084 return credential
6185}
6286
@@ -72,29 +96,30 @@ async function write(toWrite: unknown, outPath?: string) {
7296async function run ( ) {
7397 await yargs ( process . argv . slice ( 2 ) )
7498 . command (
75- 'fromCredential < pathToCredential> ' ,
76- 'create a Did Configuration Resource from an existing Kilt Credential Presentation ' ,
99+ 'fromCredential [ pathToCredential..] ' ,
100+ 'create a Did Configuration Resource from one or more existing Domain Linkage Credentials ' ,
77101 ( ygs ) =>
78102 ygs . options ( commonOpts ) . positional ( 'pathToCredential' , {
79- describe : 'Path to a json file containing the credential presentation ' ,
103+ describe : 'Path to a json file containing a Domain Linkage Credential ' ,
80104 type : 'string' ,
81105 demandOption : true ,
106+ array : true ,
82107 } ) ,
83108 async ( { pathToCredential, outFile } ) => {
84- let credential : ICredentialPresentation
85- try {
86- credential = JSON . parse ( await readFile ( pathToCredential , { encoding : 'utf-8' } ) )
87- } catch ( cause ) {
88- throw new Error ( `Cannot parse file ${ pathToCredential } ` , { cause } )
89- }
90- if ( ! Credential . isPresentation ( credential ) ) {
91- throw new Error ( `Malformed Credential Presentation loaded from ${ pathToCredential } ` )
92- }
109+ const credentials : DomainLinkageCredential [ ] = await Promise . all (
110+ pathToCredential . map ( async ( path ) => {
111+ try {
112+ return JSON . parse ( await readFile ( path , { encoding : 'utf-8' } ) )
113+ } catch ( cause ) {
114+ throw new Error ( `Cannot parse file ${ pathToCredential } ` , { cause } )
115+ }
116+ } )
117+ )
93118 let didResource : DidConfigResource
94119 try {
95- didResource = await didConfigResourceFromCredential ( credential )
120+ didResource = didConfigResourceFromCredentials ( credentials )
96121 } catch ( cause ) {
97- throw new Error ( 'Credential Presentation is not suitable for use in a Did Configuration Resource' , {
122+ throw new Error ( 'Credential is not suitable for use in a Did Configuration Resource' , {
98123 cause,
99124 } )
100125 }
@@ -103,20 +128,38 @@ async function run() {
103128 )
104129 . command (
105130 'credentialOnly' ,
106- 'issue a new Kilt Credential Presentation for use in a Did Configuration Resource' ,
107- { ...createCredentialOpts , ...commonOpts } ,
108- async ( { origin, seed, keyType, wsAddress, outFile, did } ) => {
109- const credential = await issueCredential ( did as DidUri , origin , seed , keyType , wsAddress )
131+ 'issue a new Domain Linkage Credential for use in a Did Configuration Resource' ,
132+ {
133+ ...createCredentialOpts ,
134+ ...commonOpts ,
135+ proofType : {
136+ alias : 'p' ,
137+ choices : [ DataIntegrity . PROOF_TYPE , KILT_SELF_SIGNED_PROOF_TYPE ] as const ,
138+ default : KILT_SELF_SIGNED_PROOF_TYPE ,
139+ describe :
140+ 'Which proof type to use in the credential. DataIntegrity is the more modern proof type, but might not be accepted by all extensions yet. Did Configuration Resources can contain multiple credentials, though.' ,
141+ } ,
142+ } ,
143+ async ( { origin, seed, keyType, wsAddress, outFile, did, proofType } ) => {
144+ await connect ( wsAddress )
145+ validateDid ( did )
146+ const credential = await issueCredential ( { did : did as Did , origin, seed, keyType, proofType } )
110147 await write ( credential , outFile )
111148 }
112149 )
113150 . command (
114151 '$0' ,
115- 'create a Did Configuration Resource from a freshly issued Kilt Credential ' ,
152+ 'create a Did Configuration Resource containing newly issued Domain Linkage Credentials ' ,
116153 { ...createCredentialOpts , ...commonOpts } ,
117154 async ( { origin, seed, keyType, wsAddress, outFile, did } ) => {
118- const credential = await issueCredential ( did as DidUri , origin , seed , keyType , wsAddress )
119- const didResource = await didConfigResourceFromCredential ( credential )
155+ await connect ( wsAddress )
156+ validateDid ( did )
157+ const credentials = await Promise . all (
158+ [ DataIntegrity . PROOF_TYPE , KILT_SELF_SIGNED_PROOF_TYPE ] . map ( ( proofType ) =>
159+ issueCredential ( { did : did as Did , origin, seed, keyType, proofType } )
160+ )
161+ )
162+ const didResource = didConfigResourceFromCredentials ( credentials )
120163 await write ( didResource , outFile )
121164 }
122165 )
0 commit comments