UNPKG

@veramo/cli

Version:
253 lines 8.68 kB
import { getAgent } from './setup.js'; import { Command } from 'commander'; import inquirer from 'inquirer'; import qrcode from 'qrcode-terminal'; import { readStdin } from './util.js'; import * as fs from 'fs'; import * as json5 from 'json5'; import { extractIssuer } from '@veramo/utils'; const presentation = new Command('presentation').description('W3C Verifiable Presentation'); presentation .command('create', { isDefault: true }) .description('Create W3C Verifiable Presentation') .option('-s, --send', 'Send') .option('-q, --qrcode', 'Show qrcode') .action(async (opts, cmd) => { const agent = await getAgent(cmd.optsWithGlobals().config); const myIdentifiers = await agent.didManagerFind(); if (myIdentifiers.length === 0) { console.error('No dids'); process.exit(); } const ids = await agent.dataStoreORMGetIdentifiers(); const identifiers = [ { name: 'Enter manually', value: 'manual', }, ...ids.map((id) => id.did), ]; let aud = []; const answers = await inquirer.prompt([ { type: 'list', name: 'iss', choices: myIdentifiers.map((item) => ({ name: `${item.did} ${item.alias}`, value: item.did, })), message: 'Holder DID', }, { type: 'input', name: 'tag', message: 'Tag (threadId)', default: 'xyz123', }, { type: 'input', name: 'audnum', message: 'Number of Verifiers', default: 1, }, { type: 'input', name: 'type', message: 'Presentation type', default: 'VerifiablePresentation,Profile', }, ]); for (let i = 0; i < answers.audnum; i++) { let answer = null; const audAnswer = await inquirer.prompt([ { type: 'list', name: 'aud', message: 'Select Verifier or enter manually', choices: identifiers, }, ]); answer = audAnswer.aud; if (answer === 'manual') { const manualAnswer = await inquirer.prompt([ { type: 'input', name: 'aud', message: 'Enter Verifier DID', }, ]); answer = manualAnswer.aud; } aud = [...aud, answer]; } const credentials = await agent.dataStoreORMGetVerifiableCredentials({ where: [{ column: 'subject', value: [answers.iss] }], }); const list = []; if (credentials.length > 0) { for (const credential of credentials) { list.push({ name: JSON.stringify(credential.verifiableCredential.credentialSubject) + ' | Issuer: ' + extractIssuer(credential.verifiableCredential), value: credential.verifiableCredential, }); } let addMoreCredentials = true; const verifiableCredential = []; while (addMoreCredentials) { const answers2 = await inquirer.prompt([ { type: 'list', name: 'credential', choices: list, message: 'Select credential', }, { type: 'list', name: 'addMore', message: 'Add another credential?', choices: [ { name: 'Yes', value: true }, { name: 'No', value: false }, ], }, ]); verifiableCredential.push(answers2.credential); addMoreCredentials = answers2.addMore; } const verifiablePresentation = await agent.createVerifiablePresentation({ save: true, presentation: { holder: answers.iss, verifier: aud, tag: answers.tag, '@context': ['https://www.w3.org/2018/credentials/v1'], type: answers.type.split(','), issuanceDate: new Date().toISOString(), verifiableCredential, }, proofFormat: 'jwt', }); if (opts.send) { for (var verifier in aud) { try { const message = await agent.sendMessageDIDCommAlpha1({ save: true, data: { from: answers.iss, to: verifier, type: 'jwt', body: verifiablePresentation.proof.jwt, }, }); console.dir(message, { depth: 10 }); } catch (e) { console.error(e); } } } if (opts.qrcode) { qrcode.generate(verifiablePresentation.proof.jwt); } else { console.dir(verifiablePresentation, { depth: 10 }); } } }); presentation .command('verify') .description('Verify a W3C Verifiable Presentation provided as a string param or a file or from stdin') .option('-c, --challenge <string>', 'Optional. Specify a challenge that the presentation should match.') .option('-d, --domain <string>', 'Optional. Specify a domain that the presentation should match.') .option('-f, --filename <string>', 'Optional. Read the presentation from a file instead of stdin') .option('-r, --raw <string>', 'Optional. Presentation as a parameter string instead of a file or stdin.') .action(async (options, cmd) => { const agent = await getAgent(cmd.optsWithGlobals().config); let raw = ''; if (options.raw) { raw = options.raw; } else if (options.filename) { raw = await fs.promises.readFile(options.filename, 'utf-8'); } else { raw = await readStdin(); } let presentationAsJSON; try { presentationAsJSON = json5.parse(raw); } catch (e) { presentationAsJSON = { proof: { type: 'JwtProof2020', jwt: raw, }, }; } const result = await agent.verifyPresentation({ presentation: presentationAsJSON, challenge: options.challenge, domain: options.domain, }); if (result.verified === true) { console.log('Presentation was verified successfully.'); } else { console.error('Presentation could not be verified.'); } }); presentation .command('output') .description('Print W3C Verifiable Presentation to stdout') .option('-t, --tag <string>', 'Optional. Specify the tag for the presentation.') .action(async (options, cmd) => { const agent = await getAgent(cmd.optsWithGlobals().config); const presentations = await agent.dataStoreORMGetVerifiablePresentations({}); if (presentations.length > 0) { let selected = null; const list = []; if (options.tag) { const matches = presentations.filter((pres) => pres.verifiablePresentation.tag === options.tag); if (matches.length > 1) { console.log('Found multiple matching presentations. Only showing the first one.'); } selected = matches[0]; } else { for (const pres of presentations) { list.push({ name: 'Issuance Date: ' + pres.verifiablePresentation.issuanceDate + ' | Holder: ' + pres.verifiablePresentation.holder + ' | Tag: ' + pres.verifiablePresentation.tag, value: pres, }); } const answers = await inquirer.prompt([ { type: 'list', name: 'presentation', choices: list, message: 'Select presentation', }, ]); selected = answers.presentation; } if (selected) { console.dir(selected, { depth: 10 }); } else { console.log('Presentation not found.'); } } else { console.log('No presentations found.'); } }); export { presentation }; //# sourceMappingURL=presentation.js.map