Skip to content

Commit

Permalink
Implement VC creation in web5/api
Browse files Browse the repository at this point in the history
  • Loading branch information
ianpatton committed Oct 11, 2023
1 parent 150b419 commit c0cc08c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 17 deletions.
42 changes: 36 additions & 6 deletions packages/api/src/vc-api.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,46 @@
import type { Web5Agent } from '@web5/agent';
import type { Web5ManagedAgent } from '@web5/agent';

import { VerifiableCredential, VerifiableCredentialTypeV1 } from '@web5/credentials';

export class VcApi {
private agent: Web5Agent;
private agent: Web5ManagedAgent;
private connectedDid: string;

constructor(options: { agent: Web5Agent, connectedDid: string }) {
constructor(options: { agent: Web5ManagedAgent, connectedDid: string }) {
this.agent = options.agent;
this.connectedDid = options.connectedDid;
}

async create() {
// TODO: implement
throw new Error('Not implemented.');
getKeyId(did: string): string {
const secondColonIndex = did.indexOf(':', 4); // start search for : from the method portion
const methodSpecificId = did.substring(secondColonIndex + 1);
const keyId = `${did}#${methodSpecificId}`;
return keyId;
}

getSigner(keyId: string) {
const km = this.agent.keyManager;

return async function (data: Uint8Array): Promise<Uint8Array> {
const key = await km.getKey({ keyRef: keyId });
// @ts-ignore
const algorithm = key.algorithm || key.publicKey.algorithm;
const signature = await km.sign({ data, keyRef: keyId, algorithm });
return signature;
};

}

async create({ verifiableCredential, subjectDid }: { verifiableCredential: VerifiableCredentialTypeV1, subjectDid: string }) {
const keyId = this.getKeyId(this.connectedDid);

const verifiableCredentialJWT = await VerifiableCredential.create({
kid : keyId,
issuerDid : this.connectedDid,
subjectDid,
signer : this.getSigner(keyId)
}, undefined, verifiableCredential);

return verifiableCredentialJWT;
}
}
8 changes: 4 additions & 4 deletions packages/api/src/web5.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AppDataStore, Web5Agent } from '@web5/agent';
import type { AppDataStore, Web5ManagedAgent } from '@web5/agent';

import ms from 'ms';
import { Web5UserAgent } from '@web5/user-agent';
Expand All @@ -23,7 +23,7 @@ export type TechPreviewOptions = {
export type Web5ConnectOptions = {
/** Provide a {@link Web5Agent} implementation. Defaults to creating a local
* {@link Web5UserAgent} if one isn't provided */
agent?: Web5Agent;
agent?: Web5ManagedAgent;

/** Provide an instance of a {@link AppDataStore} implementation. Defaults to
* a LevelDB-backed store with an insecure, static unlock passphrase if one
Expand All @@ -48,12 +48,12 @@ export type Web5ConnectOptions = {
* @see {@link Web5ConnectOptions}
*/
type Web5Options = {
agent: Web5Agent;
agent: Web5ManagedAgent;
connectedDid: string;
};

export class Web5 {
agent: Web5Agent;
agent: Web5ManagedAgent;
did: DidApi;
dwn: DwnApi;
vc: VcApi;
Expand Down
25 changes: 18 additions & 7 deletions packages/api/tests/vc-api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { TestManagedAgent } from '@web5/agent';
import { VcApi } from '../src/vc-api.js';
import { TestUserAgent } from './utils/test-user-agent.js';

import { VerifiableCredentialTypeV1, utils } from '@web5/credentials';

describe('VcApi', () => {
let vc: VcApi;
let testAgent: TestManagedAgent;
let connectedDid: string;

before(async () => {
testAgent = await TestManagedAgent.create({
Expand All @@ -30,6 +33,7 @@ describe('VcApi', () => {

// Instantiate VcApi.
vc = new VcApi({ agent: testAgent.agent, connectedDid: identity.did });
connectedDid = identity.did;
});

after(async () => {
Expand All @@ -38,13 +42,20 @@ describe('VcApi', () => {
});

describe('create()', () => {
it('is not implemented', async () => {
try {
await vc.create();
expect.fail('Expected method to throw, but it did not.');
} catch(e) {
expect(e.message).to.include('Not implemented.');
}
it('should create a verifiable credential JWT', async () => {
const verifiableCredential: VerifiableCredentialTypeV1 = {
'@context' : ['https://www.w3.org/2018/credentials/v1'],
id : 'test-id',
type : ['VerifiableCredential', 'TestCredential'],
issuer : connectedDid,
issuanceDate : utils.getCurrentXmlSchema112Timestamp(),
credentialSubject : { test: true }
};

const jwt = await vc.create({ verifiableCredential, subjectDid: '' });

expect(jwt).to.be.a('string');

});
});
});

0 comments on commit c0cc08c

Please sign in to comment.