From 54a0899daf256e549003ab4d65154393adfaa6ae Mon Sep 17 00:00:00 2001 From: Neal Date: Wed, 8 Nov 2023 18:25:59 -0600 Subject: [PATCH 1/4] adding web vc create --- packages/agent/src/index.ts | 1 + packages/agent/src/test-managed-agent.ts | 5 + packages/agent/src/types/agent.ts | 20 +++- packages/agent/src/vc-manager.ts | 110 ++++++++++++++++++ packages/api/src/vc-api.ts | 23 +++- packages/api/tests/utils/test-user-agent.ts | 11 +- packages/api/tests/vc-api.spec.ts | 19 +-- packages/identity-agent/src/identity-agent.ts | 18 ++- packages/user-agent/src/user-agent.ts | 23 +++- 9 files changed, 206 insertions(+), 24 deletions(-) create mode 100644 packages/agent/src/vc-manager.ts diff --git a/packages/agent/src/index.ts b/packages/agent/src/index.ts index ed39e790e..68c9c81f5 100644 --- a/packages/agent/src/index.ts +++ b/packages/agent/src/index.ts @@ -14,5 +14,6 @@ export * from './store-managed-key.js'; export * from './store-managed-identity.js'; export * from './sync-manager.js'; export * from './utils.js'; +export * from './vc-manager.js'; export * from './test-managed-agent.js'; \ No newline at end of file diff --git a/packages/agent/src/test-managed-agent.ts b/packages/agent/src/test-managed-agent.ts index c5eda8b77..0260cba2c 100644 --- a/packages/agent/src/test-managed-agent.ts +++ b/packages/agent/src/test-managed-agent.ts @@ -21,6 +21,7 @@ import { DidStoreDwn, DidStoreMemory } from './store-managed-did.js'; import { IdentityManager, ManagedIdentity } from './identity-manager.js'; import { IdentityStoreDwn, IdentityStoreMemory } from './store-managed-identity.js'; import { KeyStoreDwn, KeyStoreMemory, PrivateKeyStoreDwn, PrivateKeyStoreMemory } from './store-managed-key.js'; +import {VcManager} from './vc-manager.js'; type CreateMethodOptions = { agentClass: new (options: any) => Web5ManagedAgent @@ -131,6 +132,9 @@ export class TestManagedAgent { // Instantiate a DwnManager using the custom DWN instance. const dwnManager = new DwnManager({ dwn }); + // Instantiate a VcManager. + const vcManager = new VcManager({}); + // Instantiate an RPC Client. const rpcClient = new Web5RpcClient(); @@ -146,6 +150,7 @@ export class TestManagedAgent { dwnManager, identityManager, keyManager, + vcManager, rpcClient, syncManager }); diff --git a/packages/agent/src/types/agent.ts b/packages/agent/src/types/agent.ts index 5ce8f05ee..51900c6f0 100644 --- a/packages/agent/src/types/agent.ts +++ b/packages/agent/src/types/agent.ts @@ -116,9 +116,25 @@ export type DwnRpcResponse = UnionMessageReply; * Verifiable Credential Types */ -export type ProcessVcRequest = { /** empty */ } +/** + * Type definition for a request to process a Verifiable Credential (VC). + * + * @param issuer The issuer URI of the credential, as a [String]. + * @param subject The subject URI of the credential, as a [String]. + * @param dataType The type of the credential, as a [String]. + * @param data The credential data, as a generic type [T]. + * @param expirationDate The expiration date. + */ +export type ProcessVcRequest = { + issuer: string; + subject: string; + dataType: string, + data: any, + expirationDate?: string +} + export type SendVcRequest = { /** empty */ } -export type VcResponse = { /** empty */ } +export type VcResponse = { vcJwt: string } /** * Web5 Agent Types diff --git a/packages/agent/src/vc-manager.ts b/packages/agent/src/vc-manager.ts new file mode 100644 index 000000000..540e96ee1 --- /dev/null +++ b/packages/agent/src/vc-manager.ts @@ -0,0 +1,110 @@ +import { Jose } from '@web5/crypto'; +import { utils as didUtils } from '@web5/dids'; +import { VerifiableCredential } from '@web5/credentials'; +import { Signer } from '@tbd54566975/dwn-sdk-js'; +import { isManagedKeyPair } from './utils.js'; + +import type { VcResponse, ProcessVcRequest, Web5ManagedAgent } from './types/agent.js'; + +export type VcManagerOptions = { agent?: Web5ManagedAgent; } + +export class VcManager { + /** + * Holds the instance of a `Web5ManagedAgent` that represents the current + * execution context for the `KeyManager`. This agent is utilized + * to interact with other Web5 agent components. It's vital + * to ensure this instance is set to correctly contextualize + * operations within the broader Web5 agent framework. + */ + private _agent?: Web5ManagedAgent; + + constructor(options: VcManagerOptions) { + const { agent } = options; + this._agent = agent; + } + + /** + * Retrieves the `Web5ManagedAgent` execution context. + * If the `agent` instance proprety is undefined, it will throw an error. + * + * @returns The `Web5ManagedAgent` instance that represents the current execution + * context. + * + * @throws Will throw an error if the `agent` instance property is undefined. + */ + get agent(): Web5ManagedAgent { + if (this._agent === undefined) { + throw new Error('VcManager: Unable to determine agent execution context.'); + } + + return this._agent; + } + + set agent(agent: Web5ManagedAgent) { + this._agent = agent; + } + + /** + * Processes a request to create and sign a verifiable credential. + * The process involves creating a VC object with the provided data, constructing a signer, + * and signing the VC with the signer's sign function. The resultant VC is a JWT (JSON Web Token). + */ + async processRequest(request: ProcessVcRequest): Promise { + const { dataType, issuer, subject, data } = request; + const vc = VerifiableCredential.create(dataType, issuer, subject, data); + + const vcSigner = await this.constructVcSigner(issuer); + const vcSignOptions = { + issuerDid : issuer, + subjectDid : subject, + kid : issuer + '#' + issuer.split(':')[2], + signer : vcSigner.sign + }; + + const vcJwt = await vc.sign(vcSignOptions); + return {vcJwt: vcJwt}; + } + + private async constructVcSigner(author: string): Promise { + // const signingKeyId = await this.getAuthorSigningKeyId({ did: author }); + const signingKeyId = await this.agent.didManager.getDefaultSigningKey({ did: author }); + + if (!signingKeyId) { + throw new Error (`VcManager: Unable to determine signing key id for author: '${author}'`); + } + + /** + * DID keys stored in KeyManager use the canonicalId as an alias, so + * normalize the signing key ID before attempting to retrieve the key. + */ + const parsedDid = didUtils.parseDid({ didUrl: signingKeyId }); + if (!parsedDid) { + throw new Error(`DidIonMethod: Unable to parse DID: ${signingKeyId}`); + } + + const normalizedDid = parsedDid.did.split(':', 3).join(':'); + const normalizedSigningKeyId = `${normalizedDid}#${parsedDid.fragment}`; + const signingKey = await this.agent.keyManager.getKey({ keyRef: normalizedSigningKeyId }); + + if (!isManagedKeyPair(signingKey)) { + throw new Error(`VcManager: Signing key not found for author: '${author}'`); + } + + const { alg } = Jose.webCryptoToJose(signingKey.privateKey.algorithm); + if (alg === undefined) { + throw Error(`No algorithm provided to sign with key ID ${signingKeyId}`); + } + + return { + keyId : signingKeyId, + algorithm : alg, + sign : async (content: Uint8Array): Promise => { + return await this.agent.keyManager.sign({ + algorithm : signingKey.privateKey.algorithm, + data : content, + keyRef : normalizedSigningKeyId + }); + } + }; + } +} \ No newline at end of file diff --git a/packages/api/src/vc-api.ts b/packages/api/src/vc-api.ts index ccf346be2..dc7617daf 100644 --- a/packages/api/src/vc-api.ts +++ b/packages/api/src/vc-api.ts @@ -15,10 +15,25 @@ export class VcApi { } /** - * Issues a VC (Not implemented yet) + * Issues a VC to the subject did + * + * @param issuer The issuer URI of the credential, as a [String]. + * @param subject The subject URI of the credential, as a [String]. + * @param dataType The type of the credential, as a [String]. + * @param data The credential data, as a generic type [T]. + * @param expirationDate The expiration date. + * @return A VerifiableCredential JWT. */ - async create() { - // TODO: implement - throw new Error('Not implemented.'); + async create(issuer: string, subject: string, dataType: string, data: any, expirationDate?: string): Promise { + const agentResponse = await this.agent.processVcRequest({ + issuer : issuer, + subject : subject, + dataType : dataType, + data : data, + expirationDate : expirationDate + }); + + const { vcJwt } = agentResponse; + return vcJwt; } } \ No newline at end of file diff --git a/packages/api/tests/utils/test-user-agent.ts b/packages/api/tests/utils/test-user-agent.ts index 34b85c58e..e526f4fb9 100644 --- a/packages/api/tests/utils/test-user-agent.ts +++ b/packages/api/tests/utils/test-user-agent.ts @@ -26,6 +26,7 @@ import { DidManager, DwnManager, KeyManager, + VcManager, AppDataVault, Web5RpcClient, IdentityManager, @@ -43,6 +44,7 @@ type TestUserAgentOptions = { dwnManager: DwnManager; identityManager: IdentityManager; keyManager: KeyManager; + vcManager: VcManager, rpcClient: DwnRpc; syncManager: SyncManager; @@ -60,6 +62,7 @@ export class TestUserAgent implements Web5ManagedAgent { dwnManager: DwnManager; identityManager: IdentityManager; keyManager: KeyManager; + vcManager: VcManager; rpcClient: DwnRpc; syncManager: SyncManager; @@ -78,6 +81,7 @@ export class TestUserAgent implements Web5ManagedAgent { this.dwnManager = options.dwnManager; this.identityManager = options.identityManager; this.keyManager = options.keyManager; + this.vcManager = options.vcManager; this.rpcClient = options.rpcClient; this.syncManager = options.syncManager; @@ -86,6 +90,7 @@ export class TestUserAgent implements Web5ManagedAgent { this.dwnManager.agent = this; this.identityManager.agent = this; this.keyManager.agent = this; + this.vcManager.agent = this; this.syncManager.agent = this; // TestUserAgent-specific properties. @@ -128,6 +133,7 @@ export class TestUserAgent implements Web5ManagedAgent { memory: new LocalKms({ kmsName: 'memory' }) }; const keyManager = new KeyManager({ kms }); + const vcManager = new VcManager({}); // Instantiate DID resolver. const didMethodApis = [DidKeyMethod]; @@ -160,6 +166,7 @@ export class TestUserAgent implements Web5ManagedAgent { dwnManager, identityManager, keyManager, + vcManager, rpcClient, syncManager, }); @@ -181,8 +188,8 @@ export class TestUserAgent implements Web5ManagedAgent { return this.dwnManager.processRequest(request); } - async processVcRequest(_request: ProcessVcRequest): Promise { - throw new Error('Not implemented'); + async processVcRequest(request: ProcessVcRequest): Promise { + return this.vcManager.processRequest(request); } async sendDidRequest(_request: SendDidRequest): Promise { diff --git a/packages/api/tests/vc-api.spec.ts b/packages/api/tests/vc-api.spec.ts index dcfd9b03d..f4e8c6ba4 100644 --- a/packages/api/tests/vc-api.spec.ts +++ b/packages/api/tests/vc-api.spec.ts @@ -3,10 +3,12 @@ import { TestManagedAgent } from '@web5/agent'; import { VcApi } from '../src/vc-api.js'; import { TestUserAgent } from './utils/test-user-agent.js'; +import { VerifiableCredential } from '@web5/credentials'; describe('VcApi', () => { let vc: VcApi; let testAgent: TestManagedAgent; + let identityDid: string; before(async () => { testAgent = await TestManagedAgent.create({ @@ -28,8 +30,9 @@ describe('VcApi', () => { kms : 'local' }); + identityDid = identity.did; // Instantiate VcApi. - vc = new VcApi({ agent: testAgent.agent, connectedDid: identity.did }); + vc = new VcApi({ agent: testAgent.agent, connectedDid: identityDid }); }); after(async () => { @@ -38,13 +41,13 @@ 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('returns a self signed vc', async () => { + const vcJwt = await vc.create(identityDid, identityDid, 'ExampleDataType', {example: 'goodStuff'}); + + expect(vcJwt).to.not.be.null; + expect(vcJwt.split('.').length).to.equal(3); + + await expect(VerifiableCredential.verify(vcJwt)).to.be.fulfilled; }); }); }); \ No newline at end of file diff --git a/packages/identity-agent/src/identity-agent.ts b/packages/identity-agent/src/identity-agent.ts index cb9220a14..e103b4d17 100644 --- a/packages/identity-agent/src/identity-agent.ts +++ b/packages/identity-agent/src/identity-agent.ts @@ -22,6 +22,7 @@ import { DidManager, DwnManager, KeyManager, + VcManager, DidStoreDwn, KeyStoreDwn, AppDataVault, @@ -41,6 +42,7 @@ export type IdentityAgentOptions = { dwnManager: DwnManager; identityManager: IdentityManager; keyManager: KeyManager; + vcManager: VcManager; rpcClient: DwnRpc; syncManager: SyncManager; } @@ -53,6 +55,7 @@ export class IdentityAgent implements Web5ManagedAgent { dwnManager: DwnManager; identityManager: IdentityManager; keyManager: KeyManager; + vcManager: VcManager; rpcClient: DwnRpc; syncManager: SyncManager; @@ -64,6 +67,7 @@ export class IdentityAgent implements Web5ManagedAgent { this.dwnManager = options.dwnManager; this.identityManager = options.identityManager; this.keyManager = options.keyManager; + this.vcManager = options.vcManager; this.rpcClient = options.rpcClient; this.syncManager = options.syncManager; @@ -72,13 +76,14 @@ export class IdentityAgent implements Web5ManagedAgent { this.dwnManager.agent = this; this.identityManager.agent = this; this.keyManager.agent = this; + this.vcManager.agent = this; this.syncManager.agent = this; } static async create(options: Partial = {}): Promise { let { agentDid, appData, didManager, didResolver, dwnManager, - identityManager, keyManager, rpcClient, syncManager + identityManager, keyManager, vcManager, rpcClient, syncManager } = options; if (agentDid === undefined) { @@ -143,6 +148,12 @@ export class IdentityAgent implements Web5ManagedAgent { }); } + if (vcManager === undefined) { + // A custom VcManager implementation was not specified, so + // instantiate a default. + vcManager = new VcManager({}); + } + if (rpcClient === undefined) { // A custom RPC Client implementation was not specified, so // instantiate a default. @@ -164,6 +175,7 @@ export class IdentityAgent implements Web5ManagedAgent { dwnManager, identityManager, keyManager, + vcManager, rpcClient, syncManager }); @@ -207,8 +219,8 @@ export class IdentityAgent implements Web5ManagedAgent { return this.dwnManager.processRequest(request); } - async processVcRequest(_request: ProcessVcRequest): Promise { - throw new Error('Not implemented'); + async processVcRequest(request: ProcessVcRequest): Promise { + return this.vcManager.processRequest(request); } async sendDidRequest(_request: SendDidRequest): Promise { diff --git a/packages/user-agent/src/user-agent.ts b/packages/user-agent/src/user-agent.ts index c8b33eb05..f7628c6c4 100644 --- a/packages/user-agent/src/user-agent.ts +++ b/packages/user-agent/src/user-agent.ts @@ -22,6 +22,7 @@ import { DidManager, DwnManager, KeyManager, + VcManager, DidStoreDwn, KeyStoreDwn, AppDataVault, @@ -41,6 +42,7 @@ export type Web5UserAgentOptions = { dwnManager: DwnManager; identityManager: IdentityManager; keyManager: KeyManager; + vcManager: VcManager; rpcClient: DwnRpc; syncManager: SyncManager; } @@ -53,6 +55,7 @@ export class Web5UserAgent implements Web5ManagedAgent { dwnManager: DwnManager; identityManager: IdentityManager; keyManager: KeyManager; + vcManager: VcManager; rpcClient: DwnRpc; syncManager: SyncManager; @@ -60,6 +63,7 @@ export class Web5UserAgent implements Web5ManagedAgent { this.agentDid = options.agentDid; this.appData = options.appData; this.keyManager = options.keyManager; + this.vcManager = options.vcManager; this.didManager = options.didManager; this.didResolver = options.didResolver; this.dwnManager = options.dwnManager; @@ -72,13 +76,14 @@ export class Web5UserAgent implements Web5ManagedAgent { this.dwnManager.agent = this; this.identityManager.agent = this; this.keyManager.agent = this; + this.vcManager.agent = this; this.syncManager.agent = this; } static async create(options: Partial = {}): Promise { let { agentDid, appData, didManager, didResolver, dwnManager, - identityManager, keyManager, rpcClient, syncManager + identityManager, keyManager, vcManager, rpcClient, syncManager } = options; if (agentDid === undefined) { @@ -147,6 +152,13 @@ export class Web5UserAgent implements Web5ManagedAgent { }); } + + if (vcManager === undefined) { + /** A custom VcManager implementation was not specified, so + * instantiate a default. */ + vcManager = new VcManager({}); + } + if (rpcClient === undefined) { // A custom RPC Client implementation was not specified, so // instantiate a default. @@ -167,6 +179,7 @@ export class Web5UserAgent implements Web5ManagedAgent { didResolver, dwnManager, keyManager, + vcManager, identityManager, rpcClient, syncManager @@ -209,16 +222,16 @@ export class Web5UserAgent implements Web5ManagedAgent { return this.dwnManager.processRequest(request); } - async processVcRequest(_request: ProcessVcRequest): Promise { - throw new Error('Not implemented'); + async processVcRequest(request: ProcessVcRequest): Promise { + return this.vcManager.processRequest(request); } async sendDidRequest(_request: SendDidRequest): Promise { throw new Error('Not implemented'); } - async sendDwnRequest(request: SendDwnRequest): Promise { - return this.dwnManager.sendRequest(request); + async sendDwnRequest(_request: SendDwnRequest): Promise { + return this.dwnManager.sendRequest(_request); } async sendVcRequest(_request: SendVcRequest): Promise { From defeb832c605bf9552529aefba2e89b7f63cb733 Mon Sep 17 00:00:00 2001 From: Neal Date: Wed, 8 Nov 2023 18:33:50 -0600 Subject: [PATCH 2/4] small fixes --- packages/agent/src/vc-manager.ts | 3 +-- packages/user-agent/src/user-agent.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/agent/src/vc-manager.ts b/packages/agent/src/vc-manager.ts index 540e96ee1..a21cd0849 100644 --- a/packages/agent/src/vc-manager.ts +++ b/packages/agent/src/vc-manager.ts @@ -11,7 +11,7 @@ export type VcManagerOptions = { agent?: Web5ManagedAgent; } export class VcManager { /** * Holds the instance of a `Web5ManagedAgent` that represents the current - * execution context for the `KeyManager`. This agent is utilized + * execution context for the `VcManager`. This agent is utilized * to interact with other Web5 agent components. It's vital * to ensure this instance is set to correctly contextualize * operations within the broader Web5 agent framework. @@ -66,7 +66,6 @@ export class VcManager { } private async constructVcSigner(author: string): Promise { - // const signingKeyId = await this.getAuthorSigningKeyId({ did: author }); const signingKeyId = await this.agent.didManager.getDefaultSigningKey({ did: author }); if (!signingKeyId) { diff --git a/packages/user-agent/src/user-agent.ts b/packages/user-agent/src/user-agent.ts index f7628c6c4..08a9f4295 100644 --- a/packages/user-agent/src/user-agent.ts +++ b/packages/user-agent/src/user-agent.ts @@ -230,8 +230,8 @@ export class Web5UserAgent implements Web5ManagedAgent { throw new Error('Not implemented'); } - async sendDwnRequest(_request: SendDwnRequest): Promise { - return this.dwnManager.sendRequest(_request); + async sendDwnRequest(request: SendDwnRequest): Promise { + return this.dwnManager.sendRequest(request); } async sendVcRequest(_request: SendVcRequest): Promise { From 2fab1df123ec591ebdd188b3e3b61389cd1f3e84 Mon Sep 17 00:00:00 2001 From: Neal Date: Thu, 9 Nov 2023 11:34:34 -0600 Subject: [PATCH 3/4] adding alg to vc sign options --- packages/agent/src/vc-manager.ts | 3 ++- packages/credentials/src/verifiable-credential.ts | 7 ++++--- packages/credentials/tests/presentation-exchange.spec.ts | 1 + packages/credentials/tests/verifiable-credential.spec.ts | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/agent/src/vc-manager.ts b/packages/agent/src/vc-manager.ts index a21cd0849..ec6b6de25 100644 --- a/packages/agent/src/vc-manager.ts +++ b/packages/agent/src/vc-manager.ts @@ -57,7 +57,8 @@ export class VcManager { const vcSignOptions = { issuerDid : issuer, subjectDid : subject, - kid : issuer + '#' + issuer.split(':')[2], + kid : vcSigner.keyId, + alg : vcSigner.algorithm, signer : vcSigner.sign }; diff --git a/packages/credentials/src/verifiable-credential.ts b/packages/credentials/src/verifiable-credential.ts index 2da6086bf..4d62afd78 100644 --- a/packages/credentials/src/verifiable-credential.ts +++ b/packages/credentials/src/verifiable-credential.ts @@ -22,9 +22,10 @@ export const DEFAULT_VC_TYPE = 'VerifiableCredential'; export type VcDataModel = ICredential; export type SignOptions = { - kid: string; issuerDid: string; subjectDid: string; + kid: string; + alg: string; signer: Signer, } @@ -262,9 +263,9 @@ function decode(jwt: string): DecodedVcJwt { } async function createJwt(payload: any, signOptions: SignOptions) { - const { issuerDid, subjectDid, signer, kid } = signOptions; + const { issuerDid, subjectDid, signer, kid, alg } = signOptions; - const header: JwtHeaderParams = { alg: 'EdDSA', typ: 'JWT', kid: kid }; + const header: JwtHeaderParams = { alg: alg, typ: 'JWT', kid: kid }; const jwtPayload = { iss : issuerDid, diff --git a/packages/credentials/tests/presentation-exchange.spec.ts b/packages/credentials/tests/presentation-exchange.spec.ts index 881614b85..ea70a3116 100644 --- a/packages/credentials/tests/presentation-exchange.spec.ts +++ b/packages/credentials/tests/presentation-exchange.spec.ts @@ -33,6 +33,7 @@ describe('PresentationExchange', () => { issuerDid : alice.did, subjectDid : alice.did, kid : alice.did + '#' + alice.did.split(':')[2], + alg : 'EdDSA', signer : signer }; diff --git a/packages/credentials/tests/verifiable-credential.spec.ts b/packages/credentials/tests/verifiable-credential.spec.ts index 13a9476dc..f8bcd472b 100644 --- a/packages/credentials/tests/verifiable-credential.spec.ts +++ b/packages/credentials/tests/verifiable-credential.spec.ts @@ -26,6 +26,7 @@ describe('Verifiable Credential Tests', () => { issuerDid : alice.did, subjectDid : alice.did, kid : alice.did + '#' + alice.did.split(':')[2], + alg : 'EdDSA', signer : signer }; }); @@ -128,6 +129,7 @@ describe('Verifiable Credential Tests', () => { issuerDid : 'bad:did: invalidDid', subjectDid : signOptions.subjectDid, kid : signOptions.issuerDid + '#' + signOptions.issuerDid.split(':')[2], + alg : 'EdDSA', signer : signer }; From 6695b3b214070f8f3b84249e7f2687cd56ec8a40 Mon Sep 17 00:00:00 2001 From: Neal Date: Tue, 14 Nov 2023 11:51:07 -0600 Subject: [PATCH 4/4] adding dwn write comments --- packages/api/tests/utils/test-user-agent.ts | 36 +++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/api/tests/utils/test-user-agent.ts b/packages/api/tests/utils/test-user-agent.ts index e526f4fb9..3f29b9ffc 100644 --- a/packages/api/tests/utils/test-user-agent.ts +++ b/packages/api/tests/utils/test-user-agent.ts @@ -14,9 +14,15 @@ import type { SyncManager, } from '@web5/agent'; -import { Dwn, EventLogLevel, +import { + Dwn, + EventLogLevel, DataStoreLevel, - MessageStoreLevel, } from '@tbd54566975/dwn-sdk-js'; + MessageStoreLevel, + // RecordsWriteOptions, + // DwnInterfaceName, + // DwnMethodName, +} from '@tbd54566975/dwn-sdk-js'; import { DidResolver, DidKeyMethod, @@ -189,7 +195,31 @@ export class TestUserAgent implements Web5ManagedAgent { } async processVcRequest(request: ProcessVcRequest): Promise { - return this.vcManager.processRequest(request); + const vcResponse = await this.vcManager.processRequest(request); + + // TODO: Write to DWN and Update VcResponse Object with optional dwnResponse + // const messageOptions: Partial = { + // schema : request.dataType, + // dataFormat : 'application/vc+jwt', + // }; + // + // const vcDataBlob = new Blob([vcResponse.vcJwt], { type: 'text/plain' }); + // + // const dwnProcessOptions = { + // author : request.issuer, + // dataStream : vcDataBlob, + // messageOptions, + // messageType : DwnInterfaceName.Records + DwnMethodName.Write, + // store : true, + // target : request.issuer + // }; + // + // const dwnResponse = await this.processDwnRequest(dwnProcessOptions); + // + // console.log('DWN RESPONSE:'); + // console.log(dwnResponse); + + return vcResponse; } async sendDidRequest(_request: SendDidRequest): Promise {