@dwn-protocol/id-sdk
Version:
SDK for accessing the features and capabilities
165 lines (130 loc) • 5 kB
text/typescript
import type { PortableDid } from '../dids/index.js';
import type { IDManagedAgent } from './types/agent.js';
import type { CreateDidMethodOptions, ManagedDid } from './did-manager.js';
import type { ManagedIdentityStore } from './store-managed-identity.js';
import { IdentityStoreMemory } from './store-managed-identity.js';
type CreateWithDid = Required<Pick<CreateIdentityOptions, 'did'>>
& Pick<CreateIdentityOptions, 'context' | 'name' | 'kms'>
type CreateWithDidMethod<M extends DidMethod> = Pick<CreateIdentityOptions, 'context' | 'kms' | 'name'> & {
didMethod: M;
didOptions?: CreateDidMethodOptions[M];
}
type DidMethod = keyof CreateDidMethodOptions;
export type CreateIdentityOptions = {
did?: PortableDid;
didMethod?: any;
didOptions?: any;
context?: string;
kms?: string;
name: string;
}
export type IdentityManagerOptions = {
agent?: IDManagedAgent;
store?: ManagedIdentityStore;
}
export type ImportIdentityOptions = {
context?: string;
did?: PortableDid;
identity: ManagedIdentity;
kms?: string;
}
export interface ManagedIdentity {
did: string;
name: string;
}
export class IdentityManager {
/**
* Holds the instance of a `IDManagedAgent` that represents the current
* execution context for the `KeyManager`. This agent is utilized
* to interact with other agent components. It's vital
* to ensure this instance is set to correctly contextualize
* operations within the broader agent framework.
*/
private _agent?: IDManagedAgent;
private _store: ManagedIdentityStore;
constructor(options?: IdentityManagerOptions) {
const { agent, store } = options ?? {};
this._agent = agent;
this._store = store ?? new IdentityStoreMemory();
}
/**
* Retrieves the `IDManagedAgent` execution context.
* If the `agent` instance proprety is undefined, it will throw an error.
*
* @returns The `IDManagedAgent` instance that represents the current execution
* context.
*
* @throws Will throw an error if the `agent` instance property is undefined.
*/
get agent(): IDManagedAgent {
if (this._agent === undefined) {
throw new Error('IdentityManager: Unable to determine agent execution context.');
}
return this._agent;
}
set agent(agent: IDManagedAgent) {
this._agent = agent;
}
async create<M extends DidMethod>(options: CreateWithDidMethod<M>): Promise<ManagedIdentity>;
async create(options: CreateWithDid): Promise<ManagedIdentity>;
async create(options: CreateIdentityOptions): Promise<ManagedIdentity> {
let { context, did, didMethod, didOptions, kms, name } = options;
if (!(didMethod ? !did : did)) {
throw new Error(`Either 'did' or 'didMethod' must be defined, but not both.`);
}
let managedDid: ManagedDid | undefined;
// Get the agent instance.
const agent = this.agent;
if (didMethod) {
// Create new DID and generate key set.
managedDid = await agent.didManager.create({ method: didMethod, context, kms, ...didOptions });
} else if (did) {
// Import given DID and key set.
managedDid = await agent.didManager.import({ did, context, kms });
}
if (managedDid === undefined) {
throw new Error('IdentityManager: Unable to generate or import DID.');
}
// Create a ManagedIdentity.
const identity: ManagedIdentity = {
did : managedDid.did,
name : name
};
/** If context is undefined, then the Identity will be stored under the
* tenant of the created DID. Otherwise, the Identity records will
* be stored under the tenant of the specified context. */
context ??= identity.did;
// Store the ManagedIdentity in the store.
await this._store.importIdentity({ identity, agent, context });
return identity;
}
async get(options: {
did: string,
context?: string
}): Promise<ManagedIdentity | undefined> {
const { context, did } = options;
const identity = this._store.getIdentity({ did, agent: this.agent, context });
return identity;
}
async import(options: ImportIdentityOptions): Promise<ManagedIdentity> {
let { context, did, identity, kms } = options;
// Get the agent instance.
const agent = this.agent;
// If provided, import the given DID and key set.
if (did) {
await agent.didManager.import({ did, context, kms });
}
/** If context is undefined, then the Identity will be stored under the
* tenant of the imported DID. Otherwise, the Identity record will
* be stored under the tenant of the specified context. */
context ??= identity.did;
// Store the ManagedIdentity in the store.
await this._store.importIdentity({ identity, agent, context });
return identity;
}
async list(options?: { context?: string }): Promise<ManagedIdentity[]> {
const { context } = options ?? {};
const identities = this._store.listIdentities({ agent: this.agent, context });
return identities;
}
}