diff --git a/demos/browser/src/App.tsx b/demos/browser/src/App.tsx index 1635a8955..1dd2a6ae2 100644 --- a/demos/browser/src/App.tsx +++ b/demos/browser/src/App.tsx @@ -20,25 +20,12 @@ const RequestPresentation = SDK.RequestPresentation; const apollo = new SDK.Apollo(); const castor = new SDK.Castor(apollo); -const api = new SDK.ApiImpl(); const defaultMediatorDID = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9zaXQtcHJpc20tbWVkaWF0b3IuYXRhbGFwcmlzbS5pbyIsInIiOltdLCJhIjpbImRpZGNvbW0vdjIiXX0"; const pluto = new PlutoInMemory(); const useSDK = (mediatorDID: SDK.Domain.DID) => { - const didcomm = new SDK.DIDCommWrapper(apollo, castor, pluto); - const mercury = new SDK.Mercury(castor, didcomm, api); - const store = new SDK.PublicMediatorStore(pluto); - const handler = new SDK.BasicMediatorHandler(mediatorDID, mercury, store); - const manager = new SDK.ConnectionsManager(castor, mercury, pluto, handler); - const agent = new SDK.Agent( - apollo, - castor, - pluto, - mercury, - handler, - manager, - apollo.createRandomSeed().seed - ); + const agent = SDK.Agent.initialize({ mediatorDID, pluto }); + return { agent, pluto }; }; diff --git a/src/apollo/index.ts b/src/apollo/index.ts new file mode 100644 index 000000000..ca2da52e0 --- /dev/null +++ b/src/apollo/index.ts @@ -0,0 +1,3 @@ +import Apollo from "./Apollo"; + +export default Apollo; diff --git a/src/castor/index.ts b/src/castor/index.ts new file mode 100644 index 000000000..492e23977 --- /dev/null +++ b/src/castor/index.ts @@ -0,0 +1,3 @@ +import Castor from "./Castor"; + +export default Castor; diff --git a/src/domain/models/DID.ts b/src/domain/models/DID.ts index 7523b55a2..e18384b3b 100644 --- a/src/domain/models/DID.ts +++ b/src/domain/models/DID.ts @@ -15,6 +15,23 @@ export class DID { return `${this.schema}:${this.method}:${this.methodId}`; } + /** + * parse value into a DID + * @param {DID | string} value - some representation of a DID + * @returns {DID} + */ + static from(value: DID | string): DID { + if (value instanceof DID) { + return value; + } + + if (typeof value === "string") { + return DID.fromString(value); + } + + throw new Error("Invalid DID value"); + } + static fromString(text: string): DID { const schema = DID.getSchemaFromString(text); const method = DID.getMethodFromString(text); diff --git a/src/mercury/didcomm/DIDResolver.ts b/src/mercury/didcomm/DIDResolver.ts index 0aea082df..12589e09d 100644 --- a/src/mercury/didcomm/DIDResolver.ts +++ b/src/mercury/didcomm/DIDResolver.ts @@ -6,11 +6,10 @@ import type { } from "didcomm-node"; import * as Domain from "../../domain"; -import Castor from "../../castor/Castor"; import { PeerDIDService } from "../../peer-did/PeerDID"; export class DIDCommDIDResolver implements DIDResolver { - constructor(private readonly castor: Castor) {} + constructor(private readonly castor: Domain.Castor) {} async resolve(did: string): Promise { const doc = await this.castor.resolveDID(did); diff --git a/src/mercury/didcomm/SecretsResolver.ts b/src/mercury/didcomm/SecretsResolver.ts index fada04275..77a128aef 100644 --- a/src/mercury/didcomm/SecretsResolver.ts +++ b/src/mercury/didcomm/SecretsResolver.ts @@ -1,22 +1,13 @@ import type { Secret, SecretsResolver } from "didcomm-node"; import * as Domain from "../../domain"; -import { - Curve, - KeyTypes, - VerificationMethod, - VerificationMethods, -} from "../../domain"; -import Apollo from "../../apollo/Apollo"; -import Castor from "../../castor/Castor"; -import { Pluto } from "../../domain"; import * as DIDURLParser from "../../castor/parser/DIDUrlParser"; import { base64url } from "multiformats/bases/base64"; export class DIDCommSecretsResolver implements SecretsResolver { constructor( - private readonly apollo: Apollo, - private readonly castor: Castor, - private readonly pluto: Pluto + private readonly apollo: Domain.Apollo, + private readonly castor: Domain.Castor, + private readonly pluto: Domain.Pluto ) {} async find_secrets(secret_ids: string[]): Promise { @@ -39,8 +30,8 @@ export class DIDCommSecretsResolver implements SecretsResolver { const did = await this.castor.resolveDID(found.did.toString()); const [publicKeyJWK] = did.coreProperties.reduce((all, property) => { - if (property instanceof VerificationMethods) { - const matchingValue: VerificationMethod | undefined = + if (property instanceof Domain.VerificationMethods) { + const matchingValue: Domain.VerificationMethod | undefined = property.values.find( (verificationMethod) => verificationMethod.id === secret_id ); @@ -65,14 +56,14 @@ export class DIDCommSecretsResolver implements SecretsResolver { publicKeyJWK: Domain.PublicKeyJWK ): Secret { const privateKeyBuffer = peerDid.privateKeys.find( - (key) => key.keyCurve.curve === Curve.X25519 + (key) => key.keyCurve.curve === Domain.Curve.X25519 ); if (!privateKeyBuffer) { - throw new Error(`Invalid PrivateKey Curve ${Curve.X25519}`); + throw new Error(`Invalid PrivateKey Curve ${Domain.Curve.X25519}`); } const privateKey = this.apollo.createPrivateKey({ - type: KeyTypes.Curve25519, - curve: Curve.X25519, + type: Domain.KeyTypes.Curve25519, + curve: Domain.Curve.X25519, raw: privateKeyBuffer.value, }); @@ -86,7 +77,7 @@ export class DIDCommSecretsResolver implements SecretsResolver { id, type: "JsonWebKey2020", privateKeyJwk: { - crv: Curve.X25519, + crv: Domain.Curve.X25519, kty: "OKP", d: Buffer.from(privateKey.getEncoded()).toString(), x: publicKeyJWK.x, diff --git a/src/mercury/didcomm/Wrapper.ts b/src/mercury/didcomm/Wrapper.ts index dcea53ee3..7e671f539 100644 --- a/src/mercury/didcomm/Wrapper.ts +++ b/src/mercury/didcomm/Wrapper.ts @@ -7,10 +7,8 @@ import type { Attachment, AttachmentData, } from "didcomm-node"; + import * as Domain from "../../domain"; -import Apollo from "../../apollo/Apollo"; -import Castor from "../../castor/Castor"; -import { Pluto } from "../../domain"; import { DIDCommDIDResolver } from "./DIDResolver"; import { DIDCommSecretsResolver } from "./SecretsResolver"; import { DIDCommProtocol } from "../DIDCommProtocol"; @@ -38,9 +36,9 @@ export class DIDCommWrapper implements DIDCommProtocol { private readonly secretsResolver: SecretsResolver; constructor( - readonly apollo: Apollo, - readonly castor: Castor, - readonly pluto: Pluto + readonly apollo: Domain.Apollo, + readonly castor: Domain.Castor, + readonly pluto: Domain.Pluto ) { this.didResolver = new DIDCommDIDResolver(castor); this.secretsResolver = new DIDCommSecretsResolver(apollo, castor, pluto); diff --git a/src/mercury/index.ts b/src/mercury/index.ts new file mode 100644 index 000000000..c9b93b3c4 --- /dev/null +++ b/src/mercury/index.ts @@ -0,0 +1,3 @@ +import Mercury from "./Mercury"; + +export default Mercury; diff --git a/src/pollux/index.ts b/src/pollux/index.ts new file mode 100644 index 000000000..9d17f4141 --- /dev/null +++ b/src/pollux/index.ts @@ -0,0 +1,3 @@ +import Pollux from "./Pollux"; + +export default Pollux; diff --git a/src/prism-agent/Agent.ts b/src/prism-agent/Agent.ts index 3f7caeffb..64e4f252d 100644 --- a/src/prism-agent/Agent.ts +++ b/src/prism-agent/Agent.ts @@ -1,19 +1,12 @@ -import { Apollo } from "../domain/buildingBlocks/Apollo"; -import { - DID, - Message, - Seed, - Service as DIDDocumentService, - Signature, - Credential, -} from "../domain"; -import { Castor } from "../domain/buildingBlocks/Castor"; -import { Pluto } from "../domain/buildingBlocks/Pluto"; -import { Mercury } from "../domain/buildingBlocks/Mercury"; -import { Api } from "../domain/models/Api"; +import * as Domain from "../domain"; + +import Apollo from "../apollo"; +import Castor from "../castor"; +import Mercury from "../mercury"; +import Pollux from "../pollux"; + import { ApiImpl } from "./helpers/ApiImpl"; -import { AgentError } from "../domain/models/Errors"; import { AgentCredentials as AgentCredentialsClass, AgentDIDHigherFunctions as AgentDIDHigherFunctionsClass, @@ -24,17 +17,20 @@ import { MediatorHandler, PrismOnboardingInvitation, } from "./types"; -import { OutOfBandInvitation } from "./protocols/invitation/v2/OutOfBandInvitation"; + import { AgentCredentials } from "./Agent.Credentials"; import { AgentDIDHigherFunctions } from "./Agent.DIDHigherFunctions"; import { AgentInvitations } from "./Agent.Invitations"; import { ConnectionsManager } from "./connectionsManager/ConnectionsManager"; +import { OutOfBandInvitation } from "./protocols/invitation/v2/OutOfBandInvitation"; import { OfferCredential } from "./protocols/issueCredential/OfferCredential"; import { RequestCredential } from "./protocols/issueCredential/RequestCredential"; -import Pollux from "../pollux/Pollux"; import { IssueCredential } from "./protocols/issueCredential/IssueCredential"; import { Presentation } from "./protocols/proofPresentation/Presentation"; import { RequestPresentation } from "./protocols/proofPresentation/RequestPresentation"; +import { DIDCommWrapper } from "../mercury/didcomm/Wrapper"; +import { PublicMediatorStore } from "./mediator/PlutoMediatorStore"; +import { BasicMediatorHandler } from "./mediator/BasicMediatorHandler"; enum AgentState { STOPPED = "stopped", @@ -43,9 +39,6 @@ enum AgentState { STOPPING = "stopping", } -interface AgentConfig { - endpointUrl: string; -} /** * Edge agent implementation * @@ -55,10 +48,9 @@ interface AgentConfig { */ export default class Agent implements - AgentCredentialsClass, - AgentDIDHigherFunctionsClass, - AgentInvitationsClass -{ + AgentCredentialsClass, + AgentDIDHigherFunctionsClass, + AgentInvitationsClass { /** * Agent state * @@ -70,15 +62,8 @@ export default class Agent private agentCredentials: AgentCredentials; private agentDIDHigherFunctions: AgentDIDHigherFunctions; private agentInvitations: AgentInvitations; - private apollo: Apollo; - private castor: Castor; - private pluto: Pluto; + private pollux: Pollux; - private mercury: Mercury; - private mediationHandler: MediatorHandler; - private connectionManager; - private seed: Seed; - private api: Api; /** * Creates an instance of Agent. @@ -94,22 +79,15 @@ export default class Agent * @param {Api} [api=new ApiImpl()] */ constructor( - apollo: Apollo, - castor: Castor, - pluto: Pluto, - mercury: Mercury, - mediationHandler: MediatorHandler, - connectionManager: ConnectionsManager, - seed: Seed = apollo.createRandomSeed().seed, - api: Api = new ApiImpl() + public readonly apollo: Domain.Apollo, + public readonly castor: Domain.Castor, + public readonly pluto: Domain.Pluto, + public readonly mercury: Domain.Mercury, + public readonly mediationHandler: MediatorHandler, + public readonly connectionManager: ConnectionsManager, + public readonly seed: Domain.Seed = apollo.createRandomSeed().seed, + public readonly api: Domain.Api = new ApiImpl() ) { - this.apollo = apollo; - this.castor = castor; - this.pluto = pluto; - this.mercury = mercury; - this.mediationHandler = mediationHandler; - this.seed = seed; - this.api = api; this.pollux = new Pollux(castor); this.connectionManager = @@ -123,6 +101,7 @@ export default class Agent this.pollux, seed ); + this.agentDIDHigherFunctions = new AgentDIDHigherFunctions( apollo, castor, @@ -131,6 +110,7 @@ export default class Agent mediationHandler, seed ); + this.agentInvitations = new AgentInvitations( this.pluto, this.api, @@ -139,6 +119,58 @@ export default class Agent ); } + /** + * Convenience initializer for Agent + * allowing default instantiation, omitting all but the absolute necessary parameters + * + * @param {Object} params - dependencies object + * @param {DID | string} params.mediatorDID - did of the mediator to be used + * @param {Pluto} params.pluto - storage implementation + * @param {Api} [params.api] + * @param {Apollo} [params.apollo] + * @param {Castor} [params.castor] + * @param {Mercury} [params.mercury] + * @param {Seed} [params.seed] + * @returns {Agent} + */ + static initialize(params: { + mediatorDID: Domain.DID | string; + pluto: Domain.Pluto; + api?: Domain.Api; + apollo?: Domain.Apollo; + castor?: Domain.Castor; + mercury?: Domain.Mercury; + seed?: Domain.Seed; + }): Agent { + const mediatorDID = Domain.DID.from(params.mediatorDID); + const pluto = params.pluto; + + const api = params.api ?? new ApiImpl(); + const apollo = params.apollo ?? new Apollo(); + const castor = params.castor ?? new Castor(apollo); + + const didcomm = new DIDCommWrapper(apollo, castor, pluto); + const mercury = params.mercury ?? new Mercury(castor, didcomm, api); + + const store = new PublicMediatorStore(pluto); + const handler = new BasicMediatorHandler(mediatorDID, mercury, store); + const manager = new ConnectionsManager(castor, mercury, pluto, handler); + const seed = params.seed ?? apollo.createRandomSeed().seed; + + const agent = new Agent( + apollo, + castor, + pluto, + mercury, + handler, + manager, + seed, + api + ); + + return agent; + } + /** * Get current mediator DID if available or null * @@ -151,7 +183,7 @@ export default class Agent } /** - * Mainly for testing porposed but instanciating the Agne tfrom a ConnectionManager directly + * Mainly for testing purposes but instantiating the Agent from a ConnectionManager directly * * @static * @param {Apollo} apollo @@ -166,11 +198,11 @@ export default class Agent static instanceFromConnectionManager( apollo: Apollo, castor: Castor, - pluto: Pluto, + pluto: Domain.Pluto, mercury: Mercury, connectionManager: ConnectionsManager, - seed?: Seed, - api?: Api + seed?: Domain.Seed, + api?: Domain.Api ) { return new Agent( apollo, @@ -200,7 +232,7 @@ export default class Agent await this.pollux.start(); await this.connectionManager.startMediator(); } catch (e) { - if (e instanceof AgentError.NoMediatorAvailableError) { + if (e instanceof Domain.AgentError.NoMediatorAvailableError) { const hostDID = await this.createNewPeerDID([], false); await this.connectionManager.registerMediator(hostDID); } else throw e; @@ -210,7 +242,7 @@ export default class Agent this.connectionManager.startFetchingMessages(5); this.state = AgentState.RUNNING; } else { - throw new AgentError.MediationRequestFailedError("Mediation failed"); + throw new Domain.AgentError.MediationRequestFailedError("Mediation failed"); } const storedLinkSecret = await this.pluto.getLinkSecret(); @@ -249,9 +281,9 @@ export default class Agent */ async createNewPrismDID( alias: string, - services: DIDDocumentService[] = [], + services: Domain.Service[] = [], keyPathIndex?: number - ): Promise { + ): Promise { return this.agentDIDHigherFunctions.createNewPrismDID( alias, services, @@ -268,9 +300,9 @@ export default class Agent * @returns {Promise} */ async createNewPeerDID( - services: DIDDocumentService[] = [], + services: Domain.Service[] = [], updateMediator = true - ): Promise { + ): Promise { return this.agentDIDHigherFunctions.createNewPeerDID( services, updateMediator @@ -307,7 +339,7 @@ export default class Agent * @param {Uint8Array} message * @returns {Promise} */ - async signWith(did: DID, message: Uint8Array): Promise { + async signWith(did: Domain.DID, message: Uint8Array): Promise { return this.agentDIDHigherFunctions.signWith(did, message); } @@ -369,16 +401,16 @@ export default class Agent * @param {Message} message * @returns {Promise} */ - sendMessage(message: Message): Promise { + sendMessage(message: Domain.Message): Promise { return this.connectionManager.sendMessage(message); } /** * Asyncronously get all verifiable credentials * - * @returns {Promise} + * @returns {Promise} */ - verifiableCredentials(): Promise { + verifiableCredentials(): Promise { return this.agentCredentials.verifiableCredentials(); } @@ -425,7 +457,7 @@ export default class Agent */ async processIssuedCredentialMessage( message: IssueCredential - ): Promise { + ): Promise { return this.agentCredentials.processIssuedCredentialMessage(message); } @@ -441,7 +473,7 @@ export default class Agent */ async createPresentationForRequestProof( request: RequestPresentation, - credential: Credential + credential: Domain.Credential ): Promise { return this.agentCredentials.createPresentationForRequestProof( request,