UNPKG

@web5/agent

Version:
262 lines 12.4 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { BearerIdentity } from './bearer-identity.js'; import { isPortableDid } from './prototyping/dids/utils.js'; import { InMemoryIdentityStore } from './store-identity.js'; import { getDwnServiceEndpointUrls } from './utils.js'; export function isPortableIdentity(obj) { // Validate that the given value is an object that has the necessary properties of PortableIdentity. return !(!obj || typeof obj !== 'object' || obj === null) && 'did' in obj && 'metadata' in obj && isPortableDid(obj.did); } /** * This API is used to manage and interact with Identities within the Web5 Agent framework. * An Identity is a DID that is associated with metadata that describes the Identity. * Metadata includes A name(label), and whether or not the Identity is connected (delegated to act on the behalf of another DID). * * A KeyManager is used to manage the cryptographic keys associated with the Identities. * * The `DidApi` is used internally to create, store, and manage DIDs. * When a DWN Data Store is used, the Identity and DID information are stored under the Agent DID's tenant. */ export class AgentIdentityApi { constructor({ agent, store } = {}) { this._agent = agent; // If `store` is not given, use an in-memory store by default. this._store = store !== null && store !== void 0 ? store : new InMemoryIdentityStore(); } /** * Retrieves the `Web5PlatformAgent` execution context. * * @returns The `Web5PlatformAgent` instance that represents the current execution context. * @throws Will throw an error if the `agent` instance property is undefined. */ get agent() { if (this._agent === undefined) { throw new Error('AgentIdentityApi: Unable to determine agent execution context.'); } return this._agent; } set agent(agent) { this._agent = agent; } get tenant() { if (!this._agent) { throw new Error('AgentIdentityApi: The agent must be set to perform tenant specific actions.'); } return this._agent.agentDid.uri; } create({ metadata, didMethod = 'dht', didOptions, store }) { return __awaiter(this, void 0, void 0, function* () { const bearerDid = yield this.agent.did.create({ method: didMethod, options: didOptions, tenant: this.tenant, store, }); // Create the BearerIdentity object. const identity = new BearerIdentity({ did: bearerDid, metadata: Object.assign(Object.assign({}, metadata), { uri: bearerDid.uri, tenant: this.tenant }) }); // Persist the Identity to the store, by default, unless the `store` option is set to false. if (store !== null && store !== void 0 ? store : true) { yield this._store.set({ id: identity.did.uri, data: identity.metadata, agent: this.agent, tenant: identity.metadata.tenant, preventDuplicates: false, useCache: true }); } return identity; }); } export({ didUri }) { return __awaiter(this, void 0, void 0, function* () { const bearerIdentity = yield this.get({ didUri }); if (!bearerIdentity) { throw new Error(`AgentIdentityApi: Failed to export due to Identity not found: ${didUri}`); } // If the Identity was found, return the Identity in a portable format, and if supported by the // Agent's key manager, the private key material. const portableIdentity = yield bearerIdentity.export(); return portableIdentity; }); } get({ didUri }) { return __awaiter(this, void 0, void 0, function* () { const storedIdentity = yield this._store.get({ id: didUri, agent: this.agent, useCache: true }); // If the Identity is not found in the store, return undefined. if (!storedIdentity) return undefined; // Retrieve the DID from the Agent's DID store using the tenant value from the stored // Identity's metadata. const storedDid = yield this.agent.did.get({ didUri, tenant: storedIdentity.tenant }); // If the Identity is present but the DID is not found, throw an error. if (!storedDid) { throw new Error(`AgentIdentityApi: Identity is present in the store but DID is missing: ${didUri}`); } // Create the BearerIdentity object. const identity = new BearerIdentity({ did: storedDid, metadata: storedIdentity }); return identity; }); } import({ portableIdentity }) { return __awaiter(this, void 0, void 0, function* () { // set the tenant of the portable identity to the agent's tenant portableIdentity.metadata.tenant = this.tenant; // Import the PortableDid to the Agent's DID store. const storedDid = yield this.agent.did.import({ portableDid: portableIdentity.portableDid, tenant: portableIdentity.metadata.tenant }); // Verify the DID is present in the Agent's DID store. if (!storedDid) { throw new Error(`AgentIdentityApi: Failed to import Identity: ${portableIdentity.metadata.uri}`); } // Create the BearerIdentity object. const identity = new BearerIdentity({ did: storedDid, metadata: portableIdentity.metadata }); // Store the Identity metadata in the Agent's Identity store. yield this._store.set({ id: identity.did.uri, data: identity.metadata, agent: this.agent, tenant: identity.metadata.tenant, preventDuplicates: true, useCache: true }); return identity; }); } list({ tenant } = {}) { return __awaiter(this, void 0, void 0, function* () { // Retrieve the list of Identities from the Agent's Identity store. const storedIdentities = yield this._store.list({ agent: this.agent, tenant }); const identities = yield Promise.all(storedIdentities.map(metadata => this.get({ didUri: metadata.uri }))); return identities.filter(identity => typeof identity !== 'undefined'); }); } delete({ didUri }) { return __awaiter(this, void 0, void 0, function* () { const storedIdentity = yield this._store.get({ id: didUri, agent: this.agent, useCache: true }); if (!storedIdentity) { throw new Error(`AgentIdentityApi: Failed to purge due to Identity not found: ${didUri}`); } // Delete the Identity from the Agent's Identity store. yield this._store.delete({ id: didUri, agent: this.agent }); }); } /** * Returns the DWN endpoints for the given DID. * * @param didUri - The DID URI to get the DWN endpoints for. * @returns An array of DWN endpoints. * @throws An error if the DID is not found, or no DWN service exists. */ getDwnEndpoints({ didUri }) { return getDwnServiceEndpointUrls(didUri, this.agent.did); } /** * Sets the DWN endpoints for the given DID. * * @param didUri - The DID URI to set the DWN endpoints for. * @param endpoints - The array of DWN endpoints to set. * @throws An error if the DID is not found, or if an update cannot be performed. */ setDwnEndpoints({ didUri, endpoints }) { var _a; return __awaiter(this, void 0, void 0, function* () { const bearerDid = yield this.agent.did.get({ didUri }); if (!bearerDid) { throw new Error(`AgentIdentityApi: Failed to set DWN endpoints due to DID not found: ${didUri}`); } const portableDid = yield bearerDid.export(); const dwnService = (_a = portableDid.document.service) === null || _a === void 0 ? void 0 : _a.find(service => service.id.endsWith('dwn')); if (dwnService) { // Update the existing DWN Service with the provided endpoints dwnService.serviceEndpoint = endpoints; } else { // create a DWN Service to add to the DID document const newDwnService = { id: 'dwn', type: 'DecentralizedWebNode', serviceEndpoint: endpoints, enc: '#enc', sig: '#sig' }; // if no other services exist, create a new array with the DWN service if (!portableDid.document.service) { portableDid.document.service = [newDwnService]; } else { // otherwise, push the new DWN service to the existing services portableDid.document.service.push(newDwnService); } } yield this.agent.did.update({ portableDid, tenant: this.agent.agentDid.uri }); }); } /** * Updates the Identity's metadata name field. * * @param didUri - The DID URI of the Identity to update. * @param name - The new name to set for the Identity. * * @throws An error if the Identity is not found, name is not provided, or no changes are detected. */ setMetadataName({ didUri, name }) { return __awaiter(this, void 0, void 0, function* () { if (!name) { throw new Error('AgentIdentityApi: Failed to set metadata name due to missing name value.'); } const identity = yield this.get({ didUri }); if (!identity) { throw new Error(`AgentIdentityApi: Failed to set metadata name due to Identity not found: ${didUri}`); } if (identity.metadata.name === name) { throw new Error('AgentIdentityApi: No changes detected.'); } // Update the name in the Identity's metadata and store it yield this._store.set({ id: identity.did.uri, data: Object.assign(Object.assign({}, identity.metadata), { name }), agent: this.agent, tenant: identity.metadata.tenant, updateExisting: true, useCache: true }); }); } /** * Returns the connected Identity, if one is available. * * Accepts optional `connectedDid` parameter to filter the a specific connected identity, * if none is provided the first connected identity is returned. */ connectedIdentity({ connectedDid } = {}) { return __awaiter(this, void 0, void 0, function* () { const identities = yield this.list(); if (identities.length < 1) { return undefined; } // If a specific connected DID is provided, return the first identity that matches it. // Otherwise, return the first connected identity. return connectedDid ? identities.find(identity => identity.metadata.connectedDid === connectedDid) : identities.find(identity => identity.metadata.connectedDid !== undefined); }); } } //# sourceMappingURL=identity-api.js.map