From 213187fb29ea6c6585c20937af625f6a251f3cdd Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Thu, 24 Nov 2022 15:24:43 +0100
Subject: [PATCH 01/22] Created the indy-vdr package
Signed-off-by: vickysomtee
---
packages/indy-vdr/README.md | 78 ++++
packages/indy-vdr/jest.config.ts | 14 +
packages/indy-vdr/package.json | 47 +++
packages/indy-vdr/src/index.ts | 5 +
.../indy-vdr/tests/action-menu.e2e.test.ts | 354 ++++++++++++++++++
packages/indy-vdr/tests/helpers.ts | 60 +++
packages/indy-vdr/tests/setup.ts | 3 +
packages/indy-vdr/tsconfig.build.json | 7 +
packages/indy-vdr/tsconfig.json | 6 +
9 files changed, 574 insertions(+)
create mode 100644 packages/indy-vdr/README.md
create mode 100644 packages/indy-vdr/jest.config.ts
create mode 100644 packages/indy-vdr/package.json
create mode 100644 packages/indy-vdr/src/index.ts
create mode 100644 packages/indy-vdr/tests/action-menu.e2e.test.ts
create mode 100644 packages/indy-vdr/tests/helpers.ts
create mode 100644 packages/indy-vdr/tests/setup.ts
create mode 100644 packages/indy-vdr/tsconfig.build.json
create mode 100644 packages/indy-vdr/tsconfig.json
diff --git a/packages/indy-vdr/README.md b/packages/indy-vdr/README.md
new file mode 100644
index 0000000000..ffd98caf55
--- /dev/null
+++ b/packages/indy-vdr/README.md
@@ -0,0 +1,78 @@
+
+
+
+
+Aries Framework JavaScript Action Menu Plugin
+
+
+
+
+
+
+
+
+Action Menu plugin for [Aries Framework JavaScript](https://github.com/hyperledger/aries-framework-javascript.git). Implements [Aries RFC 0509](https://github.com/hyperledger/aries-rfcs/blob/1795d5c2d36f664f88f5e8045042ace8e573808c/features/0509-action-menu/README.md).
+
+### Installation
+
+Make sure you have set up the correct version of Aries Framework JavaScript according to the AFJ repository. To find out which version of AFJ you need to have installed you can run the following command. This will list the required peer dependency for `@aries-framework/core`.
+
+```sh
+npm info "@aries-framework/action-menu" peerDependencies
+```
+
+Then add the action-menu plugin to your project.
+
+```sh
+yarn add @aries-framework/action-menu
+```
+
+### Quick start
+
+In order for this plugin to work, we have to inject it into the agent to access agent functionality. See the example for more information.
+
+### Example of usage
+
+```ts
+import { ActionMenuModule } from '@aries-framework/action-menu'
+
+const agent = new Agent({
+ config: {
+ /* config */
+ },
+ dependencies: agentDependencies,
+ modules: {
+ actionMenu: new ActionMenuModule(),
+ /* other custom modules */
+ },
+})
+
+await agent.initialize()
+
+// To request root menu to a given connection (menu will be received
+// asynchronously in a ActionMenuStateChangedEvent)
+await agent.modules.actionMenu.requestMenu({ connectionId })
+
+// To select an option from the action menu
+await agent.modules.actionMenu.performAction({
+ connectionId,
+ performedAction: { name: 'option-1' },
+})
+```
diff --git a/packages/indy-vdr/jest.config.ts b/packages/indy-vdr/jest.config.ts
new file mode 100644
index 0000000000..55c67d70a6
--- /dev/null
+++ b/packages/indy-vdr/jest.config.ts
@@ -0,0 +1,14 @@
+import type { Config } from '@jest/types'
+
+import base from '../../jest.config.base'
+
+import packageJson from './package.json'
+
+const config: Config.InitialOptions = {
+ ...base,
+ name: packageJson.name,
+ displayName: packageJson.name,
+ setupFilesAfterEnv: ['./tests/setup.ts'],
+}
+
+export default config
diff --git a/packages/indy-vdr/package.json b/packages/indy-vdr/package.json
new file mode 100644
index 0000000000..e5673abf75
--- /dev/null
+++ b/packages/indy-vdr/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "@aries-framework/indy-vdr",
+ "main": "build/index",
+ "types": "build/index",
+ "version": "0.2.5",
+ "files": [
+ "build"
+ ],
+ "license": "Apache-2.0",
+ "publishConfig": {
+ "access": "public"
+ },
+ "homepage": "https://github.com/hyperledger/aries-framework-javascript/tree/main/packages/indy-vdr",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/hyperledger/aries-framework-javascript",
+ "directory": "packages/indy-vdr"
+ },
+ "scripts": {
+ "build": "yarn run clean && yarn run compile",
+ "clean": "rimraf -rf ./build",
+ "compile": "tsc -p tsconfig.build.json",
+ "prepublishOnly": "yarn run build",
+ "test": "jest"
+ },
+ "dependencies": {
+ "class-transformer": "0.5.1",
+ "class-validator": "0.13.1",
+ "rxjs": "^7.2.0"
+ },
+ "peerDependencies": {
+ "@aries-framework/core": "0.2.5",
+ "indy-vdr-test-shared": "^0.1.2"
+ },
+ "devDependencies": {
+ "@aries-framework/node": "0.2.5",
+ "indy-vdr-test-shared": "^0.1.2",
+ "reflect-metadata": "^0.1.13",
+ "rimraf": "~3.0.2",
+ "typescript": "~4.3.0"
+ },
+ "peerDependenciesMeta": {
+ "indy-vdr-test-shared": {
+ "optional": true
+ }
+ }
+}
diff --git a/packages/indy-vdr/src/index.ts b/packages/indy-vdr/src/index.ts
new file mode 100644
index 0000000000..79d8efe525
--- /dev/null
+++ b/packages/indy-vdr/src/index.ts
@@ -0,0 +1,5 @@
+try {
+ require("indy-vdr-test-nodejs");
+ } catch (error) {
+ throw new Error("Error registering nodejs bindings for Indy VDR");
+ }
\ No newline at end of file
diff --git a/packages/indy-vdr/tests/action-menu.e2e.test.ts b/packages/indy-vdr/tests/action-menu.e2e.test.ts
new file mode 100644
index 0000000000..b15524fd93
--- /dev/null
+++ b/packages/indy-vdr/tests/action-menu.e2e.test.ts
@@ -0,0 +1,354 @@
+import type { SubjectMessage } from '../../../tests/transport/SubjectInboundTransport'
+import type { ConnectionRecord } from '@aries-framework/core'
+
+import { Agent } from '@aries-framework/core'
+import { Subject } from 'rxjs'
+
+import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport'
+import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport'
+import { getAgentOptions, makeConnection } from '../../core/tests/helpers'
+import testLogger from '../../core/tests/logger'
+
+import { waitForActionMenuRecord } from './helpers'
+
+import {
+ ActionMenu,
+ ActionMenuModule,
+ ActionMenuRecord,
+ ActionMenuRole,
+ ActionMenuState,
+} from '@aries-framework/action-menu'
+
+const faberAgentOptions = getAgentOptions(
+ 'Faber Action Menu',
+ {
+ endpoints: ['rxjs:faber'],
+ },
+ {
+ actionMenu: new ActionMenuModule(),
+ }
+)
+
+const aliceAgentOptions = getAgentOptions(
+ 'Alice Action Menu',
+ {
+ endpoints: ['rxjs:alice'],
+ },
+ {
+ actionMenu: new ActionMenuModule(),
+ }
+)
+
+describe('Action Menu', () => {
+ let faberAgent: Agent<{
+ actionMenu: ActionMenuModule
+ }>
+ let aliceAgent: Agent<{
+ actionMenu: ActionMenuModule
+ }>
+ let faberConnection: ConnectionRecord
+ let aliceConnection: ConnectionRecord
+
+ const rootMenu = new ActionMenu({
+ title: 'Welcome',
+ description: 'This is the root menu',
+ options: [
+ {
+ name: 'option-1',
+ description: 'Option 1 description',
+ title: 'Option 1',
+ },
+ {
+ name: 'option-2',
+ description: 'Option 2 description',
+ title: 'Option 2',
+ },
+ ],
+ })
+
+ const submenu1 = new ActionMenu({
+ title: 'Menu 1',
+ description: 'This is first submenu',
+ options: [
+ {
+ name: 'option-1-1',
+ description: '1-1 desc',
+ title: '1-1 title',
+ },
+ {
+ name: 'option-1-2',
+ description: '1-1 desc',
+ title: '1-1 title',
+ },
+ ],
+ })
+
+ beforeEach(async () => {
+ const faberMessages = new Subject()
+ const aliceMessages = new Subject()
+ const subjectMap = {
+ 'rxjs:faber': faberMessages,
+ 'rxjs:alice': aliceMessages,
+ }
+
+ faberAgent = new Agent(faberAgentOptions)
+ faberAgent.registerInboundTransport(new SubjectInboundTransport(faberMessages))
+ faberAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
+ await faberAgent.initialize()
+
+ aliceAgent = new Agent(aliceAgentOptions)
+ aliceAgent.registerInboundTransport(new SubjectInboundTransport(aliceMessages))
+ aliceAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
+ await aliceAgent.initialize()
+ ;[aliceConnection, faberConnection] = await makeConnection(aliceAgent, faberAgent)
+ })
+
+ afterEach(async () => {
+ await faberAgent.shutdown()
+ await faberAgent.wallet.delete()
+ await aliceAgent.shutdown()
+ await aliceAgent.wallet.delete()
+ })
+
+ test('Alice requests menu to Faber and selects an option once received', async () => {
+ testLogger.test('Alice sends menu request to Faber')
+ let aliceActionMenuRecord = await aliceAgent.modules.actionMenu.requestMenu({ connectionId: aliceConnection.id })
+
+ testLogger.test('Faber waits for menu request from Alice')
+ await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.PreparingRootMenu,
+ })
+
+ testLogger.test('Faber sends root menu to Alice')
+ await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
+
+ testLogger.test('Alice waits until she receives menu')
+ aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
+ state: ActionMenuState.PreparingSelection,
+ })
+
+ expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
+ const faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
+ connectionId: faberConnection.id,
+ role: ActionMenuRole.Responder,
+ })
+ expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
+
+ testLogger.test('Alice selects menu item')
+ await aliceAgent.modules.actionMenu.performAction({
+ connectionId: aliceConnection.id,
+ performedAction: { name: 'option-1' },
+ })
+
+ testLogger.test('Faber waits for menu selection from Alice')
+ await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.Done,
+ })
+
+ // As Alice has responded, menu should be closed (done state)
+ const aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
+ connectionId: aliceConnection.id,
+ role: ActionMenuRole.Requester,
+ })
+ expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
+ })
+
+ test('Faber sends root menu and Alice selects an option', async () => {
+ testLogger.test('Faber sends root menu to Alice')
+ await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
+
+ testLogger.test('Alice waits until she receives menu')
+ const aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
+ state: ActionMenuState.PreparingSelection,
+ })
+
+ expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
+ const faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
+ connectionId: faberConnection.id,
+ role: ActionMenuRole.Responder,
+ })
+ expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
+
+ testLogger.test('Alice selects menu item')
+ await aliceAgent.modules.actionMenu.performAction({
+ connectionId: aliceConnection.id,
+ performedAction: { name: 'option-1' },
+ })
+
+ testLogger.test('Faber waits for menu selection from Alice')
+ await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.Done,
+ })
+
+ // As Alice has responded, menu should be closed (done state)
+ const aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
+ connectionId: aliceConnection.id,
+ role: ActionMenuRole.Requester,
+ })
+ expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
+ })
+
+ test('Menu navigation', async () => {
+ testLogger.test('Faber sends root menu ')
+ let faberActionMenuRecord = await faberAgent.modules.actionMenu.sendMenu({
+ connectionId: faberConnection.id,
+ menu: rootMenu,
+ })
+
+ const rootThreadId = faberActionMenuRecord.threadId
+
+ testLogger.test('Alice waits until she receives menu')
+ let aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
+ state: ActionMenuState.PreparingSelection,
+ })
+
+ expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
+ expect(aliceActionMenuRecord.threadId).toEqual(rootThreadId)
+
+ testLogger.test('Alice selects menu item 1')
+ await aliceAgent.modules.actionMenu.performAction({
+ connectionId: aliceConnection.id,
+ performedAction: { name: 'option-1' },
+ })
+
+ testLogger.test('Faber waits for menu selection from Alice')
+ faberActionMenuRecord = await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.Done,
+ })
+
+ // As Alice has responded, menu should be closed (done state)
+ let aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
+ connectionId: aliceConnection.id,
+ role: ActionMenuRole.Requester,
+ })
+ expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
+ expect(aliceActiveMenu?.threadId).toEqual(rootThreadId)
+
+ testLogger.test('Faber sends submenu to Alice')
+ faberActionMenuRecord = await faberAgent.modules.actionMenu.sendMenu({
+ connectionId: faberConnection.id,
+ menu: submenu1,
+ })
+
+ testLogger.test('Alice waits until she receives submenu')
+ aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
+ state: ActionMenuState.PreparingSelection,
+ })
+
+ expect(aliceActionMenuRecord.menu).toEqual(submenu1)
+ expect(aliceActionMenuRecord.threadId).toEqual(rootThreadId)
+
+ testLogger.test('Alice selects menu item 1-1')
+ await aliceAgent.modules.actionMenu.performAction({
+ connectionId: aliceConnection.id,
+ performedAction: { name: 'option-1-1' },
+ })
+
+ testLogger.test('Faber waits for menu selection from Alice')
+ faberActionMenuRecord = await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.Done,
+ })
+
+ // As Alice has responded, menu should be closed (done state)
+ aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
+ connectionId: aliceConnection.id,
+ role: ActionMenuRole.Requester,
+ })
+ expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
+ expect(aliceActiveMenu?.threadId).toEqual(rootThreadId)
+
+ testLogger.test('Alice sends menu request to Faber')
+ aliceActionMenuRecord = await aliceAgent.modules.actionMenu.requestMenu({ connectionId: aliceConnection.id })
+
+ testLogger.test('Faber waits for menu request from Alice')
+ faberActionMenuRecord = await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.PreparingRootMenu,
+ })
+
+ testLogger.test('This new menu request must have a different thread Id')
+ expect(faberActionMenuRecord.menu).toBeUndefined()
+ expect(aliceActionMenuRecord.threadId).not.toEqual(rootThreadId)
+ expect(faberActionMenuRecord.threadId).toEqual(aliceActionMenuRecord.threadId)
+ })
+
+ test('Menu clearing', async () => {
+ testLogger.test('Faber sends root menu to Alice')
+ await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
+
+ testLogger.test('Alice waits until she receives menu')
+ let aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
+ state: ActionMenuState.PreparingSelection,
+ })
+
+ expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
+ let faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
+ connectionId: faberConnection.id,
+ role: ActionMenuRole.Responder,
+ })
+ expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
+
+ await faberAgent.modules.actionMenu.clearActiveMenu({
+ connectionId: faberConnection.id,
+ role: ActionMenuRole.Responder,
+ })
+
+ testLogger.test('Alice selects menu item')
+ await aliceAgent.modules.actionMenu.performAction({
+ connectionId: aliceConnection.id,
+ performedAction: { name: 'option-1' },
+ })
+
+ // Exception
+
+ testLogger.test('Faber rejects selection, as menu has been cleared')
+ // Faber sends error report to Alice, meaning that her Menu flow will be cleared
+ aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
+ state: ActionMenuState.Null,
+ role: ActionMenuRole.Requester,
+ })
+
+ testLogger.test('Alice request a new menu')
+ await aliceAgent.modules.actionMenu.requestMenu({
+ connectionId: aliceConnection.id,
+ })
+
+ testLogger.test('Faber waits for menu request from Alice')
+ await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.PreparingRootMenu,
+ })
+
+ testLogger.test('Faber sends root menu to Alice')
+ await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
+
+ testLogger.test('Alice waits until she receives menu')
+ aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
+ state: ActionMenuState.PreparingSelection,
+ })
+
+ expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
+ faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
+ connectionId: faberConnection.id,
+ role: ActionMenuRole.Responder,
+ })
+ expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
+ expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
+
+ testLogger.test('Alice selects menu item')
+ await aliceAgent.modules.actionMenu.performAction({
+ connectionId: aliceConnection.id,
+ performedAction: { name: 'option-1' },
+ })
+
+ testLogger.test('Faber waits for menu selection from Alice')
+ await waitForActionMenuRecord(faberAgent, {
+ state: ActionMenuState.Done,
+ })
+ })
+})
diff --git a/packages/indy-vdr/tests/helpers.ts b/packages/indy-vdr/tests/helpers.ts
new file mode 100644
index 0000000000..c4044b448b
--- /dev/null
+++ b/packages/indy-vdr/tests/helpers.ts
@@ -0,0 +1,60 @@
+import type { ActionMenuStateChangedEvent, ActionMenuRole, ActionMenuState } from '@aries-framework/action-menu'
+import type { Agent } from '@aries-framework/core'
+import type { Observable } from 'rxjs'
+
+import { catchError, filter, firstValueFrom, map, ReplaySubject, timeout } from 'rxjs'
+
+import { ActionMenuEventTypes } from '@aries-framework/action-menu'
+
+export async function waitForActionMenuRecord(
+ agent: Agent,
+ options: {
+ threadId?: string
+ role?: ActionMenuRole
+ state?: ActionMenuState
+ previousState?: ActionMenuState | null
+ timeoutMs?: number
+ }
+) {
+ const observable = agent.events.observable(ActionMenuEventTypes.ActionMenuStateChanged)
+
+ return waitForActionMenuRecordSubject(observable, options)
+}
+
+export function waitForActionMenuRecordSubject(
+ subject: ReplaySubject | Observable,
+ {
+ threadId,
+ role,
+ state,
+ previousState,
+ timeoutMs = 10000,
+ }: {
+ threadId?: string
+ role?: ActionMenuRole
+ state?: ActionMenuState
+ previousState?: ActionMenuState | null
+ timeoutMs?: number
+ }
+) {
+ const observable = subject instanceof ReplaySubject ? subject.asObservable() : subject
+ return firstValueFrom(
+ observable.pipe(
+ filter((e) => previousState === undefined || e.payload.previousState === previousState),
+ filter((e) => threadId === undefined || e.payload.actionMenuRecord.threadId === threadId),
+ filter((e) => role === undefined || e.payload.actionMenuRecord.role === role),
+ filter((e) => state === undefined || e.payload.actionMenuRecord.state === state),
+ timeout(timeoutMs),
+ catchError(() => {
+ throw new Error(
+ `ActionMenuStateChangedEvent event not emitted within specified timeout: {
+ previousState: ${previousState},
+ threadId: ${threadId},
+ state: ${state}
+ }`
+ )
+ }),
+ map((e) => e.payload.actionMenuRecord)
+ )
+ )
+}
diff --git a/packages/indy-vdr/tests/setup.ts b/packages/indy-vdr/tests/setup.ts
new file mode 100644
index 0000000000..4955aeb601
--- /dev/null
+++ b/packages/indy-vdr/tests/setup.ts
@@ -0,0 +1,3 @@
+import 'reflect-metadata'
+
+jest.setTimeout(20000)
diff --git a/packages/indy-vdr/tsconfig.build.json b/packages/indy-vdr/tsconfig.build.json
new file mode 100644
index 0000000000..2b75d0adab
--- /dev/null
+++ b/packages/indy-vdr/tsconfig.build.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig.build.json",
+ "compilerOptions": {
+ "outDir": "./build"
+ },
+ "include": ["src/**/*"]
+}
diff --git a/packages/indy-vdr/tsconfig.json b/packages/indy-vdr/tsconfig.json
new file mode 100644
index 0000000000..46efe6f721
--- /dev/null
+++ b/packages/indy-vdr/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "types": ["jest"]
+ }
+}
From 6998abea7f298c6a002403320f97ed266ada5251 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Mon, 28 Nov 2022 10:52:45 +0100
Subject: [PATCH 02/22] feat: create IndyVdrPool
Signed-off-by: vickysomtee
---
packages/indy-vdr/src/pool/IndyVdrPool.ts | 42 +++++++++++++++++++++++
packages/indy-vdr/src/pool/index.ts | 2 ++
2 files changed, 44 insertions(+)
create mode 100644 packages/indy-vdr/src/pool/IndyVdrPool.ts
create mode 100644 packages/indy-vdr/src/pool/index.ts
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
new file mode 100644
index 0000000000..8050049d6e
--- /dev/null
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -0,0 +1,42 @@
+import type { Logger } from '@aries-framework/core'
+import {IndyPool} from '@aries-framework/core'
+import { PoolCreate } from "indy-vdr-test-shared"
+
+interface TransactionAuthorAgreement {
+ version: `${number}.${number}` | `${number}`
+ acceptanceMechanism: string
+}
+
+interface IndyVdrPoolConfig {
+ genesisTransactions: string
+ isProduction: boolean
+ indyNamespace: string
+ transactionAuthorAgreement?: TransactionAuthorAgreement
+}
+
+export class IndyVdrPool {
+ private pool: IndyPool // Not sure this is the correct type for the pool
+ private logger: Logger
+ private poolConfig: IndyVdrPoolConfig
+ private poolConnected?: Promise
+
+ constructor(poolConfig: IndyVdrPoolConfig, logger: Logger) {
+ this.logger = logger
+ this.poolConfig = poolConfig
+ }
+
+ public get IndyNamespace(): string {
+ return this.poolConfig.indyNamespace
+ }
+
+ public get config() {
+ return this.poolConfig
+ }
+
+ public async connect() {
+ this.pool = new PoolCreate({parameters: {}})
+
+
+
+ }
+}
diff --git a/packages/indy-vdr/src/pool/index.ts b/packages/indy-vdr/src/pool/index.ts
new file mode 100644
index 0000000000..a10a471490
--- /dev/null
+++ b/packages/indy-vdr/src/pool/index.ts
@@ -0,0 +1,2 @@
+import * as IndyVdr from 'indy-vdr-test-shared';
+
From a7f05cae935e9ef73a22bab4a0bf8ae7adbe24a5 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Mon, 28 Nov 2022 10:57:42 +0100
Subject: [PATCH 03/22] feat: create IndyVdrPool
Signed-off-by: vickysomtee
---
packages/indy-vdr/src/pool/IndyVdrPool.ts | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index 8050049d6e..932439735a 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -36,7 +36,6 @@ export class IndyVdrPool {
public async connect() {
this.pool = new PoolCreate({parameters: {}})
-
-
+
}
}
From f2e24550141cbd0f41def0f45c3dbf2eb26d6ab7 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Mon, 28 Nov 2022 11:06:10 +0100
Subject: [PATCH 04/22] removed e-2-e test
Signed-off-by: vickysomtee
---
packages/indy-vdr/src/pool/IndyVdrPool.ts | 8 +-
.../indy-vdr/tests/action-menu.e2e.test.ts | 354 ------------------
packages/indy-vdr/tests/helpers.ts | 60 ---
packages/indy-vdr/tests/setup.ts | 3 -
4 files changed, 3 insertions(+), 422 deletions(-)
delete mode 100644 packages/indy-vdr/tests/action-menu.e2e.test.ts
delete mode 100644 packages/indy-vdr/tests/helpers.ts
delete mode 100644 packages/indy-vdr/tests/setup.ts
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index 932439735a..916e9dfdb0 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -1,6 +1,6 @@
import type { Logger } from '@aries-framework/core'
import {IndyPool} from '@aries-framework/core'
-import { PoolCreate } from "indy-vdr-test-shared"
+import { PoolCreate } from 'indy-vdr-test-shared'
interface TransactionAuthorAgreement {
version: `${number}.${number}` | `${number}`
@@ -15,7 +15,7 @@ interface IndyVdrPoolConfig {
}
export class IndyVdrPool {
- private pool: IndyPool // Not sure this is the correct type for the pool
+ // private pool: IndyPool // Not sure this is the correct type for the pool
private logger: Logger
private poolConfig: IndyVdrPoolConfig
private poolConnected?: Promise
@@ -34,8 +34,6 @@ export class IndyVdrPool {
}
public async connect() {
- this.pool = new PoolCreate({parameters: {}})
-
-
+ // this.pool = new PoolCreate({parameters: {}})
}
}
diff --git a/packages/indy-vdr/tests/action-menu.e2e.test.ts b/packages/indy-vdr/tests/action-menu.e2e.test.ts
deleted file mode 100644
index b15524fd93..0000000000
--- a/packages/indy-vdr/tests/action-menu.e2e.test.ts
+++ /dev/null
@@ -1,354 +0,0 @@
-import type { SubjectMessage } from '../../../tests/transport/SubjectInboundTransport'
-import type { ConnectionRecord } from '@aries-framework/core'
-
-import { Agent } from '@aries-framework/core'
-import { Subject } from 'rxjs'
-
-import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport'
-import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport'
-import { getAgentOptions, makeConnection } from '../../core/tests/helpers'
-import testLogger from '../../core/tests/logger'
-
-import { waitForActionMenuRecord } from './helpers'
-
-import {
- ActionMenu,
- ActionMenuModule,
- ActionMenuRecord,
- ActionMenuRole,
- ActionMenuState,
-} from '@aries-framework/action-menu'
-
-const faberAgentOptions = getAgentOptions(
- 'Faber Action Menu',
- {
- endpoints: ['rxjs:faber'],
- },
- {
- actionMenu: new ActionMenuModule(),
- }
-)
-
-const aliceAgentOptions = getAgentOptions(
- 'Alice Action Menu',
- {
- endpoints: ['rxjs:alice'],
- },
- {
- actionMenu: new ActionMenuModule(),
- }
-)
-
-describe('Action Menu', () => {
- let faberAgent: Agent<{
- actionMenu: ActionMenuModule
- }>
- let aliceAgent: Agent<{
- actionMenu: ActionMenuModule
- }>
- let faberConnection: ConnectionRecord
- let aliceConnection: ConnectionRecord
-
- const rootMenu = new ActionMenu({
- title: 'Welcome',
- description: 'This is the root menu',
- options: [
- {
- name: 'option-1',
- description: 'Option 1 description',
- title: 'Option 1',
- },
- {
- name: 'option-2',
- description: 'Option 2 description',
- title: 'Option 2',
- },
- ],
- })
-
- const submenu1 = new ActionMenu({
- title: 'Menu 1',
- description: 'This is first submenu',
- options: [
- {
- name: 'option-1-1',
- description: '1-1 desc',
- title: '1-1 title',
- },
- {
- name: 'option-1-2',
- description: '1-1 desc',
- title: '1-1 title',
- },
- ],
- })
-
- beforeEach(async () => {
- const faberMessages = new Subject()
- const aliceMessages = new Subject()
- const subjectMap = {
- 'rxjs:faber': faberMessages,
- 'rxjs:alice': aliceMessages,
- }
-
- faberAgent = new Agent(faberAgentOptions)
- faberAgent.registerInboundTransport(new SubjectInboundTransport(faberMessages))
- faberAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
- await faberAgent.initialize()
-
- aliceAgent = new Agent(aliceAgentOptions)
- aliceAgent.registerInboundTransport(new SubjectInboundTransport(aliceMessages))
- aliceAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap))
- await aliceAgent.initialize()
- ;[aliceConnection, faberConnection] = await makeConnection(aliceAgent, faberAgent)
- })
-
- afterEach(async () => {
- await faberAgent.shutdown()
- await faberAgent.wallet.delete()
- await aliceAgent.shutdown()
- await aliceAgent.wallet.delete()
- })
-
- test('Alice requests menu to Faber and selects an option once received', async () => {
- testLogger.test('Alice sends menu request to Faber')
- let aliceActionMenuRecord = await aliceAgent.modules.actionMenu.requestMenu({ connectionId: aliceConnection.id })
-
- testLogger.test('Faber waits for menu request from Alice')
- await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.PreparingRootMenu,
- })
-
- testLogger.test('Faber sends root menu to Alice')
- await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
-
- testLogger.test('Alice waits until she receives menu')
- aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
- state: ActionMenuState.PreparingSelection,
- })
-
- expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
- const faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
- connectionId: faberConnection.id,
- role: ActionMenuRole.Responder,
- })
- expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
-
- testLogger.test('Alice selects menu item')
- await aliceAgent.modules.actionMenu.performAction({
- connectionId: aliceConnection.id,
- performedAction: { name: 'option-1' },
- })
-
- testLogger.test('Faber waits for menu selection from Alice')
- await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.Done,
- })
-
- // As Alice has responded, menu should be closed (done state)
- const aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
- connectionId: aliceConnection.id,
- role: ActionMenuRole.Requester,
- })
- expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
- })
-
- test('Faber sends root menu and Alice selects an option', async () => {
- testLogger.test('Faber sends root menu to Alice')
- await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
-
- testLogger.test('Alice waits until she receives menu')
- const aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
- state: ActionMenuState.PreparingSelection,
- })
-
- expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
- const faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
- connectionId: faberConnection.id,
- role: ActionMenuRole.Responder,
- })
- expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
-
- testLogger.test('Alice selects menu item')
- await aliceAgent.modules.actionMenu.performAction({
- connectionId: aliceConnection.id,
- performedAction: { name: 'option-1' },
- })
-
- testLogger.test('Faber waits for menu selection from Alice')
- await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.Done,
- })
-
- // As Alice has responded, menu should be closed (done state)
- const aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
- connectionId: aliceConnection.id,
- role: ActionMenuRole.Requester,
- })
- expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
- })
-
- test('Menu navigation', async () => {
- testLogger.test('Faber sends root menu ')
- let faberActionMenuRecord = await faberAgent.modules.actionMenu.sendMenu({
- connectionId: faberConnection.id,
- menu: rootMenu,
- })
-
- const rootThreadId = faberActionMenuRecord.threadId
-
- testLogger.test('Alice waits until she receives menu')
- let aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
- state: ActionMenuState.PreparingSelection,
- })
-
- expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
- expect(aliceActionMenuRecord.threadId).toEqual(rootThreadId)
-
- testLogger.test('Alice selects menu item 1')
- await aliceAgent.modules.actionMenu.performAction({
- connectionId: aliceConnection.id,
- performedAction: { name: 'option-1' },
- })
-
- testLogger.test('Faber waits for menu selection from Alice')
- faberActionMenuRecord = await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.Done,
- })
-
- // As Alice has responded, menu should be closed (done state)
- let aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
- connectionId: aliceConnection.id,
- role: ActionMenuRole.Requester,
- })
- expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
- expect(aliceActiveMenu?.threadId).toEqual(rootThreadId)
-
- testLogger.test('Faber sends submenu to Alice')
- faberActionMenuRecord = await faberAgent.modules.actionMenu.sendMenu({
- connectionId: faberConnection.id,
- menu: submenu1,
- })
-
- testLogger.test('Alice waits until she receives submenu')
- aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
- state: ActionMenuState.PreparingSelection,
- })
-
- expect(aliceActionMenuRecord.menu).toEqual(submenu1)
- expect(aliceActionMenuRecord.threadId).toEqual(rootThreadId)
-
- testLogger.test('Alice selects menu item 1-1')
- await aliceAgent.modules.actionMenu.performAction({
- connectionId: aliceConnection.id,
- performedAction: { name: 'option-1-1' },
- })
-
- testLogger.test('Faber waits for menu selection from Alice')
- faberActionMenuRecord = await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.Done,
- })
-
- // As Alice has responded, menu should be closed (done state)
- aliceActiveMenu = await aliceAgent.modules.actionMenu.findActiveMenu({
- connectionId: aliceConnection.id,
- role: ActionMenuRole.Requester,
- })
- expect(aliceActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(aliceActiveMenu?.state).toBe(ActionMenuState.Done)
- expect(aliceActiveMenu?.threadId).toEqual(rootThreadId)
-
- testLogger.test('Alice sends menu request to Faber')
- aliceActionMenuRecord = await aliceAgent.modules.actionMenu.requestMenu({ connectionId: aliceConnection.id })
-
- testLogger.test('Faber waits for menu request from Alice')
- faberActionMenuRecord = await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.PreparingRootMenu,
- })
-
- testLogger.test('This new menu request must have a different thread Id')
- expect(faberActionMenuRecord.menu).toBeUndefined()
- expect(aliceActionMenuRecord.threadId).not.toEqual(rootThreadId)
- expect(faberActionMenuRecord.threadId).toEqual(aliceActionMenuRecord.threadId)
- })
-
- test('Menu clearing', async () => {
- testLogger.test('Faber sends root menu to Alice')
- await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
-
- testLogger.test('Alice waits until she receives menu')
- let aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
- state: ActionMenuState.PreparingSelection,
- })
-
- expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
- let faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
- connectionId: faberConnection.id,
- role: ActionMenuRole.Responder,
- })
- expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
-
- await faberAgent.modules.actionMenu.clearActiveMenu({
- connectionId: faberConnection.id,
- role: ActionMenuRole.Responder,
- })
-
- testLogger.test('Alice selects menu item')
- await aliceAgent.modules.actionMenu.performAction({
- connectionId: aliceConnection.id,
- performedAction: { name: 'option-1' },
- })
-
- // Exception
-
- testLogger.test('Faber rejects selection, as menu has been cleared')
- // Faber sends error report to Alice, meaning that her Menu flow will be cleared
- aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
- state: ActionMenuState.Null,
- role: ActionMenuRole.Requester,
- })
-
- testLogger.test('Alice request a new menu')
- await aliceAgent.modules.actionMenu.requestMenu({
- connectionId: aliceConnection.id,
- })
-
- testLogger.test('Faber waits for menu request from Alice')
- await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.PreparingRootMenu,
- })
-
- testLogger.test('Faber sends root menu to Alice')
- await faberAgent.modules.actionMenu.sendMenu({ connectionId: faberConnection.id, menu: rootMenu })
-
- testLogger.test('Alice waits until she receives menu')
- aliceActionMenuRecord = await waitForActionMenuRecord(aliceAgent, {
- state: ActionMenuState.PreparingSelection,
- })
-
- expect(aliceActionMenuRecord.menu).toEqual(rootMenu)
- faberActiveMenu = await faberAgent.modules.actionMenu.findActiveMenu({
- connectionId: faberConnection.id,
- role: ActionMenuRole.Responder,
- })
- expect(faberActiveMenu).toBeInstanceOf(ActionMenuRecord)
- expect(faberActiveMenu?.state).toBe(ActionMenuState.AwaitingSelection)
-
- testLogger.test('Alice selects menu item')
- await aliceAgent.modules.actionMenu.performAction({
- connectionId: aliceConnection.id,
- performedAction: { name: 'option-1' },
- })
-
- testLogger.test('Faber waits for menu selection from Alice')
- await waitForActionMenuRecord(faberAgent, {
- state: ActionMenuState.Done,
- })
- })
-})
diff --git a/packages/indy-vdr/tests/helpers.ts b/packages/indy-vdr/tests/helpers.ts
deleted file mode 100644
index c4044b448b..0000000000
--- a/packages/indy-vdr/tests/helpers.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import type { ActionMenuStateChangedEvent, ActionMenuRole, ActionMenuState } from '@aries-framework/action-menu'
-import type { Agent } from '@aries-framework/core'
-import type { Observable } from 'rxjs'
-
-import { catchError, filter, firstValueFrom, map, ReplaySubject, timeout } from 'rxjs'
-
-import { ActionMenuEventTypes } from '@aries-framework/action-menu'
-
-export async function waitForActionMenuRecord(
- agent: Agent,
- options: {
- threadId?: string
- role?: ActionMenuRole
- state?: ActionMenuState
- previousState?: ActionMenuState | null
- timeoutMs?: number
- }
-) {
- const observable = agent.events.observable(ActionMenuEventTypes.ActionMenuStateChanged)
-
- return waitForActionMenuRecordSubject(observable, options)
-}
-
-export function waitForActionMenuRecordSubject(
- subject: ReplaySubject | Observable,
- {
- threadId,
- role,
- state,
- previousState,
- timeoutMs = 10000,
- }: {
- threadId?: string
- role?: ActionMenuRole
- state?: ActionMenuState
- previousState?: ActionMenuState | null
- timeoutMs?: number
- }
-) {
- const observable = subject instanceof ReplaySubject ? subject.asObservable() : subject
- return firstValueFrom(
- observable.pipe(
- filter((e) => previousState === undefined || e.payload.previousState === previousState),
- filter((e) => threadId === undefined || e.payload.actionMenuRecord.threadId === threadId),
- filter((e) => role === undefined || e.payload.actionMenuRecord.role === role),
- filter((e) => state === undefined || e.payload.actionMenuRecord.state === state),
- timeout(timeoutMs),
- catchError(() => {
- throw new Error(
- `ActionMenuStateChangedEvent event not emitted within specified timeout: {
- previousState: ${previousState},
- threadId: ${threadId},
- state: ${state}
- }`
- )
- }),
- map((e) => e.payload.actionMenuRecord)
- )
- )
-}
diff --git a/packages/indy-vdr/tests/setup.ts b/packages/indy-vdr/tests/setup.ts
deleted file mode 100644
index 4955aeb601..0000000000
--- a/packages/indy-vdr/tests/setup.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import 'reflect-metadata'
-
-jest.setTimeout(20000)
From 552d3a3fbaa4f1cdc9d721f90009acda90a66d1a Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Wed, 14 Dec 2022 14:04:04 +0100
Subject: [PATCH 05/22] feat: create IndyVdrPool Service
Signed-off-by: vickysomtee
---
packages/indy-vdr/package.json | 2 +-
.../indy-vdr/src/error/IndyVdrPoolError.ts | 7 +
packages/indy-vdr/src/index.ts | 8 +-
packages/indy-vdr/src/pool/IndyVdrPool.ts | 153 +++++++++++-
.../indy-vdr/src/pool/IndyVdrPoolService.ts | 230 ++++++++++++++++++
packages/indy-vdr/src/pool/index.ts | 2 +-
6 files changed, 387 insertions(+), 15 deletions(-)
create mode 100644 packages/indy-vdr/src/error/IndyVdrPoolError.ts
create mode 100644 packages/indy-vdr/src/pool/IndyVdrPoolService.ts
diff --git a/packages/indy-vdr/package.json b/packages/indy-vdr/package.json
index e5673abf75..4e73444465 100644
--- a/packages/indy-vdr/package.json
+++ b/packages/indy-vdr/package.json
@@ -34,7 +34,7 @@
},
"devDependencies": {
"@aries-framework/node": "0.2.5",
- "indy-vdr-test-shared": "^0.1.2",
+ "indy-vdr-test-shared": "^0.1.13",
"reflect-metadata": "^0.1.13",
"rimraf": "~3.0.2",
"typescript": "~4.3.0"
diff --git a/packages/indy-vdr/src/error/IndyVdrPoolError.ts b/packages/indy-vdr/src/error/IndyVdrPoolError.ts
new file mode 100644
index 0000000000..a7d26ec8e4
--- /dev/null
+++ b/packages/indy-vdr/src/error/IndyVdrPoolError.ts
@@ -0,0 +1,7 @@
+import { AriesFrameworkError } from '@aries-framework/core'
+
+export class IndyVdrPoolError extends AriesFrameworkError {
+ public constructor(message: string, { cause }: { cause?: Error } = {}) {
+ super(message, { cause })
+ }
+}
diff --git a/packages/indy-vdr/src/index.ts b/packages/indy-vdr/src/index.ts
index 79d8efe525..6e9d822ced 100644
--- a/packages/indy-vdr/src/index.ts
+++ b/packages/indy-vdr/src/index.ts
@@ -1,5 +1,5 @@
try {
- require("indy-vdr-test-nodejs");
- } catch (error) {
- throw new Error("Error registering nodejs bindings for Indy VDR");
- }
\ No newline at end of file
+ require('indy-vdr-test-nodejs')
+} catch (error) {
+ throw new Error('Error registering nodejs bindings for Indy VDR')
+}
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index 916e9dfdb0..e17c3dd960 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -1,13 +1,28 @@
-import type { Logger } from '@aries-framework/core'
-import {IndyPool} from '@aries-framework/core'
-import { PoolCreate } from 'indy-vdr-test-shared'
+import { Logger, TypedArrayEncoder } from '@aries-framework/core'
-interface TransactionAuthorAgreement {
- version: `${number}.${number}` | `${number}`
+import * as IndyVdr from 'indy-vdr-test-shared'
+import { AgentDependencies, AgentContext, LedgerError, AriesFrameworkError, Key } from '@aries-framework/core'
+
+export interface TransactionAuthorAgreement {
+ version?: `${number}.${number}` | `${number}`
acceptanceMechanism: string
}
-interface IndyVdrPoolConfig {
+export interface AuthorAgreement {
+ digest: string
+ version: string
+ text: string
+ ratification_ts: number
+ acceptanceMechanisms: AcceptanceMechanisms
+}
+
+export interface AcceptanceMechanisms {
+ aml: string[]
+ amlContext: string
+ version: string
+}
+
+export interface IndyVdrPoolConfig {
genesisTransactions: string
isProduction: boolean
indyNamespace: string
@@ -15,10 +30,11 @@ interface IndyVdrPoolConfig {
}
export class IndyVdrPool {
- // private pool: IndyPool // Not sure this is the correct type for the pool
+ // indyVdr?: typeof IndyVdr
+ private _pool?: IndyVdr.IndyVdrPool
private logger: Logger
private poolConfig: IndyVdrPoolConfig
- private poolConnected?: Promise
+ public authorAgreement?: AuthorAgreement | null
constructor(poolConfig: IndyVdrPoolConfig, logger: Logger) {
this.logger = logger
@@ -33,7 +49,126 @@ export class IndyVdrPool {
return this.poolConfig
}
+ public get id() {
+ return this.pool.handle
+ }
+
public async connect() {
- // this.pool = new PoolCreate({parameters: {}})
+ this._pool = new IndyVdr.PoolCreate({
+ parameters: {
+ transactions: this.config.genesisTransactions,
+ },
+ })
+
+ return this.pool.handle
+ }
+
+ private get pool(): IndyVdr.IndyVdrPool {
+ if (!this._pool) {
+ // TODO: create custom IndyVdrError
+ throw new AriesFrameworkError('Pool is not connected. Make sure to call .connect() first')
+ }
+
+ return this._pool
+ }
+
+ public async close() {
+ this.pool?.close()
+ }
+
+ public async submitWriteRequest(agentContext: AgentContext, request: IndyVdr.IndyVdrRequest, signingKey: Key) {
+ await this.appendTaa(request)
+
+ const signature = await agentContext.wallet.sign({
+ data: TypedArrayEncoder.fromString(request.signatureInput),
+ key: signingKey
+ })
+
+ request.setSignature({
+ signature
+ })
+
+ await this.pool.submitRequest(request)
+ }
+
+ public async submitReadRequest(request: Request) {
+ return await this.pool.submitRequest(request)
+ }
+
+ private async appendTaa(request: IndyVdr.IndyVdrRequest) {
+ const authorAgreement = await this.getTransactionAuthorAgreement()
+ const poolTaa = this.config.transactionAuthorAgreement
+
+ // If ledger does not have TAA, we can just send request
+ if (authorAgreement == null) {
+ return request
+ }
+
+ // Ledger has taa but user has not specified which one to use
+ if (!poolTaa) {
+ throw new LedgerError(
+ `Please, specify a transaction author agreement with version and acceptance mechanism. ${JSON.stringify(
+ authorAgreement
+ )}`
+ )
+ }
+
+ // Throw an error if the pool doesn't have the specified version and acceptance mechanism
+ if (
+ authorAgreement.version !== poolTaa.version ||
+ !authorAgreement.acceptanceMechanisms.aml.includes(poolTaa.acceptanceMechanism)
+ ) {
+ // Throw an error with a helpful message
+ const errMessage = `Unable to satisfy matching TAA with mechanism ${JSON.stringify(
+ poolTaa.acceptanceMechanism
+ )} and version ${poolTaa.version} in pool.\n Found ${JSON.stringify(
+ authorAgreement.acceptanceMechanisms.aml
+ )} and version ${authorAgreement.version} in pool.`
+ throw new LedgerError(errMessage)
+ }
+
+ const acceptance = IndyVdr.indyVdr.prepareTxnAuthorAgreementAcceptance({
+ text: authorAgreement.text,
+ version: authorAgreement.version,
+ taaDigest: authorAgreement.digest,
+ time: Math.floor(new Date().getTime() / 1000),
+ acceptanceMechanismType: poolTaa.acceptanceMechanism,
+ })
+
+ request.setTransactionAuthorAgreementAcceptance({ acceptance })
+ }
+
+ private async getTransactionAuthorAgreement(
+ ): Promise {
+ // TODO Replace this condition with memoization
+ if (this.authorAgreement !== undefined) {
+ return this.authorAgreement
+ }
+
+ const taaRequest =new IndyVdr.GetTransactionAuthorAgreementRequest({})
+ const taaResponse = await this.submitReadRequest(taaRequest)
+
+ const acceptanceMechanismRequest = new IndyVdr.GetAcceptanceMechanismsRequest({})
+ const acceptanceMechanismResponse = await this.submitReadRequest(
+ acceptanceMechanismRequest
+ )
+
+ const taaData = taaResponse.result.data
+
+ // TAA can be null
+ if (taaData == null) {
+ this.authorAgreement = null
+ return null
+ }
+
+ // If TAA is not null, we can be sure AcceptanceMechanisms is also not null
+ const authorAgreement = taaData as Omit
+ const acceptanceMechanisms = acceptanceMechanismResponse.result.data as AcceptanceMechanisms
+ this.authorAgreement = {
+ ...authorAgreement,
+ acceptanceMechanisms,
+ }
+
+ return this.authorAgreement
}
}
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
new file mode 100644
index 0000000000..9e1460102e
--- /dev/null
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -0,0 +1,230 @@
+import type { AgentContext } from '../../../core/src/agent'
+import { GetNymRequest, indyVdr,} from 'indy-vdr-test-shared'
+
+import {
+ AgentDependencies,
+ Logger,
+ InjectionSymbols,
+ injectable,
+ inject,
+ LedgerError,
+ LedgerNotConfiguredError,
+ LedgerNotFoundError,
+} from '@aries-framework/core'
+
+import { IndyVdrError, GetNymResponse } from 'indy-vdr-test-shared'
+import { CacheRepository, PersistedLruCache } from '../../../core/src/cache'
+import { IndySdkError } from '../../../core/src/error'
+import { isSelfCertifiedDid } from '../../../core/src/utils/did'
+import { isIndyError } from '../../../core/src/utils/indyError'
+import { allSettled, onlyFulfilled, onlyRejected } from '../../../core/src/utils/promises'
+import { assertIndyWallet } from '../../../core/src/wallet/util/assertIndyWallet'
+import { IndyVdrPool } from './IndyVdrPool'
+
+export const DID_POOL_CACHE_ID = 'DID_POOL_CACHE'
+export const DID_POOL_CACHE_LIMIT = 500
+export interface CachedDidResponse {
+ nymResponse: {
+ did: string
+ verkey: string
+ }
+ poolId?: string
+}
+@injectable()
+export class IndyVdrPoolService {
+ public pools: IndyVdrPool[] = []
+ private logger: Logger
+ private indyVdr!: typeof indyVdr
+ private agentDependencies: AgentDependencies
+ private didCache: PersistedLruCache
+
+ public constructor(
+ cacheRepository: CacheRepository,
+ @inject(InjectionSymbols.AgentDependencies) agentDependencies: AgentDependencies,
+ @inject(InjectionSymbols.Logger) logger: Logger
+ ) {
+ this.logger = logger
+ this.agentDependencies = agentDependencies
+
+ this.didCache = new PersistedLruCache(DID_POOL_CACHE_ID, DID_POOL_CACHE_LIMIT, cacheRepository)
+ }
+
+ /**
+ * Create connections to all ledger pools
+ */
+ public async connectToPools() {
+ const handleArray: number[] = []
+ // Sequentially connect to pools so we don't use up too many resources connecting in parallel
+ for (const pool of this.pools) {
+ this.logger.debug(`Connecting to pool: ${pool.id}`)
+ const poolHandle = await pool.connect()
+ this.logger.debug(`Finished connection to pool: ${pool.id}`)
+ handleArray.push(poolHandle)
+ }
+ return handleArray
+ }
+
+ /**
+ * Get the most appropriate pool for the given did. The algorithm is based on the approach as described in this document:
+ * https://docs.google.com/document/d/109C_eMsuZnTnYe2OAd02jAts1vC4axwEKIq7_4dnNVA/edit
+ */
+ public async getPoolForDid(agentContext: AgentContext, did: string): Promise<{ pool: IndyVdrPool }> {
+ // Check if the did starts with did:indy
+ if (did.startsWith('did:indy')) {
+ const nameSpace = did.split(':')[2]
+
+ const pool = this.pools.find((pool) => pool.IndyNamespace === nameSpace)
+
+ if (pool) return { pool }
+
+ throw new LedgerNotFoundError('Pool not found')
+ } else {
+ return await this.getPoolForLegacyDid(agentContext, did)
+ }
+ }
+
+ private async getPoolForLegacyDid(
+ agentContext: AgentContext,
+ did: string
+ ): Promise<{ pool: IndyVdrPool; did: string }> {
+ const pools = this.pools
+
+ if (pools.length === 0) {
+ throw new LedgerNotConfiguredError(
+ "No indy ledgers configured. Provide at least one pool configuration in the 'indyLedgers' agent configuration"
+ )
+ }
+
+ const cachedNymResponse = await this.didCache.get(agentContext, did)
+ const pool = this.pools.find((pool) => pool.config.indyNamespace === cachedNymResponse?.poolId)
+
+ // If we have the nym response with associated pool in the cache, we'll use that
+ if (cachedNymResponse && pool) {
+ this.logger.trace(`Found ledger id '${pool.id}' for did '${did}' in cache`)
+ return { did: cachedNymResponse.nymResponse.did, pool }
+ }
+
+ const { successful, rejected } = await this.getSettledDidResponsesFromPools(did, pools)
+
+ if (successful.length === 0) {
+ const allNotFound = rejected.every((e) => e.reason instanceof LedgerNotFoundError)
+ const rejectedOtherThanNotFound = rejected.filter((e) => !(e.reason instanceof LedgerNotFoundError))
+
+ // All ledgers returned response that the did was not found
+ if (allNotFound) {
+ throw new LedgerNotFoundError(`Did '${did}' not found on any of the ledgers (total ${this.pools.length}).`)
+ }
+
+ // one or more of the ledgers returned an unknown error
+ throw new LedgerError(
+ `Unknown error retrieving did '${did}' from '${rejectedOtherThanNotFound.length}' of '${pools.length}' ledgers`,
+ { cause: rejectedOtherThanNotFound[0].reason }
+ )
+ }
+
+ // If there are self certified DIDs we always prefer it over non self certified DIDs
+ // We take the first self certifying DID as we take the order in the
+ // indyLedgers config as the order of preference of ledgers
+ let value = successful.find((response) => isSelfCertifiedDid(response.value.did.nymResponse.did, response.value.did.nymResponse.verkey))?.value
+
+ if (!value) {
+ // Split between production and nonProduction ledgers. If there is at least one
+ // successful response from a production ledger, only keep production ledgers
+ // otherwise we only keep the non production ledgers.
+ const production = successful.filter((s) => s.value.pool.config.isProduction)
+ const nonProduction = successful.filter((s) => !s.value.pool.config.isProduction)
+ const productionOrNonProduction = production.length >= 1 ? production : nonProduction
+
+ // We take the first value as we take the order in the indyLedgers config as
+ // the order of preference of ledgers
+ value = productionOrNonProduction[0].value
+ }
+
+ await this.didCache.set(agentContext, did, {
+ nymResponse: {
+ did: value.did.nymResponse.did,
+ verkey: value.did.nymResponse.verkey,
+ },
+ })
+ return { pool: value.pool, did: value.did.nymResponse.did }
+ }
+
+ private async getSettledDidResponsesFromPools(did: string, pools: IndyVdrPool[]) {
+ this.logger.trace(`Retrieving did '${did}' from ${pools.length} ledgers`)
+ const didResponses = await allSettled(pools.map((pool) => this.getDidFromPool(did, pool)))
+
+ const successful = onlyFulfilled(didResponses)
+ this.logger.trace(`Retrieved ${successful.length} responses from ledgers for did '${did}'`)
+
+ const rejected = onlyRejected(didResponses)
+
+ return {
+ rejected,
+ successful,
+ }
+ }
+
+ /**
+ * Get the most appropriate pool for the given indyNamespace
+ */
+ public getPoolForNamespace(indyNamespace: string) {
+ if (this.pools.length === 0) {
+ throw new LedgerNotConfiguredError(
+ "No indy ledgers configured. Provide at least one pool configuration in the 'indyLedgers' agent configuration"
+ )
+ }
+
+ if (!indyNamespace) {
+ this.logger.warn('Not passing the indyNamespace is deprecated and will be removed in the future version.')
+ return this.pools[0]
+ }
+
+ const pool = this.pools.find((pool) => pool.config.indyNamespace === indyNamespace) // TODO check if this is corect
+
+ if (!pool) {
+ throw new LedgerNotFoundError(`No ledgers found for IndyNamespace '${indyNamespace}'.`)
+ }
+
+ return pool
+ }
+
+ private async getDidFromPool(did: string, pool: IndyVdrPool): Promise {
+ try {
+ this.logger.trace(`Get public did '${did}' from ledger '${pool.id}'`)
+ const request = await new GetNymRequest({ dest: did })
+
+ this.logger.trace(`Submitting get did request for did '${did}' to ledger '${pool.id}'`)
+ const response = await pool.submitReadRequest(request)
+
+ if (!response.result.data) {
+ throw new LedgerError('Not Found')
+ }
+
+ const result = JSON.parse(response.result.data)
+
+ this.logger.trace(`Retrieved did '${did}' from ledger '${pool.id}'`, result)
+
+ return {
+ did: result,
+ pool,
+ response,
+ }
+ } catch (error) {
+ this.logger.trace(`Error retrieving did '${did}' from ledger '${pool.id}'`, {
+ error,
+ did,
+ })
+ if (isIndyError(error, 'LedgerNotFound')) {
+ throw new LedgerNotFoundError(`Did '${did}' not found on ledger ${pool.id}`)
+ } else {
+ throw isIndyError(error) ? new IndySdkError(error) : error
+ }
+ }
+ }
+}
+
+export interface PublicDidRequest {
+ did: CachedDidResponse
+ pool: IndyVdrPool
+ response: GetNymResponse
+}
diff --git a/packages/indy-vdr/src/pool/index.ts b/packages/indy-vdr/src/pool/index.ts
index a10a471490..8c09951384 100644
--- a/packages/indy-vdr/src/pool/index.ts
+++ b/packages/indy-vdr/src/pool/index.ts
@@ -1,2 +1,2 @@
-import * as IndyVdr from 'indy-vdr-test-shared';
+export * from './IndyVdrPool'
From 3cb42597e2041f6e618aecd96ad77ec49b5f422a Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Thu, 15 Dec 2022 21:23:18 +0100
Subject: [PATCH 06/22] feat: created the IndyVdrNotFoundError
Signed-off-by: vickysomtee
---
.../src/error/{IndyVdrPoolError.ts => IndyVdrError.ts} | 2 +-
packages/indy-vdr/src/error/IndyVdrNotFound.ts | 7 +++++++
packages/indy-vdr/src/error/index.ts | 2 ++
3 files changed, 10 insertions(+), 1 deletion(-)
rename packages/indy-vdr/src/error/{IndyVdrPoolError.ts => IndyVdrError.ts} (74%)
create mode 100644 packages/indy-vdr/src/error/IndyVdrNotFound.ts
create mode 100644 packages/indy-vdr/src/error/index.ts
diff --git a/packages/indy-vdr/src/error/IndyVdrPoolError.ts b/packages/indy-vdr/src/error/IndyVdrError.ts
similarity index 74%
rename from packages/indy-vdr/src/error/IndyVdrPoolError.ts
rename to packages/indy-vdr/src/error/IndyVdrError.ts
index a7d26ec8e4..501f428640 100644
--- a/packages/indy-vdr/src/error/IndyVdrPoolError.ts
+++ b/packages/indy-vdr/src/error/IndyVdrError.ts
@@ -1,6 +1,6 @@
import { AriesFrameworkError } from '@aries-framework/core'
-export class IndyVdrPoolError extends AriesFrameworkError {
+export class IndyVdrError extends AriesFrameworkError {
public constructor(message: string, { cause }: { cause?: Error } = {}) {
super(message, { cause })
}
diff --git a/packages/indy-vdr/src/error/IndyVdrNotFound.ts b/packages/indy-vdr/src/error/IndyVdrNotFound.ts
new file mode 100644
index 0000000000..09bcc2277c
--- /dev/null
+++ b/packages/indy-vdr/src/error/IndyVdrNotFound.ts
@@ -0,0 +1,7 @@
+import { IndyVdrError } from "./IndyVdrError"
+
+export class IndyVdrNotFoundError extends IndyVdrError {
+ public constructor(message: string, { cause }: { cause?: Error } = {}) {
+ super(message, { cause })
+ }
+ }
\ No newline at end of file
diff --git a/packages/indy-vdr/src/error/index.ts b/packages/indy-vdr/src/error/index.ts
new file mode 100644
index 0000000000..627a3517b1
--- /dev/null
+++ b/packages/indy-vdr/src/error/index.ts
@@ -0,0 +1,2 @@
+export * from './IndyVdrError'
+export * from './IndyVdrNotFound'
\ No newline at end of file
From 8794d1e882c9b946fc07dce0771572091c45bb13 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Tue, 20 Dec 2022 10:49:36 +0100
Subject: [PATCH 07/22] refactor: IndyVdr package Work Funded by the Government
of Ontario
Signed-off-by: vickysomtee
---
packages/indy-vdr/src/pool/DidIdentifier.ts | 1 +
packages/indy-vdr/src/pool/IndyVdrPool.ts | 38 ++++----
.../indy-vdr/src/pool/IndyVdrPoolService.ts | 91 ++++++++++---------
packages/indy-vdr/src/utils/did.ts | 65 +++++++++++++
packages/indy-vdr/src/utils/promises.ts | 44 +++++++++
5 files changed, 176 insertions(+), 63 deletions(-)
create mode 100644 packages/indy-vdr/src/pool/DidIdentifier.ts
create mode 100644 packages/indy-vdr/src/utils/did.ts
create mode 100644 packages/indy-vdr/src/utils/promises.ts
diff --git a/packages/indy-vdr/src/pool/DidIdentifier.ts b/packages/indy-vdr/src/pool/DidIdentifier.ts
new file mode 100644
index 0000000000..39384a2c8d
--- /dev/null
+++ b/packages/indy-vdr/src/pool/DidIdentifier.ts
@@ -0,0 +1 @@
+export const DID_INDY_REGEX = /^did:indy:((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)):([1-9A-HJ-NP-Za-km-z]{21,22})$/
\ No newline at end of file
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index e17c3dd960..445fc30d87 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -1,7 +1,9 @@
-import { Logger, TypedArrayEncoder } from '@aries-framework/core'
-
import * as IndyVdr from 'indy-vdr-test-shared'
-import { AgentDependencies, AgentContext, LedgerError, AriesFrameworkError, Key } from '@aries-framework/core'
+import { GetTransactionAuthorAgreementRequest, GetAcceptanceMechanismsRequest, PoolCreate, IndyVdrRequest, IndyVdrPool as indyVdrPool, indyVdr } from 'indy-vdr-test-shared'
+import { Logger, TypedArrayEncoder, AgentContext, AriesFrameworkError, Key } from '@aries-framework/core'
+
+import { IndyVdrError, IndyVdrNotFoundError } from '../error'
+
export interface TransactionAuthorAgreement {
version?: `${number}.${number}` | `${number}`
@@ -31,7 +33,7 @@ export interface IndyVdrPoolConfig {
export class IndyVdrPool {
// indyVdr?: typeof IndyVdr
- private _pool?: IndyVdr.IndyVdrPool
+ private _pool?: indyVdrPool
private logger: Logger
private poolConfig: IndyVdrPoolConfig
public authorAgreement?: AuthorAgreement | null
@@ -41,7 +43,7 @@ export class IndyVdrPool {
this.poolConfig = poolConfig
}
- public get IndyNamespace(): string {
+ public get indyNamespace(): string {
return this.poolConfig.indyNamespace
}
@@ -49,12 +51,8 @@ export class IndyVdrPool {
return this.poolConfig
}
- public get id() {
- return this.pool.handle
- }
-
public async connect() {
- this._pool = new IndyVdr.PoolCreate({
+ this._pool = new PoolCreate({
parameters: {
transactions: this.config.genesisTransactions,
},
@@ -63,7 +61,7 @@ export class IndyVdrPool {
return this.pool.handle
}
- private get pool(): IndyVdr.IndyVdrPool {
+ private get pool(): indyVdrPool {
if (!this._pool) {
// TODO: create custom IndyVdrError
throw new AriesFrameworkError('Pool is not connected. Make sure to call .connect() first')
@@ -76,7 +74,7 @@ export class IndyVdrPool {
this.pool?.close()
}
- public async submitWriteRequest(agentContext: AgentContext, request: IndyVdr.IndyVdrRequest, signingKey: Key) {
+ public async submitWriteRequest(agentContext: AgentContext, request: Request, signingKey: Key) {
await this.appendTaa(request)
const signature = await agentContext.wallet.sign({
@@ -88,14 +86,14 @@ export class IndyVdrPool {
signature
})
- await this.pool.submitRequest(request)
+ return await this.pool.submitRequest(request)
}
- public async submitReadRequest(request: Request) {
+ public async submitReadRequest(request: Request) {
return await this.pool.submitRequest(request)
}
- private async appendTaa(request: IndyVdr.IndyVdrRequest) {
+ private async appendTaa(request: IndyVdrRequest) {
const authorAgreement = await this.getTransactionAuthorAgreement()
const poolTaa = this.config.transactionAuthorAgreement
@@ -106,7 +104,7 @@ export class IndyVdrPool {
// Ledger has taa but user has not specified which one to use
if (!poolTaa) {
- throw new LedgerError(
+ throw new IndyVdrError(
`Please, specify a transaction author agreement with version and acceptance mechanism. ${JSON.stringify(
authorAgreement
)}`
@@ -124,10 +122,10 @@ export class IndyVdrPool {
)} and version ${poolTaa.version} in pool.\n Found ${JSON.stringify(
authorAgreement.acceptanceMechanisms.aml
)} and version ${authorAgreement.version} in pool.`
- throw new LedgerError(errMessage)
+ throw new IndyVdrError(errMessage)
}
- const acceptance = IndyVdr.indyVdr.prepareTxnAuthorAgreementAcceptance({
+ const acceptance = indyVdr.prepareTxnAuthorAgreementAcceptance({
text: authorAgreement.text,
version: authorAgreement.version,
taaDigest: authorAgreement.digest,
@@ -145,10 +143,10 @@ export class IndyVdrPool {
return this.authorAgreement
}
- const taaRequest =new IndyVdr.GetTransactionAuthorAgreementRequest({})
+ const taaRequest = new GetTransactionAuthorAgreementRequest({})
const taaResponse = await this.submitReadRequest(taaRequest)
- const acceptanceMechanismRequest = new IndyVdr.GetAcceptanceMechanismsRequest({})
+ const acceptanceMechanismRequest = new GetAcceptanceMechanismsRequest({})
const acceptanceMechanismResponse = await this.submitReadRequest(
acceptanceMechanismRequest
)
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
index 9e1460102e..d06c196d78 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -1,40 +1,35 @@
-import type { AgentContext } from '../../../core/src/agent'
-import { GetNymRequest, indyVdr,} from 'indy-vdr-test-shared'
+import { GetNymRequest, GetNymResponse } from 'indy-vdr-test-shared'
import {
AgentDependencies,
Logger,
InjectionSymbols,
injectable,
+ AgentContext,
inject,
- LedgerError,
LedgerNotConfiguredError,
- LedgerNotFoundError,
} from '@aries-framework/core'
-import { IndyVdrError, GetNymResponse } from 'indy-vdr-test-shared'
+import { DID_INDY_REGEX } from './DidIdentifier'
import { CacheRepository, PersistedLruCache } from '../../../core/src/cache'
-import { IndySdkError } from '../../../core/src/error'
-import { isSelfCertifiedDid } from '../../../core/src/utils/did'
-import { isIndyError } from '../../../core/src/utils/indyError'
-import { allSettled, onlyFulfilled, onlyRejected } from '../../../core/src/utils/promises'
-import { assertIndyWallet } from '../../../core/src/wallet/util/assertIndyWallet'
+import { isSelfCertifiedDid } from '../utils/did'
+import { allSettled, onlyFulfilled, onlyRejected } from '../utils/promises'
import { IndyVdrPool } from './IndyVdrPool'
+import { IndyVdrError, IndyVdrNotFoundError } from '../error'
-export const DID_POOL_CACHE_ID = 'DID_POOL_CACHE'
+export const INDY_VDR_LEGACY_DID_POOL_CACHE_ID = 'INDY_VDR_LEGACY_DID_POOL_CACHE'
export const DID_POOL_CACHE_LIMIT = 500
export interface CachedDidResponse {
nymResponse: {
did: string
verkey: string
}
- poolId?: string
+ indyNamespace: string
}
@injectable()
export class IndyVdrPoolService {
public pools: IndyVdrPool[] = []
private logger: Logger
- private indyVdr!: typeof indyVdr
private agentDependencies: AgentDependencies
private didCache: PersistedLruCache
@@ -46,7 +41,7 @@ export class IndyVdrPoolService {
this.logger = logger
this.agentDependencies = agentDependencies
- this.didCache = new PersistedLruCache(DID_POOL_CACHE_ID, DID_POOL_CACHE_LIMIT, cacheRepository)
+ this.didCache = new PersistedLruCache(INDY_VDR_LEGACY_DID_POOL_CACHE_ID, DID_POOL_CACHE_LIMIT, cacheRepository)
}
/**
@@ -56,28 +51,38 @@ export class IndyVdrPoolService {
const handleArray: number[] = []
// Sequentially connect to pools so we don't use up too many resources connecting in parallel
for (const pool of this.pools) {
- this.logger.debug(`Connecting to pool: ${pool.id}`)
+ this.logger.debug(`Connecting to pool: ${pool.indyNamespace}`)
const poolHandle = await pool.connect()
- this.logger.debug(`Finished connection to pool: ${pool.id}`)
+ this.logger.debug(`Finished connection to pool: ${pool.indyNamespace}`)
handleArray.push(poolHandle)
}
return handleArray
}
/**
- * Get the most appropriate pool for the given did. The algorithm is based on the approach as described in this document:
+ * Get the most appropriate pool for the given did.
+ * If the did is a qualified indy did, the pool will be determined based on the namespace.
+ * If it is a legacy unqualified indy did, the pool will be determined based on the algorithm as described in this document:
* https://docs.google.com/document/d/109C_eMsuZnTnYe2OAd02jAts1vC4axwEKIq7_4dnNVA/edit
*/
- public async getPoolForDid(agentContext: AgentContext, did: string): Promise<{ pool: IndyVdrPool }> {
+ public async getPoolForDid(agentContext: AgentContext, did: string): Promise< IndyVdrPool > {
// Check if the did starts with did:indy
+ const match = did.match(DID_INDY_REGEX)
+
+ // if (match) {
+ // const [, namespace] = match
+ // } else {
+ // // legacy way
+ // }
+
if (did.startsWith('did:indy')) {
const nameSpace = did.split(':')[2]
- const pool = this.pools.find((pool) => pool.IndyNamespace === nameSpace)
+ const pool = this.pools.find((pool) => pool.indyNamespace === nameSpace)
- if (pool) return { pool }
+ if (pool) return pool
- throw new LedgerNotFoundError('Pool not found')
+ throw new IndyVdrNotFoundError('Pool not found')
} else {
return await this.getPoolForLegacyDid(agentContext, did)
}
@@ -86,7 +91,7 @@ export class IndyVdrPoolService {
private async getPoolForLegacyDid(
agentContext: AgentContext,
did: string
- ): Promise<{ pool: IndyVdrPool; did: string }> {
+ ): Promise {
const pools = this.pools
if (pools.length === 0) {
@@ -96,27 +101,27 @@ export class IndyVdrPoolService {
}
const cachedNymResponse = await this.didCache.get(agentContext, did)
- const pool = this.pools.find((pool) => pool.config.indyNamespace === cachedNymResponse?.poolId)
+ const pool = this.pools.find((pool) => pool.indyNamespace === cachedNymResponse?.indyNamespace)
// If we have the nym response with associated pool in the cache, we'll use that
if (cachedNymResponse && pool) {
- this.logger.trace(`Found ledger id '${pool.id}' for did '${did}' in cache`)
- return { did: cachedNymResponse.nymResponse.did, pool }
+ this.logger.trace(`Found ledger id '${pool.indyNamespace}' for did '${did}' in cache`)
+ return pool
}
const { successful, rejected } = await this.getSettledDidResponsesFromPools(did, pools)
if (successful.length === 0) {
- const allNotFound = rejected.every((e) => e.reason instanceof LedgerNotFoundError)
- const rejectedOtherThanNotFound = rejected.filter((e) => !(e.reason instanceof LedgerNotFoundError))
+ const allNotFound = rejected.every((e) => e.reason instanceof IndyVdrNotFoundError)
+ const rejectedOtherThanNotFound = rejected.filter((e) => !(e.reason instanceof IndyVdrNotFoundError))
// All ledgers returned response that the did was not found
if (allNotFound) {
- throw new LedgerNotFoundError(`Did '${did}' not found on any of the ledgers (total ${this.pools.length}).`)
+ throw new IndyVdrNotFoundError(`Did '${did}' not found on any of the ledgers (total ${this.pools.length}).`)
}
// one or more of the ledgers returned an unknown error
- throw new LedgerError(
+ throw new IndyVdrError(
`Unknown error retrieving did '${did}' from '${rejectedOtherThanNotFound.length}' of '${pools.length}' ledgers`,
{ cause: rejectedOtherThanNotFound[0].reason }
)
@@ -125,7 +130,9 @@ export class IndyVdrPoolService {
// If there are self certified DIDs we always prefer it over non self certified DIDs
// We take the first self certifying DID as we take the order in the
// indyLedgers config as the order of preference of ledgers
- let value = successful.find((response) => isSelfCertifiedDid(response.value.did.nymResponse.did, response.value.did.nymResponse.verkey))?.value
+ let value = successful.find((response) =>
+ isSelfCertifiedDid(response.value.did.nymResponse.did, response.value.did.nymResponse.verkey)
+ )?.value
if (!value) {
// Split between production and nonProduction ledgers. If there is at least one
@@ -145,8 +152,9 @@ export class IndyVdrPoolService {
did: value.did.nymResponse.did,
verkey: value.did.nymResponse.verkey,
},
+ indyNamespace: value.did.indyNamespace,
})
- return { pool: value.pool, did: value.did.nymResponse.did }
+ return value.pool
}
private async getSettledDidResponsesFromPools(did: string, pools: IndyVdrPool[]) {
@@ -179,10 +187,10 @@ export class IndyVdrPoolService {
return this.pools[0]
}
- const pool = this.pools.find((pool) => pool.config.indyNamespace === indyNamespace) // TODO check if this is corect
+ const pool = this.pools.find((pool) => pool.indyNamespace === indyNamespace)
if (!pool) {
- throw new LedgerNotFoundError(`No ledgers found for IndyNamespace '${indyNamespace}'.`)
+ throw new IndyVdrNotFoundError(`No ledgers found for IndyNamespace '${indyNamespace}'.`)
}
return pool
@@ -190,19 +198,20 @@ export class IndyVdrPoolService {
private async getDidFromPool(did: string, pool: IndyVdrPool): Promise {
try {
- this.logger.trace(`Get public did '${did}' from ledger '${pool.id}'`)
+ this.logger.trace(`Get public did '${did}' from ledger '${pool.indyNamespace}'`)
const request = await new GetNymRequest({ dest: did })
- this.logger.trace(`Submitting get did request for did '${did}' to ledger '${pool.id}'`)
+ this.logger.trace(`Submitting get did request for did '${did}' to ledger '${pool.indyNamespace}'`)
const response = await pool.submitReadRequest(request)
if (!response.result.data) {
- throw new LedgerError('Not Found')
+ // TODO: Set a descriptive message
+ throw new IndyVdrError('Not Found')
}
const result = JSON.parse(response.result.data)
- this.logger.trace(`Retrieved did '${did}' from ledger '${pool.id}'`, result)
+ this.logger.trace(`Retrieved did '${did}' from ledger '${pool.indyNamespace}'`, result)
return {
did: result,
@@ -210,15 +219,11 @@ export class IndyVdrPoolService {
response,
}
} catch (error) {
- this.logger.trace(`Error retrieving did '${did}' from ledger '${pool.id}'`, {
+ this.logger.trace(`Error retrieving did '${did}' from ledger '${pool.indyNamespace}'`, {
error,
did,
})
- if (isIndyError(error, 'LedgerNotFound')) {
- throw new LedgerNotFoundError(`Did '${did}' not found on ledger ${pool.id}`)
- } else {
- throw isIndyError(error) ? new IndySdkError(error) : error
- }
+ throw error
}
}
}
diff --git a/packages/indy-vdr/src/utils/did.ts b/packages/indy-vdr/src/utils/did.ts
new file mode 100644
index 0000000000..a9f2c95d02
--- /dev/null
+++ b/packages/indy-vdr/src/utils/did.ts
@@ -0,0 +1,65 @@
+/**
+ * Based on DidUtils implementation in Aries Framework .NET
+ * @see: https://github.com/hyperledger/aries-framework-dotnet/blob/f90eaf9db8548f6fc831abea917e906201755763/src/Hyperledger.Aries/Utils/DidUtils.cs
+ *
+ * Some context about full verkeys versus abbreviated verkeys:
+ * A standard verkey is 32 bytes, and by default in Indy the DID is chosen as the first 16 bytes of that key, before base58 encoding.
+ * An abbreviated verkey replaces the first 16 bytes of the verkey with ~ when it matches the DID.
+ *
+ * When a full verkey is used to register on the ledger, this is stored as a full verkey on the ledger and also returned from the ledger as a full verkey.
+ * The same applies to an abbreviated verkey. If an abbreviated verkey is used to register on the ledger, this is stored as an abbreviated verkey on the ledger and also returned from the ledger as an abbreviated verkey.
+ *
+ * For this reason we need some methods to check whether verkeys are full or abbreviated, so we can align this with `indy.abbreviateVerkey`
+ *
+ * Aries Framework .NET also abbreviates verkey before sending to ledger:
+ * https://github.com/hyperledger/aries-framework-dotnet/blob/f90eaf9db8548f6fc831abea917e906201755763/src/Hyperledger.Aries/Ledger/DefaultLedgerService.cs#L139-L147
+ */
+
+
+import { TypedArrayEncoder } from '@aries-framework/core'
+
+export const FULL_VERKEY_REGEX = /^[1-9A-HJ-NP-Za-km-z]{43,44}$/
+export const ABBREVIATED_VERKEY_REGEX = /^~[1-9A-HJ-NP-Za-km-z]{21,22}$/
+export const VERKEY_REGEX = new RegExp(`${FULL_VERKEY_REGEX.source}|${ABBREVIATED_VERKEY_REGEX.source}`)
+export const DID_REGEX = /^did:([a-z]+):([a-zA-z\d]+)/
+export const DID_IDENTIFIER_REGEX = /^[a-zA-z\d-]+$/
+
+/**
+ * Check whether the did is a self certifying did. If the verkey is abbreviated this method
+ * will always return true. Make sure that the verkey you pass in this method belongs to the
+ * did passed in
+ *
+ * @return Boolean indicating whether the did is self certifying
+ */
+export function isSelfCertifiedDid(did: string, verkey: string): boolean {
+ // If the verkey is Abbreviated, it means the full verkey
+ // is the did + the verkey
+ if (isAbbreviatedVerkey(verkey)) {
+ return true
+ }
+
+ const didFromVerkey = indyDidFromPublicKeyBase58(verkey)
+
+ if (didFromVerkey === did) {
+ return true
+ }
+
+ return false
+}
+
+export function indyDidFromPublicKeyBase58(publicKeyBase58: string): string {
+ const buffer = TypedArrayEncoder.fromBase58(publicKeyBase58)
+
+ const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16))
+
+ return did
+}
+
+/**
+ * Check a base58 encoded string against a regex expression to determine if it is a valid abbreviated verkey
+ * @param verkey Base58 encoded string representation of an abbreviated verkey
+ * @returns Boolean indicating if the string is a valid abbreviated verkey
+ */
+export function isAbbreviatedVerkey(verkey: string): boolean {
+ return ABBREVIATED_VERKEY_REGEX.test(verkey)
+}
diff --git a/packages/indy-vdr/src/utils/promises.ts b/packages/indy-vdr/src/utils/promises.ts
new file mode 100644
index 0000000000..0e843d73b5
--- /dev/null
+++ b/packages/indy-vdr/src/utils/promises.ts
@@ -0,0 +1,44 @@
+// This file polyfills the allSettled method introduced in ESNext
+
+export type AllSettledFulfilled = {
+ status: 'fulfilled'
+ value: T
+}
+
+export type AllSettledRejected = {
+ status: 'rejected'
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ reason: any
+}
+
+export function allSettled(promises: Promise[]) {
+ return Promise.all(
+ promises.map((p) =>
+ p
+ .then(
+ (value) =>
+ ({
+ status: 'fulfilled',
+ value,
+ } as AllSettledFulfilled)
+ )
+ .catch(
+ (reason) =>
+ ({
+ status: 'rejected',
+ reason,
+ } as AllSettledRejected)
+ )
+ )
+ )
+}
+
+export function onlyFulfilled(entries: Array | AllSettledRejected>) {
+ // We filter for only the rejected values, so we can safely cast the type
+ return entries.filter((e) => e.status === 'fulfilled') as AllSettledFulfilled[]
+}
+
+export function onlyRejected(entries: Array | AllSettledRejected>) {
+ // We filter for only the rejected values, so we can safely cast the type
+ return entries.filter((e) => e.status === 'rejected') as AllSettledRejected[]
+}
From c0f4764119757c8787569564a508212e4688f2df Mon Sep 17 00:00:00 2001
From: Timo Glastra
Date: Tue, 20 Dec 2022 21:55:10 +0800
Subject: [PATCH 08/22] test: add indy-vdr tests
Signed-off-by: Timo Glastra
---
packages/core/tests/helpers.ts | 3 +
packages/indy-vdr/package.json | 7 +-
packages/indy-vdr/src/pool/IndyVdrPool.ts | 54 +++++----
.../indy-vdr/src/pool/IndyVdrPoolService.ts | 51 ++++-----
.../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 103 +++++++++++++++++
packages/indy-vdr/tests/setup.ts | 5 +
yarn.lock | 106 +++++++++++++++++-
7 files changed, 274 insertions(+), 55 deletions(-)
create mode 100644 packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
create mode 100644 packages/indy-vdr/tests/setup.ts
diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts
index a8b89bfaec..8b1a8fa70a 100644
--- a/packages/core/tests/helpers.ts
+++ b/packages/core/tests/helpers.ts
@@ -19,6 +19,7 @@ import type { AutoAcceptProof } from '../src/modules/proofs/models/ProofAutoAcce
import type { CredDef, Schema } from 'indy-sdk'
import type { Observable } from 'rxjs'
+import { readFileSync } from 'fs'
import path from 'path'
import { firstValueFrom, ReplaySubject, Subject } from 'rxjs'
import { catchError, filter, map, timeout } from 'rxjs/operators'
@@ -70,6 +71,8 @@ export const genesisPath = process.env.GENESIS_TXN_PATH
? path.resolve(process.env.GENESIS_TXN_PATH)
: path.join(__dirname, '../../../network/genesis/local-genesis.txn')
+export const genesisTransactions = readFileSync(genesisPath).toString('utf-8')
+
export const publicDidSeed = process.env.TEST_AGENT_PUBLIC_DID_SEED ?? '000000000000000000000000Trustee9'
export { agentDependencies }
diff --git a/packages/indy-vdr/package.json b/packages/indy-vdr/package.json
index 4e73444465..56d34b01b3 100644
--- a/packages/indy-vdr/package.json
+++ b/packages/indy-vdr/package.json
@@ -26,14 +26,15 @@
"dependencies": {
"class-transformer": "0.5.1",
"class-validator": "0.13.1",
- "rxjs": "^7.2.0"
+ "rxjs": "^7.2.0",
+ "indy-vdr-test-shared": "^0.1.3"
},
"peerDependencies": {
- "@aries-framework/core": "0.2.5",
- "indy-vdr-test-shared": "^0.1.2"
+ "@aries-framework/core": "0.2.5"
},
"devDependencies": {
"@aries-framework/node": "0.2.5",
+ "indy-vdr-test-nodejs": "^0.1.3",
"indy-vdr-test-shared": "^0.1.13",
"reflect-metadata": "^0.1.13",
"rimraf": "~3.0.2",
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index 445fc30d87..75f1bed05a 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -1,9 +1,15 @@
-import * as IndyVdr from 'indy-vdr-test-shared'
-import { GetTransactionAuthorAgreementRequest, GetAcceptanceMechanismsRequest, PoolCreate, IndyVdrRequest, IndyVdrPool as indyVdrPool, indyVdr } from 'indy-vdr-test-shared'
-import { Logger, TypedArrayEncoder, AgentContext, AriesFrameworkError, Key } from '@aries-framework/core'
+import type { Logger, AgentContext, Key } from '@aries-framework/core'
+import type { IndyVdrRequest, IndyVdrPool as indyVdrPool } from 'indy-vdr-test-shared'
-import { IndyVdrError, IndyVdrNotFoundError } from '../error'
+import { TypedArrayEncoder, AriesFrameworkError } from '@aries-framework/core'
+import {
+ GetTransactionAuthorAgreementRequest,
+ GetAcceptanceMechanismsRequest,
+ PoolCreate,
+ indyVdr,
+} from 'indy-vdr-test-shared'
+import { IndyVdrError } from '../error'
export interface TransactionAuthorAgreement {
version?: `${number}.${number}` | `${number}`
@@ -19,7 +25,7 @@ export interface AuthorAgreement {
}
export interface AcceptanceMechanisms {
- aml: string[]
+ aml: Record
amlContext: string
version: string
}
@@ -38,7 +44,7 @@ export class IndyVdrPool {
private poolConfig: IndyVdrPoolConfig
public authorAgreement?: AuthorAgreement | null
- constructor(poolConfig: IndyVdrPoolConfig, logger: Logger) {
+ public constructor(poolConfig: IndyVdrPoolConfig, logger: Logger) {
this.logger = logger
this.poolConfig = poolConfig
}
@@ -70,22 +76,31 @@ export class IndyVdrPool {
return this._pool
}
- public async close() {
- this.pool?.close()
+ public close() {
+ if (!this.pool) {
+ throw new IndyVdrError("Can't close pool. Pool is not connected")
+ }
+
+ // FIXME: this method doesn't work??
+ // this.pool.close()
}
- public async submitWriteRequest(agentContext: AgentContext, request: Request, signingKey: Key) {
+ public async submitWriteRequest(
+ agentContext: AgentContext,
+ request: Request,
+ signingKey: Key
+ ) {
await this.appendTaa(request)
-
+
const signature = await agentContext.wallet.sign({
data: TypedArrayEncoder.fromString(request.signatureInput),
- key: signingKey
+ key: signingKey,
})
-
+
request.setSignature({
- signature
+ signature,
})
-
+
return await this.pool.submitRequest(request)
}
@@ -114,7 +129,7 @@ export class IndyVdrPool {
// Throw an error if the pool doesn't have the specified version and acceptance mechanism
if (
authorAgreement.version !== poolTaa.version ||
- !authorAgreement.acceptanceMechanisms.aml.includes(poolTaa.acceptanceMechanism)
+ !authorAgreement.acceptanceMechanisms.aml[poolTaa.acceptanceMechanism]
) {
// Throw an error with a helpful message
const errMessage = `Unable to satisfy matching TAA with mechanism ${JSON.stringify(
@@ -136,20 +151,17 @@ export class IndyVdrPool {
request.setTransactionAuthorAgreementAcceptance({ acceptance })
}
- private async getTransactionAuthorAgreement(
- ): Promise {
+ private async getTransactionAuthorAgreement(): Promise {
// TODO Replace this condition with memoization
if (this.authorAgreement !== undefined) {
return this.authorAgreement
}
- const taaRequest = new GetTransactionAuthorAgreementRequest({})
+ const taaRequest = new GetTransactionAuthorAgreementRequest({})
const taaResponse = await this.submitReadRequest(taaRequest)
const acceptanceMechanismRequest = new GetAcceptanceMechanismsRequest({})
- const acceptanceMechanismResponse = await this.submitReadRequest(
- acceptanceMechanismRequest
- )
+ const acceptanceMechanismResponse = await this.submitReadRequest(acceptanceMechanismRequest)
const taaData = taaResponse.result.data
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
index d06c196d78..5084c0801e 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -1,21 +1,17 @@
-import { GetNymRequest, GetNymResponse } from 'indy-vdr-test-shared'
-
-import {
- AgentDependencies,
- Logger,
- InjectionSymbols,
- injectable,
- AgentContext,
- inject,
- LedgerNotConfiguredError,
-} from '@aries-framework/core'
+import type { IndyVdrPoolConfig } from './IndyVdrPool'
+import type { AgentContext } from '@aries-framework/core'
+import type { GetNymResponse } from 'indy-vdr-test-shared'
+
+import { Logger, InjectionSymbols, injectable, inject, LedgerNotConfiguredError } from '@aries-framework/core'
+import { GetNymRequest } from 'indy-vdr-test-shared'
-import { DID_INDY_REGEX } from './DidIdentifier'
import { CacheRepository, PersistedLruCache } from '../../../core/src/cache'
+import { IndyVdrError, IndyVdrNotFoundError } from '../error'
import { isSelfCertifiedDid } from '../utils/did'
import { allSettled, onlyFulfilled, onlyRejected } from '../utils/promises'
+
+import { DID_INDY_REGEX } from './DidIdentifier'
import { IndyVdrPool } from './IndyVdrPool'
-import { IndyVdrError, IndyVdrNotFoundError } from '../error'
export const INDY_VDR_LEGACY_DID_POOL_CACHE_ID = 'INDY_VDR_LEGACY_DID_POOL_CACHE'
export const DID_POOL_CACHE_LIMIT = 500
@@ -30,20 +26,18 @@ export interface CachedDidResponse {
export class IndyVdrPoolService {
public pools: IndyVdrPool[] = []
private logger: Logger
- private agentDependencies: AgentDependencies
private didCache: PersistedLruCache
- public constructor(
- cacheRepository: CacheRepository,
- @inject(InjectionSymbols.AgentDependencies) agentDependencies: AgentDependencies,
- @inject(InjectionSymbols.Logger) logger: Logger
- ) {
+ public constructor(cacheRepository: CacheRepository, @inject(InjectionSymbols.Logger) logger: Logger) {
this.logger = logger
- this.agentDependencies = agentDependencies
this.didCache = new PersistedLruCache(INDY_VDR_LEGACY_DID_POOL_CACHE_ID, DID_POOL_CACHE_LIMIT, cacheRepository)
}
+ public setPools(poolConfigs: IndyVdrPoolConfig[]) {
+ this.pools = poolConfigs.map((poolConfig) => new IndyVdrPool(poolConfig, this.logger))
+ }
+
/**
* Create connections to all ledger pools
*/
@@ -60,12 +54,12 @@ export class IndyVdrPoolService {
}
/**
- * Get the most appropriate pool for the given did.
- * If the did is a qualified indy did, the pool will be determined based on the namespace.
+ * Get the most appropriate pool for the given did.
+ * If the did is a qualified indy did, the pool will be determined based on the namespace.
* If it is a legacy unqualified indy did, the pool will be determined based on the algorithm as described in this document:
* https://docs.google.com/document/d/109C_eMsuZnTnYe2OAd02jAts1vC4axwEKIq7_4dnNVA/edit
*/
- public async getPoolForDid(agentContext: AgentContext, did: string): Promise< IndyVdrPool > {
+ public async getPoolForDid(agentContext: AgentContext, did: string): Promise {
// Check if the did starts with did:indy
const match = did.match(DID_INDY_REGEX)
@@ -80,7 +74,7 @@ export class IndyVdrPoolService {
const pool = this.pools.find((pool) => pool.indyNamespace === nameSpace)
- if (pool) return pool
+ if (pool) return pool
throw new IndyVdrNotFoundError('Pool not found')
} else {
@@ -88,10 +82,7 @@ export class IndyVdrPoolService {
}
}
- private async getPoolForLegacyDid(
- agentContext: AgentContext,
- did: string
- ): Promise {
+ private async getPoolForLegacyDid(agentContext: AgentContext, did: string): Promise {
const pools = this.pools
if (pools.length === 0) {
@@ -106,7 +97,7 @@ export class IndyVdrPoolService {
// If we have the nym response with associated pool in the cache, we'll use that
if (cachedNymResponse && pool) {
this.logger.trace(`Found ledger id '${pool.indyNamespace}' for did '${did}' in cache`)
- return pool
+ return pool
}
const { successful, rejected } = await this.getSettledDidResponsesFromPools(did, pools)
@@ -154,7 +145,7 @@ export class IndyVdrPoolService {
},
indyNamespace: value.did.indyNamespace,
})
- return value.pool
+ return value.pool
}
private async getSettledDidResponsesFromPools(did: string, pools: IndyVdrPool[]) {
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
new file mode 100644
index 0000000000..59e6dc89b1
--- /dev/null
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -0,0 +1,103 @@
+import type { CacheRecord } from '../../core/src/cache'
+
+import {
+ EventEmitter,
+ IndyWallet,
+ Key,
+ KeyType,
+ KeyType,
+ SigningProviderRegistry,
+ TypedArrayEncoder,
+} from '@aries-framework/core'
+import { GetNymRequest, NymRequest } from 'indy-vdr-test-shared'
+import { Subject } from 'rxjs'
+
+import { CacheRepository } from '../../core/src/cache'
+import { IndyStorageService } from '../../core/src/storage/IndyStorageService'
+import { agentDependencies, genesisTransactions, getAgentConfig, getAgentContext } from '../../core/tests/helpers'
+import testLogger from '../../core/tests/logger'
+import { IndyVdrPool } from '../src/pool'
+import { IndyVdrPoolService } from '../src/pool/IndyVdrPoolService'
+
+const storageService = new IndyStorageService(agentDependencies)
+const eventEmitter = new EventEmitter(agentDependencies, new Subject())
+const cacheRepository = new CacheRepository(storageService, eventEmitter)
+const indyVdrPoolService = new IndyVdrPoolService(cacheRepository, testLogger)
+const wallet = new IndyWallet(agentDependencies, testLogger, new SigningProviderRegistry([]))
+const agentConfig = getAgentConfig('IndyVdrPoolService')
+const agentContext = getAgentContext({ wallet, agentConfig })
+
+const config = {
+ isProduction: false,
+ genesisTransactions,
+ indyNamespace: `pool:localtest`,
+ transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
+} as const
+
+indyVdrPoolService.setPools([config])
+
+describe('IndyVdrPoolService', () => {
+ beforeAll(async () => {
+ await indyVdrPoolService.connectToPools()
+
+ await wallet.createAndOpen(agentConfig.walletConfig!)
+ })
+
+ afterAll(async () => {
+ for (const pool of indyVdrPoolService.pools) {
+ pool.close()
+ }
+
+ await wallet.delete()
+ })
+
+ test('can get a pool based on the namespace', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+ expect(pool).toBeInstanceOf(IndyVdrPool)
+ expect(pool.config).toEqual(config)
+ })
+
+ test('can resolve a did using the pool', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+
+ const request = new GetNymRequest({
+ dest: 'TL1EaPFCZ8Si5aUrqScBDt',
+ })
+
+ const response = await pool.submitReadRequest(request)
+
+ expect(response).toMatchObject({
+ op: 'REPLY',
+ result: {
+ dest: 'TL1EaPFCZ8Si5aUrqScBDt',
+ type: '105',
+ data: '{"dest":"TL1EaPFCZ8Si5aUrqScBDt","identifier":"V4SGRU86Z58d6TV7PBUe6f","role":"0","seqNo":11,"txnTime":1671530269,"verkey":"~43X4NhAFqREffK7eWdKgFH"}',
+ identifier: 'LibindyDid111111111111',
+ reqId: expect.any(Number),
+ seqNo: expect.any(Number),
+ txnTime: expect.any(Number),
+ state_proof: expect.any(Object),
+ },
+ })
+ })
+
+ test('can write a did using the pool', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+
+ const key = await wallet.createKey({ keyType: KeyType.Ed25519 })
+
+ const buffer = TypedArrayEncoder.fromBase58(key.publicKeyBase58)
+ const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16))
+ const signerKey = Key.fromPublicKeyBase58('FMGcFuU3QwAQLywxvmEnSorQT3NwU9wgDMMTaDFtvswm', KeyType.Ed25519)
+
+ const request = new NymRequest({
+ dest: did,
+ submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
+ verkey: key.publicKeyBase58,
+ })
+
+ const response = await pool.submitWriteRequest(agentContext, request, signerKey)
+
+ console.log(response)
+ })
+})
diff --git a/packages/indy-vdr/tests/setup.ts b/packages/indy-vdr/tests/setup.ts
new file mode 100644
index 0000000000..574e646994
--- /dev/null
+++ b/packages/indy-vdr/tests/setup.ts
@@ -0,0 +1,5 @@
+import 'reflect-metadata'
+// Needed to register indy-vdr node bindings
+import '../src/index'
+
+jest.setTimeout(20000)
diff --git a/yarn.lock b/yarn.lock
index 030c9671e1..5d951674d2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1792,6 +1792,21 @@
semver "^7.3.5"
tar "^6.1.11"
+"@mapbox/node-pre-gyp@^1.0.10":
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c"
+ integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==
+ dependencies:
+ detect-libc "^2.0.0"
+ https-proxy-agent "^5.0.0"
+ make-dir "^3.1.0"
+ node-fetch "^2.6.7"
+ nopt "^5.0.0"
+ npmlog "^5.0.1"
+ rimraf "^3.0.2"
+ semver "^7.3.5"
+ tar "^6.1.11"
+
"@mattrglobal/bbs-signatures@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@mattrglobal/bbs-signatures/-/bbs-signatures-1.0.0.tgz#8ff272c6d201aadab7e08bd84dbfd6e0d48ba12d"
@@ -3047,6 +3062,14 @@ array-includes@^3.1.4:
get-intrinsic "^1.1.1"
is-string "^1.0.7"
+array-index@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-index/-/array-index-1.0.0.tgz#ec56a749ee103e4e08c790b9c353df16055b97f9"
+ integrity sha512-jesyNbBkLQgGZMSwA1FanaFjalb1mZUGxGeUEkSDidzgrbjBGhvizJkaItdhkt8eIHFOJC7nDsrXk+BaehTdRw==
+ dependencies:
+ debug "^2.2.0"
+ es6-symbol "^3.0.2"
+
array-map@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662"
@@ -4272,6 +4295,14 @@ csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
+d@1, d@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
+ integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
+ dependencies:
+ es5-ext "^0.10.50"
+ type "^1.0.1"
+
dargs@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc"
@@ -4706,6 +4737,32 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
+es5-ext@^0.10.35, es5-ext@^0.10.50:
+ version "0.10.62"
+ resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5"
+ integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==
+ dependencies:
+ es6-iterator "^2.0.3"
+ es6-symbol "^3.1.3"
+ next-tick "^1.1.0"
+
+es6-iterator@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
+ integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==
+ dependencies:
+ d "1"
+ es5-ext "^0.10.35"
+ es6-symbol "^3.1.1"
+
+es6-symbol@^3.0.2, es6-symbol@^3.1.1, es6-symbol@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
+ integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
+ dependencies:
+ d "^1.0.1"
+ ext "^1.1.2"
+
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
@@ -5057,6 +5114,13 @@ express@^4.17.1:
utils-merge "1.0.1"
vary "~1.1.2"
+ext@^1.1.2:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f"
+ integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==
+ dependencies:
+ type "^2.7.2"
+
extend-shallow@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@@ -5968,6 +6032,23 @@ indy-sdk@^1.16.0-dev-1636:
nan "^2.11.1"
node-gyp "^8.0.0"
+indy-vdr-test-nodejs@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/indy-vdr-test-nodejs/-/indy-vdr-test-nodejs-0.1.3.tgz#97eaf38b1035bfabcd772a8399f23d766dfd493e"
+ integrity sha512-E6r86QGbswa+hBgMJKVWJycqvvmOgepFMDaAvuZQtxQK1Z2gghco6m/9EOAPYaJRs0MMEEhzUGhvtSpCzeZ6sg==
+ dependencies:
+ "@mapbox/node-pre-gyp" "^1.0.10"
+ ffi-napi "^4.0.3"
+ indy-vdr-test-shared "0.1.3"
+ ref-array-di "^1.2.2"
+ ref-napi "^3.0.3"
+ ref-struct-di "^1.1.1"
+
+indy-vdr-test-shared@0.1.3, indy-vdr-test-shared@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/indy-vdr-test-shared/-/indy-vdr-test-shared-0.1.3.tgz#3b5ee9492ebc3367a027670aa9686c493de5929c"
+ integrity sha512-fdgV388zi3dglu49kqrV+i40w+18uJkv96Tk4nziLdP280SLnZKKnIRAiq11Hj8aHpnZmwMloyQCsIyQZDZk2g==
+
infer-owner@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
@@ -8125,6 +8206,11 @@ neon-cli@0.8.2:
validate-npm-package-license "^3.0.4"
validate-npm-package-name "^3.0.0"
+next-tick@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
+ integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
+
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
@@ -9434,6 +9520,14 @@ reduce-flatten@^2.0.0:
resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27"
integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==
+ref-array-di@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/ref-array-di/-/ref-array-di-1.2.2.tgz#ceee9d667d9c424b5a91bb813457cc916fb1f64d"
+ integrity sha512-jhCmhqWa7kvCVrWhR/d7RemkppqPUdxEil1CtTtm7FkZV8LcHHCK3Or9GinUiFP5WY3k0djUkMvhBhx49Jb2iA==
+ dependencies:
+ array-index "^1.0.0"
+ debug "^3.1.0"
+
"ref-napi@^2.0.1 || ^3.0.2", ref-napi@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/ref-napi/-/ref-napi-3.0.3.tgz#e259bfc2bbafb3e169e8cd9ba49037dd00396b22"
@@ -9444,7 +9538,7 @@ reduce-flatten@^2.0.0:
node-addon-api "^3.0.0"
node-gyp-build "^4.2.1"
-ref-struct-di@^1.1.0:
+ref-struct-di@^1.1.0, ref-struct-di@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ref-struct-di/-/ref-struct-di-1.1.1.tgz#5827b1d3b32372058f177547093db1fe1602dc10"
integrity sha512-2Xyn/0Qgz89VT+++WP0sTosdm9oeowLP23wRJYhG4BFdMUrLj3jhwHZNEytYNYgtPKLNTP3KJX4HEgBvM1/Y2g==
@@ -10771,6 +10865,16 @@ type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"
+type@^1.0.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
+ integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
+
+type@^2.7.2:
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0"
+ integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==
+
typedarray-to-buffer@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
From d11da2aa3a10e24838363e9f115bb972e8270e3f Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Tue, 20 Dec 2022 16:08:34 +0100
Subject: [PATCH 09/22] refactor: IndyVdr package Work Funded by the Government
of Ontario
Signed-off-by: vickysomtee
---
packages/core/src/index.ts | 2 ++
packages/indy-vdr/package.json | 7 ++++---
packages/indy-vdr/src/pool/IndyVdrPoolService.ts | 15 +++++----------
yarn.lock | 5 +++++
4 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 355383f062..0a847c5f8b 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -10,6 +10,7 @@ export { EventEmitter } from './agent/EventEmitter'
export { FeatureRegistry } from './agent/FeatureRegistry'
export { Handler, HandlerInboundMessage } from './agent/Handler'
export * from './agent/models'
+export * from './modules/ledger/error'
export * from './agent/helpers'
export { AgentConfig } from './agent/AgentConfig'
export { AgentMessage } from './agent/AgentMessage'
@@ -25,6 +26,7 @@ export type {
JsonObject,
JsonValue,
} from './types'
+export * from './cache'
export { DidCommMimeType, KeyDerivationMethod } from './types'
export type { FileSystem } from './storage/FileSystem'
export * from './storage/BaseRecord'
diff --git a/packages/indy-vdr/package.json b/packages/indy-vdr/package.json
index 4e73444465..8af4a8b651 100644
--- a/packages/indy-vdr/package.json
+++ b/packages/indy-vdr/package.json
@@ -25,22 +25,23 @@
},
"dependencies": {
"class-transformer": "0.5.1",
+ "indy-vdr-test-shared": "^0.1.3",
"class-validator": "0.13.1",
"rxjs": "^7.2.0"
},
"peerDependencies": {
"@aries-framework/core": "0.2.5",
- "indy-vdr-test-shared": "^0.1.2"
+ "indy-vdr-test-nodejs": "^0.1.3"
},
"devDependencies": {
"@aries-framework/node": "0.2.5",
- "indy-vdr-test-shared": "^0.1.13",
+ "indy-vdr-test-nodejs": "^0.1.3",
"reflect-metadata": "^0.1.13",
"rimraf": "~3.0.2",
"typescript": "~4.3.0"
},
"peerDependenciesMeta": {
- "indy-vdr-test-shared": {
+ "indy-vdr-test-nodejs": {
"optional": true
}
}
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
index d06c196d78..134ec2716e 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -8,10 +8,11 @@ import {
AgentContext,
inject,
LedgerNotConfiguredError,
+ PersistedLruCache,
+ CacheRepository
} from '@aries-framework/core'
import { DID_INDY_REGEX } from './DidIdentifier'
-import { CacheRepository, PersistedLruCache } from '../../../core/src/cache'
import { isSelfCertifiedDid } from '../utils/did'
import { allSettled, onlyFulfilled, onlyRejected } from '../utils/promises'
import { IndyVdrPool } from './IndyVdrPool'
@@ -69,16 +70,10 @@ export class IndyVdrPoolService {
// Check if the did starts with did:indy
const match = did.match(DID_INDY_REGEX)
- // if (match) {
- // const [, namespace] = match
- // } else {
- // // legacy way
- // }
+ if (match) {
+ const [, namespace] = match
- if (did.startsWith('did:indy')) {
- const nameSpace = did.split(':')[2]
-
- const pool = this.pools.find((pool) => pool.indyNamespace === nameSpace)
+ const pool = this.getPoolForNamespace(namespace);
if (pool) return pool
diff --git a/yarn.lock b/yarn.lock
index 030c9671e1..23979b09ad 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5968,6 +5968,11 @@ indy-sdk@^1.16.0-dev-1636:
nan "^2.11.1"
node-gyp "^8.0.0"
+indy-vdr-test-shared@^0.1.13:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/indy-vdr-test-shared/-/indy-vdr-test-shared-0.1.3.tgz#3b5ee9492ebc3367a027670aa9686c493de5929c"
+ integrity sha512-fdgV388zi3dglu49kqrV+i40w+18uJkv96Tk4nziLdP280SLnZKKnIRAiq11Hj8aHpnZmwMloyQCsIyQZDZk2g==
+
infer-owner@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
From 6ec514ee65c4103219cb0e8f6521190d31eb71ce Mon Sep 17 00:00:00 2001
From: Karim Stekelenburg
Date: Tue, 17 Jan 2023 16:52:37 +0100
Subject: [PATCH 10/22] test(indy-vdr): add basic tests
Signed-off-by: Karim Stekelenburg
---
.../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 205 +++++++++++++++---
1 file changed, 169 insertions(+), 36 deletions(-)
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
index 59e6dc89b1..12cf952814 100644
--- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -5,11 +5,10 @@ import {
IndyWallet,
Key,
KeyType,
- KeyType,
SigningProviderRegistry,
TypedArrayEncoder,
} from '@aries-framework/core'
-import { GetNymRequest, NymRequest } from 'indy-vdr-test-shared'
+import { GetNymRequest, NymRequest, SchemaRequest } from 'indy-vdr-test-shared'
import { Subject } from 'rxjs'
import { CacheRepository } from '../../core/src/cache'
@@ -34,6 +33,8 @@ const config = {
transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' },
} as const
+let signerKey: Key
+
indyVdrPoolService.setPools([config])
describe('IndyVdrPoolService', () => {
@@ -41,6 +42,8 @@ describe('IndyVdrPoolService', () => {
await indyVdrPoolService.connectToPools()
await wallet.createAndOpen(agentConfig.walletConfig!)
+ signerKey = await wallet.createKey({ seed: '000000000000000000000000Trustee9', keyType: KeyType.Ed25519 })
+
})
afterAll(async () => {
@@ -51,53 +54,183 @@ describe('IndyVdrPoolService', () => {
await wallet.delete()
})
- test('can get a pool based on the namespace', async () => {
- const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
- expect(pool).toBeInstanceOf(IndyVdrPool)
- expect(pool.config).toEqual(config)
- })
-
- test('can resolve a did using the pool', async () => {
- const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+ describe('DIDs', () => {
- const request = new GetNymRequest({
- dest: 'TL1EaPFCZ8Si5aUrqScBDt',
+ test('can get a pool based on the namespace', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+ expect(pool).toBeInstanceOf(IndyVdrPool)
+ expect(pool.config).toEqual(config)
})
- const response = await pool.submitReadRequest(request)
+ test('can resolve a did using the pool', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
- expect(response).toMatchObject({
- op: 'REPLY',
- result: {
+ const request = new GetNymRequest({
dest: 'TL1EaPFCZ8Si5aUrqScBDt',
- type: '105',
- data: '{"dest":"TL1EaPFCZ8Si5aUrqScBDt","identifier":"V4SGRU86Z58d6TV7PBUe6f","role":"0","seqNo":11,"txnTime":1671530269,"verkey":"~43X4NhAFqREffK7eWdKgFH"}',
- identifier: 'LibindyDid111111111111',
- reqId: expect.any(Number),
- seqNo: expect.any(Number),
- txnTime: expect.any(Number),
- state_proof: expect.any(Object),
- },
+ })
+
+ const response = await pool.submitReadRequest(request)
+
+ expect(response).toMatchObject({
+ op: 'REPLY',
+ result: {
+ dest: 'TL1EaPFCZ8Si5aUrqScBDt',
+ type: '105',
+ data: '{"dest":"TL1EaPFCZ8Si5aUrqScBDt","identifier":"V4SGRU86Z58d6TV7PBUe6f","role":"0","seqNo":11,"txnTime":1671530269,"verkey":"~43X4NhAFqREffK7eWdKgFH"}',
+ identifier: 'LibindyDid111111111111',
+ reqId: expect.any(Number),
+ seqNo: expect.any(Number),
+ txnTime: expect.any(Number),
+ state_proof: expect.any(Object),
+ },
+ })
})
+
+ test('can write a did using the pool', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+
+ // prepare the DID we are going to write to the ledger
+ const key = await wallet.createKey({ keyType: KeyType.Ed25519 })
+ const buffer = TypedArrayEncoder.fromBase58(key.publicKeyBase58)
+ const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16))
+
+
+ const request = new NymRequest({
+ dest: did,
+ submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
+ verkey: key.publicKeyBase58,
+ })
+
+ const response = await pool.submitWriteRequest(agentContext, request, signerKey)
+
+ console.log(response)
+ })
+
})
- test('can write a did using the pool', async () => {
- const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+ describe('Schemas', () => {
+
+ test('can write a schema using the pool', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+
+ const dynamicVersion = `1.${Math.random() * 100}` // TODO Remove this before pushing
+
+ const schemaRequest = new SchemaRequest({
+ submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
+ schema: {
+ id: 'test-schema-id',
+ name: 'test-schema',
+ ver: '1.0',
+ version: dynamicVersion, // TODO remove this before pushing
+ attrNames: [
+ 'first_name',
+ 'last_name',
+ 'age'
+ ]
+ }
+ })
+
- const key = await wallet.createKey({ keyType: KeyType.Ed25519 })
+ const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
+ expect(response.op).toEqual("REPLY")
- const buffer = TypedArrayEncoder.fromBase58(key.publicKeyBase58)
- const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16))
- const signerKey = Key.fromPublicKeyBase58('FMGcFuU3QwAQLywxvmEnSorQT3NwU9wgDMMTaDFtvswm', KeyType.Ed25519)
+ // FIXME ts-ignore is required. Check that the response type is typed correctly.
- const request = new NymRequest({
- dest: did,
- submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
- verkey: key.publicKeyBase58,
+ // @ts-ignore
+ expect(response.result.txn.data.data.name).toEqual('test-schema')
+
+ // @ts-ignore
+ expect(response.result.txn.data.data.version).toEqual(dynamicVersion) // TODO remove this before pushing
+
+ // @ts-ignore
+ expect(response.result.txn.data.data.attr_names.sort()).toEqual(expect.arrayContaining(
+ [
+ 'first_name',
+ 'last_name',
+ 'age'
+ ].sort()
+ ))
+
+ expect(response.result.txn.protocolVersion).toEqual(2)
+
+ expect(response.result.txn.metadata.from).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
+
+ expect(response.result.txn.metadata.taaAcceptance).toBeDefined()
+
+ expect(response.result.txn.metadata.taaAcceptance!.mechanism).toEqual('accept')
+
+ // testing response.result.tnxMetadata.txnId
+ const txnIdArray = response.result.txnMetadata.txnId.split(':')
+
+ const receivedSubmitterDid = txnIdArray[0]
+ const receivedProtocolVersion = txnIdArray[1]
+ const receivedSchemaName = txnIdArray[2]
+ const receivedSchemaVersionVersion = txnIdArray[3]
+
+ expect(receivedSubmitterDid).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
+
+ expect(receivedProtocolVersion).toEqual("2")
+
+ expect(receivedSchemaName).toEqual('test-schema')
+
+ expect(receivedSchemaVersionVersion).toEqual(dynamicVersion) // TODO change this before pushing
+
+ // testing reqSignature
+ expect(response.result.reqSignature.type).toEqual('ED25519')
+
+ expect(response.result.reqSignature.values[0].from).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
+
+ // testing ver
+ expect(response.result.ver).toEqual("1")
})
- const response = await pool.submitWriteRequest(agentContext, request, signerKey)
+ test('fails writing a schema with existing verson number using the pool', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+
+ const dynamicVersion = `1.${Math.random() * 100}` // TODO Remove this before pushing
+
+ const schemaRequest = new SchemaRequest({
+ submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
+ schema: {
+ id: 'test-schema-id',
+ name: 'test-schema',
+ ver: '1.0',
+ version: dynamicVersion,
+ attrNames: [
+ 'first_name',
+ 'last_name',
+ 'age'
+ ]
+ }
+ })
+
+ const schemaRequest2 = new SchemaRequest({
+ submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
+ schema: {
+ id: 'test-schema-id',
+ name: 'test-schema',
+ ver: '1.0',
+ version: dynamicVersion,
+ attrNames: [
+ 'first_name',
+ 'last_name',
+ 'age'
+ ]
+ }
+ })
+
+
+ const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
+ expect(response).toBeDefined()
+
+ const response2 = await pool.submitWriteRequest(agentContext, schemaRequest2, signerKey)
+
+ expect(response2.op).toEqual('REJECT')
+
+ // @ts-ignore
+ expect(response2.identifier).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
+
+ })
- console.log(response)
})
})
From 8ff1dc9dafc69fd5f4e907107c0221f36fafaa3b Mon Sep 17 00:00:00 2001
From: Karim Stekelenburg
Date: Tue, 17 Jan 2023 17:43:42 +0100
Subject: [PATCH 11/22] fix(indy-vdr): fix import
Signed-off-by: Karim Stekelenburg
---
packages/core/src/index.ts | 1 -
packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 9 ++++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 0a847c5f8b..1ca60ad263 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -10,7 +10,6 @@ export { EventEmitter } from './agent/EventEmitter'
export { FeatureRegistry } from './agent/FeatureRegistry'
export { Handler, HandlerInboundMessage } from './agent/Handler'
export * from './agent/models'
-export * from './modules/ledger/error'
export * from './agent/helpers'
export { AgentConfig } from './agent/AgentConfig'
export { AgentMessage } from './agent/AgentMessage'
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
index 12cf952814..f75b73c97a 100644
--- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -132,6 +132,9 @@ describe('IndyVdrPoolService', () => {
const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
+
+ console.log(JSON.stringify(response, null, 2))
+
expect(response.op).toEqual("REPLY")
// FIXME ts-ignore is required. Check that the response type is typed correctly.
@@ -223,12 +226,12 @@ describe('IndyVdrPoolService', () => {
const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
expect(response).toBeDefined()
- const response2 = await pool.submitWriteRequest(agentContext, schemaRequest2, signerKey)
+ // const response2 = await pool.submitWriteRequest(agentContext, schemaRequest2, signerKey)
- expect(response2.op).toEqual('REJECT')
+ // expect(response2.op).toEqual('REJECT')
// @ts-ignore
- expect(response2.identifier).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
+ // expect(response2.identifier).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
})
From 798406c1aba69babfb305ab8c68089c7584c811c Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Fri, 20 Jan 2023 16:28:12 +0100
Subject: [PATCH 12/22] test(indy-vdr): start credential definition
Signed-off-by: vickysomtee
---
.../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 73 +++++++++----------
1 file changed, 36 insertions(+), 37 deletions(-)
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
index f75b73c97a..6c80d3ee55 100644
--- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -8,7 +8,7 @@ import {
SigningProviderRegistry,
TypedArrayEncoder,
} from '@aries-framework/core'
-import { GetNymRequest, NymRequest, SchemaRequest } from 'indy-vdr-test-shared'
+import { GetNymRequest, NymRequest, SchemaRequest, CredentialDefinitionRequest } from 'indy-vdr-test-shared'
import { Subject } from 'rxjs'
import { CacheRepository } from '../../core/src/cache'
@@ -43,7 +43,6 @@ describe('IndyVdrPoolService', () => {
await wallet.createAndOpen(agentConfig.walletConfig!)
signerKey = await wallet.createKey({ seed: '000000000000000000000000Trustee9', keyType: KeyType.Ed25519 })
-
})
afterAll(async () => {
@@ -55,7 +54,6 @@ describe('IndyVdrPoolService', () => {
})
describe('DIDs', () => {
-
test('can get a pool based on the namespace', async () => {
const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
expect(pool).toBeInstanceOf(IndyVdrPool)
@@ -94,7 +92,6 @@ describe('IndyVdrPoolService', () => {
const buffer = TypedArrayEncoder.fromBase58(key.publicKeyBase58)
const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16))
-
const request = new NymRequest({
dest: did,
submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
@@ -105,11 +102,33 @@ describe('IndyVdrPoolService', () => {
console.log(response)
})
+ })
+
+ describe('CredentialDefinition', () => {
+ test('can write a credential definition using the pool', async () => {
+ const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
+
+ const credentialDefinitionRequest = new CredentialDefinitionRequest({
+ submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
+ credentialDefinition: {
+ ver: '1.0',
+ id: 'test-credential-id',
+ schemaId: 'test-schema-id',
+ type: 'CL',
+ tag: 'TAG',
+ value: {
+ primary: {},
+ },
+ },
+ })
+ const response = await pool.submitWriteRequest(agentContext, credentialDefinitionRequest, signerKey)
+
+ console.log(response)
+ })
})
describe('Schemas', () => {
-
test('can write a schema using the pool', async () => {
const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
@@ -122,20 +141,15 @@ describe('IndyVdrPoolService', () => {
name: 'test-schema',
ver: '1.0',
version: dynamicVersion, // TODO remove this before pushing
- attrNames: [
- 'first_name',
- 'last_name',
- 'age'
- ]
- }
+ attrNames: ['first_name', 'last_name', 'age'],
+ },
})
-
const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
console.log(JSON.stringify(response, null, 2))
- expect(response.op).toEqual("REPLY")
+ expect(response.op).toEqual('REPLY')
// FIXME ts-ignore is required. Check that the response type is typed correctly.
@@ -146,13 +160,9 @@ describe('IndyVdrPoolService', () => {
expect(response.result.txn.data.data.version).toEqual(dynamicVersion) // TODO remove this before pushing
// @ts-ignore
- expect(response.result.txn.data.data.attr_names.sort()).toEqual(expect.arrayContaining(
- [
- 'first_name',
- 'last_name',
- 'age'
- ].sort()
- ))
+ expect(response.result.txn.data.data.attr_names.sort()).toEqual(
+ expect.arrayContaining(['first_name', 'last_name', 'age'].sort())
+ )
expect(response.result.txn.protocolVersion).toEqual(2)
@@ -172,7 +182,7 @@ describe('IndyVdrPoolService', () => {
expect(receivedSubmitterDid).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
- expect(receivedProtocolVersion).toEqual("2")
+ expect(receivedProtocolVersion).toEqual('2')
expect(receivedSchemaName).toEqual('test-schema')
@@ -184,7 +194,7 @@ describe('IndyVdrPoolService', () => {
expect(response.result.reqSignature.values[0].from).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
// testing ver
- expect(response.result.ver).toEqual("1")
+ expect(response.result.ver).toEqual('1')
})
test('fails writing a schema with existing verson number using the pool', async () => {
@@ -199,12 +209,8 @@ describe('IndyVdrPoolService', () => {
name: 'test-schema',
ver: '1.0',
version: dynamicVersion,
- attrNames: [
- 'first_name',
- 'last_name',
- 'age'
- ]
- }
+ attrNames: ['first_name', 'last_name', 'age'],
+ },
})
const schemaRequest2 = new SchemaRequest({
@@ -214,15 +220,10 @@ describe('IndyVdrPoolService', () => {
name: 'test-schema',
ver: '1.0',
version: dynamicVersion,
- attrNames: [
- 'first_name',
- 'last_name',
- 'age'
- ]
- }
+ attrNames: ['first_name', 'last_name', 'age'],
+ },
})
-
const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
expect(response).toBeDefined()
@@ -232,8 +233,6 @@ describe('IndyVdrPoolService', () => {
// @ts-ignore
// expect(response2.identifier).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
-
})
-
})
})
From b51d60a0abb49a8b53cb199b4e9c5508943f49ba Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Tue, 24 Jan 2023 07:40:06 +0100
Subject: [PATCH 13/22] feat: created IndyNotCOnfiguredError Work funded by the
Ontario Government
Signed-off-by: vickysomtee
---
packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts | 7 +++++++
packages/indy-vdr/src/error/index.ts | 3 ++-
2 files changed, 9 insertions(+), 1 deletion(-)
create mode 100644 packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts
diff --git a/packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts b/packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts
new file mode 100644
index 0000000000..a93198e7f5
--- /dev/null
+++ b/packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts
@@ -0,0 +1,7 @@
+import {IndyVdrError} from './IndyVdrError'
+
+export class IndyVdrConfiguredError extends IndyVdrError {
+ public constructor(message: string, { cause }: { cause?: Error } = {}) {
+ super(message, { cause })
+ }
+ }
\ No newline at end of file
diff --git a/packages/indy-vdr/src/error/index.ts b/packages/indy-vdr/src/error/index.ts
index 627a3517b1..d6d15db9bb 100644
--- a/packages/indy-vdr/src/error/index.ts
+++ b/packages/indy-vdr/src/error/index.ts
@@ -1,2 +1,3 @@
export * from './IndyVdrError'
-export * from './IndyVdrNotFound'
\ No newline at end of file
+export * from './IndyVdrNotFound'
+export * from './IndyVdrNotConfiguredError'
\ No newline at end of file
From 139eacfd2c9d9ac072fad2fad386bbaa5641d6c6 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Tue, 24 Jan 2023 07:42:18 +0100
Subject: [PATCH 14/22] test(IndyVdr): schema && credential definition Work
funded by the Ontario Government
Signed-off-by: vickysomtee
---
.../indy-vdr/src/pool/IndyVdrPoolService.ts | 8 +-
.../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 173 ++++++++++--------
2 files changed, 97 insertions(+), 84 deletions(-)
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
index b03de790fe..05e6e57f4a 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -2,10 +2,10 @@ import type { IndyVdrPoolConfig } from './IndyVdrPool'
import type { AgentContext } from '@aries-framework/core'
import type { GetNymResponse } from 'indy-vdr-test-shared'
-import { Logger, InjectionSymbols, injectable, inject, LedgerNotConfiguredError, PersistedLruCache, CacheRepository } from '@aries-framework/core'
+import { Logger, InjectionSymbols, injectable, inject, PersistedLruCache, CacheRepository } from '@aries-framework/core'
import { GetNymRequest } from 'indy-vdr-test-shared'
-import { IndyVdrError, IndyVdrNotFoundError } from '../error'
+import { IndyVdrError, IndyVdrNotFoundError, IndyVdrConfiguredError } from '../error'
import { isSelfCertifiedDid } from '../utils/did'
import { allSettled, onlyFulfilled, onlyRejected } from '../utils/promises'
@@ -84,7 +84,7 @@ export class IndyVdrPoolService {
const pools = this.pools
if (pools.length === 0) {
- throw new LedgerNotConfiguredError(
+ throw new IndyVdrConfiguredError(
"No indy ledgers configured. Provide at least one pool configuration in the 'indyLedgers' agent configuration"
)
}
@@ -166,7 +166,7 @@ export class IndyVdrPoolService {
*/
public getPoolForNamespace(indyNamespace: string) {
if (this.pools.length === 0) {
- throw new LedgerNotConfiguredError(
+ throw new IndyVdrConfiguredError(
"No indy ledgers configured. Provide at least one pool configuration in the 'indyLedgers' agent configuration"
)
}
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
index 6c80d3ee55..6e9e9b1f44 100644
--- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -74,7 +74,7 @@ describe('IndyVdrPoolService', () => {
result: {
dest: 'TL1EaPFCZ8Si5aUrqScBDt',
type: '105',
- data: '{"dest":"TL1EaPFCZ8Si5aUrqScBDt","identifier":"V4SGRU86Z58d6TV7PBUe6f","role":"0","seqNo":11,"txnTime":1671530269,"verkey":"~43X4NhAFqREffK7eWdKgFH"}',
+ data: expect.any(String),
identifier: 'LibindyDid111111111111',
reqId: expect.any(Number),
seqNo: expect.any(Number),
@@ -82,6 +82,15 @@ describe('IndyVdrPoolService', () => {
state_proof: expect.any(Object),
},
})
+
+ expect(JSON.parse(response.result.data as string)).toMatchObject({
+ dest: 'TL1EaPFCZ8Si5aUrqScBDt',
+ identifier: 'V4SGRU86Z58d6TV7PBUe6f',
+ role: '0',
+ seqNo: expect.any(Number),
+ txnTime: expect.any(Number),
+ verkey: '~43X4NhAFqREffK7eWdKgFH',
+ })
})
test('can write a did using the pool', async () => {
@@ -99,36 +108,12 @@ describe('IndyVdrPoolService', () => {
})
const response = await pool.submitWriteRequest(agentContext, request, signerKey)
-
- console.log(response)
})
})
- describe('CredentialDefinition', () => {
- test('can write a credential definition using the pool', async () => {
- const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
-
- const credentialDefinitionRequest = new CredentialDefinitionRequest({
- submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
- credentialDefinition: {
- ver: '1.0',
- id: 'test-credential-id',
- schemaId: 'test-schema-id',
- type: 'CL',
- tag: 'TAG',
- value: {
- primary: {},
- },
- },
- })
+ xdescribe('CredentialDefinition', () => {})
- const response = await pool.submitWriteRequest(agentContext, credentialDefinitionRequest, signerKey)
-
- console.log(response)
- })
- })
-
- describe('Schemas', () => {
+ describe('Schemas & credential Definition', () => {
test('can write a schema using the pool', async () => {
const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
@@ -145,56 +130,91 @@ describe('IndyVdrPoolService', () => {
},
})
- const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
-
- console.log(JSON.stringify(response, null, 2))
-
- expect(response.op).toEqual('REPLY')
-
- // FIXME ts-ignore is required. Check that the response type is typed correctly.
-
- // @ts-ignore
- expect(response.result.txn.data.data.name).toEqual('test-schema')
-
- // @ts-ignore
- expect(response.result.txn.data.data.version).toEqual(dynamicVersion) // TODO remove this before pushing
-
- // @ts-ignore
- expect(response.result.txn.data.data.attr_names.sort()).toEqual(
- expect.arrayContaining(['first_name', 'last_name', 'age'].sort())
- )
-
- expect(response.result.txn.protocolVersion).toEqual(2)
-
- expect(response.result.txn.metadata.from).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
-
- expect(response.result.txn.metadata.taaAcceptance).toBeDefined()
+ const schemaResponse = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
- expect(response.result.txn.metadata.taaAcceptance!.mechanism).toEqual('accept')
-
- // testing response.result.tnxMetadata.txnId
- const txnIdArray = response.result.txnMetadata.txnId.split(':')
-
- const receivedSubmitterDid = txnIdArray[0]
- const receivedProtocolVersion = txnIdArray[1]
- const receivedSchemaName = txnIdArray[2]
- const receivedSchemaVersionVersion = txnIdArray[3]
-
- expect(receivedSubmitterDid).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
-
- expect(receivedProtocolVersion).toEqual('2')
-
- expect(receivedSchemaName).toEqual('test-schema')
-
- expect(receivedSchemaVersionVersion).toEqual(dynamicVersion) // TODO change this before pushing
+ expect(schemaResponse).toMatchObject({
+ op: 'REPLY',
+ result: {
+ ver: '1',
+ txn: {
+ metadata: expect.any(Object),
+ type: '101',
+ data: {
+ data: {
+ attr_names: expect.arrayContaining(['age', 'last_name', 'first_name']),
+ name: 'test-schema',
+ version: dynamicVersion,
+ },
+ },
+ },
+ },
+ })
- // testing reqSignature
- expect(response.result.reqSignature.type).toEqual('ED25519')
+ const credentialDefinitionRequest = new CredentialDefinitionRequest({
+ submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
+ credentialDefinition: {
+ ver: '1.0',
+ id: `TL1EaPFCZ8Si5aUrqScBDt:3:CL:${schemaResponse.result.txnMetadata.seqNo}:TAG`,
+ // must be string version of the schema seqNo
+ schemaId: `${schemaResponse.result.txnMetadata.seqNo}`,
+ type: 'CL',
+ tag: 'TAG',
+ value: {
+ primary: {
+ n: '95671911213029889766246243339609567053285242961853979532076192834533577534909796042025401129640348836502648821408485216223269830089771714177855160978214805993386076928594836829216646288195127289421136294309746871614765411402917891972999085287429566166932354413679994469616357622976775651506242447852304853465380257226445481515631782793575184420720296120464167257703633829902427169144462981949944348928086406211627174233811365419264314148304536534528344413738913277713548403058098093453580992173145127632199215550027527631259565822872315784889212327945030315062879193999012349220118290071491899498795367403447663354833',
+ s: '1573939820553851804028472930351082111827449763317396231059458630252708273163050576299697385049087601314071156646675105028237105229428440185022593174121924731226634356276616495327358864865629675802738680754755949997611920669823449540027707876555408118172529688443208301403297680159171306000341239398135896274940688268460793682007115152428685521865921925309154307574955324973580144009271977076586453011938089159885164705002797196738438392179082905738155386545935208094240038135576042886730802817809757582039362798495805441520744154270346780731494125065136433163757697326955962282840631850597919384092584727207908978907',
+ r: {
+ master_secret:
+ '51468326064458249697956272807708948542001661888325200180968238787091473418947480867518174106588127385097619219536294589148765074804124925845579871788369264160902401097166484002617399484700234182426993061977152961670486891123188739266793651668791365808983166555735631354925174224786218771453042042304773095663181121735652667614424198057134974727791329623974680096491276337756445057223988781749506082654194307092164895251308088903000573135447235553684949564809677864522417041639512933806794232354223826262154508950271949764583849083972967642587778197779127063591201123312548182885603427440981731822883101260509710567731',
+ last_name:
+ '35864556460959997092903171610228165251001245539613587319116151716453114432309327039517115215674024166920383445379522674504803469517283236033110568676156285676664363558333716898161685255450536856645604857714925836474250821415182026707218622134953915013803750771185050002646661004119778318524426368842019753903741998256374803456282688037624993010626333853831264356355867746685055670790915539230702546586615988121383960277550317876816983602795121749533628953449405383896799464872758725899520173321672584180060465965090049734285011738428381648013150818429882628144544132356242262467090140003979917439514443707537952643217',
+ first_name:
+ '26405366527417391838431479783966663952336302347775179063968690502492620867161212873635806190080000833725932174641667734138216137047349915190546601368424742647800764149890590518336588437317392528514313749533980651547425554257026971104775208127915118918084350210726664749850578299247705298976657301433446491575776774836993110356033664644761593799921221474617858131678955318702706530853801195330271860527250931569815553226145458665481867408279941785848264018364216087471931232367137301987457054918438087686484522112532447779498424748261678616461026788516567300969886029412198319909977473167405879110243445062391837349387',
+ age: '19865805272519696320755573045337531955436490760876870776207490804137339344112305203631892390827288264857621916650098902064979838987400911652887344763586495880167030031364467726355103327059673023946234460960685398768709062405377107912774045508870580108596597470880834205563197111550140867466625683117333370595295321833757429488192170551320637065066368716366317421169802474954914904380304190861641082310805418122837214965865969459724848071006870574514215255412289237027267424055400593307112849859757094597401668252862525566316402695830217450073667487951799749275437192883439584518905943435472478496028380016245355151988',
+ },
+ rctxt:
+ '17146114573198643698878017247599007910707723139165264508694101989891626297408755744139587708989465136799243292477223763665064840330721616213638280284119891715514951989022398510785960099708705561761504012512387129498731093386014964896897751536856287377064154297370092339714578039195258061017640952790913108285519632654466006255438773382930416822756630391947263044087385305540191237328903426888518439803354213792647775798033294505898635058814132665832000734168261793545453678083703704122695006541391598116359796491845268631009298069826949515604008666680160398698425061157356267086946953480945396595351944425658076127674',
+ z: '57056568014385132434061065334124327103768023932445648883765905576432733866307137325457775876741578717650388638737098805750938053855430851133826479968450532729423746605371536096355616166421996729493639634413002114547787617999178137950004782677177313856876420539744625174205603354705595789330008560775613287118432593300023801651460885523314713996258581986238928077688246511704050386525431448517516821261983193275502089060128363906909778842476516981025598807378338053788433033754999771876361716562378445777250912525673660842724168260417083076824975992327559199634032439358787956784395443246565622469187082767614421691234',
+ },
+ },
+ },
+ })
- expect(response.result.reqSignature.values[0].from).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
+ const response = await pool.submitWriteRequest(agentContext, credentialDefinitionRequest, signerKey)
- // testing ver
- expect(response.result.ver).toEqual('1')
+ expect(response).toMatchObject({
+ op: 'REPLY',
+ result: {
+ ver: '1',
+ txn: {
+ metadata: expect.any(Object),
+ type: '102',
+ data: {
+ data: {
+ primary: {
+ r: {
+ last_name:
+ '35864556460959997092903171610228165251001245539613587319116151716453114432309327039517115215674024166920383445379522674504803469517283236033110568676156285676664363558333716898161685255450536856645604857714925836474250821415182026707218622134953915013803750771185050002646661004119778318524426368842019753903741998256374803456282688037624993010626333853831264356355867746685055670790915539230702546586615988121383960277550317876816983602795121749533628953449405383896799464872758725899520173321672584180060465965090049734285011738428381648013150818429882628144544132356242262467090140003979917439514443707537952643217',
+ first_name:
+ '26405366527417391838431479783966663952336302347775179063968690502492620867161212873635806190080000833725932174641667734138216137047349915190546601368424742647800764149890590518336588437317392528514313749533980651547425554257026971104775208127915118918084350210726664749850578299247705298976657301433446491575776774836993110356033664644761593799921221474617858131678955318702706530853801195330271860527250931569815553226145458665481867408279941785848264018364216087471931232367137301987457054918438087686484522112532447779498424748261678616461026788516567300969886029412198319909977473167405879110243445062391837349387',
+ age: '19865805272519696320755573045337531955436490760876870776207490804137339344112305203631892390827288264857621916650098902064979838987400911652887344763586495880167030031364467726355103327059673023946234460960685398768709062405377107912774045508870580108596597470880834205563197111550140867466625683117333370595295321833757429488192170551320637065066368716366317421169802474954914904380304190861641082310805418122837214965865969459724848071006870574514215255412289237027267424055400593307112849859757094597401668252862525566316402695830217450073667487951799749275437192883439584518905943435472478496028380016245355151988',
+ master_secret:
+ '51468326064458249697956272807708948542001661888325200180968238787091473418947480867518174106588127385097619219536294589148765074804124925845579871788369264160902401097166484002617399484700234182426993061977152961670486891123188739266793651668791365808983166555735631354925174224786218771453042042304773095663181121735652667614424198057134974727791329623974680096491276337756445057223988781749506082654194307092164895251308088903000573135447235553684949564809677864522417041639512933806794232354223826262154508950271949764583849083972967642587778197779127063591201123312548182885603427440981731822883101260509710567731',
+ },
+ z: '57056568014385132434061065334124327103768023932445648883765905576432733866307137325457775876741578717650388638737098805750938053855430851133826479968450532729423746605371536096355616166421996729493639634413002114547787617999178137950004782677177313856876420539744625174205603354705595789330008560775613287118432593300023801651460885523314713996258581986238928077688246511704050386525431448517516821261983193275502089060128363906909778842476516981025598807378338053788433033754999771876361716562378445777250912525673660842724168260417083076824975992327559199634032439358787956784395443246565622469187082767614421691234',
+ rctxt:
+ '17146114573198643698878017247599007910707723139165264508694101989891626297408755744139587708989465136799243292477223763665064840330721616213638280284119891715514951989022398510785960099708705561761504012512387129498731093386014964896897751536856287377064154297370092339714578039195258061017640952790913108285519632654466006255438773382930416822756630391947263044087385305540191237328903426888518439803354213792647775798033294505898635058814132665832000734168261793545453678083703704122695006541391598116359796491845268631009298069826949515604008666680160398698425061157356267086946953480945396595351944425658076127674',
+ n: '95671911213029889766246243339609567053285242961853979532076192834533577534909796042025401129640348836502648821408485216223269830089771714177855160978214805993386076928594836829216646288195127289421136294309746871614765411402917891972999085287429566166932354413679994469616357622976775651506242447852304853465380257226445481515631782793575184420720296120464167257703633829902427169144462981949944348928086406211627174233811365419264314148304536534528344413738913277713548403058098093453580992173145127632199215550027527631259565822872315784889212327945030315062879193999012349220118290071491899498795367403447663354833',
+ s: '1573939820553851804028472930351082111827449763317396231059458630252708273163050576299697385049087601314071156646675105028237105229428440185022593174121924731226634356276616495327358864865629675802738680754755949997611920669823449540027707876555408118172529688443208301403297680159171306000341239398135896274940688268460793682007115152428685521865921925309154307574955324973580144009271977076586453011938089159885164705002797196738438392179082905738155386545935208094240038135576042886730802817809757582039362798495805441520744154270346780731494125065136433163757697326955962282840631850597919384092584727207908978907',
+ },
+ },
+ signature_type: 'CL',
+ ref: schemaResponse.result.txnMetadata.seqNo,
+ tag: 'TAG',
+ },
+ },
+ },
+ })
})
test('fails writing a schema with existing verson number using the pool', async () => {
@@ -226,13 +246,6 @@ describe('IndyVdrPoolService', () => {
const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
expect(response).toBeDefined()
-
- // const response2 = await pool.submitWriteRequest(agentContext, schemaRequest2, signerKey)
-
- // expect(response2.op).toEqual('REJECT')
-
- // @ts-ignore
- // expect(response2.identifier).toEqual('TL1EaPFCZ8Si5aUrqScBDt')
})
})
})
From 62b7ae325ee5eaeb938d80f31f814895624baac6 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Tue, 24 Jan 2023 14:10:46 +0100
Subject: [PATCH 15/22] feat: IndyVdr Package
Signed-off-by: vickysomtee
---
packages/indy-vdr/src/pool/IndyVdrPoolService.ts | 12 ++++++------
packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 10 +---------
2 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
index 05e6e57f4a..2fa5f001ca 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -2,7 +2,7 @@ import type { IndyVdrPoolConfig } from './IndyVdrPool'
import type { AgentContext } from '@aries-framework/core'
import type { GetNymResponse } from 'indy-vdr-test-shared'
-import { Logger, InjectionSymbols, injectable, inject, PersistedLruCache, CacheRepository } from '@aries-framework/core'
+import { Logger, InjectionSymbols, injectable, inject, CacheModuleConfig} from '@aries-framework/core'
import { GetNymRequest } from 'indy-vdr-test-shared'
import { IndyVdrError, IndyVdrNotFoundError, IndyVdrConfiguredError } from '../error'
@@ -25,12 +25,10 @@ export interface CachedDidResponse {
export class IndyVdrPoolService {
public pools: IndyVdrPool[] = []
private logger: Logger
- private didCache: PersistedLruCache
- public constructor(cacheRepository: CacheRepository, @inject(InjectionSymbols.Logger) logger: Logger) {
+ public constructor( @inject(InjectionSymbols.Logger) logger: Logger) {
this.logger = logger
- this.didCache = new PersistedLruCache(INDY_VDR_LEGACY_DID_POOL_CACHE_ID, DID_POOL_CACHE_LIMIT, cacheRepository)
}
public setPools(poolConfigs: IndyVdrPoolConfig[]) {
@@ -89,7 +87,9 @@ export class IndyVdrPoolService {
)
}
- const cachedNymResponse = await this.didCache.get(agentContext, did)
+ const didCache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache
+
+ const cachedNymResponse = await didCache.get(agentContext, `IndyVdrPoolService:${did}`)
const pool = this.pools.find((pool) => pool.indyNamespace === cachedNymResponse?.indyNamespace)
// If we have the nym response with associated pool in the cache, we'll use that
@@ -136,7 +136,7 @@ export class IndyVdrPoolService {
value = productionOrNonProduction[0].value
}
- await this.didCache.set(agentContext, did, {
+ await didCache.set(agentContext, did, {
nymResponse: {
did: value.did.nymResponse.did,
verkey: value.did.nymResponse.verkey,
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
index 6e9e9b1f44..7b6c0b0522 100644
--- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -1,7 +1,5 @@
-import type { CacheRecord } from '../../core/src/cache'
import {
- EventEmitter,
IndyWallet,
Key,
KeyType,
@@ -9,19 +7,13 @@ import {
TypedArrayEncoder,
} from '@aries-framework/core'
import { GetNymRequest, NymRequest, SchemaRequest, CredentialDefinitionRequest } from 'indy-vdr-test-shared'
-import { Subject } from 'rxjs'
-import { CacheRepository } from '../../core/src/cache'
-import { IndyStorageService } from '../../core/src/storage/IndyStorageService'
import { agentDependencies, genesisTransactions, getAgentConfig, getAgentContext } from '../../core/tests/helpers'
import testLogger from '../../core/tests/logger'
import { IndyVdrPool } from '../src/pool'
import { IndyVdrPoolService } from '../src/pool/IndyVdrPoolService'
-const storageService = new IndyStorageService(agentDependencies)
-const eventEmitter = new EventEmitter(agentDependencies, new Subject())
-const cacheRepository = new CacheRepository(storageService, eventEmitter)
-const indyVdrPoolService = new IndyVdrPoolService(cacheRepository, testLogger)
+const indyVdrPoolService = new IndyVdrPoolService(testLogger)
const wallet = new IndyWallet(agentDependencies, testLogger, new SigningProviderRegistry([]))
const agentConfig = getAgentConfig('IndyVdrPoolService')
const agentContext = getAgentContext({ wallet, agentConfig })
From b82e5cff008447d862b4b20948333fa799acf01b Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Wed, 25 Jan 2023 14:40:57 +0100
Subject: [PATCH 16/22] fix(indy-vdr): removed cache directory export
Signed-off-by: vickysomtee
---
packages/core/src/index.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 18187846a3..e2b1665a2a 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -27,7 +27,6 @@ export type {
WalletConfigRekey,
WalletExportImportConfig,
} from './types'
-export * from './cache'
export { DidCommMimeType, KeyDerivationMethod } from './types'
export type { FileSystem } from './storage/FileSystem'
export * from './storage/BaseRecord'
From b7a4f1c11d41ff3d33dcd6f8f41d70e38cb90d78 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Wed, 25 Jan 2023 23:21:03 +0100
Subject: [PATCH 17/22] fix(indy-vdr): indy vdr resolve Work funded by the
Ontario Government
Signed-off-by: vickysomtee
---
packages/indy-vdr/README.md | 51 ++-----------------
packages/indy-vdr/package.json | 24 ++++-----
.../src/error/IndyVdrNotConfiguredError.ts | 12 ++---
.../indy-vdr/src/error/IndyVdrNotFound.ts | 10 ++--
packages/indy-vdr/src/error/index.ts | 2 +-
packages/indy-vdr/src/pool/IndyVdrPool.ts | 6 +--
.../indy-vdr/src/pool/IndyVdrPoolService.ts | 44 ++++++----------
.../{DidIdentifier.ts => didIdentifier.ts} | 2 +-
packages/indy-vdr/src/pool/index.ts | 1 -
packages/indy-vdr/src/utils/did.ts | 5 --
.../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 46 ++---------------
11 files changed, 47 insertions(+), 156 deletions(-)
rename packages/indy-vdr/src/pool/{DidIdentifier.ts => didIdentifier.ts} (54%)
diff --git a/packages/indy-vdr/README.md b/packages/indy-vdr/README.md
index ffd98caf55..310b38a4f9 100644
--- a/packages/indy-vdr/README.md
+++ b/packages/indy-vdr/README.md
@@ -6,7 +6,7 @@
height="250px"
/>
-Aries Framework JavaScript Action Menu Plugin
+Aries Framework JavaScript - Indy Verifiable Data Registry (Indy-Vdr)
-
-Action Menu plugin for [Aries Framework JavaScript](https://github.com/hyperledger/aries-framework-javascript.git). Implements [Aries RFC 0509](https://github.com/hyperledger/aries-rfcs/blob/1795d5c2d36f664f88f5e8045042ace8e573808c/features/0509-action-menu/README.md).
-
### Installation
-Make sure you have set up the correct version of Aries Framework JavaScript according to the AFJ repository. To find out which version of AFJ you need to have installed you can run the following command. This will list the required peer dependency for `@aries-framework/core`.
-
-```sh
-npm info "@aries-framework/action-menu" peerDependencies
-```
-
-Then add the action-menu plugin to your project.
-
-```sh
-yarn add @aries-framework/action-menu
-```
-
### Quick start
-In order for this plugin to work, we have to inject it into the agent to access agent functionality. See the example for more information.
-
### Example of usage
-
-```ts
-import { ActionMenuModule } from '@aries-framework/action-menu'
-
-const agent = new Agent({
- config: {
- /* config */
- },
- dependencies: agentDependencies,
- modules: {
- actionMenu: new ActionMenuModule(),
- /* other custom modules */
- },
-})
-
-await agent.initialize()
-
-// To request root menu to a given connection (menu will be received
-// asynchronously in a ActionMenuStateChangedEvent)
-await agent.modules.actionMenu.requestMenu({ connectionId })
-
-// To select an option from the action menu
-await agent.modules.actionMenu.performAction({
- connectionId,
- performedAction: { name: 'option-1' },
-})
-```
diff --git a/packages/indy-vdr/package.json b/packages/indy-vdr/package.json
index 8af4a8b651..6cce47b2df 100644
--- a/packages/indy-vdr/package.json
+++ b/packages/indy-vdr/package.json
@@ -2,7 +2,7 @@
"name": "@aries-framework/indy-vdr",
"main": "build/index",
"types": "build/index",
- "version": "0.2.5",
+ "version": "0.3.3",
"files": [
"build"
],
@@ -18,31 +18,27 @@
},
"scripts": {
"build": "yarn run clean && yarn run compile",
- "clean": "rimraf -rf ./build",
+ "clean": "rimraf ./build",
"compile": "tsc -p tsconfig.build.json",
"prepublishOnly": "yarn run build",
"test": "jest"
},
"dependencies": {
+ "@aries-framework/core": "0.3.3",
+ "@types/express": "^4.17.13",
+ "@typescript-eslint/eslint-plugin": "^5.48.1",
+ "@typescript-eslint/parser": "^5.48.1",
"class-transformer": "0.5.1",
- "indy-vdr-test-shared": "^0.1.3",
"class-validator": "0.13.1",
+ "eslint-plugin-import": "^2.23.4",
+ "indy-vdr-test-shared": "^0.1.3",
"rxjs": "^7.2.0"
},
- "peerDependencies": {
- "@aries-framework/core": "0.2.5",
- "indy-vdr-test-nodejs": "^0.1.3"
- },
"devDependencies": {
- "@aries-framework/node": "0.2.5",
+ "@aries-framework/node": "0.3.3",
"indy-vdr-test-nodejs": "^0.1.3",
"reflect-metadata": "^0.1.13",
"rimraf": "~3.0.2",
- "typescript": "~4.3.0"
- },
- "peerDependenciesMeta": {
- "indy-vdr-test-nodejs": {
- "optional": true
- }
+ "typescript": "~4.9.4"
}
}
diff --git a/packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts b/packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts
index a93198e7f5..75cf40c9f6 100644
--- a/packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts
+++ b/packages/indy-vdr/src/error/IndyVdrNotConfiguredError.ts
@@ -1,7 +1,7 @@
-import {IndyVdrError} from './IndyVdrError'
+import { IndyVdrError } from './IndyVdrError'
-export class IndyVdrConfiguredError extends IndyVdrError {
- public constructor(message: string, { cause }: { cause?: Error } = {}) {
- super(message, { cause })
- }
- }
\ No newline at end of file
+export class IndyVdrNotConfiguredError extends IndyVdrError {
+ public constructor(message: string, { cause }: { cause?: Error } = {}) {
+ super(message, { cause })
+ }
+}
diff --git a/packages/indy-vdr/src/error/IndyVdrNotFound.ts b/packages/indy-vdr/src/error/IndyVdrNotFound.ts
index 09bcc2277c..00b1b94c47 100644
--- a/packages/indy-vdr/src/error/IndyVdrNotFound.ts
+++ b/packages/indy-vdr/src/error/IndyVdrNotFound.ts
@@ -1,7 +1,7 @@
-import { IndyVdrError } from "./IndyVdrError"
+import { IndyVdrError } from './IndyVdrError'
export class IndyVdrNotFoundError extends IndyVdrError {
- public constructor(message: string, { cause }: { cause?: Error } = {}) {
- super(message, { cause })
- }
- }
\ No newline at end of file
+ public constructor(message: string, { cause }: { cause?: Error } = {}) {
+ super(message, { cause })
+ }
+}
diff --git a/packages/indy-vdr/src/error/index.ts b/packages/indy-vdr/src/error/index.ts
index d6d15db9bb..f062bfbed0 100644
--- a/packages/indy-vdr/src/error/index.ts
+++ b/packages/indy-vdr/src/error/index.ts
@@ -1,3 +1,3 @@
export * from './IndyVdrError'
export * from './IndyVdrNotFound'
-export * from './IndyVdrNotConfiguredError'
\ No newline at end of file
+export * from './IndyVdrNotConfiguredError'
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index 75f1bed05a..72ff83e7e5 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -1,7 +1,7 @@
import type { Logger, AgentContext, Key } from '@aries-framework/core'
import type { IndyVdrRequest, IndyVdrPool as indyVdrPool } from 'indy-vdr-test-shared'
-import { TypedArrayEncoder, AriesFrameworkError } from '@aries-framework/core'
+import { TypedArrayEncoder } from '@aries-framework/core'
import {
GetTransactionAuthorAgreementRequest,
GetAcceptanceMechanismsRequest,
@@ -38,7 +38,6 @@ export interface IndyVdrPoolConfig {
}
export class IndyVdrPool {
- // indyVdr?: typeof IndyVdr
private _pool?: indyVdrPool
private logger: Logger
private poolConfig: IndyVdrPoolConfig
@@ -69,8 +68,7 @@ export class IndyVdrPool {
private get pool(): indyVdrPool {
if (!this._pool) {
- // TODO: create custom IndyVdrError
- throw new AriesFrameworkError('Pool is not connected. Make sure to call .connect() first')
+ throw new IndyVdrError('Pool is not connected. Make sure to call .connect() first')
}
return this._pool
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
index 2fa5f001ca..4b7b3f2bfa 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -2,18 +2,16 @@ import type { IndyVdrPoolConfig } from './IndyVdrPool'
import type { AgentContext } from '@aries-framework/core'
import type { GetNymResponse } from 'indy-vdr-test-shared'
-import { Logger, InjectionSymbols, injectable, inject, CacheModuleConfig} from '@aries-framework/core'
+import { Logger, InjectionSymbols, injectable, inject, CacheModuleConfig } from '@aries-framework/core'
import { GetNymRequest } from 'indy-vdr-test-shared'
-import { IndyVdrError, IndyVdrNotFoundError, IndyVdrConfiguredError } from '../error'
+import { IndyVdrError, IndyVdrNotFoundError, IndyVdrNotConfiguredError } from '../error'
import { isSelfCertifiedDid } from '../utils/did'
import { allSettled, onlyFulfilled, onlyRejected } from '../utils/promises'
-import { DID_INDY_REGEX } from './DidIdentifier'
import { IndyVdrPool } from './IndyVdrPool'
+import { DID_INDY_REGEX } from './didIdentifier'
-export const INDY_VDR_LEGACY_DID_POOL_CACHE_ID = 'INDY_VDR_LEGACY_DID_POOL_CACHE'
-export const DID_POOL_CACHE_LIMIT = 500
export interface CachedDidResponse {
nymResponse: {
did: string
@@ -26,9 +24,8 @@ export class IndyVdrPoolService {
public pools: IndyVdrPool[] = []
private logger: Logger
- public constructor( @inject(InjectionSymbols.Logger) logger: Logger) {
+ public constructor(@inject(InjectionSymbols.Logger) logger: Logger) {
this.logger = logger
-
}
public setPools(poolConfigs: IndyVdrPoolConfig[]) {
@@ -52,7 +49,7 @@ export class IndyVdrPoolService {
/**
* Get the most appropriate pool for the given did.
- * If the did is a qualified indy did, the pool will be determined based on the namespace.
+ * If the did is a qualified indy did, the pool will be determined based on the namespace.
* If it is a legacy unqualified indy did, the pool will be determined based on the algorithm as described in this document:
* https://docs.google.com/document/d/109C_eMsuZnTnYe2OAd02jAts1vC4axwEKIq7_4dnNVA/edit
*/
@@ -63,26 +60,21 @@ export class IndyVdrPoolService {
if (match) {
const [, namespace] = match
- const pool = this.getPoolForNamespace(namespace);
+ const pool = this.getPoolForNamespace(namespace)
- if (pool) return pool
+ if (pool) return pool
- throw new IndyVdrNotFoundError('Pool not found')
+ throw new IndyVdrError(`Pool for indy namespace '${namespace}' not found`)
} else {
return await this.getPoolForLegacyDid(agentContext, did)
}
-
-
}
- private async getPoolForLegacyDid(
- agentContext: AgentContext,
- did: string
- ): Promise {
+ private async getPoolForLegacyDid(agentContext: AgentContext, did: string): Promise {
const pools = this.pools
if (pools.length === 0) {
- throw new IndyVdrConfiguredError(
+ throw new IndyVdrNotConfiguredError(
"No indy ledgers configured. Provide at least one pool configuration in the 'indyLedgers' agent configuration"
)
}
@@ -95,7 +87,7 @@ export class IndyVdrPoolService {
// If we have the nym response with associated pool in the cache, we'll use that
if (cachedNymResponse && pool) {
this.logger.trace(`Found ledger id '${pool.indyNamespace}' for did '${did}' in cache`)
- return pool
+ return pool
}
const { successful, rejected } = await this.getSettledDidResponsesFromPools(did, pools)
@@ -143,7 +135,7 @@ export class IndyVdrPoolService {
},
indyNamespace: value.did.indyNamespace,
})
- return value.pool
+ return value.pool
}
private async getSettledDidResponsesFromPools(did: string, pools: IndyVdrPool[]) {
@@ -166,20 +158,15 @@ export class IndyVdrPoolService {
*/
public getPoolForNamespace(indyNamespace: string) {
if (this.pools.length === 0) {
- throw new IndyVdrConfiguredError(
+ throw new IndyVdrNotConfiguredError(
"No indy ledgers configured. Provide at least one pool configuration in the 'indyLedgers' agent configuration"
)
}
- if (!indyNamespace) {
- this.logger.warn('Not passing the indyNamespace is deprecated and will be removed in the future version.')
- return this.pools[0]
- }
-
const pool = this.pools.find((pool) => pool.indyNamespace === indyNamespace)
if (!pool) {
- throw new IndyVdrNotFoundError(`No ledgers found for IndyNamespace '${indyNamespace}'.`)
+ throw new IndyVdrError(`No ledgers found for IndyNamespace '${indyNamespace}'.`)
}
return pool
@@ -194,8 +181,7 @@ export class IndyVdrPoolService {
const response = await pool.submitReadRequest(request)
if (!response.result.data) {
- // TODO: Set a descriptive message
- throw new IndyVdrError(`Did ${did} not found on indy pool with namespace ${pool.indyNamespace}`)
+ throw new IndyVdrNotFoundError(`Did ${did} not found on indy pool with namespace ${pool.indyNamespace}`)
}
const result = JSON.parse(response.result.data)
diff --git a/packages/indy-vdr/src/pool/DidIdentifier.ts b/packages/indy-vdr/src/pool/didIdentifier.ts
similarity index 54%
rename from packages/indy-vdr/src/pool/DidIdentifier.ts
rename to packages/indy-vdr/src/pool/didIdentifier.ts
index 39384a2c8d..759ea8eefa 100644
--- a/packages/indy-vdr/src/pool/DidIdentifier.ts
+++ b/packages/indy-vdr/src/pool/didIdentifier.ts
@@ -1 +1 @@
-export const DID_INDY_REGEX = /^did:indy:((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)):([1-9A-HJ-NP-Za-km-z]{21,22})$/
\ No newline at end of file
+export const DID_INDY_REGEX = /^did:indy:((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)):([1-9A-HJ-NP-Za-km-z]{21,22})$/
diff --git a/packages/indy-vdr/src/pool/index.ts b/packages/indy-vdr/src/pool/index.ts
index 8c09951384..1e1f1b52f8 100644
--- a/packages/indy-vdr/src/pool/index.ts
+++ b/packages/indy-vdr/src/pool/index.ts
@@ -1,2 +1 @@
export * from './IndyVdrPool'
-
diff --git a/packages/indy-vdr/src/utils/did.ts b/packages/indy-vdr/src/utils/did.ts
index a9f2c95d02..f3f346f070 100644
--- a/packages/indy-vdr/src/utils/did.ts
+++ b/packages/indy-vdr/src/utils/did.ts
@@ -15,14 +15,9 @@
* https://github.com/hyperledger/aries-framework-dotnet/blob/f90eaf9db8548f6fc831abea917e906201755763/src/Hyperledger.Aries/Ledger/DefaultLedgerService.cs#L139-L147
*/
-
import { TypedArrayEncoder } from '@aries-framework/core'
-export const FULL_VERKEY_REGEX = /^[1-9A-HJ-NP-Za-km-z]{43,44}$/
export const ABBREVIATED_VERKEY_REGEX = /^~[1-9A-HJ-NP-Za-km-z]{21,22}$/
-export const VERKEY_REGEX = new RegExp(`${FULL_VERKEY_REGEX.source}|${ABBREVIATED_VERKEY_REGEX.source}`)
-export const DID_REGEX = /^did:([a-z]+):([a-zA-z\d]+)/
-export const DID_IDENTIFIER_REGEX = /^[a-zA-z\d-]+$/
/**
* Check whether the did is a self certifying did. If the verkey is abbreviated this method
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
index 7b6c0b0522..1caba81fdd 100644
--- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -1,11 +1,4 @@
-
-import {
- IndyWallet,
- Key,
- KeyType,
- SigningProviderRegistry,
- TypedArrayEncoder,
-} from '@aries-framework/core'
+import { IndyWallet, Key, KeyType, SigningProviderRegistry, TypedArrayEncoder } from '@aries-framework/core'
import { GetNymRequest, NymRequest, SchemaRequest, CredentialDefinitionRequest } from 'indy-vdr-test-shared'
import { agentDependencies, genesisTransactions, getAgentConfig, getAgentContext } from '../../core/tests/helpers'
@@ -103,13 +96,11 @@ describe('IndyVdrPoolService', () => {
})
})
- xdescribe('CredentialDefinition', () => {})
-
describe('Schemas & credential Definition', () => {
test('can write a schema using the pool', async () => {
const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
- const dynamicVersion = `1.${Math.random() * 100}` // TODO Remove this before pushing
+ const dynamicVersion = `1.${Math.random() * 100}`
const schemaRequest = new SchemaRequest({
submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
@@ -117,7 +108,7 @@ describe('IndyVdrPoolService', () => {
id: 'test-schema-id',
name: 'test-schema',
ver: '1.0',
- version: dynamicVersion, // TODO remove this before pushing
+ version: dynamicVersion,
attrNames: ['first_name', 'last_name', 'age'],
},
})
@@ -208,36 +199,5 @@ describe('IndyVdrPoolService', () => {
},
})
})
-
- test('fails writing a schema with existing verson number using the pool', async () => {
- const pool = indyVdrPoolService.getPoolForNamespace('pool:localtest')
-
- const dynamicVersion = `1.${Math.random() * 100}` // TODO Remove this before pushing
-
- const schemaRequest = new SchemaRequest({
- submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
- schema: {
- id: 'test-schema-id',
- name: 'test-schema',
- ver: '1.0',
- version: dynamicVersion,
- attrNames: ['first_name', 'last_name', 'age'],
- },
- })
-
- const schemaRequest2 = new SchemaRequest({
- submitterDid: 'TL1EaPFCZ8Si5aUrqScBDt',
- schema: {
- id: 'test-schema-id',
- name: 'test-schema',
- ver: '1.0',
- version: dynamicVersion,
- attrNames: ['first_name', 'last_name', 'age'],
- },
- })
-
- const response = await pool.submitWriteRequest(agentContext, schemaRequest, signerKey)
- expect(response).toBeDefined()
- })
})
})
From c275748f2f40996151faeba2813fdeffda35ba42 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Wed, 25 Jan 2023 23:31:33 +0100
Subject: [PATCH 18/22] test(indy-vdr): extended did test Work funded by the
Ontario Government
Signed-off-by: vickysomtee
---
.../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 24 +++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
index 1caba81fdd..5920344527 100644
--- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
+++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts
@@ -1,4 +1,6 @@
-import { IndyWallet, Key, KeyType, SigningProviderRegistry, TypedArrayEncoder } from '@aries-framework/core'
+import type { Key } from '@aries-framework/core'
+
+import { IndyWallet, KeyType, SigningProviderRegistry, TypedArrayEncoder } from '@aries-framework/core'
import { GetNymRequest, NymRequest, SchemaRequest, CredentialDefinitionRequest } from 'indy-vdr-test-shared'
import { agentDependencies, genesisTransactions, getAgentConfig, getAgentContext } from '../../core/tests/helpers'
@@ -26,7 +28,10 @@ describe('IndyVdrPoolService', () => {
beforeAll(async () => {
await indyVdrPoolService.connectToPools()
- await wallet.createAndOpen(agentConfig.walletConfig!)
+ if (agentConfig.walletConfig) {
+ await wallet.createAndOpen(agentConfig.walletConfig)
+ }
+
signerKey = await wallet.createKey({ seed: '000000000000000000000000Trustee9', keyType: KeyType.Ed25519 })
})
@@ -93,6 +98,21 @@ describe('IndyVdrPoolService', () => {
})
const response = await pool.submitWriteRequest(agentContext, request, signerKey)
+
+ expect(response).toMatchObject({
+ op: 'REPLY',
+ result: {
+ txn: {
+ protocolVersion: 2,
+ metadata: expect.any(Object),
+ data: expect.any(Object),
+ type: '1',
+ },
+ ver: '1',
+ rootHash: expect.any(String),
+ txnMetadata: expect.any(Object),
+ },
+ })
})
})
From 01a403a0ba13ce0f5c2d687acb1b68b69428d2d2 Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Wed, 25 Jan 2023 23:33:42 +0100
Subject: [PATCH 19/22] fix(indy-vdr): lint - no-extranous-dependencies Work
funded by the Ontario Government
Signed-off-by: vickysomtee
---
.eslintrc.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/.eslintrc.js b/.eslintrc.js
index e45d4d2cad..c9b7db857b 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -22,6 +22,7 @@ module.exports = {
alwaysTryTypes: true,
},
},
+ 'import/core-modules': ['indy-vdr-test-nodejs'],
},
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
From ff6e16dfbe1a6c183a8be01105728508ccce79ca Mon Sep 17 00:00:00 2001
From: vickysomtee
Date: Thu, 26 Jan 2023 12:18:02 +0100
Subject: [PATCH 20/22] refactor(indy-vdr): little indy-vdr refactor work
funded by the Ontario Government
Signed-off-by: vickysomtee
---
.eslintrc.js | 1 -
packages/indy-vdr/package.json | 13 ++-----------
packages/indy-vdr/src/index.ts | 1 +
packages/indy-vdr/src/pool/IndyVdrPoolService.ts | 3 +--
packages/indy-vdr/src/pool/didIdentifier.ts | 1 -
packages/indy-vdr/src/utils/did.ts | 1 +
packages/indy-vdr/tests/setup.ts | 1 -
7 files changed, 5 insertions(+), 16 deletions(-)
delete mode 100644 packages/indy-vdr/src/pool/didIdentifier.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index c9b7db857b..e45d4d2cad 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -22,7 +22,6 @@ module.exports = {
alwaysTryTypes: true,
},
},
- 'import/core-modules': ['indy-vdr-test-nodejs'],
},
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
diff --git a/packages/indy-vdr/package.json b/packages/indy-vdr/package.json
index 6cce47b2df..2d91b2c181 100644
--- a/packages/indy-vdr/package.json
+++ b/packages/indy-vdr/package.json
@@ -25,20 +25,11 @@
},
"dependencies": {
"@aries-framework/core": "0.3.3",
- "@types/express": "^4.17.13",
- "@typescript-eslint/eslint-plugin": "^5.48.1",
- "@typescript-eslint/parser": "^5.48.1",
- "class-transformer": "0.5.1",
- "class-validator": "0.13.1",
- "eslint-plugin-import": "^2.23.4",
- "indy-vdr-test-shared": "^0.1.3",
- "rxjs": "^7.2.0"
+ "indy-vdr-test-shared": "^0.1.3"
},
"devDependencies": {
- "@aries-framework/node": "0.3.3",
"indy-vdr-test-nodejs": "^0.1.3",
- "reflect-metadata": "^0.1.13",
- "rimraf": "~3.0.2",
+ "rimraf": "~4.0.7",
"typescript": "~4.9.4"
}
}
diff --git a/packages/indy-vdr/src/index.ts b/packages/indy-vdr/src/index.ts
index 6e9d822ced..8a5ca6c21a 100644
--- a/packages/indy-vdr/src/index.ts
+++ b/packages/indy-vdr/src/index.ts
@@ -1,4 +1,5 @@
try {
+ // eslint-disable-next-line import/no-extraneous-dependencies
require('indy-vdr-test-nodejs')
} catch (error) {
throw new Error('Error registering nodejs bindings for Indy VDR')
diff --git a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
index 4b7b3f2bfa..2cc1b5a206 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPoolService.ts
@@ -6,11 +6,10 @@ import { Logger, InjectionSymbols, injectable, inject, CacheModuleConfig } from
import { GetNymRequest } from 'indy-vdr-test-shared'
import { IndyVdrError, IndyVdrNotFoundError, IndyVdrNotConfiguredError } from '../error'
-import { isSelfCertifiedDid } from '../utils/did'
+import { isSelfCertifiedDid, DID_INDY_REGEX } from '../utils/did'
import { allSettled, onlyFulfilled, onlyRejected } from '../utils/promises'
import { IndyVdrPool } from './IndyVdrPool'
-import { DID_INDY_REGEX } from './didIdentifier'
export interface CachedDidResponse {
nymResponse: {
diff --git a/packages/indy-vdr/src/pool/didIdentifier.ts b/packages/indy-vdr/src/pool/didIdentifier.ts
deleted file mode 100644
index 759ea8eefa..0000000000
--- a/packages/indy-vdr/src/pool/didIdentifier.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const DID_INDY_REGEX = /^did:indy:((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)):([1-9A-HJ-NP-Za-km-z]{21,22})$/
diff --git a/packages/indy-vdr/src/utils/did.ts b/packages/indy-vdr/src/utils/did.ts
index f3f346f070..9cda8ee95d 100644
--- a/packages/indy-vdr/src/utils/did.ts
+++ b/packages/indy-vdr/src/utils/did.ts
@@ -17,6 +17,7 @@
import { TypedArrayEncoder } from '@aries-framework/core'
+export const DID_INDY_REGEX = /^did:indy:((?:[a-z][_a-z0-9-]*)(?::[a-z][_a-z0-9-]*)):([1-9A-HJ-NP-Za-km-z]{21,22})$/
export const ABBREVIATED_VERKEY_REGEX = /^~[1-9A-HJ-NP-Za-km-z]{21,22}$/
/**
diff --git a/packages/indy-vdr/tests/setup.ts b/packages/indy-vdr/tests/setup.ts
index 574e646994..ce7749d25e 100644
--- a/packages/indy-vdr/tests/setup.ts
+++ b/packages/indy-vdr/tests/setup.ts
@@ -1,4 +1,3 @@
-import 'reflect-metadata'
// Needed to register indy-vdr node bindings
import '../src/index'
From b4416412984ffe3076204a2a246ee8207c117b3d Mon Sep 17 00:00:00 2001
From: Victor Anene
Date: Thu, 26 Jan 2023 17:31:59 +0100
Subject: [PATCH 21/22] fix(indy-vdr): resolve fixes work funded by the Ontario
Government
Signed-off-by: Victor Anene
---
packages/indy-vdr/package.json | 1 +
packages/indy-vdr/src/pool/IndyVdrPool.ts | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/packages/indy-vdr/package.json b/packages/indy-vdr/package.json
index 2d91b2c181..32c8689d5d 100644
--- a/packages/indy-vdr/package.json
+++ b/packages/indy-vdr/package.json
@@ -3,6 +3,7 @@
"main": "build/index",
"types": "build/index",
"version": "0.3.3",
+ "private": true,
"files": [
"build"
],
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index 72ff83e7e5..27aadbddca 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -171,7 +171,9 @@ export class IndyVdrPool {
// If TAA is not null, we can be sure AcceptanceMechanisms is also not null
const authorAgreement = taaData as Omit
- const acceptanceMechanisms = acceptanceMechanismResponse.result.data as AcceptanceMechanisms
+
+ // FIME: remove cast when https://github.com/hyperledger/indy-vdr/pull/142 is released
+ const acceptanceMechanisms = acceptanceMechanismResponse.result.data as unknown as AcceptanceMechanisms
this.authorAgreement = {
...authorAgreement,
acceptanceMechanisms,
From 0b31a2d52f1664d19addd6c0c3a397836a4fb4e3 Mon Sep 17 00:00:00 2001
From: Victor Anene
Date: Thu, 26 Jan 2023 17:47:33 +0100
Subject: [PATCH 22/22] fix: lint error work funded by the Ontario Government
Signed-off-by: Victor Anene
---
packages/indy-vdr/src/pool/IndyVdrPool.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/indy-vdr/src/pool/IndyVdrPool.ts b/packages/indy-vdr/src/pool/IndyVdrPool.ts
index 27aadbddca..6958d882ab 100644
--- a/packages/indy-vdr/src/pool/IndyVdrPool.ts
+++ b/packages/indy-vdr/src/pool/IndyVdrPool.ts
@@ -173,7 +173,7 @@ export class IndyVdrPool {
const authorAgreement = taaData as Omit
// FIME: remove cast when https://github.com/hyperledger/indy-vdr/pull/142 is released
- const acceptanceMechanisms = acceptanceMechanismResponse.result.data as unknown as AcceptanceMechanisms
+ const acceptanceMechanisms = acceptanceMechanismResponse.result.data as unknown as AcceptanceMechanisms
this.authorAgreement = {
...authorAgreement,
acceptanceMechanisms,