From 96c5ef89a4e33228ff3a8e25680c139398bd4122 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Fri, 8 Jul 2022 12:18:00 +0200 Subject: [PATCH] feat: add base agent class (#922) Signed-off-by: Timo Glastra --- packages/core/src/agent/Agent.ts | 243 ++++-------------- packages/core/src/agent/BaseAgent.ts | 194 ++++++++++++++ .../src/modules/vc/W3cCredentialService.ts | 2 +- .../src/storage/migration/UpdateAssistant.ts | 15 +- .../core/src/storage/migration/updates.ts | 4 +- .../migration/updates/0.1-0.2/connection.ts | 13 +- .../migration/updates/0.1-0.2/credential.ts | 16 +- .../migration/updates/0.1-0.2/index.ts | 4 +- .../migration/updates/0.1-0.2/mediation.ts | 9 +- 9 files changed, 277 insertions(+), 223 deletions(-) create mode 100644 packages/core/src/agent/BaseAgent.ts diff --git a/packages/core/src/agent/Agent.ts b/packages/core/src/agent/Agent.ts index cfc0b6b791..8b2d4ce997 100644 --- a/packages/core/src/agent/Agent.ts +++ b/packages/core/src/agent/Agent.ts @@ -1,10 +1,9 @@ -import type { Logger } from '../logger' +import type { DependencyManager } from '../plugins' import type { InboundTransport } from '../transport/InboundTransport' import type { OutboundTransport } from '../transport/OutboundTransport' import type { InitConfig } from '../types' import type { AgentDependencies } from './AgentDependencies' import type { AgentMessageReceivedEvent } from './Events' -import type { TransportSession } from './TransportService' import type { Subscription } from 'rxjs' import type { DependencyContainer } from 'tsyringe' @@ -29,19 +28,15 @@ import { ProofsModule } from '../modules/proofs/ProofsModule' import { QuestionAnswerModule } from '../modules/question-answer/QuestionAnswerModule' import { MediatorModule } from '../modules/routing/MediatorModule' import { RecipientModule } from '../modules/routing/RecipientModule' -import { RoutingService } from '../modules/routing/services/RoutingService' import { W3cVcModule } from '../modules/vc/module' -import { DependencyManager } from '../plugins' -import { StorageUpdateService, DidCommMessageRepository, StorageVersionRepository } from '../storage' +import { DidCommMessageRepository, StorageUpdateService, StorageVersionRepository } from '../storage' import { InMemoryMessageRepository } from '../storage/InMemoryMessageRepository' import { IndyStorageService } from '../storage/IndyStorageService' -import { UpdateAssistant } from '../storage/migration/UpdateAssistant' -import { DEFAULT_UPDATE_CONFIG } from '../storage/migration/updates' import { IndyWallet } from '../wallet/IndyWallet' import { WalletModule } from '../wallet/WalletModule' -import { WalletError } from '../wallet/error' import { AgentConfig } from './AgentConfig' +import { BaseAgent } from './BaseAgent' import { Dispatcher } from './Dispatcher' import { EnvelopeService } from './EnvelopeService' import { EventEmitter } from './EventEmitter' @@ -51,92 +46,25 @@ import { MessageSender } from './MessageSender' import { TransportService } from './TransportService' import { AgentContext, DefaultAgentContextProvider } from './context' -export class Agent { - protected agentConfig: AgentConfig - protected logger: Logger - public readonly dependencyManager: DependencyManager - protected eventEmitter: EventEmitter - protected messageReceiver: MessageReceiver - protected transportService: TransportService - protected messageSender: MessageSender - private _isInitialized = false +export class Agent extends BaseAgent { public messageSubscription: Subscription - private routingService: RoutingService - private agentContext: AgentContext - private stop$ = new Subject() - - public readonly connections: ConnectionsModule - public readonly proofs: ProofsModule - public readonly basicMessages: BasicMessagesModule - public readonly genericRecords: GenericRecordsModule - public readonly ledger: LedgerModule - public readonly questionAnswer!: QuestionAnswerModule - public readonly credentials: CredentialsModule - public readonly mediationRecipient: RecipientModule - public readonly mediator: MediatorModule - public readonly discovery: DiscoverFeaturesModule - public readonly dids: DidsModule - public readonly wallet: WalletModule - public readonly oob!: OutOfBandModule public constructor( initialConfig: InitConfig, dependencies: AgentDependencies, injectionContainer?: DependencyContainer ) { - // Take input container or child container so we don't interfere with anything outside of this agent - const container = injectionContainer ?? baseContainer.createChildContainer() - - this.dependencyManager = new DependencyManager(container) - - this.agentConfig = new AgentConfig(initialConfig, dependencies) - this.logger = this.agentConfig.logger - - this.logger.info('Creating agent with config', { - ...initialConfig, - // Prevent large object being logged. - // Will display true/false to indicate if value is present in config - logger: initialConfig.logger != undefined, - }) - - if (!this.agentConfig.walletConfig) { - this.logger.warn( - 'Wallet config has not been set on the agent config. ' + - 'Make sure to initialize the wallet yourself before initializing the agent, ' + - 'or provide the required wallet configuration in the agent constructor' - ) - } + // NOTE: we can't create variables before calling super as TS will complain that the super call must be the + // the first statement in the constructor. + super(new AgentConfig(initialConfig, dependencies), injectionContainer ?? baseContainer.createChildContainer()) - this.registerDependencies(this.dependencyManager) - - // Resolve instances after everything is registered - this.eventEmitter = this.dependencyManager.resolve(EventEmitter) - this.messageSender = this.dependencyManager.resolve(MessageSender) - this.messageReceiver = this.dependencyManager.resolve(MessageReceiver) - this.transportService = this.dependencyManager.resolve(TransportService) - this.routingService = this.dependencyManager.resolve(RoutingService) - this.agentContext = this.dependencyManager.resolve(AgentContext) - - // We set the modules in the constructor because that allows to set them as read-only - this.connections = this.dependencyManager.resolve(ConnectionsModule) - this.credentials = this.dependencyManager.resolve(CredentialsModule) as CredentialsModule - this.proofs = this.dependencyManager.resolve(ProofsModule) - this.mediator = this.dependencyManager.resolve(MediatorModule) - this.mediationRecipient = this.dependencyManager.resolve(RecipientModule) - this.basicMessages = this.dependencyManager.resolve(BasicMessagesModule) - this.questionAnswer = this.dependencyManager.resolve(QuestionAnswerModule) - this.genericRecords = this.dependencyManager.resolve(GenericRecordsModule) - this.ledger = this.dependencyManager.resolve(LedgerModule) - this.discovery = this.dependencyManager.resolve(DiscoverFeaturesModule) - this.dids = this.dependencyManager.resolve(DidsModule) - this.wallet = this.dependencyManager.resolve(WalletModule) - this.oob = this.dependencyManager.resolve(OutOfBandModule) + const stop$ = this.dependencyManager.resolve>(InjectionSymbols.Stop$) // Listen for new messages (either from transports or somewhere else in the framework / extensions) this.messageSubscription = this.eventEmitter .observable(AgentEventTypes.AgentMessageReceived) .pipe( - takeUntil(this.stop$), + takeUntil(stop$), concatMap((e) => this.messageReceiver.receiveMessage(e.payload.message, { connection: e.payload.connection, @@ -172,51 +100,9 @@ export class Agent { } public async initialize() { - const { connectToIndyLedgersOnStartup, publicDidSeed, walletConfig, mediatorConnectionsInvite } = this.agentConfig - - if (this._isInitialized) { - throw new AriesFrameworkError( - 'Agent already initialized. Currently it is not supported to re-initialize an already initialized agent.' - ) - } - - if (!this.wallet.isInitialized && walletConfig) { - await this.wallet.initialize(walletConfig) - } else if (!this.wallet.isInitialized) { - throw new WalletError( - 'Wallet config has not been set on the agent config. ' + - 'Make sure to initialize the wallet yourself before initializing the agent, ' + - 'or provide the required wallet configuration in the agent constructor' - ) - } - - // Make sure the storage is up to date - const storageUpdateService = this.dependencyManager.resolve(StorageUpdateService) - const isStorageUpToDate = await storageUpdateService.isUpToDate(this.agentContext) - this.logger.info(`Agent storage is ${isStorageUpToDate ? '' : 'not '}up to date.`) - - if (!isStorageUpToDate && this.agentConfig.autoUpdateStorageOnStartup) { - const updateAssistant = new UpdateAssistant(this, DEFAULT_UPDATE_CONFIG) - - await updateAssistant.initialize() - await updateAssistant.update() - } else if (!isStorageUpToDate) { - const currentVersion = await storageUpdateService.getCurrentStorageVersion(this.agentContext) - // Close wallet to prevent un-initialized agent with initialized wallet - await this.wallet.close() - throw new AriesFrameworkError( - // TODO: add link to where documentation on how to update can be found. - `Current agent storage is not up to date. ` + - `To prevent the framework state from getting corrupted the agent initialization is aborted. ` + - `Make sure to update the agent storage (currently at ${currentVersion}) to the latest version (${UpdateAssistant.frameworkStorageVersion}). ` + - `You can also downgrade your version of Aries Framework JavaScript.` - ) - } + const { connectToIndyLedgersOnStartup, mediatorConnectionsInvite } = this.agentConfig - if (publicDidSeed) { - // If an agent has publicDid it will be used as routing key. - await this.agentContext.wallet.initPublicDid({ seed: publicDidSeed }) - } + await super.initialize() // set the pools on the ledger. this.ledger.setPools(this.agentContext.config.indyLedgers) @@ -250,84 +136,20 @@ export class Agent { } public async shutdown() { + const stop$ = this.dependencyManager.resolve>(InjectionSymbols.Stop$) // All observables use takeUntil with the stop$ observable // this means all observables will stop running if a value is emitted on this observable - this.stop$.next(true) + stop$.next(true) // Stop transports const allTransports = [...this.inboundTransports, ...this.outboundTransports] const transportPromises = allTransports.map((transport) => transport.stop()) await Promise.all(transportPromises) - // close wallet if still initialized - if (this.wallet.isInitialized) { - await this.wallet.close() - } - this._isInitialized = false - } - - public get publicDid() { - return this.agentContext.wallet.publicDid - } - - /** - * Receive a message. This should mainly be used for receiving connection-less messages. - * - * If you want to receive messages that originated from e.g. a transport make sure to use the {@link MessageReceiver} - * for this. The `receiveMessage` method on the `Agent` class will associate the current context to the message, which - * may not be what should happen (e.g. in case of multi tenancy). - */ - public async receiveMessage(inboundMessage: unknown, session?: TransportSession) { - return await this.messageReceiver.receiveMessage(inboundMessage, { - session, - contextCorrelationId: this.agentContext.contextCorrelationId, - }) - } - - public get injectionContainer() { - return this.dependencyManager.container - } - - public get config() { - return this.agentConfig - } - - public get context() { - return this.agentContext - } - - private async getMediationConnection(mediatorInvitationUrl: string) { - const outOfBandInvitation = this.oob.parseInvitation(mediatorInvitationUrl) - const outOfBandRecord = await this.oob.findByInvitationId(outOfBandInvitation.id) - const [connection] = outOfBandRecord ? await this.connections.findAllByOutOfBandId(outOfBandRecord.id) : [] - - if (!connection) { - this.logger.debug('Mediation connection does not exist, creating connection') - // We don't want to use the current default mediator when connecting to another mediator - const routing = await this.routingService.getRouting(this.agentContext, { useDefaultMediator: false }) - - this.logger.debug('Routing created', routing) - const { connectionRecord: newConnection } = await this.oob.receiveInvitation(outOfBandInvitation, { - routing, - }) - this.logger.debug(`Mediation invitation processed`, { outOfBandInvitation }) - - if (!newConnection) { - throw new AriesFrameworkError('No connection record to provision mediation.') - } - - return this.connections.returnWhenIsConnected(newConnection.id) - } - - if (!connection.isReady) { - return this.connections.returnWhenIsConnected(connection.id) - } - return connection + await super.shutdown() } - private registerDependencies(dependencyManager: DependencyManager) { - const dependencies = this.agentConfig.agentDependencies - + protected registerDependencies(dependencyManager: DependencyManager) { // Register internal dependencies dependencyManager.registerSingleton(EventEmitter) dependencyManager.registerSingleton(MessageSender) @@ -342,9 +164,9 @@ export class Agent { dependencyManager.registerSingleton(StorageUpdateService) dependencyManager.registerInstance(AgentConfig, this.agentConfig) - dependencyManager.registerInstance(InjectionSymbols.AgentDependencies, dependencies) - dependencyManager.registerInstance(InjectionSymbols.FileSystem, new dependencies.FileSystem()) - dependencyManager.registerInstance(InjectionSymbols.Stop$, this.stop$) + dependencyManager.registerInstance(InjectionSymbols.AgentDependencies, this.agentConfig.agentDependencies) + dependencyManager.registerInstance(InjectionSymbols.Stop$, new Subject()) + dependencyManager.registerInstance(InjectionSymbols.FileSystem, new this.agentConfig.agentDependencies.FileSystem()) // Register possibly already defined services if (!dependencyManager.isRegistered(InjectionSymbols.Wallet)) { @@ -391,4 +213,33 @@ export class Agent { this.dependencyManager.registerSingleton(InjectionSymbols.AgentContextProvider, DefaultAgentContextProvider) } } + + protected async getMediationConnection(mediatorInvitationUrl: string) { + const outOfBandInvitation = this.oob.parseInvitation(mediatorInvitationUrl) + const outOfBandRecord = await this.oob.findByInvitationId(outOfBandInvitation.id) + const [connection] = outOfBandRecord ? await this.connections.findAllByOutOfBandId(outOfBandRecord.id) : [] + + if (!connection) { + this.logger.debug('Mediation connection does not exist, creating connection') + // We don't want to use the current default mediator when connecting to another mediator + const routing = await this.mediationRecipient.getRouting({ useDefaultMediator: false }) + + this.logger.debug('Routing created', routing) + const { connectionRecord: newConnection } = await this.oob.receiveInvitation(outOfBandInvitation, { + routing, + }) + this.logger.debug(`Mediation invitation processed`, { outOfBandInvitation }) + + if (!newConnection) { + throw new AriesFrameworkError('No connection record to provision mediation.') + } + + return this.connections.returnWhenIsConnected(newConnection.id) + } + + if (!connection.isReady) { + return this.connections.returnWhenIsConnected(connection.id) + } + return connection + } } diff --git a/packages/core/src/agent/BaseAgent.ts b/packages/core/src/agent/BaseAgent.ts new file mode 100644 index 0000000000..eea807e245 --- /dev/null +++ b/packages/core/src/agent/BaseAgent.ts @@ -0,0 +1,194 @@ +import type { Logger } from '../logger' +import type { AgentConfig } from './AgentConfig' +import type { TransportSession } from './TransportService' +import type { DependencyContainer } from 'tsyringe' + +import { AriesFrameworkError } from '../error' +import { BasicMessagesModule } from '../modules/basic-messages/BasicMessagesModule' +import { ConnectionsModule } from '../modules/connections/ConnectionsModule' +import { CredentialsModule } from '../modules/credentials/CredentialsModule' +import { DidsModule } from '../modules/dids/DidsModule' +import { DiscoverFeaturesModule } from '../modules/discover-features' +import { GenericRecordsModule } from '../modules/generic-records/GenericRecordsModule' +import { LedgerModule } from '../modules/ledger/LedgerModule' +import { OutOfBandModule } from '../modules/oob/OutOfBandModule' +import { ProofsModule } from '../modules/proofs/ProofsModule' +import { QuestionAnswerModule } from '../modules/question-answer/QuestionAnswerModule' +import { MediatorModule } from '../modules/routing/MediatorModule' +import { RecipientModule } from '../modules/routing/RecipientModule' +import { DependencyManager } from '../plugins' +import { StorageUpdateService } from '../storage' +import { UpdateAssistant } from '../storage/migration/UpdateAssistant' +import { DEFAULT_UPDATE_CONFIG } from '../storage/migration/updates' +import { WalletModule } from '../wallet/WalletModule' +import { WalletError } from '../wallet/error' + +import { EventEmitter } from './EventEmitter' +import { MessageReceiver } from './MessageReceiver' +import { MessageSender } from './MessageSender' +import { TransportService } from './TransportService' +import { AgentContext } from './context' + +export abstract class BaseAgent { + protected agentConfig: AgentConfig + protected logger: Logger + public readonly dependencyManager: DependencyManager + protected eventEmitter: EventEmitter + protected messageReceiver: MessageReceiver + protected transportService: TransportService + protected messageSender: MessageSender + protected _isInitialized = false + protected agentContext: AgentContext + + public readonly connections: ConnectionsModule + public readonly proofs: ProofsModule + public readonly basicMessages: BasicMessagesModule + public readonly genericRecords: GenericRecordsModule + public readonly ledger: LedgerModule + public readonly questionAnswer!: QuestionAnswerModule + public readonly credentials: CredentialsModule + public readonly mediationRecipient: RecipientModule + public readonly mediator: MediatorModule + public readonly discovery: DiscoverFeaturesModule + public readonly dids: DidsModule + public readonly wallet: WalletModule + public readonly oob: OutOfBandModule + + public constructor(agentConfig: AgentConfig, container: DependencyContainer) { + this.dependencyManager = new DependencyManager(container) + + this.agentConfig = agentConfig + this.logger = this.agentConfig.logger + + this.logger.info('Creating agent with config', { + ...agentConfig, + // Prevent large object being logged. + // Will display true/false to indicate if value is present in config + logger: agentConfig.logger != undefined, + }) + + if (!this.agentConfig.walletConfig) { + this.logger.warn( + 'Wallet config has not been set on the agent config. ' + + 'Make sure to initialize the wallet yourself before initializing the agent, ' + + 'or provide the required wallet configuration in the agent constructor' + ) + } + + this.registerDependencies(this.dependencyManager) + + // Resolve instances after everything is registered + this.eventEmitter = this.dependencyManager.resolve(EventEmitter) + this.messageSender = this.dependencyManager.resolve(MessageSender) + this.messageReceiver = this.dependencyManager.resolve(MessageReceiver) + this.transportService = this.dependencyManager.resolve(TransportService) + this.agentContext = this.dependencyManager.resolve(AgentContext) + + // We set the modules in the constructor because that allows to set them as read-only + this.connections = this.dependencyManager.resolve(ConnectionsModule) + this.credentials = this.dependencyManager.resolve(CredentialsModule) as CredentialsModule + this.proofs = this.dependencyManager.resolve(ProofsModule) + this.mediator = this.dependencyManager.resolve(MediatorModule) + this.mediationRecipient = this.dependencyManager.resolve(RecipientModule) + this.basicMessages = this.dependencyManager.resolve(BasicMessagesModule) + this.questionAnswer = this.dependencyManager.resolve(QuestionAnswerModule) + this.genericRecords = this.dependencyManager.resolve(GenericRecordsModule) + this.ledger = this.dependencyManager.resolve(LedgerModule) + this.discovery = this.dependencyManager.resolve(DiscoverFeaturesModule) + this.dids = this.dependencyManager.resolve(DidsModule) + this.wallet = this.dependencyManager.resolve(WalletModule) + this.oob = this.dependencyManager.resolve(OutOfBandModule) + } + + public get isInitialized() { + return this._isInitialized && this.wallet.isInitialized + } + + public async initialize() { + const { publicDidSeed, walletConfig } = this.agentConfig + + if (this._isInitialized) { + throw new AriesFrameworkError( + 'Agent already initialized. Currently it is not supported to re-initialize an already initialized agent.' + ) + } + + if (!this.wallet.isInitialized && walletConfig) { + await this.wallet.initialize(walletConfig) + } else if (!this.wallet.isInitialized) { + throw new WalletError( + 'Wallet config has not been set on the agent config. ' + + 'Make sure to initialize the wallet yourself before initializing the agent, ' + + 'or provide the required wallet configuration in the agent constructor' + ) + } + + // Make sure the storage is up to date + const storageUpdateService = this.dependencyManager.resolve(StorageUpdateService) + const isStorageUpToDate = await storageUpdateService.isUpToDate(this.agentContext) + this.logger.info(`Agent storage is ${isStorageUpToDate ? '' : 'not '}up to date.`) + + if (!isStorageUpToDate && this.agentConfig.autoUpdateStorageOnStartup) { + const updateAssistant = new UpdateAssistant(this, DEFAULT_UPDATE_CONFIG) + + await updateAssistant.initialize() + await updateAssistant.update() + } else if (!isStorageUpToDate) { + const currentVersion = await storageUpdateService.getCurrentStorageVersion(this.agentContext) + // Close wallet to prevent un-initialized agent with initialized wallet + await this.wallet.close() + throw new AriesFrameworkError( + // TODO: add link to where documentation on how to update can be found. + `Current agent storage is not up to date. ` + + `To prevent the framework state from getting corrupted the agent initialization is aborted. ` + + `Make sure to update the agent storage (currently at ${currentVersion}) to the latest version (${UpdateAssistant.frameworkStorageVersion}). ` + + `You can also downgrade your version of Aries Framework JavaScript.` + ) + } + + if (publicDidSeed) { + // If an agent has publicDid it will be used as routing key. + await this.agentContext.wallet.initPublicDid({ seed: publicDidSeed }) + } + } + + public async shutdown() { + // close wallet if still initialized + if (this.wallet.isInitialized) { + await this.wallet.close() + } + this._isInitialized = false + } + + public get publicDid() { + return this.agentContext.wallet.publicDid + } + + /** + * Receive a message. This should mainly be used for receiving connection-less messages. + * + * If you want to receive messages that originated from e.g. a transport make sure to use the {@link MessageReceiver} + * for this. The `receiveMessage` method on the `Agent` class will associate the current context to the message, which + * may not be what should happen (e.g. in case of multi tenancy). + */ + public async receiveMessage(inboundMessage: unknown, session?: TransportSession) { + return await this.messageReceiver.receiveMessage(inboundMessage, { + session, + contextCorrelationId: this.agentContext.contextCorrelationId, + }) + } + + public get injectionContainer() { + return this.dependencyManager.container + } + + public get config() { + return this.agentConfig + } + + public get context() { + return this.agentContext + } + + protected abstract registerDependencies(dependencyManager: DependencyManager): void +} diff --git a/packages/core/src/modules/vc/W3cCredentialService.ts b/packages/core/src/modules/vc/W3cCredentialService.ts index 5c724388a3..e46260224f 100644 --- a/packages/core/src/modules/vc/W3cCredentialService.ts +++ b/packages/core/src/modules/vc/W3cCredentialService.ts @@ -1,4 +1,4 @@ -import type { AgentContext } from '../..' +import type { AgentContext } from '../../agent/context' import type { Key } from '../../crypto/Key' import type { DocumentLoader } from './jsonldUtil' import type { W3cVerifyCredentialResult } from './models' diff --git a/packages/core/src/storage/migration/UpdateAssistant.ts b/packages/core/src/storage/migration/UpdateAssistant.ts index cb07798529..3cca35ab59 100644 --- a/packages/core/src/storage/migration/UpdateAssistant.ts +++ b/packages/core/src/storage/migration/UpdateAssistant.ts @@ -1,8 +1,7 @@ -import type { Agent } from '../../agent/Agent' +import type { BaseAgent } from '../../agent/BaseAgent' import type { FileSystem } from '../FileSystem' import type { UpdateConfig } from './updates' -import { AgentContext } from '../../agent' import { InjectionSymbols } from '../../constants' import { AriesFrameworkError } from '../../error' import { isFirstVersionHigherThanSecond, parseVersionString } from '../../utils/version' @@ -12,11 +11,10 @@ import { StorageUpdateService } from './StorageUpdateService' import { StorageUpdateError } from './error/StorageUpdateError' import { CURRENT_FRAMEWORK_STORAGE_VERSION, supportedUpdates } from './updates' -export class UpdateAssistant { +export class UpdateAssistant { private agent: Agent private storageUpdateService: StorageUpdateService private updateConfig: UpdateConfig - private agentContext: AgentContext private fileSystem: FileSystem public constructor(agent: Agent, updateConfig: UpdateConfig) { @@ -24,7 +22,6 @@ export class UpdateAssistant { this.updateConfig = updateConfig this.storageUpdateService = this.agent.dependencyManager.resolve(StorageUpdateService) - this.agentContext = this.agent.dependencyManager.resolve(AgentContext) this.fileSystem = this.agent.dependencyManager.resolve(InjectionSymbols.FileSystem) } @@ -46,11 +43,11 @@ export class UpdateAssistant { } public async isUpToDate() { - return this.storageUpdateService.isUpToDate(this.agentContext) + return this.storageUpdateService.isUpToDate(this.agent.context) } public async getCurrentAgentStorageVersion() { - return this.storageUpdateService.getCurrentStorageVersion(this.agentContext) + return this.storageUpdateService.getCurrentStorageVersion(this.agent.context) } public static get frameworkStorageVersion() { @@ -59,7 +56,7 @@ export class UpdateAssistant { public async getNeededUpdates() { const currentStorageVersion = parseVersionString( - await this.storageUpdateService.getCurrentStorageVersion(this.agentContext) + await this.storageUpdateService.getCurrentStorageVersion(this.agent.context) ) // Filter updates. We don't want older updates we already applied @@ -113,7 +110,7 @@ export class UpdateAssistant { await update.doUpdate(this.agent, this.updateConfig) // Update the framework version in storage - await this.storageUpdateService.setCurrentStorageVersion(this.agentContext, update.toVersion) + await this.storageUpdateService.setCurrentStorageVersion(this.agent.context, update.toVersion) this.agent.config.logger.info( `Successfully updated agent storage from version ${update.fromVersion} to version ${update.toVersion}` ) diff --git a/packages/core/src/storage/migration/updates.ts b/packages/core/src/storage/migration/updates.ts index c2f7fabb03..86d9ef5b71 100644 --- a/packages/core/src/storage/migration/updates.ts +++ b/packages/core/src/storage/migration/updates.ts @@ -1,4 +1,4 @@ -import type { Agent } from '../../agent/Agent' +import type { BaseAgent } from '../../agent/BaseAgent' import type { VersionString } from '../../utils/version' import type { V0_1ToV0_2UpdateConfig } from './updates/0.1-0.2' @@ -9,7 +9,7 @@ export const INITIAL_STORAGE_VERSION = '0.1' export interface Update { fromVersion: VersionString toVersion: VersionString - doUpdate: (agent: Agent, updateConfig: UpdateConfig) => Promise + doUpdate: (agent: Agent, updateConfig: UpdateConfig) => Promise } export interface UpdateConfig { diff --git a/packages/core/src/storage/migration/updates/0.1-0.2/connection.ts b/packages/core/src/storage/migration/updates/0.1-0.2/connection.ts index 0c66521d5c..8166818ef3 100644 --- a/packages/core/src/storage/migration/updates/0.1-0.2/connection.ts +++ b/packages/core/src/storage/migration/updates/0.1-0.2/connection.ts @@ -1,4 +1,4 @@ -import type { Agent } from '../../../../agent/Agent' +import type { BaseAgent } from '../../../../agent/BaseAgent' import type { ConnectionRecord } from '../../../../modules/connections' import type { JsonObject } from '../../../../types' @@ -31,7 +31,7 @@ import { JsonEncoder, JsonTransformer } from '../../../../utils' * - {@link extractDidDocument} * - {@link migrateToOobRecord} */ -export async function migrateConnectionRecordToV0_2(agent: Agent) { +export async function migrateConnectionRecordToV0_2(agent: Agent) { agent.config.logger.info('Migrating connection records to storage version 0.2') const connectionRepository = agent.dependencyManager.resolve(ConnectionRepository) @@ -87,7 +87,10 @@ export async function migrateConnectionRecordToV0_2(agent: Agent) { * } * ``` */ -export async function updateConnectionRoleAndState(agent: Agent, connectionRecord: ConnectionRecord) { +export async function updateConnectionRoleAndState( + agent: Agent, + connectionRecord: ConnectionRecord +) { agent.config.logger.debug( `Extracting 'didDoc' and 'theirDidDoc' from connection record into separate DidRecord and updating unqualified dids to did:peer dids` ) @@ -140,7 +143,7 @@ export async function updateConnectionRoleAndState(agent: Agent, connectionRecor * } * ``` */ -export async function extractDidDocument(agent: Agent, connectionRecord: ConnectionRecord) { +export async function extractDidDocument(agent: Agent, connectionRecord: ConnectionRecord) { agent.config.logger.debug( `Extracting 'didDoc' and 'theirDidDoc' from connection record into separate DidRecord and updating unqualified dids to did:peer dids` ) @@ -286,7 +289,7 @@ export async function extractDidDocument(agent: Agent, connectionRecord: Connect * } * ``` */ -export async function migrateToOobRecord( +export async function migrateToOobRecord( agent: Agent, connectionRecord: ConnectionRecord ): Promise { diff --git a/packages/core/src/storage/migration/updates/0.1-0.2/credential.ts b/packages/core/src/storage/migration/updates/0.1-0.2/credential.ts index 2f59d915ed..647f8e8a40 100644 --- a/packages/core/src/storage/migration/updates/0.1-0.2/credential.ts +++ b/packages/core/src/storage/migration/updates/0.1-0.2/credential.ts @@ -1,4 +1,4 @@ -import type { Agent } from '../../../../agent/Agent' +import type { BaseAgent } from '../../../../agent/BaseAgent' import type { CredentialMetadata, CredentialExchangeRecord } from '../../../../modules/credentials' import type { JsonObject } from '../../../../types' @@ -16,7 +16,7 @@ import { DidCommMessageRepository, DidCommMessageRecord, DidCommMessageRole } fr * The following transformations are applied: * - {@link updateIndyMetadata} */ -export async function migrateCredentialRecordToV0_2(agent: Agent) { +export async function migrateCredentialRecordToV0_2(agent: Agent) { agent.config.logger.info('Migrating credential records to storage version 0.2') const credentialRepository = agent.dependencyManager.resolve(CredentialRepository) @@ -115,7 +115,10 @@ export function getCredentialRole(credentialRecord: CredentialExchangeRecord) { * } * ``` */ -export async function updateIndyMetadata(agent: Agent, credentialRecord: CredentialExchangeRecord) { +export async function updateIndyMetadata( + agent: Agent, + credentialRecord: CredentialExchangeRecord +) { agent.config.logger.debug(`Updating indy metadata to use the generic metadata api available to records.`) const { requestMetadata, schemaId, credentialDefinitionId, ...rest } = credentialRecord.metadata.data @@ -173,7 +176,7 @@ export async function updateIndyMetadata(agent: Agent, credentialRecord: Credent * } * ``` */ -export async function migrateInternalCredentialRecordProperties( +export async function migrateInternalCredentialRecordProperties( agent: Agent, credentialRecord: CredentialExchangeRecord ) { @@ -210,7 +213,10 @@ export async function migrateInternalCredentialRecordProperties( * This migration scripts extracts all message (proposalMessage, offerMessage, requestMessage, credentialMessage) and moves * them into the DidCommMessageRepository. */ -export async function moveDidCommMessages(agent: Agent, credentialRecord: CredentialExchangeRecord) { +export async function moveDidCommMessages( + agent: Agent, + credentialRecord: CredentialExchangeRecord +) { agent.config.logger.debug( `Moving didcomm messages from credential record with id ${credentialRecord.id} to DidCommMessageRecord` ) diff --git a/packages/core/src/storage/migration/updates/0.1-0.2/index.ts b/packages/core/src/storage/migration/updates/0.1-0.2/index.ts index 200a5f6376..17065705f3 100644 --- a/packages/core/src/storage/migration/updates/0.1-0.2/index.ts +++ b/packages/core/src/storage/migration/updates/0.1-0.2/index.ts @@ -1,4 +1,4 @@ -import type { Agent } from '../../../../agent/Agent' +import type { BaseAgent } from '../../../../agent/BaseAgent' import type { UpdateConfig } from '../../updates' import { migrateConnectionRecordToV0_2 } from './connection' @@ -9,7 +9,7 @@ export interface V0_1ToV0_2UpdateConfig { mediationRoleUpdateStrategy: 'allMediator' | 'allRecipient' | 'recipientIfEndpoint' | 'doNotChange' } -export async function updateV0_1ToV0_2(agent: Agent, config: UpdateConfig): Promise { +export async function updateV0_1ToV0_2(agent: Agent, config: UpdateConfig): Promise { await migrateCredentialRecordToV0_2(agent) await migrateMediationRecordToV0_2(agent, config.v0_1ToV0_2) await migrateConnectionRecordToV0_2(agent) diff --git a/packages/core/src/storage/migration/updates/0.1-0.2/mediation.ts b/packages/core/src/storage/migration/updates/0.1-0.2/mediation.ts index e6d3447a1c..7d41c3366d 100644 --- a/packages/core/src/storage/migration/updates/0.1-0.2/mediation.ts +++ b/packages/core/src/storage/migration/updates/0.1-0.2/mediation.ts @@ -1,4 +1,4 @@ -import type { Agent } from '../../../../agent/Agent' +import type { BaseAgent } from '../../../../agent/BaseAgent' import type { MediationRecord } from '../../../../modules/routing' import type { V0_1ToV0_2UpdateConfig } from './index' @@ -12,7 +12,10 @@ import { MediationRepository, MediationRole } from '../../../../modules/routing' * The following transformations are applied: * - {@link updateMediationRole} */ -export async function migrateMediationRecordToV0_2(agent: Agent, upgradeConfig: V0_1ToV0_2UpdateConfig) { +export async function migrateMediationRecordToV0_2( + agent: Agent, + upgradeConfig: V0_1ToV0_2UpdateConfig +) { agent.config.logger.info('Migrating mediation records to storage version 0.2') const mediationRepository = agent.dependencyManager.resolve(MediationRepository) @@ -50,7 +53,7 @@ export async function migrateMediationRecordToV0_2(agent: Agent, upgradeConfig: * Most agents only act as either the role of mediator or recipient, in which case the `allMediator` or `allRecipient` configuration is the most appropriate. If your agent acts as both a recipient and mediator, the `recipientIfEndpoint` configuration is the most appropriate. The `doNotChange` options is not recommended and can lead to errors if the role is not set correctly. * */ -export async function updateMediationRole( +export async function updateMediationRole( agent: Agent, mediationRecord: MediationRecord, { mediationRoleUpdateStrategy }: V0_1ToV0_2UpdateConfig