Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(askar): in memory wallet creation #1498

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/askar/src/wallet/AskarWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,11 @@ export class AskarWallet implements Wallet {

this.walletConfig = walletConfig
} catch (error) {
if (isAskarError(error) && error.code === AskarErrorCode.NotFound) {
if (
isAskarError(error) &&
(error.code === AskarErrorCode.NotFound ||
(error.code === AskarErrorCode.Backend && walletConfig.storage?.inMemory))
) {
const errorMessage = `Wallet '${walletConfig.id}' not found`
this.logger.debug(errorMessage)

Expand Down
66 changes: 66 additions & 0 deletions packages/askar/tests/askar-inmemory.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { SubjectMessage } from '../../../tests/transport/SubjectInboundTransport'

import { Agent } from '@aries-framework/core'
import { Subject } from 'rxjs'

import { describeRunInNodeVersion } from '../../../tests/runInVersion'
import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport'
import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport'

import { e2eTest, getSqliteAgentOptions } from './helpers'

const aliceInMemoryAgentOptions = getSqliteAgentOptions(
'AgentsAlice',
{
endpoints: ['rxjs:alice'],
},
true
)
const bobInMemoryAgentOptions = getSqliteAgentOptions(
'AgentsBob',
{
endpoints: ['rxjs:bob'],
},
true
)

// FIXME: Re-include in tests when Askar NodeJS wrapper performance is improved
describeRunInNodeVersion([18], 'Askar In Memory agents', () => {
let aliceAgent: Agent
let bobAgent: Agent

afterAll(async () => {
if (bobAgent) {
await bobAgent.shutdown()
await bobAgent.wallet.delete()
}

if (aliceAgent) {
await aliceAgent.shutdown()
await aliceAgent.wallet.delete()
}
})

test('In memory Askar wallets E2E test', async () => {
const aliceMessages = new Subject<SubjectMessage>()
const bobMessages = new Subject<SubjectMessage>()

const subjectMap = {
'rxjs:alice': aliceMessages,
'rxjs:bob': bobMessages,
}

aliceAgent = new Agent(aliceInMemoryAgentOptions)
aliceAgent.registerInboundTransport(new SubjectInboundTransport(aliceMessages))
aliceAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
await aliceAgent.initialize()

bobAgent = new Agent(bobInMemoryAgentOptions)
bobAgent.registerInboundTransport(new SubjectInboundTransport(bobMessages))
bobAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
await bobAgent.initialize()

await e2eTest(aliceAgent, bobAgent)
})
})
41 changes: 4 additions & 37 deletions packages/askar/tests/askar-postgres.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { SubjectMessage } from '../../../tests/transport/SubjectInboundTransport'
import type { AskarWalletPostgresStorageConfig } from '../src/wallet'
import type { ConnectionRecord } from '@aries-framework/core'

import { Agent, HandshakeProtocol } from '@aries-framework/core'
import { Agent } from '@aries-framework/core'
import { Subject } from 'rxjs'

import { describeRunInNodeVersion } from '../../../tests/runInVersion'
import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport'
import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport'
import { waitForBasicMessage } from '../../core/tests/helpers'

import { getPostgresAgentOptions } from './helpers'
import { e2eTest, getPostgresAgentOptions } from './helpers'

const storageConfig: AskarWalletPostgresStorageConfig = {
type: 'postgres',
Expand All @@ -35,8 +33,6 @@ const bobPostgresAgentOptions = getPostgresAgentOptions('AgentsBob', storageConf
describeRunInNodeVersion([18], 'Askar Postgres agents', () => {
let aliceAgent: Agent
let bobAgent: Agent
let aliceConnection: ConnectionRecord
let bobConnection: ConnectionRecord

afterAll(async () => {
if (bobAgent) {
Expand All @@ -50,7 +46,7 @@ describeRunInNodeVersion([18], 'Askar Postgres agents', () => {
}
})

test('make a connection between postgres agents', async () => {
test('Postgres Askar wallets E2E test', async () => {
const aliceMessages = new Subject<SubjectMessage>()
const bobMessages = new Subject<SubjectMessage>()

Expand All @@ -69,35 +65,6 @@ describeRunInNodeVersion([18], 'Askar Postgres agents', () => {
bobAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
await bobAgent.initialize()

const aliceBobOutOfBandRecord = await aliceAgent.oob.createInvitation({
handshakeProtocols: [HandshakeProtocol.Connections],
})

const { connectionRecord: bobConnectionAtBobAlice } = await bobAgent.oob.receiveInvitation(
aliceBobOutOfBandRecord.outOfBandInvitation
)
bobConnection = await bobAgent.connections.returnWhenIsConnected(bobConnectionAtBobAlice!.id)

const [aliceConnectionAtAliceBob] = await aliceAgent.connections.findAllByOutOfBandId(aliceBobOutOfBandRecord.id)
aliceConnection = await aliceAgent.connections.returnWhenIsConnected(aliceConnectionAtAliceBob!.id)
})

test('send a message to connection', async () => {
const message = 'hello, world'
await aliceAgent.basicMessages.sendMessage(aliceConnection.id, message)

const basicMessage = await waitForBasicMessage(bobAgent, {
content: message,
})

expect(basicMessage.content).toBe(message)
})

test('can shutdown and re-initialize the same postgres agent', async () => {
expect(aliceAgent.isInitialized).toBe(true)
await aliceAgent.shutdown()
expect(aliceAgent.isInitialized).toBe(false)
await aliceAgent.initialize()
expect(aliceAgent.isInitialized).toBe(true)
await e2eTest(aliceAgent, bobAgent)
})
})
47 changes: 43 additions & 4 deletions packages/askar/tests/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { AskarWalletPostgresStorageConfig } from '../src/wallet'
import type { InitConfig } from '@aries-framework/core'
import type { Agent, InitConfig } from '@aries-framework/core'

import { ConnectionsModule, LogLevel, utils } from '@aries-framework/core'
import { ConnectionsModule, HandshakeProtocol, LogLevel, utils } from '@aries-framework/core'
import { ariesAskar } from '@hyperledger/aries-askar-nodejs'
import { registerAriesAskar } from '@hyperledger/aries-askar-shared'
import path from 'path'

import { waitForBasicMessage } from '../../core/tests/helpers'
import { TestLogger } from '../../core/tests/logger'
import { agentDependencies } from '../../node/src'
import { AskarModule } from '../src/AskarModule'
Expand Down Expand Up @@ -54,14 +55,14 @@ export function getPostgresAgentOptions(
} as const
}

export function getSqliteAgentOptions(name: string, extraConfig: Partial<InitConfig> = {}) {
export function getSqliteAgentOptions(name: string, extraConfig: Partial<InitConfig> = {}, inMemory?: boolean) {
const random = utils.uuid().slice(0, 4)
const config: InitConfig = {
label: `SQLiteAgent: ${name} - ${random}`,
walletConfig: {
id: `SQLiteWallet${name} - ${random}`,
key: `Key${name}`,
storage: { type: 'sqlite' },
storage: { type: 'sqlite', inMemory },
},
autoUpdateStorageOnStartup: false,
logger: new TestLogger(LogLevel.off, name),
Expand All @@ -78,3 +79,41 @@ export function getSqliteAgentOptions(name: string, extraConfig: Partial<InitCon
},
} as const
}

/**
* Basic E2E test: connect two agents, send a basic message and verify it they can be re initialized
* @param senderAgent
* @param receiverAgent
*/
export async function e2eTest(senderAgent: Agent, receiverAgent: Agent) {
const senderReceiverOutOfBandRecord = await senderAgent.oob.createInvitation({
handshakeProtocols: [HandshakeProtocol.Connections],
})

const { connectionRecord: bobConnectionAtReceiversender } = await receiverAgent.oob.receiveInvitation(
senderReceiverOutOfBandRecord.outOfBandInvitation
)
if (!bobConnectionAtReceiversender) throw new Error('Connection not created')

await receiverAgent.connections.returnWhenIsConnected(bobConnectionAtReceiversender.id)

const [senderConnectionAtReceiver] = await senderAgent.connections.findAllByOutOfBandId(
senderReceiverOutOfBandRecord.id
)
const senderConnection = await senderAgent.connections.returnWhenIsConnected(senderConnectionAtReceiver.id)

const message = 'hello, world'
await senderAgent.basicMessages.sendMessage(senderConnection.id, message)

const basicMessage = await waitForBasicMessage(receiverAgent, {
content: message,
})

expect(basicMessage.content).toBe(message)

expect(senderAgent.isInitialized).toBe(true)
await senderAgent.shutdown()
expect(senderAgent.isInitialized).toBe(false)
await senderAgent.initialize()
expect(senderAgent.isInitialized).toBe(true)
}