import type { AskarModuleConfigOptions } from './AskarModuleConfig' import type { AgentContext, DependencyManager, Module } from '@aries-framework/core' import { AgentConfig, AriesFrameworkError, InjectionSymbols } from '@aries-framework/core' import { Store } from '@hyperledger/aries-askar-shared' import { AskarMultiWalletDatabaseScheme, AskarModuleConfig } from './AskarModuleConfig' import { AskarStorageService } from './storage' import { assertAskarWallet } from './utils/assertAskarWallet' import { AskarProfileWallet, AskarWallet } from './wallet' export class AskarModule implements Module { public readonly config: AskarModuleConfig public constructor(config: AskarModuleConfigOptions) { this.config = new AskarModuleConfig(config) } public register(dependencyManager: DependencyManager) { // Warn about experimental module dependencyManager .resolve(AgentConfig) .logger.warn( "The '@aries-framework/askar' module is experimental and could have unexpected breaking changes. When using this module, make sure to use strict versions for all @aries-framework packages." ) dependencyManager.registerInstance(AskarModuleConfig, this.config) if (dependencyManager.isRegistered(InjectionSymbols.Wallet)) { throw new AriesFrameworkError('There is an instance of Wallet already registered') } else { dependencyManager.registerContextScoped(InjectionSymbols.Wallet, AskarWallet) // If the multiWalletDatabaseScheme is set to ProfilePerWallet, we want to register the AskarProfileWallet if (this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.ProfilePerWallet) { dependencyManager.registerContextScoped(AskarProfileWallet) } } if (dependencyManager.isRegistered(InjectionSymbols.StorageService)) { throw new AriesFrameworkError('There is an instance of StorageService already registered') } else { dependencyManager.registerSingleton(InjectionSymbols.StorageService, AskarStorageService) } } public async initialize(agentContext: AgentContext): Promise { // We MUST use an askar wallet here assertAskarWallet(agentContext.wallet) const wallet = agentContext.wallet // Register the Askar store instance on the dependency manager // This allows it to be re-used for tenants agentContext.dependencyManager.registerInstance(Store, agentContext.wallet.store) // If the multiWalletDatabaseScheme is set to ProfilePerWallet, we want to register the AskarProfileWallet // and return that as the wallet for all tenants, but not for the main agent, that should use the AskarWallet if (this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.ProfilePerWallet) { agentContext.dependencyManager.container.register(InjectionSymbols.Wallet, { useFactory: (container) => { // If the container is the same as the root dependency manager container // it means we are in the main agent, and we should use the root wallet if (container === agentContext.dependencyManager.container) { return wallet } // Otherwise we want to return the AskarProfileWallet return container.resolve(AskarProfileWallet) }, }) } } }