Skip to content

Commit

Permalink
adding vc create
Browse files Browse the repository at this point in the history
  • Loading branch information
nitro-neal committed Jul 7, 2023
1 parent 9aa02be commit 4561808
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 10 deletions.
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/credentials/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@
"engines": {
"node": ">=18.0.0"
},
"dependencies": {},
"dependencies": {
"uuid": "^9.0.0"
},
"devDependencies": {
"@types/chai": "4.3.0",
"@types/eslint": "8.37.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/credentials/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function getCurrentXmlSchema112Timestamp() : string {
// Omit the milliseconds part from toISOString() output
return new Date().toISOString().replace(/\.\d+Z$/, 'Z');
}

Check warning on line 4 in packages/credentials/src/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/credentials/src/utils.ts#L2-L4

Added lines #L2 - L4 were not covered by tests
66 changes: 60 additions & 6 deletions packages/web5/src/vc-api.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,70 @@
import type { Web5Agent } from '@tbd54566975/web5-agent';
import { Web5Agent } from '@tbd54566975/web5-agent';
import type { VerifiableCredential } from '../../credentials/src/types.js';

import { getCurrentXmlSchema112Timestamp } from '../../credentials/src/utils.js';
import { v4 as uuidv4 } from 'uuid';
import { dataToBlob } from './utils.js';
import { Record } from './record.js';

import { DwnInterfaceName, DwnMethodName, RecordsWriteMessage, RecordsWriteOptions } from '@tbd54566975/dwn-sdk-js';
import { RecordsWriteResponse } from './dwn-api.js';

export type VcCreateResponse = RecordsWriteResponse & {
vc: VerifiableCredential;
};

export class VcApi {
#agent: Web5Agent;
#web5Agent: Web5Agent;
#connectedDid: string;

constructor(agent: Web5Agent, connectedDid: string) {
this.#agent = agent;
this.#web5Agent = agent;
this.#connectedDid = connectedDid;
}

async create() {
// TODO: implement
throw new Error('Not implemented.');
async create(credentialSubject: any): Promise<VcCreateResponse> {
if (!credentialSubject || typeof credentialSubject !== 'object') {
throw new Error('credentialSubject not valid');
}

const vc: VerifiableCredential = {
'@context' : ['https://www.w3.org/2018/credentials/v1'],
credentialSubject : credentialSubject,
type : ['VerifiableCredential'],
issuer : { id: this.#connectedDid },
issuanceDate : getCurrentXmlSchema112Timestamp(),
id : uuidv4(),
};

const messageOptions: Partial<RecordsWriteOptions> = { ...{ schema: 'vc/vc', dataFormat: 'application/json' } };

const { dataBlob, dataFormat } = dataToBlob(vc, 'application/json');
messageOptions.dataFormat = dataFormat;

const agentResponse = await this.#web5Agent.processDwnRequest({
author : this.#connectedDid,
dataStream : dataBlob,
messageOptions,
messageType : DwnInterfaceName.Records + DwnMethodName.Write,
store : true,
target : this.#connectedDid
});

const { message, reply: { status } } = agentResponse;
const responseMessage = message as RecordsWriteMessage;

let record: Record;
if (200 <= status.code && status.code <= 299) {
const recordOptions = {
author : this.#connectedDid,
encodedData : dataBlob,
target : this.#connectedDid,
...responseMessage,
};

record = new Record(this.#web5Agent, recordOptions);
}

return { record, status, vc };
}
}
17 changes: 14 additions & 3 deletions packages/web5/tests/web5-vc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,23 @@ describe('web5.vc', () => {
});

describe('create', () => {
it('is not implemented', async () => {
it('valid vc', async () => {
const credentialSubject = {firstName: 'alice'};
const result = await vc.create(credentialSubject);

expect(result.status.code).to.equal(202);
expect(result.status.detail).to.equal('Accepted');
expect(result.record).to.exist;
expect(await result.record?.data.json()).to.deep.equal(result.vc);
});

it('invalid credential subject', async () => {
const credentialSubject = 'badcredsubject';
try {
await vc.create();
await vc.create(credentialSubject);
expect.fail();
} catch(e) {
expect(e.message).to.include('Not implemented.');
expect(e.message).to.include('credentialSubject not valid');
}
});
});
Expand Down

0 comments on commit 4561808

Please sign in to comment.