From d1da46605a5b8a273168aed1abd48a8899c5ac08 Mon Sep 17 00:00:00 2001 From: Frank Hinek Date: Mon, 21 Aug 2023 13:49:22 -0400 Subject: [PATCH] Support BYO DID Signed-off-by: Frank Hinek --- packages/api/src/web5.ts | 14 ++++++++++---- packages/api/tests/web5.spec.ts | 30 +++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/packages/api/src/web5.ts b/packages/api/src/web5.ts index ecdd96071..b8b8da587 100644 --- a/packages/api/src/web5.ts +++ b/packages/api/src/web5.ts @@ -24,6 +24,9 @@ export type Web5ConnectOptions = { * {@link Web5UserAgent} if one isn't provided */ agent?: Web5Agent; + /** Specify an existing DID to connect to. */ + connectedDid?: string; + /** Provide an instance of a {@link AppDataStore} implementation. Defaults to * a LevelDB-backed store with an insecure, static unlock passphrase if one * isn't provided. To allow the app user to enter a secure passphrase of @@ -44,6 +47,7 @@ type Web5Options = { }; export class Web5 { + agent: Web5Agent; did: DidApi; dwn: DwnApi; vc: VcApi; @@ -51,6 +55,7 @@ export class Web5 { constructor(options: Web5Options) { const { agent, connectedDid } = options; + this.agent = agent; this.connectedDid = connectedDid; this.did = new DidApi({ agent, connectedDid }); this.dwn = new DwnApi({ agent, connectedDid }); @@ -65,7 +70,7 @@ export class Web5 { * @returns */ static async connect(options: Web5ConnectOptions = {}) { - let { agent, appData, techPreview } = options; + let { agent, appData, connectedDid, techPreview } = options; if (agent === undefined) { // A custom Web5Agent implementation was not specified, so use default managed user agent. @@ -90,18 +95,19 @@ export class Web5 { if (identities.length === 0) { const serviceEndpointNodes = techPreview?.dwnEndpoints ?? await getTechPreviewDwnEndpoints(); const didOptions = await DidIonMethod.generateDwnOptions({ serviceEndpointNodes }); - await userAgent.identityManager.create({ + const identity = await userAgent.identityManager.create({ name : 'Default', didMethod : 'ion', didOptions, kms : 'local' }); + connectedDid = identity.did; } } } - const web5 = new Web5({ agent, connectedDid: agent.agentDid }); + const web5 = new Web5({ agent, connectedDid }); - return { web5, did: agent.agentDid }; + return { web5, did: connectedDid }; } } \ No newline at end of file diff --git a/packages/api/tests/web5.spec.ts b/packages/api/tests/web5.spec.ts index 30a8c9079..6ee53da61 100644 --- a/packages/api/tests/web5.spec.ts +++ b/packages/api/tests/web5.spec.ts @@ -4,8 +4,10 @@ import { AppDataVault, TestManagedAgent } from '@web5/agent'; import { Web5 } from '../src/web5.js'; import { TestUserAgent } from './utils/test-user-agent.js'; import { MemoryStore } from '@web5/common'; +import { DidIonMethod } from '@web5/dids'; +import { Web5UserAgent } from '@web5/user-agent'; -describe('Web5', () => { +describe.only('Web5', () => { describe('using TestManagedAgent', () => { let testAgent: TestManagedAgent; @@ -26,6 +28,32 @@ describe('Web5', () => { await testAgent.closeStorage(); }); + describe('connect()', () => { + it('accepts an externally created ION DID', async () => { + // Create an ION DID. + const didOptions = await DidIonMethod.generateDwnOptions({ + serviceEndpointNodes: ['https://dwn.example.com'] + }); + const portableDid = await DidIonMethod.create({ ...didOptions }); + + // Import the previously created DID. + await testAgent.agent.identityManager.import({ + identity : { name: 'Test', did: portableDid.did }, + did : portableDid, + kms : 'local' + }); + + // Call connect() with the custom agent. + const { web5, did } = await Web5.connect({ + agent : testAgent.agent, + connectedDid : portableDid.did + }); + + expect(did).to.exist; + expect(web5).to.exist; + }).timeout(5000); + }); + describe('constructor', () => { it('instantiates Web5 API with provided Web5Agent and connectedDid', async () => { // Create a new Identity.