UNPKG

@sphereon/gx-agent-cli

Version:
175 lines (174 loc) 7.15 kB
import { program } from 'commander'; import { printTable } from 'console-table-printer'; import fs from 'fs'; import { asDID, convertDidWebToHost, exportToDIDDocument, getAgent, getVcType } from '@sphereon/gx-agent'; import nock from 'nock'; const vp = program.command('vp').description('Generic Verifiable Presentation commands'); vp.command('list') .description('Lists all persisted Verifiable Presentations') .action(async (cmd) => { const agent = await getAgent(); try { const uniqueVPs = await agent.dataStoreORMGetVerifiablePresentations({ order: [ { column: 'issuanceDate', direction: 'ASC', }, ], }); printTable(uniqueVPs.map((vp) => { return { types: vp.verifiablePresentation.verifiableCredential.map((vc) => getVcType(vc)).toString(), issuer: vp.verifiablePresentation.proof.verificationMethod, holder: vp.verifiablePresentation.holder, 'issuance-date': vp.verifiablePresentation.proof.created, id: vp.hash, }; })); } catch (e) { console.error(e.message); } }); vp.command('verify') .description('Verify a Verifiable Presentation from file or agent id') .option('-f, --input-file <string>', 'File containing a Verifiable Presentation') .option('-id, --vc-id <string>', 'Use a persisted VP in the agent as input for verification') .option('--show', 'Print the Verifiable Presentation to console') .action(async (cmd) => { const agent = await getAgent(); try { if (!cmd.inputFile && !cmd.vcId) { throw Error('Either a Verifiable Presentation input file or the id of a stored Verifiable Presentation needs to be supplied'); } else if (cmd.inputFile && cmd.vcId) { throw Error('Cannot both have a Verifiable Presentation input file and the id of a stored Verifiable Presentation'); } const verifiablePresentation = cmd.inputFile ? JSON.parse(fs.readFileSync(cmd.inputFile, 'utf-8')) : await agent.dataStoreGetVerifiablePresentation({ hash: cmd.vcId }); let id; try { id = await agent.didManagerGet({ did: verifiablePresentation.holder }); const didDoc = await exportToDIDDocument(id); const url = `https://${convertDidWebToHost(verifiablePresentation.holder)}`; nock.cleanAll(); nock(url) .get(`/.well-known/did.json`) .times(10) .reply(200, { ...didDoc, }); } catch (e) { // DID not hosted by us, which is fine } const result = await agent.checkVerifiablePresentation({ verifiablePresentation, show: cmd.show === true }); printTable([ { types: verifiablePresentation .verifiableCredential.map((vc) => vc.type.toString().replace('VerifiableCredential,', '')) .toString(), issuer: verifiablePresentation.proof.verificationMethod, holder: verifiablePresentation.holder, 'issuance-date': verifiablePresentation.proof.created, valid: result, }, ]); if (cmd.show === true) { console.log(JSON.stringify(verifiablePresentation, null, 2)); } } catch (e) { console.error(e.message); } finally { nock.cleanAll(); } }); vp.command('issue') .description('Issues a Verifiable Presentation using Credentials from input file(s) and/or stored in th eagent') .requiredOption('-d, --did <string>', 'Use domain or did') .option('-ids, --vc-ids <string...>', '1 or more Verifiable Credential IDS stored in the agent') .option('-f, --vc-files <string...>', 'File(s) containing Verifiable Credentials') .option('-c, --challenge <string>', 'Use a challenge') .option('-t, --target-domain <string>', 'Target domain, used to protect against replay attacks') .option('-p, --persist', 'Persist the presentation. If not provided the presentation will not be stored in the agent') .option('--show', 'Print the Verifiable Presentation to console') .action(async (cmd) => { const agent = await getAgent(); if (!cmd.vcFiles && !cmd.vcIds) { throw Error('Verifiable Credential IDs or files need to be selected. Please check parameters'); } try { const fileVCs = cmd.vcFiles ? cmd.vcFiles.map((file) => { return JSON.parse(fs.readFileSync(file, 'utf-8')); }) : []; const agentVCs = []; const ids = cmd.vcIds ? cmd.vcIds : []; for (const hash of ids) { agentVCs.push(await agent.dataStoreGetVerifiableCredential({ hash })); } const verifiableCredentials = fileVCs.concat(agentVCs); if (verifiableCredentials.length === 0) { throw Error('No verifiable credentials were found matching the critery. Did you use the --vc-files and/or --vc-ids options?'); } const did = await asDID(cmd.did); const id = await agent.didManagerGet({ did }); const didDoc = await exportToDIDDocument(id); const url = `https://${convertDidWebToHost(did)}`; nock.cleanAll(); nock(url) .get(`/.well-known/did.json`) .times(10) .reply(200, { ...didDoc, }); const uniqueVP = await agent.issueVerifiablePresentation({ challenge: cmd.challenge, verifiableCredentials, domain: cmd.targetDomain, persist: cmd.persist === true, }); const vp = uniqueVP.verifiablePresentation; printTable([ { types: vp.type?.toString(), holder: vp.holder, 'issuance-date': vp.proof.created, id: uniqueVP.hash, persisted: cmd.persist === true, }, ]); if (cmd.show) { console.log(JSON.stringify(vp, null, 2)); } } catch (e) { console.error(e.message); } finally { nock.cleanAll(); } }); vp.command('export') .description('Exports a Verifiable Presentation to disk') .argument('<id>', 'The id of the VerifiablePresentation that you want to export') .option('-d, --did <string>', 'the DID or domain which will be used') .option('-p, --path <string>', 'A base path to export the files to. Defaults to "exported"') .option('--show', 'Print the Verifiable Presentation to console') .action(async (id, cmd) => { const agent = await getAgent(); const exportResult = await agent.exportVCsToPath({ domain: cmd.did, hash: id, includeVPs: true, includeVCs: false, exportPath: cmd.path, }); printTable(exportResult); console.log(`Verifiable Presentation file has been written to the above path`); });