From 4d63fd9f7a5d42bae019ba238793461182daae94 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Tue, 7 Nov 2023 11:33:05 +0700 Subject: [PATCH 01/19] temp Signed-off-by: Timo Glastra --- .../setup-postgres-wallet-plugin/action.yml | 21 - .github/workflows/continuous-integration.yml | 4 - README.md | 16 +- TROUBLESHOOTING.md | 85 --- demo/package.json | 2 - demo/src/BaseAgent.ts | 51 +- package.json | 4 +- packages/anoncreds/package.json | 1 - packages/anoncreds/src/AnonCredsApi.ts | 2 + .../legacy-indy-format-services.test.ts | 2 + packages/askar/tests/helpers.ts | 1 + packages/cheqd/package.json | 2 - packages/cheqd/tests/setupCheqdModule.ts | 10 +- .../tests/migrate.test.ts | 14 +- packages/indy-sdk/CHANGELOG.md | 59 -- packages/indy-sdk/README.md | 31 - packages/indy-sdk/jest.config.ts | 13 - packages/indy-sdk/package.json | 40 -- packages/indy-sdk/src/IndySdkModule.ts | 60 -- packages/indy-sdk/src/IndySdkModuleConfig.ts | 81 --- packages/indy-sdk/src/anoncreds/index.ts | 4 - .../services/IndySdkAnonCredsRegistry.ts | 623 ----------------- .../services/IndySdkHolderService.ts | 464 ------------- .../services/IndySdkIssuerService.ts | 157 ----- .../services/IndySdkIssuerServiceMetadata.ts | 3 - .../services/IndySdkRevocationService.ts | 155 ----- .../services/IndySdkVerifierService.ts | 96 --- .../utils/__tests__/assertUnqualified.test.ts | 152 ----- .../utils/__tests__/identifiers.test.ts | 79 --- .../utils/__tests__/transform.test.ts | 114 ---- .../src/anoncreds/utils/assertUnqualified.ts | 133 ---- .../src/anoncreds/utils/identifiers.ts | 63 -- .../indy-sdk/src/anoncreds/utils/tails.ts | 45 -- .../indy-sdk/src/anoncreds/utils/transform.ts | 161 ----- .../src/dids/IndySdkIndyDidRegistrar.ts | 328 --------- .../src/dids/IndySdkIndyDidResolver.ts | 124 ---- .../src/dids/IndySdkSovDidResolver.ts | 99 --- .../__tests__/IndySdkIndyDidRegistrar.test.ts | 501 -------------- .../__tests__/IndySdkIndyDidResolver.test.ts | 127 ---- .../__tests__/IndySdkSovDidResolver.test.ts | 132 ---- .../didIndyPool1R1xKJw17sUoXhejEpugMYJ.json | 50 -- .../didIndyPool1WJz9mHyW9BZksioQnRsrAo.json | 48 -- .../didSovR1xKJw17sUoXhejEpugMYJ.json | 51 -- .../didSovWJz9mHyW9BZksioQnRsrAo.json | 49 -- packages/indy-sdk/src/dids/didIndyUtil.ts | 55 -- packages/indy-sdk/src/dids/didSovUtil.ts | 138 ---- packages/indy-sdk/src/dids/index.ts | 3 - packages/indy-sdk/src/error/IndySdkError.ts | 11 - packages/indy-sdk/src/error/index.ts | 2 - packages/indy-sdk/src/error/indyError.ts | 100 --- packages/indy-sdk/src/index.ts | 23 - packages/indy-sdk/src/ledger/IndySdkPool.ts | 218 ------ .../indy-sdk/src/ledger/IndySdkPoolService.ts | 357 ---------- .../__tests__/IndySdkPoolService.test.ts | 422 ------------ .../src/ledger/__tests__/didResponses.ts | 58 -- .../serializeRequestForSignature.test.ts | 87 --- .../src/ledger/__tests__/util.test.ts | 45 -- .../src/ledger/error/IndySdkPoolError.ts | 7 - .../error/IndySdkPoolNotConfiguredError.ts | 7 - .../ledger/error/IndySdkPoolNotFoundError.ts | 7 - packages/indy-sdk/src/ledger/error/index.ts | 3 - packages/indy-sdk/src/ledger/index.ts | 2 - .../ledger/serializeRequestForSignature.ts | 61 -- packages/indy-sdk/src/ledger/util.ts | 9 - .../src/storage/IndySdkStorageService.ts | 328 --------- .../__tests__/IndySdkStorageService.test.ts | 314 --------- packages/indy-sdk/src/storage/index.ts | 1 - packages/indy-sdk/src/types.ts | 6 - .../indy-sdk/src/utils/__tests__/did.test.ts | 77 --- .../indy-sdk/src/utils/assertIndySdkWallet.ts | 13 - packages/indy-sdk/src/utils/did.ts | 89 --- packages/indy-sdk/src/utils/promises.ts | 44 -- packages/indy-sdk/src/wallet/IndySdkWallet.ts | 645 ------------------ .../wallet/__tests__/IndySdkWallet.test.ts | 114 ---- packages/indy-sdk/src/wallet/index.ts | 1 - .../indy-sdk/tests/__fixtures__/anoncreds.ts | 30 - .../tests/indy-did-registrar.e2e.test.ts | 125 ---- .../tests/indy-did-resolver.e2e.test.ts | 99 --- .../indy-sdk-anoncreds-registry.e2e.test.ts | 345 ---------- packages/indy-sdk/tests/postgres.e2e.test.ts | 112 --- packages/indy-sdk/tests/setup.ts | 1 - packages/indy-sdk/tests/setupIndySdkModule.ts | 35 - .../tests/sov-did-resolver.e2e.test.ts | 102 --- packages/indy-sdk/tsconfig.build.json | 7 - packages/indy-sdk/tsconfig.json | 6 - .../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 6 +- packages/node/src/PostgresPlugin.ts | 108 --- packages/node/src/index.ts | 10 +- .../__tests__/QuestionAnswerService.test.ts | 6 +- .../tests/question-answer.e2e.test.ts | 8 +- packages/react-native/jest.config.ts | 4 - yarn.lock | 14 + 92 files changed, 46 insertions(+), 8476 deletions(-) delete mode 100644 .github/actions/setup-postgres-wallet-plugin/action.yml delete mode 100644 TROUBLESHOOTING.md delete mode 100644 packages/indy-sdk/CHANGELOG.md delete mode 100644 packages/indy-sdk/README.md delete mode 100644 packages/indy-sdk/jest.config.ts delete mode 100644 packages/indy-sdk/package.json delete mode 100644 packages/indy-sdk/src/IndySdkModule.ts delete mode 100644 packages/indy-sdk/src/IndySdkModuleConfig.ts delete mode 100644 packages/indy-sdk/src/anoncreds/index.ts delete mode 100644 packages/indy-sdk/src/anoncreds/services/IndySdkAnonCredsRegistry.ts delete mode 100644 packages/indy-sdk/src/anoncreds/services/IndySdkHolderService.ts delete mode 100644 packages/indy-sdk/src/anoncreds/services/IndySdkIssuerService.ts delete mode 100644 packages/indy-sdk/src/anoncreds/services/IndySdkIssuerServiceMetadata.ts delete mode 100644 packages/indy-sdk/src/anoncreds/services/IndySdkRevocationService.ts delete mode 100644 packages/indy-sdk/src/anoncreds/services/IndySdkVerifierService.ts delete mode 100644 packages/indy-sdk/src/anoncreds/utils/__tests__/assertUnqualified.test.ts delete mode 100644 packages/indy-sdk/src/anoncreds/utils/__tests__/identifiers.test.ts delete mode 100644 packages/indy-sdk/src/anoncreds/utils/__tests__/transform.test.ts delete mode 100644 packages/indy-sdk/src/anoncreds/utils/assertUnqualified.ts delete mode 100644 packages/indy-sdk/src/anoncreds/utils/identifiers.ts delete mode 100644 packages/indy-sdk/src/anoncreds/utils/tails.ts delete mode 100644 packages/indy-sdk/src/anoncreds/utils/transform.ts delete mode 100644 packages/indy-sdk/src/dids/IndySdkIndyDidRegistrar.ts delete mode 100644 packages/indy-sdk/src/dids/IndySdkIndyDidResolver.ts delete mode 100644 packages/indy-sdk/src/dids/IndySdkSovDidResolver.ts delete mode 100644 packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidRegistrar.test.ts delete mode 100644 packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidResolver.test.ts delete mode 100644 packages/indy-sdk/src/dids/__tests__/IndySdkSovDidResolver.test.ts delete mode 100644 packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1R1xKJw17sUoXhejEpugMYJ.json delete mode 100644 packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1WJz9mHyW9BZksioQnRsrAo.json delete mode 100644 packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovR1xKJw17sUoXhejEpugMYJ.json delete mode 100644 packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovWJz9mHyW9BZksioQnRsrAo.json delete mode 100644 packages/indy-sdk/src/dids/didIndyUtil.ts delete mode 100644 packages/indy-sdk/src/dids/didSovUtil.ts delete mode 100644 packages/indy-sdk/src/dids/index.ts delete mode 100644 packages/indy-sdk/src/error/IndySdkError.ts delete mode 100644 packages/indy-sdk/src/error/index.ts delete mode 100644 packages/indy-sdk/src/error/indyError.ts delete mode 100644 packages/indy-sdk/src/index.ts delete mode 100644 packages/indy-sdk/src/ledger/IndySdkPool.ts delete mode 100644 packages/indy-sdk/src/ledger/IndySdkPoolService.ts delete mode 100644 packages/indy-sdk/src/ledger/__tests__/IndySdkPoolService.test.ts delete mode 100644 packages/indy-sdk/src/ledger/__tests__/didResponses.ts delete mode 100644 packages/indy-sdk/src/ledger/__tests__/serializeRequestForSignature.test.ts delete mode 100644 packages/indy-sdk/src/ledger/__tests__/util.test.ts delete mode 100644 packages/indy-sdk/src/ledger/error/IndySdkPoolError.ts delete mode 100644 packages/indy-sdk/src/ledger/error/IndySdkPoolNotConfiguredError.ts delete mode 100644 packages/indy-sdk/src/ledger/error/IndySdkPoolNotFoundError.ts delete mode 100644 packages/indy-sdk/src/ledger/error/index.ts delete mode 100644 packages/indy-sdk/src/ledger/index.ts delete mode 100644 packages/indy-sdk/src/ledger/serializeRequestForSignature.ts delete mode 100644 packages/indy-sdk/src/ledger/util.ts delete mode 100644 packages/indy-sdk/src/storage/IndySdkStorageService.ts delete mode 100644 packages/indy-sdk/src/storage/__tests__/IndySdkStorageService.test.ts delete mode 100644 packages/indy-sdk/src/storage/index.ts delete mode 100644 packages/indy-sdk/src/types.ts delete mode 100644 packages/indy-sdk/src/utils/__tests__/did.test.ts delete mode 100644 packages/indy-sdk/src/utils/assertIndySdkWallet.ts delete mode 100644 packages/indy-sdk/src/utils/did.ts delete mode 100644 packages/indy-sdk/src/utils/promises.ts delete mode 100644 packages/indy-sdk/src/wallet/IndySdkWallet.ts delete mode 100644 packages/indy-sdk/src/wallet/__tests__/IndySdkWallet.test.ts delete mode 100644 packages/indy-sdk/src/wallet/index.ts delete mode 100644 packages/indy-sdk/tests/__fixtures__/anoncreds.ts delete mode 100644 packages/indy-sdk/tests/indy-did-registrar.e2e.test.ts delete mode 100644 packages/indy-sdk/tests/indy-did-resolver.e2e.test.ts delete mode 100644 packages/indy-sdk/tests/indy-sdk-anoncreds-registry.e2e.test.ts delete mode 100644 packages/indy-sdk/tests/postgres.e2e.test.ts delete mode 100644 packages/indy-sdk/tests/setup.ts delete mode 100644 packages/indy-sdk/tests/setupIndySdkModule.ts delete mode 100644 packages/indy-sdk/tests/sov-did-resolver.e2e.test.ts delete mode 100644 packages/indy-sdk/tsconfig.build.json delete mode 100644 packages/indy-sdk/tsconfig.json delete mode 100644 packages/node/src/PostgresPlugin.ts diff --git a/.github/actions/setup-postgres-wallet-plugin/action.yml b/.github/actions/setup-postgres-wallet-plugin/action.yml deleted file mode 100644 index a03b2f3fde..0000000000 --- a/.github/actions/setup-postgres-wallet-plugin/action.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Setup Postgres wallet plugin -description: Setup Postgres wallet plugin -author: 'sairanjit.tummalapalli@ayanworks.com' - -runs: - using: composite - steps: - # cargo build failing on latest release of rust due to - # socket2 dependency in the plugin https://users.rust-lang.org/t/build-broken-with-parse-quote-spanned-is-ambiguous/80280/2 - # so pointing rust version to 1.63.0 - - name: Setup Postgres wallet plugin - run: | - sudo apt-get install -y libzmq3-dev libsodium-dev pkg-config libssl-dev - curl https://sh.rustup.rs -sSf | bash -s -- -y - export PATH="/root/.cargo/bin:${PATH}" - rustup default 1.63.0 - cd ../ - git clone https://github.com/hyperledger/indy-sdk.git - cd indy-sdk/experimental/plugins/postgres_storage/ - cargo build --release - shell: bash diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 57edd1bb1d..f004beee36 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -12,7 +12,6 @@ env: TEST_AGENT_PUBLIC_DID_SEED: 000000000000000000000000Trustee9 ENDORSER_AGENT_PUBLIC_DID_SEED: 00000000000000000000000Endorser9 GENESIS_TXN_PATH: network/genesis/local-genesis.txn - LIB_INDY_STRG_POSTGRES: /home/runner/work/aries-framework-javascript/indy-sdk/experimental/plugins/postgres_storage/target/release # for Linux NODE_OPTIONS: --max_old_space_size=6144 # Make sure we're not running multiple release steps at the same time as this can give issues with determining the next npm version to release. @@ -107,9 +106,6 @@ jobs: - name: Setup Postgres uses: ./.github/actions/setup-postgres - - name: Setup Postgres wallet plugin - uses: ./.github/actions/setup-postgres-wallet-plugin - - name: Setup NodeJS uses: actions/setup-node@v3 with: diff --git a/README.md b/README.md index c7a2d8cccf..1ecf7e4fb8 100644 --- a/README.md +++ b/README.md @@ -82,14 +82,6 @@ Aries Framework JavaScript is a framework written in TypeScript for building **S - - @aries-framework/indy-sdk - - - @aries-framework/indy-sdk version - - - @aries-framework/indy-vdr @@ -161,6 +153,14 @@ Aries Framework JavaScript is a framework written in TypeScript for building **S + + ~~@aries-framework/indy-sdk~~ (deprecated, unmaintained after 0.4.x) + + + @aries-framework/indy-sdk version + + + ## Getting Started diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md deleted file mode 100644 index c8f698a43b..0000000000 --- a/TROUBLESHOOTING.md +++ /dev/null @@ -1,85 +0,0 @@ -# Troubleshooting - -This document contains the most common errors that arise when first installing libindy and Aries Framework JavaScript. If you encounter a problem that is not listed here and manage to fix it, please open a PR describing the steps taken to resolve the issue. - -- [macOS](#macos) - - [Unable to find `libindy.dylib`](#unable-to-find-libindydylib) - - [Unable to find `libssl.1.0.0.dylib`](#unable-to-find-libssl100dylib) - - [Library not loaded: `libsodium.18.dylib`](#library-not-loaded-libsodium18dylib) - -## macOS - -### Unable to find `libindy.dylib` - -Installing Libindy on macOS can be tricky. If the the troubleshooting section of the NodeJS Wrapper documentation doesn't provide an answer and you're getting the following error: - -``` -dlopen(//aries-framework-javascript/node_modules/indy-sdk/build/Release/indynodejs.node, 1): Library not loaded: /Users/jenkins/workspace/indy-sdk_indy-sdk-cd_master/libindy/target/release/deps/libindy.dylib - Referenced from: //aries-framework-javascript/node_modules/indy-sdk/build/Release/indynodejs.node - Reason: image not found -``` - -See this StackOverflow answer: https://stackoverflow.com/questions/19776571/error-dlopen-library-not-loaded-reason-image-not-found - -The NodeJS Wrapper tries to find the library at the hardcoded CI built path `/Users/jenkins/workspace/indy-sdk_indy-sdk-cd_master/libindy/target/release/deps/libindy.dylib`. However the library will probably be located at `/usr/local/lib/libindy.dylib` (depending on how you installed libindy). - -To check where the NodeJS wrapper points to the static CI build path you can run: - -```bash -$ otool -L node_modules/indy-sdk/build/Release/indynodejs.node -node_modules/indy-sdk/build/Release/indynodejs.node: - /Users/jenkins/workspace/indy-sdk_indy-sdk-cd_master/libindy/target/release/deps/libindy.dylib (compatibility version 0.0.0, current version 0.0.0) - /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 902.1.0) - /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1) -``` - -You can manually change the path using the `install_name_tool`. Be sure change the path if you're not using the default. - -```bash -install_name_tool -change /Users/jenkins/workspace/indy-sdk_indy-sdk-cd_master/libindy/target/release/deps/libindy.dylib /usr/local/lib/libindy.dylib node_modules/indy-sdk/build/Release/indynodejs.node -``` - -### Unable to find `libssl.1.0.0.dylib` - -Libindy makes use of OpenSSL 1.0, however macOS by default has OpenSSL version 1.1. The standard brew repo also doesn't contain version 1.0 anymore. So if you're getting something that looks like the following error: - -``` -dlopen(//aries-framework-javascript/node_modules/indy-sdk/build/Release/indynodejs.node, 1): Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib - Referenced from: //libindy_1.15.0/lib/libindy.dylib - Reason: image not found -``` - -You can manually install OpenSSL 1.0 with the following Brew command: - -```sh -brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/64555220bfbf4a25598523c2e4d3a232560eaad7/Formula/openssl.rb -f -``` - -In newer versions of HomeBrew installing packages is disabled, which will give an error that looks something like this: - -``` -Error: Calling Installation of openssl from a GitHub commit URL is disabled! Use 'brew extract openssl' to stable tap on GitHub instead. -``` - -They advise to use `brew extract` which also gives errors. The easiest way is to download the file and then extract it: - -```sh -curl https://raw.githubusercontent.com/Homebrew/homebrew-core/64555220bfbf4a25598523c2e4d3a232560eaad7/Formula/openssl.rb -o openssl.rb -brew install openssl.rb -``` - -### Library not loaded: `libsodium.18.dylib` - -When you install `libsodium` it automatically installs version 23. However libindy needs version 18. So if you're getting something that looks like the following error: - -``` -dyld: Library not loaded: /usr/local/opt/libsodium/lib/libsodium.18.dylib -``` - -You can manually link the path for version 18 to the path of version 23 with the following command: - -```sh -ln -s /usr/local/opt/libsodium/lib/libsodium.23.dylib /usr/local/opt/libsodium/lib/libsodium.18.dylib -``` - -Inspired by [this answer](https://github.com/Homebrew/homebrew-php/issues/4589) to the same error using php71-libsodium. diff --git a/demo/package.json b/demo/package.json index 4ffbef505b..096f60cfbd 100644 --- a/demo/package.json +++ b/demo/package.json @@ -24,12 +24,10 @@ "@aries-framework/anoncreds-rs": "*", "@aries-framework/askar": "*", "@aries-framework/core": "*", - "@aries-framework/indy-sdk": "*", "@aries-framework/indy-vdr": "*", "@aries-framework/cheqd": "*", "@aries-framework/node": "*", "@types/figlet": "^1.5.4", - "@types/indy-sdk": "^1.16.26", "@types/inquirer": "^8.2.6", "clear": "^0.1.0", "figlet": "^1.5.2", diff --git a/demo/src/BaseAgent.ts b/demo/src/BaseAgent.ts index c2e787e32a..8c174a7fe6 100644 --- a/demo/src/BaseAgent.ts +++ b/demo/src/BaseAgent.ts @@ -1,5 +1,4 @@ import type { InitConfig } from '@aries-framework/core' -import type { IndySdkPoolConfig } from '@aries-framework/indy-sdk' import type { IndyVdrPoolConfig } from '@aries-framework/indy-vdr' import { @@ -32,14 +31,11 @@ import { Agent, HttpOutboundTransport, } from '@aries-framework/core' -import { IndySdkAnonCredsRegistry, IndySdkModule, IndySdkSovDidResolver } from '@aries-framework/indy-sdk' import { IndyVdrIndyDidResolver, IndyVdrAnonCredsRegistry, IndyVdrModule } from '@aries-framework/indy-vdr' import { agentDependencies, HttpInboundTransport } from '@aries-framework/node' import { anoncreds } from '@hyperledger/anoncreds-nodejs' import { ariesAskar } from '@hyperledger/aries-askar-nodejs' import { indyVdr } from '@hyperledger/indy-vdr-nodejs' -import { randomUUID } from 'crypto' -import indySdk from 'indy-sdk' import { greenText } from './OutputClass' @@ -49,13 +45,11 @@ const bcovrin = `{"reqSignature":{},"txn":{"data":{"data":{"alias":"Node1","blsk {"reqSignature":{},"txn":{"data":{"data":{"alias":"Node4","blskey":"2zN3bHM1m4rLz54MJHYSwvqzPchYp8jkHswveCLAEJVcX6Mm1wHQD1SkPYMzUDTZvWvhuE6VNAkK3KxVeEmsanSmvjVkReDeBEMxeDaayjcZjFGPydyey1qxBHmTvAnBKoPydvuTAqx5f7YNNRAdeLmUi99gERUU7TD8KfAa6MpQ9bw","blskey_pop":"RPLagxaR5xdimFzwmzYnz4ZhWtYQEj8iR5ZU53T2gitPCyCHQneUn2Huc4oeLd2B2HzkGnjAff4hWTJT6C7qHYB1Mv2wU5iHHGFWkhnTX9WsEAbunJCV2qcaXScKj4tTfvdDKfLiVuU2av6hbsMztirRze7LvYBkRHV3tGwyCptsrP","client_ip":"138.197.138.255","client_port":9708,"node_ip":"138.197.138.255","node_port":9707,"services":["VALIDATOR"]},"dest":"4PS3EDQ3dW1tci1Bp6543CfuuebjFrg36kLAUcskGfaA"},"metadata":{"from":"TWwCRQRZ2ZHMJFn9TzLp7W"},"type":"0"},"txnMetadata":{"seqNo":4,"txnId":"aa5e817d7cc626170eca175822029339a444eb0ee8f0bd20d3b0b76e566fb008"},"ver":"1"}` export const indyNetworkConfig = { - // Need unique network id as we will have multiple agent processes in the agent - id: randomUUID(), genesisTransactions: bcovrin, indyNamespace: 'bcovrin:test', isProduction: false, connectOnStartup: true, -} satisfies IndySdkPoolConfig | IndyVdrPoolConfig +} satisfies IndyVdrPoolConfig type DemoAgent = Agent> @@ -167,46 +161,3 @@ function getAskarAnonCredsIndyModules() { }), } as const } - -function getLegacyIndySdkModules() { - const legacyIndyCredentialFormatService = new LegacyIndyCredentialFormatService() - const legacyIndyProofFormatService = new LegacyIndyProofFormatService() - - return { - connections: new ConnectionsModule({ - autoAcceptConnections: true, - }), - credentials: new CredentialsModule({ - autoAcceptCredentials: AutoAcceptCredential.ContentApproved, - credentialProtocols: [ - new V1CredentialProtocol({ - indyCredentialFormat: legacyIndyCredentialFormatService, - }), - new V2CredentialProtocol({ - credentialFormats: [legacyIndyCredentialFormatService], - }), - ], - }), - proofs: new ProofsModule({ - autoAcceptProofs: AutoAcceptProof.ContentApproved, - proofProtocols: [ - new V1ProofProtocol({ - indyProofFormat: legacyIndyProofFormatService, - }), - new V2ProofProtocol({ - proofFormats: [legacyIndyProofFormatService], - }), - ], - }), - anoncreds: new AnonCredsModule({ - registries: [new IndySdkAnonCredsRegistry()], - }), - indySdk: new IndySdkModule({ - indySdk, - networks: [indyNetworkConfig], - }), - dids: new DidsModule({ - resolvers: [new IndySdkSovDidResolver()], - }), - } as const -} diff --git a/package.json b/package.json index 3f7c1efbac..7a6f393934 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-workspaces": "^0.8.0", "express": "^4.17.1", - "indy-sdk": "^1.16.0-dev-1655", "jest": "^29.7.0", "lerna": "^6.5.1", "prettier": "^2.3.1", @@ -65,5 +64,8 @@ }, "engines": { "node": ">=18" + }, + "dependencies": { + "@hyperledger/aries-askar-nodejs": "^0.1.0" } } diff --git a/packages/anoncreds/package.json b/packages/anoncreds/package.json index 2a232a35c3..604bb47f59 100644 --- a/packages/anoncreds/package.json +++ b/packages/anoncreds/package.json @@ -32,7 +32,6 @@ }, "devDependencies": { "@aries-framework/node": "0.4.2", - "indy-sdk": "^1.16.0-dev-1636", "rimraf": "^4.4.0", "rxjs": "^7.8.0", "typescript": "~4.9.5" diff --git a/packages/anoncreds/src/AnonCredsApi.ts b/packages/anoncreds/src/AnonCredsApi.ts index 5659f5a813..36aaf7fa19 100644 --- a/packages/anoncreds/src/AnonCredsApi.ts +++ b/packages/anoncreds/src/AnonCredsApi.ts @@ -261,6 +261,8 @@ export class AnonCredsApi { supportRevocation: false, schema: schemaResult.schema, }, + // NOTE: indy-sdk support has been removed from main repo, but keeping + // this in place to allow the indy-sdk to still be used as a custom package // FIXME: Indy SDK requires the schema seq no to be passed in here. This is not ideal. { indyLedgerSchemaSeqNo: schemaResult.schemaMetadata.indyLedgerSeqNo, diff --git a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts index 7ca8053a38..a05a6d4199 100644 --- a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts +++ b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts @@ -122,6 +122,8 @@ describe('Legacy indy format services', () => { supportRevocation: false, }, { + // NOTE: indy-sdk support has been removed from main repo, but keeping + // this in place to allow the indy-sdk to still be used as a custom package // Need to pass this as the indy-sdk MUST have the seqNo indyLedgerSchemaSeqNo: schemaMetadata.indyLedgerSeqNo as number, } diff --git a/packages/askar/tests/helpers.ts b/packages/askar/tests/helpers.ts index e02e5cd542..cc6d1cfeed 100644 --- a/packages/askar/tests/helpers.ts +++ b/packages/askar/tests/helpers.ts @@ -15,6 +15,7 @@ import { AskarWallet } from '../src/wallet' export const askarModuleConfig = new AskarModuleConfig({ ariesAskar }) registerAriesAskar({ askar: askarModuleConfig.ariesAskar }) +export const askarModule = new AskarModule(askarModuleConfig) // When using the AskarWallet directly, the native dependency won't be loaded by default. // So in tests depending on Askar, we import this wallet so we're sure the native dependency is loaded. diff --git a/packages/cheqd/package.json b/packages/cheqd/package.json index bb396fe211..5361401ad1 100644 --- a/packages/cheqd/package.json +++ b/packages/cheqd/package.json @@ -37,8 +37,6 @@ "tsyringe": "^4.8.0" }, "devDependencies": { - "@aries-framework/indy-sdk": "0.4.2", - "@types/indy-sdk": "*", "rimraf": "^4.0.7", "typescript": "~4.9.4" } diff --git a/packages/cheqd/tests/setupCheqdModule.ts b/packages/cheqd/tests/setupCheqdModule.ts index 8dc516fe1c..3e99bbdcb5 100644 --- a/packages/cheqd/tests/setupCheqdModule.ts +++ b/packages/cheqd/tests/setupCheqdModule.ts @@ -1,16 +1,10 @@ import type { CheqdModuleConfigOptions } from '../src' import { DidsModule } from '@aries-framework/core' -import { IndySdkModule, IndySdkModuleConfig } from '@aries-framework/indy-sdk' -import indySdk from 'indy-sdk' +import { askarModule } from '../../askar/tests/helpers' import { CheqdModule, CheqdDidRegistrar, CheqdDidResolver } from '../src' -export const getIndySdkModuleConfig = () => - new IndySdkModuleConfig({ - indySdk, - }) - export const getCheqdModuleConfig = (seed?: string, rpcUrl?: string) => ({ networks: [ @@ -30,5 +24,5 @@ export const getCheqdModules = (seed?: string, rpcUrl?: string) => ({ registrars: [new CheqdDidRegistrar()], resolvers: [new CheqdDidResolver()], }), - indySdk: new IndySdkModule(getIndySdkModuleConfig()), + askarModule, }) diff --git a/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts b/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts index d4a73bd169..5688e3a49f 100644 --- a/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts +++ b/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts @@ -1,22 +1,16 @@ import type { InitConfig } from '@aries-framework/core' -import { AskarModule } from '@aries-framework/askar' import { utils, KeyDerivationMethod, Agent } from '@aries-framework/core' import { IndySdkModule } from '@aries-framework/indy-sdk' import { agentDependencies } from '@aries-framework/node' -import { ariesAskar } from '@hyperledger/aries-askar-nodejs' -import { registerAriesAskar } from '@hyperledger/aries-askar-shared' import indy from 'indy-sdk' import { homedir } from 'os' +import { askarModule } from '../../askar/tests/helpers' import { IndySdkToAskarMigrationUpdater } from '../src' import { IndySdkToAskarMigrationError } from '../src/errors/IndySdkToAskarMigrationError' describe('Indy SDK To Askar Migration', () => { - beforeAll(() => { - registerAriesAskar({ askar: ariesAskar }) - }) - test('indy-sdk sqlite to aries-askar sqlite successful migration', async () => { const indySdkAndAskarConfig: InitConfig = { label: `indy | indy-sdk sqlite to aries-askar sqlite successful migration | ${utils.uuid()}`, @@ -45,7 +39,7 @@ describe('Indy SDK To Askar Migration', () => { const askarAgent = new Agent({ config: indySdkAndAskarConfig, - modules: { askar: new AskarModule({ ariesAskar }) }, + modules: { askar: askarModule }, dependencies: agentDependencies, }) @@ -98,9 +92,7 @@ describe('Indy SDK To Askar Migration', () => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion config: { ...indySdkAndAskarConfig, walletConfig: { ...indySdkAndAskarConfig.walletConfig!, key: 'wrong-key' } }, modules: { - askar: new AskarModule({ - ariesAskar, - }), + askar: askarModule, }, dependencies: agentDependencies, }) diff --git a/packages/indy-sdk/CHANGELOG.md b/packages/indy-sdk/CHANGELOG.md deleted file mode 100644 index 162267c246..0000000000 --- a/packages/indy-sdk/CHANGELOG.md +++ /dev/null @@ -1,59 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [0.4.2](https://github.com/hyperledger/aries-framework-javascript/compare/v0.4.1...v0.4.2) (2023-10-05) - -### Bug Fixes - -- update tsyringe for ts 5 support ([#1588](https://github.com/hyperledger/aries-framework-javascript/issues/1588)) ([296955b](https://github.com/hyperledger/aries-framework-javascript/commit/296955b3a648416ac6b502da05a10001920af222)) - -## [0.4.1](https://github.com/hyperledger/aries-framework-javascript/compare/v0.4.0...v0.4.1) (2023-08-28) - -### Bug Fixes - -- **anoncreds:** wrong key name for predicates in proof object ([#1517](https://github.com/hyperledger/aries-framework-javascript/issues/1517)) ([d895c78](https://github.com/hyperledger/aries-framework-javascript/commit/d895c78e0e02954a95ad1fd7e2251ee9a02445dc)) -- force did:key resolver/registrar presence ([#1535](https://github.com/hyperledger/aries-framework-javascript/issues/1535)) ([aaa13dc](https://github.com/hyperledger/aries-framework-javascript/commit/aaa13dc77d6d5133cd02e768e4173462fa65064a)) - -### Features - -- **anoncreds:** auto create link secret ([#1521](https://github.com/hyperledger/aries-framework-javascript/issues/1521)) ([c6f03e4](https://github.com/hyperledger/aries-framework-javascript/commit/c6f03e49d79a33b1c4b459cef11add93dee051d0)) - -# [0.4.0](https://github.com/hyperledger/aries-framework-javascript/compare/v0.3.3...v0.4.0) (2023-06-03) - -### Bug Fixes - -- **anoncreds:** include prover_did for legacy indy ([#1342](https://github.com/hyperledger/aries-framework-javascript/issues/1342)) ([d38ecb1](https://github.com/hyperledger/aries-framework-javascript/commit/d38ecb14cb58f1eb78e01c91699bb990d805dc08)) -- **anoncreds:** make revocation status list inline with the spec ([#1421](https://github.com/hyperledger/aries-framework-javascript/issues/1421)) ([644e860](https://github.com/hyperledger/aries-framework-javascript/commit/644e860a05f40166e26c497a2e8619c9a38df11d)) -- did cache key not being set correctly ([#1394](https://github.com/hyperledger/aries-framework-javascript/issues/1394)) ([1125e81](https://github.com/hyperledger/aries-framework-javascript/commit/1125e81962ffa752bf40fa8f7f4226e186f22013)) -- expose indy pool configs and action menu messages ([#1333](https://github.com/hyperledger/aries-framework-javascript/issues/1333)) ([518e5e4](https://github.com/hyperledger/aries-framework-javascript/commit/518e5e4dfb59f9c0457bfd233409e9f4b3c429ee)) -- **indy-sdk:** import from core ([#1346](https://github.com/hyperledger/aries-framework-javascript/issues/1346)) ([254f661](https://github.com/hyperledger/aries-framework-javascript/commit/254f661c2e925b62dd07c3565099f9e226bd2b41)) -- issuance with unqualified identifiers ([#1431](https://github.com/hyperledger/aries-framework-javascript/issues/1431)) ([de90caf](https://github.com/hyperledger/aries-framework-javascript/commit/de90cafb8d12b7a940f881184cd745c4b5043cbc)) -- reference to indyLedgers in IndyXXXNotConfiguredError ([#1397](https://github.com/hyperledger/aries-framework-javascript/issues/1397)) ([d6e2ea2](https://github.com/hyperledger/aries-framework-javascript/commit/d6e2ea2194a4860265fe299ef8ee4cb4799ab1a6)) -- remove named capture groups ([#1378](https://github.com/hyperledger/aries-framework-javascript/issues/1378)) ([a4204ef](https://github.com/hyperledger/aries-framework-javascript/commit/a4204ef2db769de53d12f0d881d2c4422545c390)) -- seed and private key validation and return type in registrars ([#1324](https://github.com/hyperledger/aries-framework-javascript/issues/1324)) ([c0e5339](https://github.com/hyperledger/aries-framework-javascript/commit/c0e5339edfa32df92f23fb9c920796b4b59adf52)) -- various anoncreds revocation fixes ([#1416](https://github.com/hyperledger/aries-framework-javascript/issues/1416)) ([d9cfc7d](https://github.com/hyperledger/aries-framework-javascript/commit/d9cfc7df6679d2008d66070a6c8a818440d066ab)) - -- feat!: add data, cache and temp dirs to FileSystem (#1306) ([ff5596d](https://github.com/hyperledger/aries-framework-javascript/commit/ff5596d0631e93746494c017797d0191b6bdb0b1)), closes [#1306](https://github.com/hyperledger/aries-framework-javascript/issues/1306) - -### Features - -- 0.4.0 migration script ([#1392](https://github.com/hyperledger/aries-framework-javascript/issues/1392)) ([bc5455f](https://github.com/hyperledger/aries-framework-javascript/commit/bc5455f7b42612a2b85e504bc6ddd36283a42bfa)) -- add anoncreds-rs package ([#1275](https://github.com/hyperledger/aries-framework-javascript/issues/1275)) ([efe0271](https://github.com/hyperledger/aries-framework-javascript/commit/efe0271198f21f1307df0f934c380f7a5c720b06)) -- add fetch indy schema method ([#1290](https://github.com/hyperledger/aries-framework-javascript/issues/1290)) ([1d782f5](https://github.com/hyperledger/aries-framework-javascript/commit/1d782f54bbb4abfeb6b6db6cd4f7164501b6c3d9)) -- **anoncreds:** add anoncreds API ([#1232](https://github.com/hyperledger/aries-framework-javascript/issues/1232)) ([3a4c5ec](https://github.com/hyperledger/aries-framework-javascript/commit/3a4c5ecd940e49d4d192eef1d41f2aaedb34d85a)) -- **anoncreds:** add getCredential(s) methods ([#1386](https://github.com/hyperledger/aries-framework-javascript/issues/1386)) ([2efc009](https://github.com/hyperledger/aries-framework-javascript/commit/2efc0097138585391940fbb2eb504e50df57ec87)) -- **anoncreds:** add legacy indy credential format ([#1220](https://github.com/hyperledger/aries-framework-javascript/issues/1220)) ([13f3740](https://github.com/hyperledger/aries-framework-javascript/commit/13f374079262168f90ec7de7c3393beb9651295c)) -- **anoncreds:** legacy indy proof format service ([#1283](https://github.com/hyperledger/aries-framework-javascript/issues/1283)) ([c72fd74](https://github.com/hyperledger/aries-framework-javascript/commit/c72fd7416f2c1bc0497a84036e16adfa80585e49)) -- **anoncreds:** store method name in records ([#1387](https://github.com/hyperledger/aries-framework-javascript/issues/1387)) ([47636b4](https://github.com/hyperledger/aries-framework-javascript/commit/47636b4a08ffbfa9a3f2a5a3c5aebda44f7d16c8)) -- **anoncreds:** use legacy prover did ([#1374](https://github.com/hyperledger/aries-framework-javascript/issues/1374)) ([c17013c](https://github.com/hyperledger/aries-framework-javascript/commit/c17013c808a278d624210ce9e4333860cd78fc19)) -- **cache:** add caching interface ([#1229](https://github.com/hyperledger/aries-framework-javascript/issues/1229)) ([25b2bcf](https://github.com/hyperledger/aries-framework-javascript/commit/25b2bcf81648100b572784e4489a288cc9da0557)) -- **indy-vdr:** add IndyVdrAnonCredsRegistry ([#1270](https://github.com/hyperledger/aries-framework-javascript/issues/1270)) ([d056316](https://github.com/hyperledger/aries-framework-javascript/commit/d056316712b5ee5c42a159816b5dda0b05ad84a8)) -- **openid4vc:** jwt format and more crypto ([#1472](https://github.com/hyperledger/aries-framework-javascript/issues/1472)) ([bd4932d](https://github.com/hyperledger/aries-framework-javascript/commit/bd4932d34f7314a6d49097b6460c7570e1ebc7a8)) - -### BREAKING CHANGES - -- Agent-produced files will now be divided in different system paths depending on their nature: data, temp and cache. Previously, they were located at a single location, defaulting to a temporary directory. - -If you specified a custom path in `FileSystem` object constructor, you now must provide an object containing `baseDataPath`, `baseTempPath` and `baseCachePath`. They can point to the same path, although it's recommended to specify different path to avoid future file clashes. diff --git a/packages/indy-sdk/README.md b/packages/indy-sdk/README.md deleted file mode 100644 index 368d25db71..0000000000 --- a/packages/indy-sdk/README.md +++ /dev/null @@ -1,31 +0,0 @@ -

-
- Hyperledger Aries logo -

-

Aries Framework JavaScript IndySDK Module

-

- License - typescript - @aries-framework/indy-sdk version - -

-
- -IndySDK module for [Aries Framework JavaScript](https://github.com/hyperledger/aries-framework-javascript.git). diff --git a/packages/indy-sdk/jest.config.ts b/packages/indy-sdk/jest.config.ts deleted file mode 100644 index 93c0197296..0000000000 --- a/packages/indy-sdk/jest.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Config } from '@jest/types' - -import base from '../../jest.config.base' - -import packageJson from './package.json' - -const config: Config.InitialOptions = { - ...base, - displayName: packageJson.name, - setupFilesAfterEnv: ['./tests/setup.ts'], -} - -export default config diff --git a/packages/indy-sdk/package.json b/packages/indy-sdk/package.json deleted file mode 100644 index 2192662ac8..0000000000 --- a/packages/indy-sdk/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@aries-framework/indy-sdk", - "main": "build/index", - "types": "build/index", - "version": "0.4.2", - "files": [ - "build" - ], - "license": "Apache-2.0", - "publishConfig": { - "access": "public" - }, - "homepage": "https://github.com/hyperledger/aries-framework-javascript/tree/main/packages/indy-sdk", - "repository": { - "type": "git", - "url": "https://github.com/hyperledger/aries-framework-javascript", - "directory": "packages/indy-sdk" - }, - "scripts": { - "build": "yarn run clean && yarn run compile", - "clean": "rimraf ./build", - "compile": "tsc -p tsconfig.build.json", - "prepublishOnly": "yarn run build", - "test": "jest" - }, - "dependencies": { - "@aries-framework/anoncreds": "0.4.2", - "@aries-framework/core": "0.4.2", - "@stablelib/ed25519": "^1.0.3", - "@types/indy-sdk": "1.16.27", - "class-transformer": "0.5.1", - "class-validator": "0.14.0", - "rxjs": "^7.2.0", - "tsyringe": "^4.8.0" - }, - "devDependencies": { - "rimraf": "^4.4.0", - "typescript": "~4.9.5" - } -} diff --git a/packages/indy-sdk/src/IndySdkModule.ts b/packages/indy-sdk/src/IndySdkModule.ts deleted file mode 100644 index d099591543..0000000000 --- a/packages/indy-sdk/src/IndySdkModule.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { IndySdkModuleConfigOptions } from './IndySdkModuleConfig' -import type { AgentContext, DependencyManager, Module } from '@aries-framework/core' - -import { - AnonCredsHolderServiceSymbol, - AnonCredsIssuerServiceSymbol, - AnonCredsVerifierServiceSymbol, -} from '@aries-framework/anoncreds' -import { AriesFrameworkError, InjectionSymbols } from '@aries-framework/core' - -import { IndySdkModuleConfig } from './IndySdkModuleConfig' -import { IndySdkHolderService, IndySdkIssuerService, IndySdkVerifierService } from './anoncreds' -import { IndySdkPoolService } from './ledger' -import { IndySdkStorageService } from './storage' -import { IndySdkSymbol } from './types' -import { IndySdkWallet } from './wallet' - -export class IndySdkModule implements Module { - public readonly config: IndySdkModuleConfig - - public constructor(config: IndySdkModuleConfigOptions) { - this.config = new IndySdkModuleConfig(config) - } - - public register(dependencyManager: DependencyManager) { - dependencyManager.registerInstance(IndySdkSymbol, this.config.indySdk) - - // Register config - dependencyManager.registerInstance(IndySdkModuleConfig, this.config) - - if (dependencyManager.isRegistered(InjectionSymbols.Wallet)) { - throw new AriesFrameworkError('There is an instance of Wallet already registered') - } else { - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - } - - if (dependencyManager.isRegistered(InjectionSymbols.StorageService)) { - throw new AriesFrameworkError('There is an instance of StorageService already registered') - } else { - dependencyManager.registerSingleton(InjectionSymbols.StorageService, IndySdkStorageService) - } - - // NOTE: for now we are registering the needed indy services. We may want to make this - // more explicit and require the user to register the services they need on the specific modules. - dependencyManager.registerSingleton(IndySdkPoolService) - dependencyManager.registerSingleton(AnonCredsIssuerServiceSymbol, IndySdkIssuerService) - dependencyManager.registerSingleton(AnonCredsHolderServiceSymbol, IndySdkHolderService) - dependencyManager.registerSingleton(AnonCredsVerifierServiceSymbol, IndySdkVerifierService) - } - - public async initialize(agentContext: AgentContext): Promise { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - - for (const pool of indySdkPoolService.pools) { - if (pool.config.connectOnStartup) { - await pool.connect() - } - } - } -} diff --git a/packages/indy-sdk/src/IndySdkModuleConfig.ts b/packages/indy-sdk/src/IndySdkModuleConfig.ts deleted file mode 100644 index 65478f507c..0000000000 --- a/packages/indy-sdk/src/IndySdkModuleConfig.ts +++ /dev/null @@ -1,81 +0,0 @@ -import type { IndySdkPoolConfig } from './ledger' -import type * as IndySdk from 'indy-sdk' - -/** - * IndySdkModuleConfigOptions defines the interface for the options of the IndySdkModuleConfig class. - */ -export interface IndySdkModuleConfigOptions { - /** - * Implementation of the IndySdk interface according to the @types/indy-sdk package. - * - * - * ## Node.JS - * - * ```ts - * import * as indySdk from 'indy-sdk' - * - * const indySdkModule = new IndySdkModule({ - * indySdk - * }) - * ``` - * - * ## React Native - * - * ```ts - * import indySdk from 'indy-sdk-react-native' - * - * const indySdkModule = new IndySdkModule({ - * indySdk - * }) - * ``` - */ - indySdk: typeof IndySdk - - /** - * Array of indy networks to connect to. Each item in the list must include either the `genesisPath` or `genesisTransactions` property. - * - * @default [] - * - * @example - * ``` - * { - * isProduction: false, - * genesisPath: '/path/to/genesis.txn', - * indyNamespace: 'localhost:test', - * transactionAuthorAgreement: { - * version: '1', - * acceptanceMechanism: 'accept' - * } - * } - * ``` - */ - networks?: IndySdkPoolConfig[] - - /** - * Create a default link secret if there are no created link secrets. - * @defaultValue true - */ - autoCreateLinkSecret?: boolean -} - -export class IndySdkModuleConfig { - private options: IndySdkModuleConfigOptions - - public constructor(options: IndySdkModuleConfigOptions) { - this.options = options - } - - /** See {@link IndySdkModuleConfigOptions.indySdk} */ - public get indySdk() { - return this.options.indySdk - } - - public get networks() { - return this.options.networks ?? [] - } - - /** See {@link AnonCredsModuleConfigOptions.autoCreateLinkSecret} */ - public get autoCreateLinkSecret() { - return this.options.autoCreateLinkSecret ?? true - } -} diff --git a/packages/indy-sdk/src/anoncreds/index.ts b/packages/indy-sdk/src/anoncreds/index.ts deleted file mode 100644 index adba521ce0..0000000000 --- a/packages/indy-sdk/src/anoncreds/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { IndySdkAnonCredsRegistry } from './services/IndySdkAnonCredsRegistry' -export { IndySdkHolderService } from './services/IndySdkHolderService' -export { IndySdkIssuerService } from './services/IndySdkIssuerService' -export { IndySdkVerifierService } from './services/IndySdkVerifierService' diff --git a/packages/indy-sdk/src/anoncreds/services/IndySdkAnonCredsRegistry.ts b/packages/indy-sdk/src/anoncreds/services/IndySdkAnonCredsRegistry.ts deleted file mode 100644 index 21ab95ab53..0000000000 --- a/packages/indy-sdk/src/anoncreds/services/IndySdkAnonCredsRegistry.ts +++ /dev/null @@ -1,623 +0,0 @@ -import type { IndySdkPool } from '../../ledger' -import type { IndySdk } from '../../types' -import type { - AnonCredsRegistry, - GetCredentialDefinitionReturn, - GetRevocationStatusListReturn, - GetRevocationRegistryDefinitionReturn, - GetSchemaReturn, - RegisterCredentialDefinitionOptions, - RegisterCredentialDefinitionReturn, - RegisterSchemaOptions, - RegisterSchemaReturn, -} from '@aries-framework/anoncreds' -import type { AgentContext } from '@aries-framework/core' -import type { Schema as IndySdkSchema } from 'indy-sdk' - -import { - getUnqualifiedCredentialDefinitionId, - getUnqualifiedRevocationRegistryId, - getUnqualifiedSchemaId, - parseIndyCredentialDefinitionId, - parseIndyDid, - parseIndyRevocationRegistryId, - parseIndySchemaId, -} from '@aries-framework/anoncreds' - -import { verificationKeyForIndyDid } from '../../dids/didIndyUtil' -import { IndySdkError, isIndyError } from '../../error' -import { IndySdkPoolService } from '../../ledger' -import { IndySdkSymbol } from '../../types' -import { - getDidIndyCredentialDefinitionId, - getDidIndySchemaId, - indySdkAnonCredsRegistryIdentifierRegex, -} from '../utils/identifiers' -import { anonCredsRevocationStatusListFromIndySdk } from '../utils/transform' - -export class IndySdkAnonCredsRegistry implements AnonCredsRegistry { - public readonly methodName = 'indy' - - /** - * This class supports resolving and registering objects with did:indy as well as legacy indy identifiers. - * It needs to include support for the schema, credential definition, revocation registry as well - * as the issuer id (which is needed when registering objects). - */ - public readonly supportedIdentifier = indySdkAnonCredsRegistryIdentifierRegex - - public async getSchema(agentContext: AgentContext, schemaId: string): Promise { - try { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - // parse schema id (supports did:indy and legacy) - const { did, namespaceIdentifier, schemaName, schemaVersion } = parseIndySchemaId(schemaId) - const { pool } = await indySdkPoolService.getPoolForDid(agentContext, did) - agentContext.config.logger.debug(`Getting schema '${schemaId}' from ledger '${pool.didIndyNamespace}'`) - - // even though we support did:indy and legacy identifiers we always need to fetch using the legacy identifier - const legacySchemaId = getUnqualifiedSchemaId(namespaceIdentifier, schemaName, schemaVersion) - const request = await indySdk.buildGetSchemaRequest(null, legacySchemaId) - - agentContext.config.logger.trace( - `Submitting get schema request for schema '${schemaId}' to ledger '${pool.didIndyNamespace}'` - ) - const response = await indySdkPoolService.submitReadRequest(pool, request) - - agentContext.config.logger.trace(`Got un-parsed schema '${schemaId}' from ledger '${pool.didIndyNamespace}'`, { - response, - }) - - const [, schema] = await indySdk.parseGetSchemaResponse(response) - agentContext.config.logger.debug(`Got schema '${schemaId}' from ledger '${pool.didIndyNamespace}'`, { - schema, - }) - - return { - schema: { - attrNames: schema.attrNames, - name: schema.name, - version: schema.version, - issuerId: did, - }, - schemaId, - resolutionMetadata: {}, - schemaMetadata: { - didIndyNamespace: pool.didIndyNamespace, - // NOTE: the seqNo is required by the indy-sdk even though not present in AnonCreds v1. - // For this reason we return it in the metadata. - indyLedgerSeqNo: schema.seqNo, - }, - } - } catch (error) { - agentContext.config.logger.error(`Error retrieving schema '${schemaId}'`, { - error, - schemaId, - }) - - return { - schemaId, - resolutionMetadata: { - error: 'notFound', - message: `unable to resolve credential definition: ${error.message}`, - }, - schemaMetadata: {}, - } - } - } - - public async registerSchema( - agentContext: AgentContext, - options: RegisterSchemaOptions - ): Promise { - try { - // This will throw an error if trying to register a schema with a legacy indy identifier. We only support did:indy identifiers - // for registering, that will allow us to extract the namespace and means all stored records will use did:indy identifiers. - const { namespaceIdentifier, namespace } = parseIndyDid(options.schema.issuerId) - - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - const pool = indySdkPoolService.getPoolForNamespace(namespace) - agentContext.config.logger.debug( - `Register schema on ledger '${pool.didIndyNamespace}' with did '${options.schema.issuerId}'`, - options.schema - ) - - const didIndySchemaId = getDidIndySchemaId( - namespace, - namespaceIdentifier, - options.schema.name, - options.schema.version - ) - const legacySchemaId = getUnqualifiedSchemaId(namespaceIdentifier, options.schema.name, options.schema.version) - - const schema = { - attrNames: options.schema.attrNames, - name: options.schema.name, - version: options.schema.version, - id: legacySchemaId, - ver: '1.0', - // Casted as because the type expect a seqNo, but that's not actually required for the input of - // buildSchemaRequest (seqNo is not yet known) - } as IndySdkSchema - - const request = await indySdk.buildSchemaRequest(namespaceIdentifier, schema) - const submitterKey = await verificationKeyForIndyDid(agentContext, options.schema.issuerId) - - const response = await indySdkPoolService.submitWriteRequest(agentContext, pool, request, submitterKey) - agentContext.config.logger.debug(`Registered schema '${schema.id}' on ledger '${pool.didIndyNamespace}'`, { - response, - schema, - }) - - return { - schemaState: { - state: 'finished', - schema: { - attrNames: schema.attrNames, - issuerId: options.schema.issuerId, - name: schema.name, - version: schema.version, - }, - schemaId: didIndySchemaId, - }, - registrationMetadata: {}, - schemaMetadata: { - // NOTE: the seqNo is required by the indy-sdk even though not present in AnonCreds v1. - // For this reason we return it in the metadata. - indyLedgerSeqNo: response.result.txnMetadata.seqNo, - }, - } - } catch (error) { - agentContext.config.logger.error(`Error registering schema for did '${options.schema.issuerId}'`, { - error, - did: options.schema.issuerId, - schema: options.schema, - }) - - return { - schemaMetadata: {}, - registrationMetadata: {}, - schemaState: { - state: 'failed', - schema: options.schema, - reason: `unknownError: ${error.message}`, - }, - } - } - } - - public async getCredentialDefinition( - agentContext: AgentContext, - credentialDefinitionId: string - ): Promise { - try { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - // we support did:indy and legacy identifiers - const { did, namespaceIdentifier, schemaSeqNo, tag } = parseIndyCredentialDefinitionId(credentialDefinitionId) - const { pool } = await indySdkPoolService.getPoolForDid(agentContext, did) - - agentContext.config.logger.debug( - `Using ledger '${pool.didIndyNamespace}' to retrieve credential definition '${credentialDefinitionId}'` - ) - - const legacyCredentialDefinitionId = getUnqualifiedCredentialDefinitionId(namespaceIdentifier, schemaSeqNo, tag) - const request = await indySdk.buildGetCredDefRequest(null, legacyCredentialDefinitionId) - - agentContext.config.logger.trace( - `Submitting get credential definition request for credential definition '${credentialDefinitionId}' to ledger '${pool.didIndyNamespace}'` - ) - - const response = await indySdkPoolService.submitReadRequest(pool, request) - agentContext.config.logger.trace( - `Got un-parsed credential definition '${credentialDefinitionId}' from ledger '${pool.didIndyNamespace}'`, - { - response, - } - ) - - const [, credentialDefinition] = await indySdk.parseGetCredDefResponse(response) - const { schema } = await this.fetchIndySchemaWithSeqNo(agentContext, pool, Number(credentialDefinition.schemaId)) - - if (credentialDefinition && schema) { - agentContext.config.logger.debug( - `Got credential definition '${credentialDefinitionId}' from ledger '${pool.didIndyNamespace}'`, - { - credentialDefinition, - } - ) - - // Format the schema id based on the type of the credential definition id - const schemaId = credentialDefinitionId.startsWith('did:indy') - ? getDidIndySchemaId(pool.didIndyNamespace, namespaceIdentifier, schema.name, schema.version) - : schema.schemaId - - return { - credentialDefinitionId, - credentialDefinition: { - issuerId: did, - schemaId, - tag: credentialDefinition.tag, - type: 'CL', - value: credentialDefinition.value, - }, - credentialDefinitionMetadata: { - didIndyNamespace: pool.didIndyNamespace, - }, - resolutionMetadata: {}, - } - } - - agentContext.config.logger.error(`Error retrieving credential definition '${credentialDefinitionId}'`, { - credentialDefinitionId, - }) - - return { - credentialDefinitionId, - credentialDefinitionMetadata: {}, - resolutionMetadata: { - error: 'notFound', - message: `unable to resolve credential definition`, - }, - } - } catch (error) { - agentContext.config.logger.error(`Error retrieving credential definition '${credentialDefinitionId}'`, { - error, - credentialDefinitionId, - }) - - return { - credentialDefinitionId, - credentialDefinitionMetadata: {}, - resolutionMetadata: { - error: 'notFound', - message: `unable to resolve credential definition: ${error.message}`, - }, - } - } - } - - public async registerCredentialDefinition( - agentContext: AgentContext, - options: RegisterCredentialDefinitionOptions - ): Promise { - try { - // This will throw an error if trying to register a credential defintion with a legacy indy identifier. We only support did:indy - // identifiers for registering, that will allow us to extract the namespace and means all stored records will use did:indy identifiers. - const { namespaceIdentifier, namespace } = parseIndyDid(options.credentialDefinition.issuerId) - - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - const pool = indySdkPoolService.getPoolForNamespace(namespace) - agentContext.config.logger.debug( - `Registering credential definition on ledger '${pool.didIndyNamespace}' with did '${options.credentialDefinition.issuerId}'`, - options.credentialDefinition - ) - - // TODO: check structure of the schemaId - // TODO: this will bypass caching if done on a higher level. - const { schema, schemaMetadata, resolutionMetadata } = await this.getSchema( - agentContext, - options.credentialDefinition.schemaId - ) - - if (!schema || !schemaMetadata.indyLedgerSeqNo || typeof schemaMetadata.indyLedgerSeqNo !== 'number') { - return { - registrationMetadata: {}, - credentialDefinitionMetadata: { - didIndyNamespace: pool.didIndyNamespace, - }, - credentialDefinitionState: { - credentialDefinition: options.credentialDefinition, - state: 'failed', - reason: `error resolving schema with id ${options.credentialDefinition.schemaId}: ${resolutionMetadata.error} ${resolutionMetadata.message}`, - }, - } - } - - const legacyCredentialDefinitionId = getUnqualifiedCredentialDefinitionId( - namespaceIdentifier, - schemaMetadata.indyLedgerSeqNo, - options.credentialDefinition.tag - ) - const didIndyCredentialDefinitionId = getDidIndyCredentialDefinitionId( - namespace, - namespaceIdentifier, - schemaMetadata.indyLedgerSeqNo, - options.credentialDefinition.tag - ) - - const request = await indySdk.buildCredDefRequest(namespaceIdentifier, { - id: legacyCredentialDefinitionId, - // Indy ledger requires the credential schemaId to be a string of the schema seqNo. - schemaId: schemaMetadata.indyLedgerSeqNo.toString(), - tag: options.credentialDefinition.tag, - type: options.credentialDefinition.type, - value: options.credentialDefinition.value, - ver: '1.0', - }) - - const submitterKey = await verificationKeyForIndyDid(agentContext, options.credentialDefinition.issuerId) - const response = await indySdkPoolService.submitWriteRequest(agentContext, pool, request, submitterKey) - - agentContext.config.logger.debug( - `Registered credential definition '${didIndyCredentialDefinitionId}' on ledger '${pool.didIndyNamespace}'`, - { - response, - credentialDefinition: options.credentialDefinition, - } - ) - - return { - credentialDefinitionMetadata: {}, - credentialDefinitionState: { - credentialDefinition: options.credentialDefinition, - credentialDefinitionId: didIndyCredentialDefinitionId, - state: 'finished', - }, - registrationMetadata: {}, - } - } catch (error) { - agentContext.config.logger.error( - `Error registering credential definition for schema '${options.credentialDefinition.schemaId}'`, - { - error, - did: options.credentialDefinition.issuerId, - credentialDefinition: options.credentialDefinition, - } - ) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async getRevocationRegistryDefinition( - agentContext: AgentContext, - revocationRegistryDefinitionId: string - ): Promise { - try { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - const { did, namespaceIdentifier, credentialDefinitionTag, revocationRegistryTag, schemaSeqNo } = - parseIndyRevocationRegistryId(revocationRegistryDefinitionId) - const { pool } = await indySdkPoolService.getPoolForDid(agentContext, did) - - agentContext.config.logger.debug( - `Using ledger '${pool.didIndyNamespace}' to retrieve revocation registry definition '${revocationRegistryDefinitionId}'` - ) - - const legacyRevocationRegistryId = getUnqualifiedRevocationRegistryId( - namespaceIdentifier, - schemaSeqNo, - credentialDefinitionTag, - revocationRegistryTag - ) - const request = await indySdk.buildGetRevocRegDefRequest(null, legacyRevocationRegistryId) - - agentContext.config.logger.trace( - `Submitting get revocation registry definition request for revocation registry definition '${revocationRegistryDefinitionId}' to ledger` - ) - const response = await indySdkPoolService.submitReadRequest(pool, request) - agentContext.config.logger.trace( - `Got un-parsed revocation registry definition '${revocationRegistryDefinitionId}' from ledger '${pool.didIndyNamespace}'`, - { - response, - } - ) - - const [, revocationRegistryDefinition] = await indySdk.parseGetRevocRegDefResponse(response) - - agentContext.config.logger.debug( - `Got revocation registry definition '${revocationRegistryDefinitionId}' from ledger`, - { - revocationRegistryDefinition, - } - ) - - const credentialDefinitionId = revocationRegistryDefinitionId.startsWith('did:indy:') - ? getDidIndyCredentialDefinitionId( - pool.didIndyNamespace, - namespaceIdentifier, - schemaSeqNo, - credentialDefinitionTag - ) - : getUnqualifiedCredentialDefinitionId(namespaceIdentifier, schemaSeqNo, credentialDefinitionTag) - - return { - resolutionMetadata: {}, - revocationRegistryDefinition: { - issuerId: did, - credDefId: credentialDefinitionId, - value: { - maxCredNum: revocationRegistryDefinition.value.maxCredNum, - publicKeys: revocationRegistryDefinition.value.publicKeys, - tailsHash: revocationRegistryDefinition.value.tailsHash, - tailsLocation: revocationRegistryDefinition.value.tailsLocation, - }, - tag: revocationRegistryDefinition.tag, - revocDefType: 'CL_ACCUM', - }, - revocationRegistryDefinitionId, - revocationRegistryDefinitionMetadata: { - issuanceType: revocationRegistryDefinition.value.issuanceType, - didIndyNamespace: pool.didIndyNamespace, - }, - } - } catch (error) { - agentContext.config.logger.error( - `Error retrieving revocation registry definition '${revocationRegistryDefinitionId}' from ledger`, - { - error, - revocationRegistryDefinitionId: revocationRegistryDefinitionId, - } - ) - - return { - resolutionMetadata: { - error: 'notFound', - message: `unable to resolve revocation registry definition: ${error.message}`, - }, - revocationRegistryDefinitionId, - revocationRegistryDefinitionMetadata: {}, - } - } - } - - public async getRevocationStatusList( - agentContext: AgentContext, - revocationRegistryId: string, - timestamp: number - ): Promise { - try { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - const { did, namespaceIdentifier, schemaSeqNo, credentialDefinitionTag, revocationRegistryTag } = - parseIndyRevocationRegistryId(revocationRegistryId) - const { pool } = await indySdkPoolService.getPoolForDid(agentContext, did) - - agentContext.config.logger.debug( - `Using ledger '${pool.didIndyNamespace}' to retrieve revocation registry deltas with revocation registry definition id '${revocationRegistryId}' until ${timestamp}` - ) - - const legacyRevocationRegistryId = getUnqualifiedRevocationRegistryId( - namespaceIdentifier, - schemaSeqNo, - credentialDefinitionTag, - revocationRegistryTag - ) - - // TODO: implement caching for returned deltas - const request = await indySdk.buildGetRevocRegDeltaRequest(null, legacyRevocationRegistryId, 0, timestamp) - - agentContext.config.logger.trace( - `Submitting get revocation registry delta request for revocation registry '${revocationRegistryId}' to ledger` - ) - - const response = await indySdkPoolService.submitReadRequest(pool, request) - agentContext.config.logger.trace( - `Got revocation registry delta unparsed-response '${revocationRegistryId}' from ledger`, - { - response, - } - ) - - const [, revocationRegistryDelta, deltaTimestamp] = await indySdk.parseGetRevocRegDeltaResponse(response) - - agentContext.config.logger.debug( - `Got revocation registry deltas '${revocationRegistryId}' until timestamp ${timestamp} from ledger`, - { - revocationRegistryDelta, - deltaTimestamp, - } - ) - - const { resolutionMetadata, revocationRegistryDefinition, revocationRegistryDefinitionMetadata } = - await this.getRevocationRegistryDefinition(agentContext, revocationRegistryId) - - if ( - !revocationRegistryDefinition || - !revocationRegistryDefinitionMetadata.issuanceType || - typeof revocationRegistryDefinitionMetadata.issuanceType !== 'string' - ) { - return { - resolutionMetadata: { - error: `error resolving revocation registry definition with id ${revocationRegistryId}: ${resolutionMetadata.error} ${resolutionMetadata.message}`, - }, - revocationStatusListMetadata: { - didIndyNamespace: pool.didIndyNamespace, - }, - } - } - - const isIssuanceByDefault = revocationRegistryDefinitionMetadata.issuanceType === 'ISSUANCE_BY_DEFAULT' - - return { - resolutionMetadata: {}, - revocationStatusList: anonCredsRevocationStatusListFromIndySdk( - revocationRegistryId, - revocationRegistryDefinition, - revocationRegistryDelta, - deltaTimestamp, - isIssuanceByDefault - ), - revocationStatusListMetadata: { - didIndyNamespace: pool.didIndyNamespace, - }, - } - } catch (error) { - agentContext.config.logger.error( - `Error retrieving revocation registry delta '${revocationRegistryId}' from ledger, potentially revocation interval ends before revocation registry creation?"`, - { - error, - revocationRegistryId: revocationRegistryId, - } - ) - - return { - resolutionMetadata: { - error: 'notFound', - message: `Error retrieving revocation registry delta '${revocationRegistryId}' from ledger, potentially revocation interval ends before revocation registry creation: ${error.message}`, - }, - revocationStatusListMetadata: {}, - } - } - } - - private async fetchIndySchemaWithSeqNo(agentContext: AgentContext, pool: IndySdkPool, seqNo: number) { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - agentContext.config.logger.debug(`Getting transaction with seqNo '${seqNo}' from ledger '${pool.didIndyNamespace}'`) - - const request = await indySdk.buildGetTxnRequest(null, 'DOMAIN', seqNo) - - agentContext.config.logger.trace(`Submitting get transaction request to ledger '${pool.didIndyNamespace}'`) - const response = await indySdkPoolService.submitReadRequest(pool, request) - - const schema = response.result.data as SchemaType - - if (schema.txn.type !== '101') { - agentContext.config.logger.error(`Could not get schema from ledger for seq no ${seqNo}'`) - return {} - } - - return { - schema: { - // txnId is the schema id - schemaId: schema.txnMetadata.txnId, - attr_name: schema.txn.data.data.attr_names, - name: schema.txn.data.data.name, - version: schema.txn.data.data.version, - issuerId: schema.txn.metadata.from, - seqNo, - }, - indyNamespace: pool.didIndyNamespace, - } - } -} - -interface SchemaType { - txnMetadata: { - txnId: string - } - txn: { - metadata: { - from: string - } - data: { - data: { - attr_names: string[] - version: string - name: string - } - } - - type: string - } -} diff --git a/packages/indy-sdk/src/anoncreds/services/IndySdkHolderService.ts b/packages/indy-sdk/src/anoncreds/services/IndySdkHolderService.ts deleted file mode 100644 index 0557305ea7..0000000000 --- a/packages/indy-sdk/src/anoncreds/services/IndySdkHolderService.ts +++ /dev/null @@ -1,464 +0,0 @@ -import type { - AnonCredsHolderService, - AnonCredsProof, - CreateCredentialRequestOptions, - CreateCredentialRequestReturn, - CreateProofOptions, - AnonCredsCredentialInfo, - GetCredentialOptions, - StoreCredentialOptions, - GetCredentialsForProofRequestOptions, - GetCredentialsForProofRequestReturn, - AnonCredsSelectedCredentials, - CreateLinkSecretOptions, - CreateLinkSecretReturn, - GetCredentialsOptions, -} from '@aries-framework/anoncreds' -import type { AgentContext } from '@aries-framework/core' -import type { - CredentialDefs, - IndyRequestedCredentials, - RevStates, - Schemas, - IndyCredential as IndySdkCredential, - IndyProofRequest, -} from 'indy-sdk' - -import { - parseIndyCredentialDefinitionId, - AnonCredsLinkSecretRepository, - generateLegacyProverDidLikeString, - storeLinkSecret, -} from '@aries-framework/anoncreds' -import { AriesFrameworkError, injectable, inject, utils } from '@aries-framework/core' - -import { IndySdkModuleConfig } from '../../IndySdkModuleConfig' -import { IndySdkError, isIndyError } from '../../error' -import { IndySdk, IndySdkSymbol } from '../../types' -import { assertIndySdkWallet } from '../../utils/assertIndySdkWallet' -import { - assertAllUnqualified, - assertUnqualifiedCredentialOffer, - assertUnqualifiedProofRequest, -} from '../utils/assertUnqualified' -import { - anonCredsCredentialRequestMetadataFromIndySdk, - indySdkCredentialDefinitionFromAnonCreds, - indySdkCredentialRequestMetadataFromAnonCreds, - indySdkRevocationRegistryDefinitionFromAnonCreds, - indySdkSchemaFromAnonCreds, -} from '../utils/transform' - -import { IndySdkRevocationService } from './IndySdkRevocationService' - -@injectable() -export class IndySdkHolderService implements AnonCredsHolderService { - private indySdk: IndySdk - private indyRevocationService: IndySdkRevocationService - - public constructor(indyRevocationService: IndySdkRevocationService, @inject(IndySdkSymbol) indySdk: IndySdk) { - this.indySdk = indySdk - this.indyRevocationService = indyRevocationService - } - - public async createLinkSecret( - agentContext: AgentContext, - options: CreateLinkSecretOptions - ): Promise { - assertIndySdkWallet(agentContext.wallet) - - const linkSecretId = options.linkSecretId ?? utils.uuid() - - try { - await this.indySdk.proverCreateMasterSecret(agentContext.wallet.handle, linkSecretId) - - // We don't have the value for the link secret when using the indy-sdk so we can't return it. - return { - linkSecretId, - } - } catch (error) { - agentContext.config.logger.error(`Error creating link secret`, { - error, - linkSecretId, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async createProof(agentContext: AgentContext, options: CreateProofOptions): Promise { - const { credentialDefinitions, proofRequest, selectedCredentials, schemas } = options - - assertIndySdkWallet(agentContext.wallet) - - // Make sure all identifiers are unqualified - assertAllUnqualified({ - schemaIds: Object.keys(options.schemas), - credentialDefinitionIds: Object.keys(options.credentialDefinitions), - revocationRegistryIds: Object.keys(options.revocationRegistries), - }) - - const linkSecretRepository = agentContext.dependencyManager.resolve(AnonCredsLinkSecretRepository) - - try { - agentContext.config.logger.debug('Creating Indy Proof') - const indyRevocationStates: RevStates = await this.indyRevocationService.createRevocationState( - agentContext, - proofRequest, - selectedCredentials, - options.revocationRegistries - ) - - // The AnonCredsSchema doesn't contain the seqNo anymore. However, the indy credential definition id - // does contain the seqNo, so we can extract it from the credential definition id. - const seqNoMap: { [schemaId: string]: number } = {} - - // Convert AnonCreds credential definitions to Indy credential definitions - const indyCredentialDefinitions: CredentialDefs = {} - for (const credentialDefinitionId in credentialDefinitions) { - const credentialDefinition = credentialDefinitions[credentialDefinitionId] - indyCredentialDefinitions[credentialDefinitionId] = indySdkCredentialDefinitionFromAnonCreds( - credentialDefinitionId, - credentialDefinition - ) - - // Get the seqNo for the schemas so we can use it when transforming the schemas - const { schemaSeqNo } = parseIndyCredentialDefinitionId(credentialDefinitionId) - seqNoMap[credentialDefinition.schemaId] = Number(schemaSeqNo) - } - - // Convert AnonCreds schemas to Indy schemas - const indySchemas: Schemas = {} - for (const schemaId in schemas) { - const schema = schemas[schemaId] - indySchemas[schemaId] = indySdkSchemaFromAnonCreds(schemaId, schema, seqNoMap[schemaId]) - } - - const linkSecretRecord = await linkSecretRepository.findDefault(agentContext) - if (!linkSecretRecord) { - // No default link secret - throw new AriesFrameworkError( - 'No default link secret found. Indy SDK requires a default link secret to be created before creating a proof.' - ) - } - - const indyProof = await this.indySdk.proverCreateProof( - agentContext.wallet.handle, - proofRequest as IndyProofRequest, - this.parseSelectedCredentials(selectedCredentials), - linkSecretRecord.linkSecretId, - indySchemas, - indyCredentialDefinitions, - indyRevocationStates - ) - - agentContext.config.logger.trace('Created Indy Proof', { - indyProof, - }) - - // FIXME IndyProof if badly typed in indy-sdk. It contains a `requested_predicates` property, which should be `predicates`. - return indyProof as unknown as AnonCredsProof - } catch (error) { - agentContext.config.logger.error(`Error creating Indy Proof`, { - error, - proofRequest, - selectedCredentials, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async storeCredential(agentContext: AgentContext, options: StoreCredentialOptions): Promise { - assertIndySdkWallet(agentContext.wallet) - assertAllUnqualified({ - schemaIds: [options.credentialDefinition.schemaId, options.credential.schema_id], - credentialDefinitionIds: [options.credentialDefinitionId, options.credential.cred_def_id], - revocationRegistryIds: [options.revocationRegistry?.id, options.credential.rev_reg_id], - }) - - const indyRevocationRegistryDefinition = options.revocationRegistry - ? indySdkRevocationRegistryDefinitionFromAnonCreds( - options.revocationRegistry.id, - options.revocationRegistry.definition - ) - : null - - try { - return await this.indySdk.proverStoreCredential( - agentContext.wallet.handle, - options.credentialId ?? null, - indySdkCredentialRequestMetadataFromAnonCreds(options.credentialRequestMetadata), - options.credential, - indySdkCredentialDefinitionFromAnonCreds(options.credentialDefinitionId, options.credentialDefinition), - indyRevocationRegistryDefinition - ) - } catch (error) { - agentContext.config.logger.error(`Error storing Indy Credential '${options.credentialId}'`, { - error, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async getCredential( - agentContext: AgentContext, - options: GetCredentialOptions - ): Promise { - assertIndySdkWallet(agentContext.wallet) - - try { - const result = await this.indySdk.proverGetCredential(agentContext.wallet.handle, options.credentialId) - - return { - credentialDefinitionId: result.cred_def_id, - attributes: result.attrs, - credentialId: result.referent, - schemaId: result.schema_id, - credentialRevocationId: result.cred_rev_id, - revocationRegistryId: result.rev_reg_id, - methodName: 'indy', - } - } catch (error) { - agentContext.config.logger.error(`Error getting Indy Credential '${options.credentialId}'`, { - error, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async getCredentials(agentContext: AgentContext, options: GetCredentialsOptions) { - assertIndySdkWallet(agentContext.wallet) - - // Indy SDK only supports indy credentials - if (options.methodName && options.methodName !== 'indy') { - return [] - } - - assertAllUnqualified({ - credentialDefinitionIds: [options.credentialDefinitionId], - schemaIds: [options.schemaId], - issuerIds: [options.issuerId, options.schemaIssuerId], - }) - - const credentials = await this.indySdk.proverGetCredentials(agentContext.wallet.handle, { - cred_def_id: options.credentialDefinitionId, - schema_id: options.schemaId, - schema_issuer_did: options.schemaIssuerId, - schema_name: options.schemaName, - schema_version: options.schemaVersion, - issuer_did: options.issuerId, - }) - - return credentials.map((credential) => ({ - credentialDefinitionId: credential.cred_def_id, - attributes: credential.attrs, - credentialId: credential.referent, - schemaId: credential.schema_id, - credentialRevocationId: credential.cred_rev_id, - revocationRegistryId: credential.rev_reg_id, - methodName: 'indy', - })) - } - - public async createCredentialRequest( - agentContext: AgentContext, - options: CreateCredentialRequestOptions - ): Promise { - assertIndySdkWallet(agentContext.wallet) - - assertUnqualifiedCredentialOffer(options.credentialOffer) - assertAllUnqualified({ - schemaIds: [options.credentialDefinition.schemaId], - issuerIds: [options.credentialDefinition.issuerId], - }) - - if (!options.useLegacyProverDid) { - throw new AriesFrameworkError('Indy SDK only supports legacy prover did for credential requests') - } - - const linkSecretRepository = agentContext.dependencyManager.resolve(AnonCredsLinkSecretRepository) - - // We just generate a prover did like string, as it's not used for anything and we don't need - // to prove ownership of the did. It's deprecated in AnonCreds v1, but kept for backwards compatibility - const proverDid = generateLegacyProverDidLikeString() - - // If a link secret is specified, use it. Otherwise, attempt to use default link secret - let linkSecretRecord = options.linkSecretId - ? await linkSecretRepository.getByLinkSecretId(agentContext, options.linkSecretId) - : await linkSecretRepository.findDefault(agentContext) - - // No default link secret. Automatically create one if set on module config - if (!linkSecretRecord) { - const moduleConfig = agentContext.dependencyManager.resolve(IndySdkModuleConfig) - if (!moduleConfig.autoCreateLinkSecret) { - throw new AriesFrameworkError( - 'No link secret provided to createCredentialRequest and no default link secret has been found' - ) - } - const { linkSecretId } = await this.createLinkSecret(agentContext, {}) - linkSecretRecord = await storeLinkSecret(agentContext, { linkSecretId, setAsDefault: true }) - } - - try { - const result = await this.indySdk.proverCreateCredentialReq( - agentContext.wallet.handle, - proverDid, - options.credentialOffer, - // NOTE: Is it safe to use the cred_def_id from the offer? I think so. You can't create a request - // for a cred def that is not in the offer - indySdkCredentialDefinitionFromAnonCreds(options.credentialOffer.cred_def_id, options.credentialDefinition), - linkSecretRecord.linkSecretId - ) - - return { - credentialRequest: result[0], - // The type is typed as a Record in the indy-sdk, but the anoncreds package contains the correct type - credentialRequestMetadata: anonCredsCredentialRequestMetadataFromIndySdk(result[1]), - } - } catch (error) { - agentContext.config.logger.error(`Error creating Indy Credential Request`, { - error, - credentialOffer: options.credentialOffer, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async deleteCredential(agentContext: AgentContext, credentialId: string): Promise { - assertIndySdkWallet(agentContext.wallet) - - try { - return await this.indySdk.proverDeleteCredential(agentContext.wallet.handle, credentialId) - } catch (error) { - agentContext.config.logger.error(`Error deleting Indy Credential from Wallet`, { - error, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async getCredentialsForProofRequest( - agentContext: AgentContext, - options: GetCredentialsForProofRequestOptions - ): Promise { - assertIndySdkWallet(agentContext.wallet) - assertUnqualifiedProofRequest(options.proofRequest) - - try { - // Open indy credential search - const searchHandle = await this.indySdk.proverSearchCredentialsForProofReq( - agentContext.wallet.handle, - options.proofRequest as IndyProofRequest, - options.extraQuery ?? null - ) - - const start = options.start ?? 0 - - try { - // Make sure database cursors start at 'start' (bit ugly, but no way around in indy) - if (start > 0) { - await this.fetchCredentialsForReferent(agentContext, searchHandle, options.attributeReferent, start) - } - - // Fetch the credentials - const credentials = await this.fetchCredentialsForReferent( - agentContext, - searchHandle, - options.attributeReferent, - options.limit - ) - - // TODO: sort the credentials (irrevocable first) - return credentials.map((credential) => ({ - credentialInfo: { - credentialDefinitionId: credential.cred_info.cred_def_id, - credentialId: credential.cred_info.referent, - attributes: credential.cred_info.attrs, - schemaId: credential.cred_info.schema_id, - revocationRegistryId: credential.cred_info.rev_reg_id, - credentialRevocationId: credential.cred_info.cred_rev_id, - methodName: 'indy', - }, - interval: credential.interval, - })) - } finally { - // Always close search - await this.indySdk.proverCloseCredentialsSearchForProofReq(searchHandle) - } - } catch (error) { - if (isIndyError(error)) { - throw new IndySdkError(error) - } - - throw error - } - } - - private async fetchCredentialsForReferent( - agentContext: AgentContext, - searchHandle: number, - referent: string, - limit?: number - ) { - try { - let credentials: IndySdkCredential[] = [] - - // Allow max of 256 per fetch operation - const chunk = limit ? Math.min(256, limit) : 256 - - // Loop while limit not reached (or no limit specified) - while (!limit || credentials.length < limit) { - // Retrieve credentials - const credentialsJson = await this.indySdk.proverFetchCredentialsForProofReq(searchHandle, referent, chunk) - credentials = [...credentials, ...credentialsJson] - - // If the number of credentials returned is less than chunk - // It means we reached the end of the iterator (no more credentials) - if (credentialsJson.length < chunk) { - return credentials - } - } - - return credentials - } catch (error) { - agentContext.config.logger.error(`Error Fetching Indy Credentials For Referent`, { - error, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - /** - * Converts a public api form of {@link AnonCredsSelectedCredentials} interface into a format {@link Indy.IndyRequestedCredentials} that Indy SDK expects. - **/ - private parseSelectedCredentials(selectedCredentials: AnonCredsSelectedCredentials): IndyRequestedCredentials { - const indyRequestedCredentials: IndyRequestedCredentials = { - requested_attributes: {}, - requested_predicates: {}, - self_attested_attributes: {}, - } - - for (const groupName in selectedCredentials.attributes) { - indyRequestedCredentials.requested_attributes[groupName] = { - cred_id: selectedCredentials.attributes[groupName].credentialId, - revealed: selectedCredentials.attributes[groupName].revealed, - timestamp: selectedCredentials.attributes[groupName].timestamp, - } - } - - for (const groupName in selectedCredentials.predicates) { - indyRequestedCredentials.requested_predicates[groupName] = { - cred_id: selectedCredentials.predicates[groupName].credentialId, - timestamp: selectedCredentials.predicates[groupName].timestamp, - } - } - - return indyRequestedCredentials - } -} diff --git a/packages/indy-sdk/src/anoncreds/services/IndySdkIssuerService.ts b/packages/indy-sdk/src/anoncreds/services/IndySdkIssuerService.ts deleted file mode 100644 index 01973d31dd..0000000000 --- a/packages/indy-sdk/src/anoncreds/services/IndySdkIssuerService.ts +++ /dev/null @@ -1,157 +0,0 @@ -import type { CreateCredentialDefinitionMetadata } from './IndySdkIssuerServiceMetadata' -import type { - AnonCredsIssuerService, - CreateCredentialDefinitionOptions, - CreateCredentialOfferOptions, - CreateCredentialOptions, - CreateCredentialReturn, - CreateSchemaOptions, - AnonCredsCredentialOffer, - AnonCredsSchema, - CreateCredentialDefinitionReturn, -} from '@aries-framework/anoncreds' -import type { AgentContext } from '@aries-framework/core' - -import { parseIndyDid, getUnqualifiedSchemaId, generateLegacyProverDidLikeString } from '@aries-framework/anoncreds' -import { injectable, AriesFrameworkError, inject } from '@aries-framework/core' - -import { IndySdkError, isIndyError } from '../../error' -import { IndySdk, IndySdkSymbol } from '../../types' -import { assertIndySdkWallet } from '../../utils/assertIndySdkWallet' -import { - assertUnqualifiedCredentialDefinitionId, - assertUnqualifiedCredentialOffer, - assertUnqualifiedCredentialRequest, - assertUnqualifiedRevocationRegistryId, -} from '../utils/assertUnqualified' -import { createTailsReader } from '../utils/tails' -import { indySdkSchemaFromAnonCreds } from '../utils/transform' - -@injectable() -export class IndySdkIssuerService implements AnonCredsIssuerService { - private indySdk: IndySdk - - public constructor(@inject(IndySdkSymbol) indySdk: IndySdk) { - this.indySdk = indySdk - } - - public async createSchema(agentContext: AgentContext, options: CreateSchemaOptions): Promise { - // We only support passing qualified did:indy issuer ids in the indy issuer service when creating objects - const { namespaceIdentifier } = parseIndyDid(options.issuerId) - - const { name, version, attrNames, issuerId } = options - assertIndySdkWallet(agentContext.wallet) - - try { - const [, schema] = await this.indySdk.issuerCreateSchema(namespaceIdentifier, name, version, attrNames) - - return { - issuerId, - attrNames: schema.attrNames, - name: schema.name, - version: schema.version, - } - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async createCredentialDefinition( - agentContext: AgentContext, - options: CreateCredentialDefinitionOptions, - metadata?: CreateCredentialDefinitionMetadata - ): Promise { - const { tag, supportRevocation, schema, issuerId, schemaId } = options - - // We only support passing qualified did:indy issuer ids in the indy issuer service when creating objects - const { namespaceIdentifier } = parseIndyDid(options.issuerId) - - // parse schema in a way that supports both unqualified and qualified identifiers - const legacySchemaId = getUnqualifiedSchemaId(namespaceIdentifier, schema.name, schema.version) - - if (!metadata) - throw new AriesFrameworkError('The metadata parameter is required when using Indy, but received undefined.') - - try { - assertIndySdkWallet(agentContext.wallet) - const [, credentialDefinition] = await this.indySdk.issuerCreateAndStoreCredentialDef( - agentContext.wallet.handle, - namespaceIdentifier, - indySdkSchemaFromAnonCreds(legacySchemaId, schema, metadata.indyLedgerSchemaSeqNo), - tag, - 'CL', - { - support_revocation: supportRevocation, - } - ) - - return { - credentialDefinition: { - issuerId, - tag: credentialDefinition.tag, - schemaId, - type: 'CL', - value: credentialDefinition.value, - }, - } - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async createCredentialOffer( - agentContext: AgentContext, - options: CreateCredentialOfferOptions - ): Promise { - assertIndySdkWallet(agentContext.wallet) - assertUnqualifiedCredentialDefinitionId(options.credentialDefinitionId) - - try { - return await this.indySdk.issuerCreateCredentialOffer(agentContext.wallet.handle, options.credentialDefinitionId) - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async createCredential( - agentContext: AgentContext, - options: CreateCredentialOptions - ): Promise { - const { tailsFilePath, credentialOffer, credentialRequest, credentialValues, revocationRegistryId } = options - - assertIndySdkWallet(agentContext.wallet) - assertUnqualifiedCredentialOffer(options.credentialOffer) - assertUnqualifiedCredentialRequest(options.credentialRequest) - if (options.revocationRegistryId) { - assertUnqualifiedRevocationRegistryId(options.revocationRegistryId) - } - - try { - // Indy SDK requires tailsReaderHandle. Use null if no tailsFilePath is present - const tailsReaderHandle = tailsFilePath ? await createTailsReader(agentContext, tailsFilePath) : 0 - - if (revocationRegistryId || tailsFilePath) { - throw new AriesFrameworkError('Revocation not supported yet') - } - - // prover_did is deprecated and thus if not provided we generate something on our side, as it's still required by the indy sdk - const proverDid = credentialRequest.prover_did ?? generateLegacyProverDidLikeString() - - const [credential, credentialRevocationId] = await this.indySdk.issuerCreateCredential( - agentContext.wallet.handle, - credentialOffer, - { ...credentialRequest, prover_did: proverDid }, - credentialValues, - revocationRegistryId ?? null, - tailsReaderHandle - ) - - return { - credential, - credentialRevocationId, - } - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } -} diff --git a/packages/indy-sdk/src/anoncreds/services/IndySdkIssuerServiceMetadata.ts b/packages/indy-sdk/src/anoncreds/services/IndySdkIssuerServiceMetadata.ts deleted file mode 100644 index bb02f17967..0000000000 --- a/packages/indy-sdk/src/anoncreds/services/IndySdkIssuerServiceMetadata.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type CreateCredentialDefinitionMetadata = { - indyLedgerSchemaSeqNo: number -} diff --git a/packages/indy-sdk/src/anoncreds/services/IndySdkRevocationService.ts b/packages/indy-sdk/src/anoncreds/services/IndySdkRevocationService.ts deleted file mode 100644 index 6690fb6ab3..0000000000 --- a/packages/indy-sdk/src/anoncreds/services/IndySdkRevocationService.ts +++ /dev/null @@ -1,155 +0,0 @@ -import type { - AnonCredsRevocationRegistryDefinition, - AnonCredsRevocationStatusList, - AnonCredsProofRequest, - AnonCredsSelectedCredentials, - AnonCredsCredentialInfo, - AnonCredsNonRevokedInterval, -} from '@aries-framework/anoncreds' -import type { AgentContext } from '@aries-framework/core' -import type { RevStates } from 'indy-sdk' - -import { assertBestPracticeRevocationInterval } from '@aries-framework/anoncreds' -import { AriesFrameworkError, inject, injectable } from '@aries-framework/core' - -import { IndySdkError, isIndyError } from '../../error' -import { IndySdk, IndySdkSymbol } from '../../types' -import { createTailsReader } from '../utils/tails' -import { - indySdkRevocationDeltaFromAnonCreds, - indySdkRevocationRegistryDefinitionFromAnonCreds, -} from '../utils/transform' - -enum RequestReferentType { - Attribute = 'attribute', - Predicate = 'predicate', - SelfAttestedAttribute = 'self-attested-attribute', -} - -/** - * Internal class that handles revocation related logic for the Indy SDK - * - * @internal - */ -@injectable() -export class IndySdkRevocationService { - private indySdk: IndySdk - - public constructor(@inject(IndySdkSymbol) indySdk: IndySdk) { - this.indySdk = indySdk - } - - /** - * Creates the revocation state for the requested credentials in a format that the Indy SDK expects. - */ - public async createRevocationState( - agentContext: AgentContext, - proofRequest: AnonCredsProofRequest, - selectedCredentials: AnonCredsSelectedCredentials, - revocationRegistries: { - [revocationRegistryDefinitionId: string]: { - // Tails is already downloaded - tailsFilePath: string - definition: AnonCredsRevocationRegistryDefinition - revocationStatusLists: { - [timestamp: string]: AnonCredsRevocationStatusList - } - } - } - ): Promise { - try { - agentContext.config.logger.debug(`Creating Revocation State(s) for proof request`, { - proofRequest, - selectedCredentials, - }) - const indyRevocationStates: RevStates = {} - const referentCredentials: Array<{ - type: RequestReferentType - referent: string - credentialInfo: AnonCredsCredentialInfo - referentRevocationInterval: AnonCredsNonRevokedInterval | undefined - timestamp: number | undefined - }> = [] - - //Retrieve information for referents and push to single array - for (const [referent, selectedCredential] of Object.entries(selectedCredentials.attributes ?? {})) { - referentCredentials.push({ - referent, - credentialInfo: selectedCredential.credentialInfo, - type: RequestReferentType.Attribute, - referentRevocationInterval: proofRequest.requested_attributes[referent].non_revoked, - timestamp: selectedCredential.timestamp, - }) - } - for (const [referent, selectedCredential] of Object.entries(selectedCredentials.predicates ?? {})) { - referentCredentials.push({ - referent, - credentialInfo: selectedCredential.credentialInfo, - type: RequestReferentType.Predicate, - referentRevocationInterval: proofRequest.requested_predicates[referent].non_revoked, - timestamp: selectedCredential.timestamp, - }) - } - - for (const { referent, credentialInfo, type, referentRevocationInterval, timestamp } of referentCredentials) { - // Prefer referent-specific revocation interval over global revocation interval - const requestRevocationInterval = referentRevocationInterval ?? proofRequest.non_revoked - const credentialRevocationId = credentialInfo.credentialRevocationId - const revocationRegistryId = credentialInfo.revocationRegistryId - - // If revocation interval is present and the credential is revocable then create revocation state - if (requestRevocationInterval && timestamp && credentialRevocationId && revocationRegistryId) { - agentContext.config.logger.trace( - `Presentation is requesting proof of non revocation for ${type} referent '${referent}', creating revocation state for credential`, - { - requestRevocationInterval, - credentialRevocationId, - revocationRegistryId, - } - ) - - assertBestPracticeRevocationInterval(requestRevocationInterval) - - const { definition, revocationStatusLists, tailsFilePath } = revocationRegistries[revocationRegistryId] - - // Extract revocation status list for the given timestamp - const revocationStatusList = revocationStatusLists[timestamp] - if (!revocationStatusList) { - throw new AriesFrameworkError( - `Revocation status list for revocation registry ${revocationRegistryId} and timestamp ${timestamp} not found in revocation status lists. All revocation status lists must be present.` - ) - } - - const tails = await createTailsReader(agentContext, tailsFilePath) - - const revocationState = await this.indySdk.createRevocationState( - tails, - indySdkRevocationRegistryDefinitionFromAnonCreds(revocationRegistryId, definition), - indySdkRevocationDeltaFromAnonCreds(revocationStatusList), - revocationStatusList.timestamp, - credentialRevocationId - ) - - if (!indyRevocationStates[revocationRegistryId]) { - indyRevocationStates[revocationRegistryId] = {} - } - indyRevocationStates[revocationRegistryId][timestamp] = revocationState - } - } - - agentContext.config.logger.debug(`Created Revocation States for Proof Request`, { - indyRevocationStates, - }) - - return indyRevocationStates - } catch (error) { - agentContext.config.logger.error(`Error creating Indy Revocation State for Proof Request`, { - error, - proofRequest, - selectedCredentials, - }) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } -} diff --git a/packages/indy-sdk/src/anoncreds/services/IndySdkVerifierService.ts b/packages/indy-sdk/src/anoncreds/services/IndySdkVerifierService.ts deleted file mode 100644 index 80aee7be6f..0000000000 --- a/packages/indy-sdk/src/anoncreds/services/IndySdkVerifierService.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { AnonCredsProof, AnonCredsVerifierService, VerifyProofOptions } from '@aries-framework/anoncreds' -import type { AgentContext } from '@aries-framework/core' -import type { CredentialDefs, Schemas, RevocRegDefs, RevRegs, IndyProofRequest, IndyProof } from 'indy-sdk' - -import { parseIndyCredentialDefinitionId } from '@aries-framework/anoncreds' -import { inject, injectable } from '@aries-framework/core' - -import { IndySdkError, isIndyError } from '../../error' -import { IndySdk, IndySdkSymbol } from '../../types' -import { assertAllUnqualified } from '../utils/assertUnqualified' -import { - indySdkCredentialDefinitionFromAnonCreds, - indySdkRevocationRegistryDefinitionFromAnonCreds, - indySdkRevocationRegistryFromAnonCreds, - indySdkSchemaFromAnonCreds, -} from '../utils/transform' - -@injectable() -export class IndySdkVerifierService implements AnonCredsVerifierService { - private indySdk: IndySdk - - public constructor(@inject(IndySdkSymbol) indySdk: IndySdk) { - this.indySdk = indySdk - } - - public async verifyProof(agentContext: AgentContext, options: VerifyProofOptions): Promise { - assertAllUnqualified({ - credentialDefinitionIds: Object.keys(options.credentialDefinitions), - schemaIds: Object.keys(options.schemas), - revocationRegistryIds: Object.keys(options.revocationRegistries), - }) - - try { - // The AnonCredsSchema doesn't contain the seqNo anymore. However, the indy credential definition id - // does contain the seqNo, so we can extract it from the credential definition id. - const seqNoMap: { [schemaId: string]: number } = {} - - // Convert AnonCreds credential definitions to Indy credential definitions - const indyCredentialDefinitions: CredentialDefs = {} - for (const credentialDefinitionId in options.credentialDefinitions) { - const credentialDefinition = options.credentialDefinitions[credentialDefinitionId] - - indyCredentialDefinitions[credentialDefinitionId] = indySdkCredentialDefinitionFromAnonCreds( - credentialDefinitionId, - credentialDefinition - ) - - // Get the seqNo for the schemas so we can use it when transforming the schemas - const { schemaSeqNo } = parseIndyCredentialDefinitionId(credentialDefinitionId) - seqNoMap[credentialDefinition.schemaId] = Number(schemaSeqNo) - } - - // Convert AnonCreds schemas to Indy schemas - const indySchemas: Schemas = {} - for (const schemaId in options.schemas) { - const schema = options.schemas[schemaId] - indySchemas[schemaId] = indySdkSchemaFromAnonCreds(schemaId, schema, seqNoMap[schemaId]) - } - - // Convert AnonCreds revocation definitions to Indy revocation definitions - const indyRevocationDefinitions: RevocRegDefs = {} - const indyRevocationRegistries: RevRegs = {} - - for (const revocationRegistryDefinitionId in options.revocationRegistries) { - const { definition, revocationStatusLists } = options.revocationRegistries[revocationRegistryDefinitionId] - indyRevocationDefinitions[revocationRegistryDefinitionId] = indySdkRevocationRegistryDefinitionFromAnonCreds( - revocationRegistryDefinitionId, - definition - ) - - // Initialize empty object for this revocation registry - indyRevocationRegistries[revocationRegistryDefinitionId] = {} - - // Also transform the revocation lists for the specified timestamps into the revocation registry - // format Indy expects - for (const timestamp in revocationStatusLists) { - const revocationStatusList = revocationStatusLists[timestamp] - indyRevocationRegistries[revocationRegistryDefinitionId][timestamp] = - indySdkRevocationRegistryFromAnonCreds(revocationStatusList) - } - } - - return await this.indySdk.verifierVerifyProof( - options.proofRequest as IndyProofRequest, - // FIXME IndyProof if badly typed in indy-sdk. It contains a `requested_predicates` property, which should be `predicates`. - options.proof as unknown as IndyProof, - indySchemas, - indyCredentialDefinitions, - indyRevocationDefinitions, - indyRevocationRegistries - ) - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } -} diff --git a/packages/indy-sdk/src/anoncreds/utils/__tests__/assertUnqualified.test.ts b/packages/indy-sdk/src/anoncreds/utils/__tests__/assertUnqualified.test.ts deleted file mode 100644 index 3475cc48bc..0000000000 --- a/packages/indy-sdk/src/anoncreds/utils/__tests__/assertUnqualified.test.ts +++ /dev/null @@ -1,152 +0,0 @@ -import type { AnonCredsCredentialOffer, AnonCredsCredentialRequest } from '@aries-framework/anoncreds' - -import { - assertUnqualifiedCredentialDefinitionId, - assertUnqualifiedCredentialOffer, - assertUnqualifiedCredentialRequest, - assertUnqualifiedIssuerId, - assertUnqualifiedProofRequest, - assertUnqualifiedRevocationRegistryId, - assertUnqualifiedSchemaId, -} from '../assertUnqualified' - -describe('assertUnqualified', () => { - describe('assertUnqualifiedCredentialDefinitionId', () => { - test('throws when a non-unqualified credential definition id is passed', () => { - expect(() => - assertUnqualifiedCredentialDefinitionId( - 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/CLAIM_DEF/100669/SCH Employee ID' - ) - ).toThrow() - }) - - test('does not throw when an unqualified credential definition id is passed', () => { - expect(() => - assertUnqualifiedCredentialDefinitionId('N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID') - ).not.toThrow() - }) - }) - - describe('assertUnqualifiedSchemaId', () => { - test('throws when a non-unqualified schema id is passed', () => { - expect(() => - assertUnqualifiedSchemaId('did:indy:local:BQ42WeE24jFHeyGg8x9XAz/anoncreds/v0/SCHEMA/Medical Bill/1.0') - ).toThrowError('Schema id') - }) - - test('does not throw when an unqualified schema id is passed', () => { - expect(() => assertUnqualifiedSchemaId('BQ42WeE24jFHeyGg8x9XAz:2:Medical Bill:1.0')).not.toThrow() - }) - }) - - describe('assertUnqualifiedRevocationRegistryId', () => { - test('throws when a non-unqualified revocation registry id is passed', () => { - expect(() => - assertUnqualifiedRevocationRegistryId( - 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/REV_REG_DEF/100669/SCH Employee ID/1-1024' - ) - ).toThrowError('Revocation registry id') - }) - - test('does not throw when an unqualified revocation registry id is passed', () => { - expect(() => - assertUnqualifiedRevocationRegistryId( - 'N7baRMcyvPwWc8v85CtZ6e:4:N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID:CL_ACCUM:1-1024' - ) - ).not.toThrow() - }) - }) - - describe('assertUnqualifiedIssuerId', () => { - test('throws when a non-unqualified issuer id is passed', () => { - expect(() => assertUnqualifiedIssuerId('did:indy:sovrin:N7baRMcyvPwWc8v85CtZ6e')).toThrowError('Issuer id') - }) - - test('does not throw when an unqualified issuer id is passed', () => { - expect(() => assertUnqualifiedIssuerId('N7baRMcyvPwWc8v85CtZ6e')).not.toThrow() - }) - }) - - describe('assertUnqualifiedCredentialOffer', () => { - test('throws when non-unqualified identifiers are passed', () => { - expect(() => - assertUnqualifiedCredentialOffer({ - cred_def_id: 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/CLAIM_DEF/100669/SCH Employee ID', - schema_id: 'BQ42WeE24jFHeyGg8x9XAz:2:Medical Bill:1.0', - } as AnonCredsCredentialOffer) - ).toThrowError('Credential definition id') - - expect(() => - assertUnqualifiedCredentialOffer({ - cred_def_id: 'N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID', - schema_id: 'did:indy:local:BQ42WeE24jFHeyGg8x9XAz/anoncreds/v0/SCHEMA/Medical Bill/1.0', - } as AnonCredsCredentialOffer) - ).toThrowError('Schema id') - }) - - test('does not throw when only unqualified identifiers are passed', () => { - expect(() => - assertUnqualifiedCredentialOffer({ - cred_def_id: 'N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID', - schema_id: 'BQ42WeE24jFHeyGg8x9XAz:2:Medical Bill:1.0', - } as AnonCredsCredentialOffer) - ).not.toThrow() - }) - }) - - describe('assertUnqualifiedCredentialRequest', () => { - test('throws when non-unqualified identifiers are passed', () => { - expect(() => - assertUnqualifiedCredentialRequest({ - cred_def_id: 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/CLAIM_DEF/100669/SCH Employee ID', - } as AnonCredsCredentialRequest) - ).toThrowError('Credential definition id') - }) - - test('does not throw when only unqualified identifiers are passed', () => { - expect(() => - assertUnqualifiedCredentialRequest({ - cred_def_id: 'N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID', - } as AnonCredsCredentialRequest) - ).not.toThrow() - }) - }) - - describe('assertUnqualifiedProofRequest', () => { - test('throws when non-unqualified identifiers are passed', () => { - expect(() => - assertUnqualifiedProofRequest({ - requested_attributes: { - a: { - restrictions: [ - { - cred_def_id: 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/CLAIM_DEF/100669/SCH Employee ID', - }, - ], - }, - }, - requested_predicates: {}, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any) - ).toThrowError('Credential definition id') - }) - - test('does not throw when only unqualified identifiers are passed', () => { - expect(() => - assertUnqualifiedProofRequest({ - requested_attributes: { - a: { - restrictions: [ - { - schema_id: 'BQ42WeE24jFHeyGg8x9XAz:2:Medical Bill:1.0', - }, - ], - }, - }, - requested_predicates: {}, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any) - ).not.toThrow() - }) - }) -}) diff --git a/packages/indy-sdk/src/anoncreds/utils/__tests__/identifiers.test.ts b/packages/indy-sdk/src/anoncreds/utils/__tests__/identifiers.test.ts deleted file mode 100644 index 9b9a54ba83..0000000000 --- a/packages/indy-sdk/src/anoncreds/utils/__tests__/identifiers.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { - getDidIndyCredentialDefinitionId, - getDidIndyRevocationRegistryId, - getDidIndySchemaId, - indySdkAnonCredsRegistryIdentifierRegex, -} from '../identifiers' - -describe('identifiers', () => { - describe('indySdkAnonCredsRegistryIdentifierRegex', () => { - test('matches against a legacy schema id, credential definition id and revocation registry id', () => { - const did = '7Tqg6BwSSWapxgUDm9KKgg' - const schemaId = 'BQ42WeE24jFHeyGg8x9XAz:2:Medical Bill:1.0' - const credentialDefinitionId = 'N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID' - const revocationRegistryId = - 'N7baRMcyvPwWc8v85CtZ6e:4:N7baRMcyvPwWc8v85CtZ6e:3:CL:100669:SCH Employee ID:CL_ACCUM:1-1024' - - const anotherId = 'some:id' - - // unqualified issuerId not in regex on purpose. See note in implementation. - expect(indySdkAnonCredsRegistryIdentifierRegex.test(did)).toEqual(false) - - expect(indySdkAnonCredsRegistryIdentifierRegex.test(schemaId)).toEqual(true) - expect(indySdkAnonCredsRegistryIdentifierRegex.test(credentialDefinitionId)).toEqual(true) - expect(indySdkAnonCredsRegistryIdentifierRegex.test(revocationRegistryId)).toEqual(true) - expect(indySdkAnonCredsRegistryIdentifierRegex.test(anotherId)).toEqual(false) - }) - - test('matches against a did indy did, schema id, credential definition id and revocation registry id', () => { - const did = 'did:indy:local:7Tqg6BwSSWapxgUDm9KKgg' - const schemaId = 'did:indy:local:BQ42WeE24jFHeyGg8x9XAz/anoncreds/v0/SCHEMA/Medical Bill/1.0' - const credentialDefinitionId = - 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/CLAIM_DEF/100669/SCH Employee ID' - const revocationRegistryId = - 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/REV_REG_DEF/100669/SCH Employee ID/1-1024' - - const anotherId = 'did:indy:local:N7baRMcyvPwWc8v85CtZ6e/anoncreds/v0/SOME_DEF' - - expect(indySdkAnonCredsRegistryIdentifierRegex.test(did)).toEqual(true) - expect(indySdkAnonCredsRegistryIdentifierRegex.test(schemaId)).toEqual(true) - expect(indySdkAnonCredsRegistryIdentifierRegex.test(credentialDefinitionId)).toEqual(true) - expect(indySdkAnonCredsRegistryIdentifierRegex.test(revocationRegistryId)).toEqual(true) - expect(indySdkAnonCredsRegistryIdentifierRegex.test(anotherId)).toEqual(false) - }) - }) - - test('getDidIndySchemaId returns a valid schema id given a did, name, and version', () => { - const namespace = 'sovrin:test' - const did = '12345' - const name = 'backbench' - const version = '420' - - expect(getDidIndySchemaId(namespace, did, name, version)).toEqual( - 'did:indy:sovrin:test:12345/anoncreds/v0/SCHEMA/backbench/420' - ) - }) - - test('getDidIndyCredentialDefinitionId returns a valid credential definition id given a did, seqNo, and tag', () => { - const namespace = 'sovrin:test' - const did = '12345' - const seqNo = 420 - const tag = 'someTag' - - expect(getDidIndyCredentialDefinitionId(namespace, did, seqNo, tag)).toEqual( - 'did:indy:sovrin:test:12345/anoncreds/v0/CLAIM_DEF/420/someTag' - ) - }) - - test('getDidIndyRevocationRegistryId returns a valid credential definition id given a did, seqNo, and tag', () => { - const namespace = 'sovrin:test' - const did = '12345' - const seqNo = 420 - const credentialDefinitionTag = 'someTag' - const tag = 'anotherTag' - - expect(getDidIndyRevocationRegistryId(namespace, did, seqNo, credentialDefinitionTag, tag)).toEqual( - 'did:indy:sovrin:test:12345/anoncreds/v0/REV_REG_DEF/420/someTag/anotherTag' - ) - }) -}) diff --git a/packages/indy-sdk/src/anoncreds/utils/__tests__/transform.test.ts b/packages/indy-sdk/src/anoncreds/utils/__tests__/transform.test.ts deleted file mode 100644 index f94060d8fd..0000000000 --- a/packages/indy-sdk/src/anoncreds/utils/__tests__/transform.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { AnonCredsCredentialDefinition, AnonCredsSchema } from '../../../../../anoncreds/src' -import type { CredDef, Schema } from 'indy-sdk' - -import { - anonCredsCredentialDefinitionFromIndySdk, - anonCredsSchemaFromIndySdk, - indySdkCredentialDefinitionFromAnonCreds, - indySdkSchemaFromAnonCreds, -} from '../transform' - -describe('transform', () => { - it('anonCredsSchemaFromIndySdk should return a valid anoncreds schema', () => { - const schema: Schema = { - attrNames: ['hello'], - id: 'TL1EaPFCZ8Si5aUrqScBDt:2:Example Schema:1.0.0', - name: 'Example Schema', - seqNo: 150, - ver: '1.0', - version: '1.0.0', - } - - expect(anonCredsSchemaFromIndySdk(schema)).toEqual({ - attrNames: ['hello'], - issuerId: 'TL1EaPFCZ8Si5aUrqScBDt', - name: 'Example Schema', - version: '1.0.0', - }) - }) - - it('indySdkSchemaFromAnonCreds should return a valid indy sdk schema', () => { - const schemaId = 'TL1EaPFCZ8Si5aUrqScBDt:2:Example Schema:1.0.0' - const schema: AnonCredsSchema = { - attrNames: ['hello'], - issuerId: 'TL1EaPFCZ8Si5aUrqScBDt', - name: 'Example Schema', - version: '1.0.0', - } - - expect(indySdkSchemaFromAnonCreds(schemaId, schema, 150)).toEqual({ - attrNames: ['hello'], - id: 'TL1EaPFCZ8Si5aUrqScBDt:2:Example Schema:1.0.0', - name: 'Example Schema', - seqNo: 150, - ver: '1.0', - version: '1.0.0', - }) - }) - - it('anonCredsCredentialDefinitionFromIndySdk should return a valid anoncreds credential definition', () => { - const credDef: CredDef = { - id: 'TL1EaPFCZ8Si5aUrqScBDt:3:CL:420:someTag', - schemaId: '8910:2:Example Schema:1.0.0', - tag: 'someTag', - type: 'CL', - value: { - primary: { - something: 'string', - }, - }, - ver: '1.0', - } - - expect(anonCredsCredentialDefinitionFromIndySdk(credDef)).toEqual({ - issuerId: 'TL1EaPFCZ8Si5aUrqScBDt', - schemaId: '8910:2:Example Schema:1.0.0', - tag: 'someTag', - type: 'CL', - value: { - primary: { - something: 'string', - }, - }, - }) - }) - - it('indySdkCredentialDefinitionFromAnonCreds should return a valid indy sdk credential definition', () => { - const credentialDefinitionId = 'TL1EaPFCZ8Si5aUrqScBDt:3:CL:420:someTag' - const credentialDefinition: AnonCredsCredentialDefinition = { - issuerId: 'TL1EaPFCZ8Si5aUrqScBDt', - schemaId: '8910:2:Example Schema:1.0.0', - tag: 'someTag', - type: 'CL', - value: { - primary: { - something: 'string', - }, - }, - } - - expect(indySdkCredentialDefinitionFromAnonCreds(credentialDefinitionId, credentialDefinition)).toEqual({ - id: 'TL1EaPFCZ8Si5aUrqScBDt:3:CL:420:someTag', - schemaId: '8910:2:Example Schema:1.0.0', - tag: 'someTag', - type: 'CL', - value: { - primary: { - something: 'string', - }, - }, - ver: '1.0', - }) - }) - - // TODO: add tests for these models once finalized in the anoncreds spec - test.todo( - 'anonCredsRevocationRegistryDefinitionFromIndySdk should return a valid anoncreds revocation registry definition' - ) - test.todo( - 'indySdkRevocationRegistryDefinitionFromAnonCreds should return a valid indy sdk revocation registry definition' - ) - test.todo('anonCredsRevocationStatusListFromIndySdk should return a valid anoncreds revocation list') - test.todo('indySdkRevocationRegistryFromAnonCreds should return a valid indy sdk revocation registry') - test.todo('indySdkRevocationDeltaFromAnonCreds should return a valid indy sdk revocation delta') -}) diff --git a/packages/indy-sdk/src/anoncreds/utils/assertUnqualified.ts b/packages/indy-sdk/src/anoncreds/utils/assertUnqualified.ts deleted file mode 100644 index 320fadcb6e..0000000000 --- a/packages/indy-sdk/src/anoncreds/utils/assertUnqualified.ts +++ /dev/null @@ -1,133 +0,0 @@ -import type { - AnonCredsCredentialOffer, - AnonCredsCredentialRequest, - AnonCredsProofRequest, -} from '@aries-framework/anoncreds' - -import { - unqualifiedRevocationRegistryIdRegex, - unqualifiedCredentialDefinitionIdRegex, - unqualifiedIndyDidRegex, - unqualifiedSchemaIdRegex, -} from '@aries-framework/anoncreds' -import { AriesFrameworkError } from '@aries-framework/core' - -/** - * Assert that a credential definition id is unqualified. - */ -export function assertUnqualifiedCredentialDefinitionId(credentialDefinitionId: string) { - if (!unqualifiedCredentialDefinitionIdRegex.test(credentialDefinitionId)) { - throw new AriesFrameworkError( - `Credential definition id '${credentialDefinitionId}' is not an unqualified credential definition id. Indy SDK only supports unqualified identifiers.` - ) - } -} - -/** - * Assert that a schema id is unqualified. - */ -export function assertUnqualifiedSchemaId(schemaId: string) { - if (!unqualifiedSchemaIdRegex.test(schemaId)) { - throw new AriesFrameworkError( - `Schema id '${schemaId}' is not an unqualified schema id. Indy SDK only supports unqualified identifiers.` - ) - } -} - -/** - * Assert that a revocation registry id is unqualified. - */ -export function assertUnqualifiedRevocationRegistryId(revocationRegistryId: string) { - if (!unqualifiedRevocationRegistryIdRegex.test(revocationRegistryId)) { - throw new AriesFrameworkError( - `Revocation registry id '${revocationRegistryId}' is not an unqualified revocation registry id. Indy SDK only supports unqualified identifiers.` - ) - } -} - -/** - * Assert that an issuer id is unqualified. - */ -export function assertUnqualifiedIssuerId(issuerId: string) { - if (!unqualifiedIndyDidRegex.test(issuerId)) { - throw new AriesFrameworkError( - `Issuer id '${issuerId}' is not an unqualified issuer id. Indy SDK only supports unqualified identifiers.` - ) - } -} - -/** - * Assert that a credential offer only contains unqualified identifiers. - */ -export function assertUnqualifiedCredentialOffer(credentialOffer: AnonCredsCredentialOffer) { - assertUnqualifiedCredentialDefinitionId(credentialOffer.cred_def_id) - assertUnqualifiedSchemaId(credentialOffer.schema_id) -} - -/** - * Assert that a credential request only contains unqualified identifiers. - */ -export function assertUnqualifiedCredentialRequest(credentialRequest: AnonCredsCredentialRequest) { - assertUnqualifiedCredentialDefinitionId(credentialRequest.cred_def_id) -} - -/** - * Assert that a proof request only contains unqualified identifiers. - */ -export function assertUnqualifiedProofRequest(proofRequest: AnonCredsProofRequest) { - const allRequested = [ - ...Object.values(proofRequest.requested_attributes), - ...Object.values(proofRequest.requested_predicates), - ] - - for (const requested of allRequested) { - for (const restriction of requested.restrictions ?? []) { - assertAllUnqualified({ - credentialDefinitionIds: [restriction.cred_def_id], - schemaIds: [restriction.schema_id], - revocationRegistryIds: [restriction.rev_reg_id], - issuerIds: [restriction.issuer_did, restriction.schema_issuer_did], - }) - } - } -} - -export function assertAllUnqualified({ - schemaIds = [], - credentialDefinitionIds = [], - revocationRegistryIds = [], - issuerIds = [], -}: { - schemaIds?: Array - credentialDefinitionIds?: Array - revocationRegistryIds?: Array - issuerIds?: Array -}) { - for (const schemaId of schemaIds) { - // We don't validate undefined values - if (!schemaId) continue - - assertUnqualifiedSchemaId(schemaId) - } - - for (const credentialDefinitionId of credentialDefinitionIds) { - // We don't validate undefined values - if (!credentialDefinitionId) continue - - assertUnqualifiedCredentialDefinitionId(credentialDefinitionId) - } - - for (const revocationRegistryId of revocationRegistryIds) { - // We don't validate undefined values - if (!revocationRegistryId) continue - - assertUnqualifiedRevocationRegistryId(revocationRegistryId) - } - - for (const issuerId of issuerIds) { - // We don't validate undefined values - if (!issuerId) continue - - assertUnqualifiedIssuerId(issuerId) - } -} diff --git a/packages/indy-sdk/src/anoncreds/utils/identifiers.ts b/packages/indy-sdk/src/anoncreds/utils/identifiers.ts deleted file mode 100644 index 4cedb11ff4..0000000000 --- a/packages/indy-sdk/src/anoncreds/utils/identifiers.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * NOTE: this file is available in both the indy-sdk and indy-vdr packages. If making changes to - * this file, make sure to update both files if applicable. - */ - -import { - unqualifiedSchemaIdRegex, - unqualifiedCredentialDefinitionIdRegex, - unqualifiedRevocationRegistryIdRegex, - didIndyCredentialDefinitionIdRegex, - didIndyRevocationRegistryIdRegex, - didIndySchemaIdRegex, - didIndyRegex, -} from '@aries-framework/anoncreds' - -// combines both legacy and did:indy anoncreds identifiers and also the issuer id -const indySdkAnonCredsRegexes = [ - // NOTE: we only include the qualified issuer id here, as we don't support registering objects based on legacy issuer ids. - // you can still resolve using legacy issuer ids, but you need to use the full did:indy identifier when registering. - // As we find a matching anoncreds registry based on the issuerId only when creating an object, this will make sure - // it will throw an no registry found for identifier error. - // issuer id - didIndyRegex, - - // schema - didIndySchemaIdRegex, - unqualifiedSchemaIdRegex, - - // credential definition - didIndyCredentialDefinitionIdRegex, - unqualifiedCredentialDefinitionIdRegex, - - // revocation registry - unqualifiedRevocationRegistryIdRegex, - didIndyRevocationRegistryIdRegex, -] - -export const indySdkAnonCredsRegistryIdentifierRegex = new RegExp( - indySdkAnonCredsRegexes.map((r) => r.source).join('|') -) - -export function getDidIndySchemaId(namespace: string, unqualifiedDid: string, name: string, version: string) { - return `did:indy:${namespace}:${unqualifiedDid}/anoncreds/v0/SCHEMA/${name}/${version}` -} - -export function getDidIndyCredentialDefinitionId( - namespace: string, - unqualifiedDid: string, - seqNo: string | number, - tag: string -) { - return `did:indy:${namespace}:${unqualifiedDid}/anoncreds/v0/CLAIM_DEF/${seqNo}/${tag}` -} - -export function getDidIndyRevocationRegistryId( - namespace: string, - unqualifiedDid: string, - seqNo: string | number, - credentialDefinitionTag: string, - revocationRegistryTag: string -) { - return `did:indy:${namespace}:${unqualifiedDid}/anoncreds/v0/REV_REG_DEF/${seqNo}/${credentialDefinitionTag}/${revocationRegistryTag}` -} diff --git a/packages/indy-sdk/src/anoncreds/utils/tails.ts b/packages/indy-sdk/src/anoncreds/utils/tails.ts deleted file mode 100644 index 787d757322..0000000000 --- a/packages/indy-sdk/src/anoncreds/utils/tails.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { IndySdk } from '../../types' -import type { AgentContext, FileSystem } from '@aries-framework/core' - -import { AriesFrameworkError, getDirFromFilePath, InjectionSymbols } from '@aries-framework/core' - -import { IndySdkError, isIndyError } from '../../error' -import { IndySdkSymbol } from '../../types' - -/** - * Get a handler for the blob storage tails file reader. - * - * @param agentContext The agent context - * @param tailsFilePath The path of the tails file - * @returns The blob storage reader handle - */ -export async function createTailsReader(agentContext: AgentContext, tailsFilePath: string) { - const fileSystem = agentContext.dependencyManager.resolve(InjectionSymbols.FileSystem) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - try { - agentContext.config.logger.debug(`Opening tails reader at path ${tailsFilePath}`) - const tailsFileExists = await fileSystem.exists(tailsFilePath) - - // Extract directory from path (should also work with windows paths) - const dirname = getDirFromFilePath(tailsFilePath) - - if (!tailsFileExists) { - throw new AriesFrameworkError(`Tails file does not exist at path ${tailsFilePath}`) - } - - const tailsReaderConfig = { - base_dir: dirname, - } - - const tailsReader = await indySdk.openBlobStorageReader('default', tailsReaderConfig) - agentContext.config.logger.debug(`Opened tails reader at path ${tailsFilePath}`) - return tailsReader - } catch (error) { - if (isIndyError(error)) { - throw new IndySdkError(error) - } - - throw error - } -} diff --git a/packages/indy-sdk/src/anoncreds/utils/transform.ts b/packages/indy-sdk/src/anoncreds/utils/transform.ts deleted file mode 100644 index 73b5441c93..0000000000 --- a/packages/indy-sdk/src/anoncreds/utils/transform.ts +++ /dev/null @@ -1,161 +0,0 @@ -import type { - AnonCredsCredentialDefinition, - AnonCredsRevocationStatusList, - AnonCredsRevocationRegistryDefinition, - AnonCredsSchema, - AnonCredsCredentialRequestMetadata, - AnonCredsLinkSecretBlindingData, -} from '@aries-framework/anoncreds' -import type { CredDef, CredReqMetadata, RevocReg, RevocRegDef, RevocRegDelta, Schema } from 'indy-sdk' - -import { parseIndyCredentialDefinitionId, parseIndySchemaId } from '@aries-framework/anoncreds' - -export function anonCredsSchemaFromIndySdk(schema: Schema): AnonCredsSchema { - const { did } = parseIndySchemaId(schema.id) - return { - issuerId: did, - name: schema.name, - version: schema.version, - attrNames: schema.attrNames, - } -} - -export function indySdkSchemaFromAnonCreds(schemaId: string, schema: AnonCredsSchema, indyLedgerSeqNo: number): Schema { - return { - id: schemaId, - attrNames: schema.attrNames, - name: schema.name, - version: schema.version, - ver: '1.0', - seqNo: indyLedgerSeqNo, - } -} - -export function anonCredsCredentialDefinitionFromIndySdk(credentialDefinition: CredDef): AnonCredsCredentialDefinition { - const { did } = parseIndyCredentialDefinitionId(credentialDefinition.id) - - return { - issuerId: did, - schemaId: credentialDefinition.schemaId, - tag: credentialDefinition.tag, - type: 'CL', - value: credentialDefinition.value, - } -} - -export function indySdkCredentialDefinitionFromAnonCreds( - credentialDefinitionId: string, - credentialDefinition: AnonCredsCredentialDefinition -): CredDef { - return { - id: credentialDefinitionId, - schemaId: credentialDefinition.schemaId, - tag: credentialDefinition.tag, - type: credentialDefinition.type, - value: credentialDefinition.value, - ver: '1.0', - } -} - -export function indySdkRevocationRegistryDefinitionFromAnonCreds( - revocationRegistryDefinitionId: string, - revocationRegistryDefinition: AnonCredsRevocationRegistryDefinition -): RevocRegDef { - return { - id: revocationRegistryDefinitionId, - credDefId: revocationRegistryDefinition.credDefId, - revocDefType: revocationRegistryDefinition.revocDefType, - tag: revocationRegistryDefinition.tag, - value: { - issuanceType: 'ISSUANCE_BY_DEFAULT', // NOTE: we always use ISSUANCE_BY_DEFAULT when passing to the indy-sdk. It doesn't matter, as we have the revocation List with the full state - maxCredNum: revocationRegistryDefinition.value.maxCredNum, - publicKeys: revocationRegistryDefinition.value.publicKeys, - tailsHash: revocationRegistryDefinition.value.tailsHash, - tailsLocation: revocationRegistryDefinition.value.tailsLocation, - }, - ver: '1.0', - } -} - -export function anonCredsRevocationStatusListFromIndySdk( - revocationRegistryDefinitionId: string, - revocationRegistryDefinition: AnonCredsRevocationRegistryDefinition, - delta: RevocRegDelta, - timestamp: number, - isIssuanceByDefault: boolean -): AnonCredsRevocationStatusList { - // 0 means unrevoked, 1 means revoked - const defaultState = isIssuanceByDefault ? 0 : 1 - - // Fill with default value - const revocationList = new Array(revocationRegistryDefinition.value.maxCredNum).fill(defaultState) - - // Set all `issuer` indexes to 0 (not revoked) - for (const issued of delta.value.issued ?? []) { - revocationList[issued] = 0 - } - - // Set all `revoked` indexes to 1 (revoked) - for (const revoked of delta.value.revoked ?? []) { - revocationList[revoked] = 1 - } - - return { - issuerId: revocationRegistryDefinition.issuerId, - currentAccumulator: delta.value.accum, - revRegDefId: revocationRegistryDefinitionId, - revocationList, - timestamp, - } -} - -export function indySdkRevocationRegistryFromAnonCreds(revocationStatusList: AnonCredsRevocationStatusList): RevocReg { - return { - ver: '1.0', - value: { - accum: revocationStatusList.currentAccumulator, - }, - } -} - -export function indySdkRevocationDeltaFromAnonCreds( - revocationStatusList: AnonCredsRevocationStatusList -): RevocRegDelta { - // Get all indices from the revocationStatusList that are revoked (so have value '1') - const revokedIndices = revocationStatusList.revocationList.reduce( - (revoked, current, index) => (current === 1 ? [...revoked, index] : revoked), - [] - ) - - return { - value: { - accum: revocationStatusList.currentAccumulator, - issued: [], - revoked: revokedIndices, - // NOTE: this must be a valid accumulator but it's not actually used. So we set it to the - // currentAccumulator as that should always be a valid accumulator. - prevAccum: revocationStatusList.currentAccumulator, - }, - ver: '1.0', - } -} - -export function anonCredsCredentialRequestMetadataFromIndySdk( - credentialRequestMetadata: CredReqMetadata -): AnonCredsCredentialRequestMetadata { - return { - link_secret_blinding_data: credentialRequestMetadata.master_secret_blinding_data as AnonCredsLinkSecretBlindingData, - link_secret_name: credentialRequestMetadata.master_secret_name as string, - nonce: credentialRequestMetadata.nonce as string, - } -} - -export function indySdkCredentialRequestMetadataFromAnonCreds( - credentialRequestMetadata: AnonCredsCredentialRequestMetadata -): CredReqMetadata { - return { - master_secret_blinding_data: credentialRequestMetadata.link_secret_blinding_data, - master_secret_name: credentialRequestMetadata.link_secret_name, - nonce: credentialRequestMetadata.nonce, - } -} diff --git a/packages/indy-sdk/src/dids/IndySdkIndyDidRegistrar.ts b/packages/indy-sdk/src/dids/IndySdkIndyDidRegistrar.ts deleted file mode 100644 index 2a3c6c3097..0000000000 --- a/packages/indy-sdk/src/dids/IndySdkIndyDidRegistrar.ts +++ /dev/null @@ -1,328 +0,0 @@ -import type { IndyEndpointAttrib } from './didSovUtil' -import type { IndySdkPool } from '../ledger' -import type { IndySdk } from '../types' -import type { - AgentContext, - Buffer, - DidCreateOptions, - DidCreateResult, - DidDeactivateResult, - DidRegistrar, - DidUpdateResult, -} from '@aries-framework/core' -import type { NymRole } from 'indy-sdk' - -import { parseIndyDid } from '@aries-framework/anoncreds' -import { DidDocumentRole, DidRecord, DidRepository, KeyType, Key } from '@aries-framework/core' - -import { IndySdkError } from '../error' -import { isIndyError } from '../error/indyError' -import { IndySdkPoolService } from '../ledger' -import { IndySdkSymbol } from '../types' -import { assertIndySdkWallet } from '../utils/assertIndySdkWallet' -import { isLegacySelfCertifiedDid, legacyIndyDidFromPublicKeyBase58 } from '../utils/did' - -import { createKeyAgreementKey, indyDidDocumentFromDid, verificationKeyForIndyDid } from './didIndyUtil' -import { addServicesFromEndpointsAttrib } from './didSovUtil' - -export class IndySdkIndyDidRegistrar implements DidRegistrar { - public readonly supportedMethods = ['indy'] - - public async create(agentContext: AgentContext, options: IndySdkIndyDidCreateOptions): Promise { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const didRepository = agentContext.dependencyManager.resolve(DidRepository) - - const { alias, role, submitterDid, endpoints } = options.options - let did = options.did - let namespaceIdentifier: string - let verificationKey: Key - const privateKey = options.secret?.privateKey - - if (did && privateKey) { - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `Only one of 'privateKey' or 'did' must be provided`, - }, - } - } - - try { - assertIndySdkWallet(agentContext.wallet) - - // Parse submitterDid and extract namespace based on the submitter did - const { namespace: submitterNamespace, namespaceIdentifier: submitterNamespaceIdentifier } = - parseIndyDid(submitterDid) - const submitterSigningKey = await verificationKeyForIndyDid(agentContext, submitterDid) - - // Only supports version 1 did identifier (which is same as did:sov) - if (did) { - if (!options.options.verkey) { - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: 'If a did is defined, a matching verkey must be provided', - }, - } - } - - const { namespace, namespaceIdentifier: _namespaceIdentifier } = parseIndyDid(did) - namespaceIdentifier = _namespaceIdentifier - - verificationKey = Key.fromPublicKeyBase58(options.options.verkey, KeyType.Ed25519) - - if (!isLegacySelfCertifiedDid(namespaceIdentifier, options.options.verkey)) { - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `Did must be first 16 bytes of the the verkey base58 encoded.`, - }, - } - } - - if (submitterNamespace !== namespace) { - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `The submitter did uses namespace ${submitterNamespace} and the did to register uses namespace ${namespace}. Namespaces must match.`, - }, - } - } - } else { - // Create a new key and calculate did according to the rules for indy did method - verificationKey = await agentContext.wallet.createKey({ privateKey, keyType: KeyType.Ed25519 }) - namespaceIdentifier = legacyIndyDidFromPublicKeyBase58(verificationKey.publicKeyBase58) - did = `did:indy:${submitterNamespace}:${namespaceIdentifier}` - } - - const pool = indySdkPoolService.getPoolForNamespace(submitterNamespace) - await this.registerPublicDid( - agentContext, - pool, - submitterNamespaceIdentifier, - submitterSigningKey, - namespaceIdentifier, - verificationKey, - alias, - role - ) - - // Create did document - const didDocumentBuilder = indyDidDocumentFromDid(did, verificationKey.publicKeyBase58) - - // Add services if endpoints object was passed. - if (endpoints) { - const keyAgreementId = `${did}#key-agreement-1` - - await this.setEndpointsForDid(agentContext, pool, namespaceIdentifier, verificationKey, endpoints) - - didDocumentBuilder - .addContext('https://w3id.org/security/suites/x25519-2019/v1') - .addVerificationMethod({ - controller: did, - id: keyAgreementId, - publicKeyBase58: createKeyAgreementKey(verificationKey.publicKeyBase58), - type: 'X25519KeyAgreementKey2019', - }) - .addKeyAgreement(keyAgreementId) - - // Process endpoint attrib following the same rules as for did:sov - addServicesFromEndpointsAttrib(didDocumentBuilder, did, endpoints, keyAgreementId) - } - - // Build did document. - const didDocument = didDocumentBuilder.build() - - // Save the did so we know we created it and can issue with it - const didRecord = new DidRecord({ - did, - role: DidDocumentRole.Created, - tags: { - recipientKeyFingerprints: didDocument.recipientKeys.map((key: Key) => key.fingerprint), - }, - }) - await didRepository.save(agentContext, didRecord) - - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'finished', - did, - didDocument, - secret: { - // FIXME: the uni-registrar creates the seed in the registrar method - // if it doesn't exist so the seed can always be returned. Currently - // we can only return it if the seed was passed in by the user. Once - // we have a secure method for generating seeds we should use the same - // approach - privateKey: options.secret?.privateKey, - }, - }, - } - } catch (error) { - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `unknownError: ${error.message}`, - }, - } - } - } - - public async update(): Promise { - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `notImplemented: updating did:indy not implemented yet`, - }, - } - } - - public async deactivate(): Promise { - return { - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `notImplemented: deactivating did:indy not implemented yet`, - }, - } - } - - private async registerPublicDid( - agentContext: AgentContext, - pool: IndySdkPool, - unqualifiedSubmitterDid: string, - submitterSigningKey: Key, - unqualifiedDid: string, - signingKey: Key, - alias: string, - role?: NymRole - ) { - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - - try { - agentContext.config.logger.debug(`Register public did '${unqualifiedDid}' on ledger '${pool.didIndyNamespace}'`) - - const request = await indySdk.buildNymRequest( - unqualifiedSubmitterDid, - unqualifiedDid, - signingKey.publicKeyBase58, - alias, - role || null - ) - - const response = await indySdkPoolService.submitWriteRequest(agentContext, pool, request, submitterSigningKey) - - agentContext.config.logger.debug( - `Registered public did '${unqualifiedDid}' on ledger '${pool.didIndyNamespace}'`, - { - response, - } - ) - } catch (error) { - agentContext.config.logger.error( - `Error registering public did '${unqualifiedDid}' on ledger '${pool.didIndyNamespace}'`, - { - error, - unqualifiedSubmitterDid, - unqualifiedDid, - verkey: signingKey.publicKeyBase58, - alias, - role, - pool: pool.didIndyNamespace, - } - ) - - throw error - } - } - - private async setEndpointsForDid( - agentContext: AgentContext, - pool: IndySdkPool, - unqualifiedDid: string, - signingKey: Key, - endpoints: IndyEndpointAttrib - ): Promise { - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - - try { - agentContext.config.logger.debug( - `Set endpoints for did '${unqualifiedDid}' on ledger '${pool.didIndyNamespace}'`, - endpoints - ) - - const request = await indySdk.buildAttribRequest( - unqualifiedDid, - unqualifiedDid, - null, - { endpoint: endpoints }, - null - ) - - const response = await indySdkPoolService.submitWriteRequest(agentContext, pool, request, signingKey) - agentContext.config.logger.debug( - `Successfully set endpoints for did '${unqualifiedDid}' on ledger '${pool.didIndyNamespace}'`, - { - response, - endpoints, - } - ) - } catch (error) { - agentContext.config.logger.error( - `Error setting endpoints for did '${unqualifiedDid}' on ledger '${pool.didIndyNamespace}'`, - { - error, - unqualifiedDid, - endpoints, - } - ) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } -} - -interface IndySdkIndyDidCreateOptionsBase extends DidCreateOptions { - // The indy sdk can only publish a very limited did document (what is mostly known as a legacy did:sov did) and thus we require everything - // needed to construct the did document to be passed through the options object. - didDocument?: never - options: { - alias: string - role?: NymRole - verkey?: string - endpoints?: IndyEndpointAttrib - submitterDid: string - } - secret?: { - privateKey?: Buffer - } -} - -interface IndySdkIndyDidCreateOptionsWithDid extends IndySdkIndyDidCreateOptionsBase { - method?: never - did: string -} - -interface IndySdkIndyDidCreateOptionsWithoutDid extends IndySdkIndyDidCreateOptionsBase { - method: 'indy' - did?: never -} - -export type IndySdkIndyDidCreateOptions = IndySdkIndyDidCreateOptionsWithDid | IndySdkIndyDidCreateOptionsWithoutDid diff --git a/packages/indy-sdk/src/dids/IndySdkIndyDidResolver.ts b/packages/indy-sdk/src/dids/IndySdkIndyDidResolver.ts deleted file mode 100644 index 1c486eb3aa..0000000000 --- a/packages/indy-sdk/src/dids/IndySdkIndyDidResolver.ts +++ /dev/null @@ -1,124 +0,0 @@ -import type { IndyEndpointAttrib } from './didSovUtil' -import type { IndySdkPool } from '../ledger' -import type { IndySdk } from '../types' -import type { DidResolutionResult, DidResolver, AgentContext } from '@aries-framework/core' - -import { parseIndyDid } from '@aries-framework/anoncreds' - -import { isIndyError, IndySdkError } from '../error' -import { IndySdkPoolService } from '../ledger/IndySdkPoolService' -import { IndySdkSymbol } from '../types' -import { getFullVerkey } from '../utils/did' - -import { createKeyAgreementKey, indyDidDocumentFromDid } from './didIndyUtil' -import { addServicesFromEndpointsAttrib } from './didSovUtil' - -export class IndySdkIndyDidResolver implements DidResolver { - public readonly supportedMethods = ['indy'] - - public async resolve(agentContext: AgentContext, did: string): Promise { - const didDocumentMetadata = {} - - try { - const { namespaceIdentifier, namespace } = parseIndyDid(did) - - const poolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const pool = poolService.getPoolForNamespace(namespace) - - const nym = await this.getPublicDid(agentContext, pool, namespaceIdentifier) - const endpoints = await this.getEndpointsForDid(agentContext, pool, namespaceIdentifier) - - // For modern did:indy DIDs, we assume that GET_NYM is always a full verkey in base58. - // For backwards compatibility, we accept a shortened verkey and convert it using previous convention - const verkey = getFullVerkey(did, nym.verkey) - const builder = indyDidDocumentFromDid(did, verkey) - - // NOTE: we don't support the `diddocContent` field in the GET_NYM response using the indy-sdk. So if the did would have the `diddocContent` field - // we will ignore it without knowing if it is present. We may be able to extract the diddocContent from the GET_NYM response in the future, but need - // some dids registered with diddocContent to test with. - if (endpoints) { - const keyAgreementId = `${did}#key-agreement-1` - - builder - .addContext('https://w3id.org/security/suites/x25519-2019/v1') - .addVerificationMethod({ - controller: did, - id: keyAgreementId, - publicKeyBase58: createKeyAgreementKey(verkey), - type: 'X25519KeyAgreementKey2019', - }) - .addKeyAgreement(keyAgreementId) - addServicesFromEndpointsAttrib(builder, did, endpoints, keyAgreementId) - } - - return { - didDocument: builder.build(), - didDocumentMetadata, - didResolutionMetadata: { contentType: 'application/did+ld+json' }, - } - } catch (error) { - return { - didDocument: null, - didDocumentMetadata, - didResolutionMetadata: { - error: 'notFound', - message: `resolver_error: Unable to resolve did '${did}': ${error}`, - }, - } - } - } - - private async getPublicDid(agentContext: AgentContext, pool: IndySdkPool, unqualifiedDid: string) { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - const request = await indySdk.buildGetNymRequest(null, unqualifiedDid) - const response = await indySdkPoolService.submitReadRequest(pool, request) - - return await indySdk.parseGetNymResponse(response) - } - - private async getEndpointsForDid(agentContext: AgentContext, pool: IndySdkPool, unqualifiedDid: string) { - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - - try { - agentContext.config.logger.debug( - `Get endpoints for did '${unqualifiedDid}' from ledger '${pool.didIndyNamespace}'` - ) - - const request = await indySdk.buildGetAttribRequest(null, unqualifiedDid, 'endpoint', null, null) - - agentContext.config.logger.debug( - `Submitting get endpoint ATTRIB request for did '${unqualifiedDid}' to ledger '${pool.didIndyNamespace}'` - ) - const response = await indySdkPoolService.submitReadRequest(pool, request) - - if (!response.result.data) { - return null - } - - const endpoints = JSON.parse(response.result.data as string)?.endpoint as IndyEndpointAttrib - agentContext.config.logger.debug( - `Got endpoints '${JSON.stringify(endpoints)}' for did '${unqualifiedDid}' from ledger '${ - pool.didIndyNamespace - }'`, - { - response, - endpoints, - } - ) - - return endpoints - } catch (error) { - agentContext.config.logger.error( - `Error retrieving endpoints for did '${unqualifiedDid}' from ledger '${pool.didIndyNamespace}'`, - { - error, - } - ) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } -} diff --git a/packages/indy-sdk/src/dids/IndySdkSovDidResolver.ts b/packages/indy-sdk/src/dids/IndySdkSovDidResolver.ts deleted file mode 100644 index ff6afc9571..0000000000 --- a/packages/indy-sdk/src/dids/IndySdkSovDidResolver.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { IndyEndpointAttrib } from './didSovUtil' -import type { IndySdkPool } from '../ledger' -import type { IndySdk } from '../types' -import type { DidResolutionResult, ParsedDid, DidResolver, AgentContext } from '@aries-framework/core' - -import { isIndyError, IndySdkError } from '../error' -import { IndySdkPoolService } from '../ledger/IndySdkPoolService' -import { IndySdkSymbol } from '../types' - -import { addServicesFromEndpointsAttrib, sovDidDocumentFromDid } from './didSovUtil' - -export class IndySdkSovDidResolver implements DidResolver { - public readonly supportedMethods = ['sov'] - - public async resolve(agentContext: AgentContext, did: string, parsed: ParsedDid): Promise { - const didDocumentMetadata = {} - - try { - const poolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const { pool, nymResponse } = await poolService.getPoolForDid(agentContext, parsed.id) - const nym = nymResponse ?? (await this.getPublicDid(agentContext, pool, parsed.id)) - const endpoints = await this.getEndpointsForDid(agentContext, pool, parsed.id) - - const keyAgreementId = `${parsed.did}#key-agreement-1` - const builder = sovDidDocumentFromDid(parsed.did, nym.verkey) - - if (endpoints) { - addServicesFromEndpointsAttrib(builder, parsed.did, endpoints, keyAgreementId) - } - - return { - didDocument: builder.build(), - didDocumentMetadata, - didResolutionMetadata: { contentType: 'application/did+ld+json' }, - } - } catch (error) { - return { - didDocument: null, - didDocumentMetadata, - didResolutionMetadata: { - error: 'notFound', - message: `resolver_error: Unable to resolve did '${did}': ${error}`, - }, - } - } - } - - private async getPublicDid(agentContext: AgentContext, pool: IndySdkPool, did: string) { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - - const request = await indySdk.buildGetNymRequest(null, did) - const response = await indySdkPoolService.submitReadRequest(pool, request) - - return await indySdk.parseGetNymResponse(response) - } - - private async getEndpointsForDid(agentContext: AgentContext, pool: IndySdkPool, unqualifiedDid: string) { - const indySdk = agentContext.dependencyManager.resolve(IndySdkSymbol) - const indySdkPoolService = agentContext.dependencyManager.resolve(IndySdkPoolService) - - try { - agentContext.config.logger.debug( - `Get endpoints for did '${unqualifiedDid}' from ledger '${pool.didIndyNamespace}'` - ) - - const request = await indySdk.buildGetAttribRequest(null, unqualifiedDid, 'endpoint', null, null) - - agentContext.config.logger.debug( - `Submitting get endpoint ATTRIB request for did '${unqualifiedDid}' to ledger '${pool.didIndyNamespace}'` - ) - const response = await indySdkPoolService.submitReadRequest(pool, request) - - if (!response.result.data) return null - - const endpoints = JSON.parse(response.result.data as string)?.endpoint as IndyEndpointAttrib - agentContext.config.logger.debug( - `Got endpoints '${JSON.stringify(endpoints)}' for did '${unqualifiedDid}' from ledger '${ - pool.didIndyNamespace - }'`, - { - response, - endpoints, - } - ) - - return endpoints ?? null - } catch (error) { - agentContext.config.logger.error( - `Error retrieving endpoints for did '${unqualifiedDid}' from ledger '${pool.didIndyNamespace}'`, - { - error, - } - ) - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } -} diff --git a/packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidRegistrar.test.ts b/packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidRegistrar.test.ts deleted file mode 100644 index f475158263..0000000000 --- a/packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidRegistrar.test.ts +++ /dev/null @@ -1,501 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -import type { IndySdkPool } from '../../ledger/IndySdkPool' -import type { DidRecord, RecordSavedEvent } from '@aries-framework/core' - -import { - SigningProviderRegistry, - DidsApi, - DidDocument, - VerificationMethod, - KeyType, - Key, - TypedArrayEncoder, - DidRepository, - JsonTransformer, - DidDocumentRole, - EventEmitter, - RepositoryEventTypes, -} from '@aries-framework/core' -import { Subject } from 'rxjs' - -import { InMemoryStorageService } from '../../../../../tests/InMemoryStorageService' -import { mockFunction, getAgentConfig, getAgentContext, agentDependencies, indySdk } from '../../../../core/tests' -import { IndySdkPoolService } from '../../ledger/IndySdkPoolService' -import { IndySdkWallet } from '../../wallet' -import { IndySdkIndyDidRegistrar } from '../IndySdkIndyDidRegistrar' - -jest.mock('../../ledger/IndySdkPoolService') -const IndySdkPoolServiceMock = IndySdkPoolService as jest.Mock -const indySdkPoolServiceMock = new IndySdkPoolServiceMock() - -const pool = { - config: { indyNamespace: 'pool1' }, -} as IndySdkPool -mockFunction(indySdkPoolServiceMock.getPoolForNamespace).mockReturnValue(pool) - -const agentConfig = getAgentConfig('IndySdkIndyDidRegistrar') -const wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) - -jest - .spyOn(wallet, 'createKey') - .mockResolvedValue(Key.fromPublicKeyBase58('E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', KeyType.Ed25519)) -const storageService = new InMemoryStorageService() -const eventEmitter = new EventEmitter(agentDependencies, new Subject()) -const didRepository = new DidRepository(storageService, eventEmitter) - -const agentContext = getAgentContext({ - wallet, - registerInstances: [ - [DidRepository, didRepository], - [IndySdkPoolService, indySdkPoolServiceMock], - [ - DidsApi, - { - resolve: jest.fn().mockResolvedValue({ - didDocument: new DidDocument({ - id: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - authentication: [ - new VerificationMethod({ - id: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg#verkey', - type: 'Ed25519VerificationKey2018', - controller: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - publicKeyBase58: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - }), - ], - }), - }), - }, - ], - ], - agentConfig, -}) - -const indySdkIndyDidRegistrar = new IndySdkIndyDidRegistrar() - -describe('IndySdkIndyDidRegistrar', () => { - afterEach(() => { - jest.clearAllMocks() - }) - - test('returns an error state if both did and privateKey are provided', async () => { - const result = await indySdkIndyDidRegistrar.create(agentContext, { - did: 'did:indy:pool1:did-value', - options: { - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - alias: 'Hello', - }, - secret: { - privateKey: TypedArrayEncoder.fromString('key'), - }, - }) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `Only one of 'privateKey' or 'did' must be provided`, - }, - }) - }) - - test('returns an error state if the submitter did is not a valid did:indy did', async () => { - const result = await indySdkIndyDidRegistrar.create(agentContext, { - method: 'indy', - options: { - submitterDid: 'BzCbsNYhMrjHiqZDTUASHg', - alias: 'Hello', - }, - }) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: 'unknownError: BzCbsNYhMrjHiqZDTUASHg is not a valid did:indy did', - }, - }) - }) - - test('returns an error state if did is provided, but it is not a valid did:indy did', async () => { - const result = await indySdkIndyDidRegistrar.create(agentContext, { - did: 'BzCbsNYhMrjHiqZDTUASHg', - options: { - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - verkey: 'verkey', - alias: 'Hello', - }, - }) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: 'unknownError: BzCbsNYhMrjHiqZDTUASHg is not a valid did:indy did', - }, - }) - }) - - test('returns an error state if did is provided, but no verkey', async () => { - const result = await indySdkIndyDidRegistrar.create(agentContext, { - did: 'BzCbsNYhMrjHiqZDTUASHg', - options: { - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - alias: 'Hello', - }, - }) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: 'If a did is defined, a matching verkey must be provided', - }, - }) - }) - - test('returns an error state if did and verkey are provided, but the did is not self certifying', async () => { - const result = await indySdkIndyDidRegistrar.create(agentContext, { - did: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - options: { - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - verkey: 'verkey', - alias: 'Hello', - }, - }) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: 'Did must be first 16 bytes of the the verkey base58 encoded.', - }, - }) - }) - - test('returns an error state if did is provided, but does not match with the namespace from the submitterDid', async () => { - const result = await indySdkIndyDidRegistrar.create(agentContext, { - did: 'did:indy:pool2:R1xKJw17sUoXhejEpugMYJ', - options: { - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - verkey: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - alias: 'Hello', - }, - }) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: - 'The submitter did uses namespace pool1 and the did to register uses namespace pool2. Namespaces must match.', - }, - }) - }) - - test('creates a did:indy document without services', async () => { - const privateKey = TypedArrayEncoder.fromString('96213c3d7fc8d4d6754c712fd969598e') - - // @ts-ignore method is private - const registerPublicDidSpy = jest.spyOn(indySdkIndyDidRegistrar, 'registerPublicDid') - // @ts-ignore type check fails because method is private - registerPublicDidSpy.mockImplementationOnce(() => Promise.resolve()) - - const result = await indySdkIndyDidRegistrar.create(agentContext, { - method: 'indy', - options: { - alias: 'Hello', - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - role: 'STEWARD', - }, - secret: { - privateKey, - }, - }) - expect(registerPublicDidSpy).toHaveBeenCalledWith( - agentContext, - pool, - // Unqualified submitter did - 'BzCbsNYhMrjHiqZDTUASHg', - // submitter signing key, - expect.any(Key), - // Unqualified created indy did - 'R1xKJw17sUoXhejEpugMYJ', - // Verkey - expect.any(Key), - // Alias - 'Hello', - // Role - 'STEWARD' - ) - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'finished', - did: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - didDocument: { - '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - verificationMethod: [ - { - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey', - type: 'Ed25519VerificationKey2018', - controller: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - publicKeyBase58: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - }, - ], - authentication: ['did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey'], - assertionMethod: undefined, - keyAgreement: undefined, - }, - secret: { - privateKey, - }, - }, - }) - }) - - test('creates a did:indy document by passing did', async () => { - // @ts-ignore method is private - const registerPublicDidSpy = jest.spyOn(indySdkIndyDidRegistrar, 'registerPublicDid') - // @ts-ignore type check fails because method is private - registerPublicDidSpy.mockImplementationOnce(() => Promise.resolve()) - - const result = await indySdkIndyDidRegistrar.create(agentContext, { - did: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - options: { - verkey: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - alias: 'Hello', - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - role: 'STEWARD', - }, - secret: {}, - }) - expect(registerPublicDidSpy).toHaveBeenCalledWith( - agentContext, - pool, - // Unqualified submitter did - 'BzCbsNYhMrjHiqZDTUASHg', - // submitter signing key, - expect.any(Key), - // Unqualified created indy did - 'R1xKJw17sUoXhejEpugMYJ', - // Verkey - expect.any(Key), - // Alias - 'Hello', - // Role - 'STEWARD' - ) - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'finished', - did: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - didDocument: { - '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - verificationMethod: [ - { - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey', - type: 'Ed25519VerificationKey2018', - controller: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - publicKeyBase58: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - }, - ], - authentication: ['did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey'], - assertionMethod: undefined, - keyAgreement: undefined, - }, - secret: {}, - }, - }) - }) - - test('creates a did:indy document with services', async () => { - const privateKey = TypedArrayEncoder.fromString('96213c3d7fc8d4d6754c712fd969598e') - - // @ts-ignore method is private - const registerPublicDidSpy = jest.spyOn(indySdkIndyDidRegistrar, 'registerPublicDid') - // @ts-ignore type check fails because method is private - registerPublicDidSpy.mockImplementationOnce(() => Promise.resolve()) - - // @ts-ignore method is private - const setEndpointsForDidSpy = jest.spyOn(indySdkIndyDidRegistrar, 'setEndpointsForDid') - // @ts-ignore type check fails because method is private - setEndpointsForDidSpy.mockImplementationOnce(() => Promise.resolve(undefined)) - - const result = await indySdkIndyDidRegistrar.create(agentContext, { - method: 'indy', - options: { - alias: 'Hello', - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - role: 'STEWARD', - endpoints: { - endpoint: 'https://example.com/endpoint', - routingKeys: ['key-1'], - types: ['DIDComm', 'did-communication', 'endpoint'], - }, - }, - secret: { - privateKey, - }, - }) - - expect(registerPublicDidSpy).toHaveBeenCalledWith( - agentContext, - pool, - // Unqualified submitter did - 'BzCbsNYhMrjHiqZDTUASHg', - // submitter signing key, - expect.any(Key), - // Unqualified created indy did - 'R1xKJw17sUoXhejEpugMYJ', - // Verkey - expect.any(Key), - // Alias - 'Hello', - // Role - 'STEWARD' - ) - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'finished', - did: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - didDocument: { - '@context': [ - 'https://w3id.org/did/v1', - 'https://w3id.org/security/suites/ed25519-2018/v1', - 'https://w3id.org/security/suites/x25519-2019/v1', - 'https://didcomm.org/messaging/contexts/v2', - ], - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - verificationMethod: [ - { - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey', - type: 'Ed25519VerificationKey2018', - controller: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - publicKeyBase58: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - }, - { - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#key-agreement-1', - type: 'X25519KeyAgreementKey2019', - controller: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - publicKeyBase58: 'Fbv17ZbnUSbafsiUBJbdGeC62M8v8GEscVMMcE59mRPt', - }, - ], - service: [ - { - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#endpoint', - serviceEndpoint: 'https://example.com/endpoint', - type: 'endpoint', - }, - { - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#did-communication', - serviceEndpoint: 'https://example.com/endpoint', - type: 'did-communication', - priority: 0, - recipientKeys: ['did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#key-agreement-1'], - routingKeys: ['key-1'], - accept: ['didcomm/aip2;env=rfc19'], - }, - { - id: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#didcomm-1', - serviceEndpoint: 'https://example.com/endpoint', - type: 'DIDComm', - routingKeys: ['key-1'], - accept: ['didcomm/v2'], - }, - ], - authentication: ['did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey'], - assertionMethod: undefined, - keyAgreement: ['did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#key-agreement-1'], - }, - secret: { - privateKey, - }, - }, - }) - }) - - test('stores the did document', async () => { - const privateKey = TypedArrayEncoder.fromString('96213c3d7fc8d4d6754c712fd969598e') - - // @ts-ignore method is private - const registerPublicDidSpy = jest.spyOn(indySdkIndyDidRegistrar, 'registerPublicDid') - // @ts-ignore type check fails because method is private - registerPublicDidSpy.mockImplementationOnce(() => Promise.resolve()) - - // @ts-ignore method is private - const setEndpointsForDidSpy = jest.spyOn(indySdkIndyDidRegistrar, 'setEndpointsForDid') - // @ts-ignore type check fails because method is private - setEndpointsForDidSpy.mockImplementationOnce(() => Promise.resolve(undefined)) - - const saveCalled = jest.fn() - eventEmitter.on>(RepositoryEventTypes.RecordSaved, saveCalled) - - await indySdkIndyDidRegistrar.create(agentContext, { - method: 'indy', - options: { - alias: 'Hello', - submitterDid: 'did:indy:pool1:BzCbsNYhMrjHiqZDTUASHg', - role: 'STEWARD', - endpoints: { - endpoint: 'https://example.com/endpoint', - routingKeys: ['key-1'], - types: ['DIDComm', 'did-communication', 'endpoint'], - }, - }, - secret: { - privateKey, - }, - }) - - expect(saveCalled).toHaveBeenCalledTimes(1) - const [saveEvent] = saveCalled.mock.calls[0] - - expect(saveEvent.payload.record).toMatchObject({ - did: 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ', - role: DidDocumentRole.Created, - _tags: { - recipientKeyFingerprints: ['z6LSrH6AdsQeZuKKmG6Ehx7abEQZsVg2psR2VU536gigUoAe'], - }, - didDocument: undefined, - }) - }) - - test('returns an error state when calling update', async () => { - const result = await indySdkIndyDidRegistrar.update() - - expect(result).toEqual({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `notImplemented: updating did:indy not implemented yet`, - }, - }) - }) - - test('returns an error state when calling deactivate', async () => { - const result = await indySdkIndyDidRegistrar.deactivate() - - expect(result).toEqual({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'failed', - reason: `notImplemented: deactivating did:indy not implemented yet`, - }, - }) - }) -}) diff --git a/packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidResolver.test.ts b/packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidResolver.test.ts deleted file mode 100644 index 7c4f294286..0000000000 --- a/packages/indy-sdk/src/dids/__tests__/IndySdkIndyDidResolver.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import type { IndySdkPool } from '../../ledger' -import type { IndyEndpointAttrib } from '../didSovUtil' -import type { GetNymResponse } from 'indy-sdk' - -import { SigningProviderRegistry, JsonTransformer } from '@aries-framework/core' -import indySdk from 'indy-sdk' - -import { mockFunction, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' -import { IndySdkPoolService } from '../../ledger/IndySdkPoolService' -import { IndySdkSymbol } from '../../types' -import { IndySdkWallet } from '../../wallet' -import { IndySdkIndyDidResolver } from '../IndySdkIndyDidResolver' - -import didIndyPool1R1xKJw17sUoXhejEpugMYJFixture from './__fixtures__/didIndyPool1R1xKJw17sUoXhejEpugMYJ.json' -import didIndyPool1WJz9mHyW9BZksioQnRsrAoFixture from './__fixtures__/didIndyPool1WJz9mHyW9BZksioQnRsrAo.json' - -jest.mock('../../ledger/IndySdkPoolService') -const IndySdkPoolServiceMock = IndySdkPoolService as jest.Mock -const indySdkPoolServiceMock = new IndySdkPoolServiceMock() - -mockFunction(indySdkPoolServiceMock.getPoolForNamespace).mockReturnValue({ - config: { indyNamespace: 'pool1' }, -} as IndySdkPool) - -const agentConfig = getAgentConfig('IndySdkIndyDidResolver') - -const wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) - -const agentContext = getAgentContext({ - wallet, - agentConfig, - registerInstances: [ - [IndySdkPoolService, indySdkPoolServiceMock], - [IndySdkSymbol, indySdk], - ], -}) - -const indySdkSovDidResolver = new IndySdkIndyDidResolver() - -describe('IndySdkIndyDidResolver', () => { - it('should correctly resolve a did:indy document', async () => { - const did = 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ' - - const nymResponse: GetNymResponse = { - did: 'R1xKJw17sUoXhejEpugMYJ', - verkey: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - role: 'ENDORSER', - } - - const endpoints: IndyEndpointAttrib = { - endpoint: 'https://ssi.com', - profile: 'https://profile.com', - hub: 'https://hub.com', - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getPublicDid').mockResolvedValue(nymResponse) - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getEndpointsForDid').mockResolvedValue(endpoints) - - const result = await indySdkSovDidResolver.resolve(agentContext, did) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocument: didIndyPool1R1xKJw17sUoXhejEpugMYJFixture, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, - }) - }) - - it('should resolve a did:indy document with routingKeys and types entries in the attrib', async () => { - const did = 'did:indy:pool1:WJz9mHyW9BZksioQnRsrAo' - - const nymResponse: GetNymResponse = { - did: 'WJz9mHyW9BZksioQnRsrAo', - verkey: 'GyYtYWU1vjwd5PFJM4VSX5aUiSV3TyZMuLBJBTQvfdF8', - role: 'ENDORSER', - } - - const endpoints: IndyEndpointAttrib = { - endpoint: 'https://agent.com', - types: ['endpoint', 'did-communication', 'DIDComm'], - routingKeys: ['routingKey1', 'routingKey2'], - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getPublicDid').mockResolvedValue(nymResponse) - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getEndpointsForDid').mockResolvedValue(endpoints) - - const result = await indySdkSovDidResolver.resolve(agentContext, did) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocument: didIndyPool1WJz9mHyW9BZksioQnRsrAoFixture, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, - }) - }) - - it('should return did resolution metadata with error if the indy ledger service throws an error', async () => { - const did = 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ' - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getPublicDid').mockRejectedValue(new Error('Error retrieving did')) - - const result = await indySdkSovDidResolver.resolve(agentContext, did) - - expect(result).toMatchObject({ - didDocument: null, - didDocumentMetadata: {}, - didResolutionMetadata: { - error: 'notFound', - message: `resolver_error: Unable to resolve did 'did:indy:pool1:R1xKJw17sUoXhejEpugMYJ': Error: Error retrieving did`, - }, - }) - }) -}) diff --git a/packages/indy-sdk/src/dids/__tests__/IndySdkSovDidResolver.test.ts b/packages/indy-sdk/src/dids/__tests__/IndySdkSovDidResolver.test.ts deleted file mode 100644 index 6f4eabab97..0000000000 --- a/packages/indy-sdk/src/dids/__tests__/IndySdkSovDidResolver.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -import type { IndySdkPool } from '../../ledger' -import type { IndyEndpointAttrib } from '../didSovUtil' -import type { GetNymResponse } from 'indy-sdk' - -import { SigningProviderRegistry, JsonTransformer } from '@aries-framework/core' -import indySdk from 'indy-sdk' - -import { parseDid } from '../../../../core/src/modules/dids/domain/parse' -import { mockFunction, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' -import { IndySdkPoolService } from '../../ledger/IndySdkPoolService' -import { IndySdkSymbol } from '../../types' -import { IndySdkWallet } from '../../wallet' -import { IndySdkSovDidResolver } from '../IndySdkSovDidResolver' - -import didSovR1xKJw17sUoXhejEpugMYJFixture from './__fixtures__/didSovR1xKJw17sUoXhejEpugMYJ.json' -import didSovWJz9mHyW9BZksioQnRsrAoFixture from './__fixtures__/didSovWJz9mHyW9BZksioQnRsrAo.json' - -jest.mock('../../ledger/IndySdkPoolService') -const IndySdkPoolServiceMock = IndySdkPoolService as jest.Mock -const indySdkPoolServiceMock = new IndySdkPoolServiceMock() - -mockFunction(indySdkPoolServiceMock.getPoolForNamespace).mockReturnValue({ - config: { indyNamespace: 'pool1' }, -} as IndySdkPool) - -mockFunction(indySdkPoolServiceMock.getPoolForDid).mockResolvedValue({ - pool: { config: { indyNamespace: 'pool1' } } as IndySdkPool, -}) - -const agentConfig = getAgentConfig('IndySdkSovDidResolver') - -const wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) - -const agentContext = getAgentContext({ - wallet, - agentConfig, - registerInstances: [ - [IndySdkPoolService, indySdkPoolServiceMock], - [IndySdkSymbol, indySdk], - ], -}) - -const indySdkSovDidResolver = new IndySdkSovDidResolver() - -describe('IndySdkSovDidResolver', () => { - it('should correctly resolve a did:sov document', async () => { - const did = 'did:sov:R1xKJw17sUoXhejEpugMYJ' - - const nymResponse: GetNymResponse = { - did: 'R1xKJw17sUoXhejEpugMYJ', - verkey: 'E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu', - role: 'ENDORSER', - } - - const endpoints: IndyEndpointAttrib = { - endpoint: 'https://ssi.com', - profile: 'https://profile.com', - hub: 'https://hub.com', - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getPublicDid').mockResolvedValue(nymResponse) - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getEndpointsForDid').mockResolvedValue(endpoints) - - const result = await indySdkSovDidResolver.resolve(agentContext, did, parseDid(did)) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocument: didSovR1xKJw17sUoXhejEpugMYJFixture, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, - }) - }) - - it('should resolve a did:sov document with routingKeys and types entries in the attrib', async () => { - const did = 'did:sov:WJz9mHyW9BZksioQnRsrAo' - - const nymResponse: GetNymResponse = { - did: 'WJz9mHyW9BZksioQnRsrAo', - verkey: 'GyYtYWU1vjwd5PFJM4VSX5aUiSV3TyZMuLBJBTQvfdF8', - role: 'ENDORSER', - } - - const endpoints: IndyEndpointAttrib = { - endpoint: 'https://agent.com', - types: ['endpoint', 'did-communication', 'DIDComm'], - routingKeys: ['routingKey1', 'routingKey2'], - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getPublicDid').mockResolvedValue(nymResponse) - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getEndpointsForDid').mockResolvedValue(endpoints) - - const result = await indySdkSovDidResolver.resolve(agentContext, did, parseDid(did)) - - expect(JsonTransformer.toJSON(result)).toMatchObject({ - didDocument: didSovWJz9mHyW9BZksioQnRsrAoFixture, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, - }) - }) - - it('should return did resolution metadata with error if the indy ledger service throws an error', async () => { - const did = 'did:sov:R1xKJw17sUoXhejEpugMYJ' - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(indySdkSovDidResolver, 'getPublicDid').mockRejectedValue(new Error('Error retrieving did')) - - const result = await indySdkSovDidResolver.resolve(agentContext, did, parseDid(did)) - - expect(result).toMatchObject({ - didDocument: null, - didDocumentMetadata: {}, - didResolutionMetadata: { - error: 'notFound', - message: `resolver_error: Unable to resolve did 'did:sov:R1xKJw17sUoXhejEpugMYJ': Error: Error retrieving did`, - }, - }) - }) -}) diff --git a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1R1xKJw17sUoXhejEpugMYJ.json b/packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1R1xKJw17sUoXhejEpugMYJ.json deleted file mode 100644 index c0bd51aa30..0000000000 --- a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1R1xKJw17sUoXhejEpugMYJ.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "@context": [ - "https://w3id.org/did/v1", - "https://w3id.org/security/suites/ed25519-2018/v1", - "https://w3id.org/security/suites/x25519-2019/v1" - ], - "id": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ", - "verificationMethod": [ - { - "type": "Ed25519VerificationKey2018", - "controller": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ", - "id": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey", - "publicKeyBase58": "E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu" - }, - { - "type": "X25519KeyAgreementKey2019", - "controller": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ", - "id": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#key-agreement-1", - "publicKeyBase58": "Fbv17ZbnUSbafsiUBJbdGeC62M8v8GEscVMMcE59mRPt" - } - ], - "authentication": ["did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#verkey"], - "keyAgreement": ["did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#key-agreement-1"], - "service": [ - { - "id": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#endpoint", - "type": "endpoint", - "serviceEndpoint": "https://ssi.com" - }, - { - "accept": ["didcomm/aip2;env=rfc19"], - "id": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#did-communication", - "priority": 0, - "recipientKeys": ["did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#key-agreement-1"], - "routingKeys": [], - "serviceEndpoint": "https://ssi.com", - "type": "did-communication" - }, - { - "id": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#profile", - "serviceEndpoint": "https://profile.com", - "type": "profile" - }, - { - "id": "did:indy:pool1:R1xKJw17sUoXhejEpugMYJ#hub", - "serviceEndpoint": "https://hub.com", - "type": "hub" - } - ] -} diff --git a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1WJz9mHyW9BZksioQnRsrAo.json b/packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1WJz9mHyW9BZksioQnRsrAo.json deleted file mode 100644 index a943f3bf9e..0000000000 --- a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didIndyPool1WJz9mHyW9BZksioQnRsrAo.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "@context": [ - "https://w3id.org/did/v1", - "https://w3id.org/security/suites/ed25519-2018/v1", - "https://w3id.org/security/suites/x25519-2019/v1", - "https://didcomm.org/messaging/contexts/v2" - ], - "id": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo", - "verificationMethod": [ - { - "type": "Ed25519VerificationKey2018", - "controller": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo", - "id": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#verkey", - "publicKeyBase58": "GyYtYWU1vjwd5PFJM4VSX5aUiSV3TyZMuLBJBTQvfdF8" - }, - { - "type": "X25519KeyAgreementKey2019", - "controller": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo", - "id": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#key-agreement-1", - "publicKeyBase58": "S3AQEEKkGYrrszT9D55ozVVX2XixYp8uynqVm4okbud" - } - ], - "authentication": ["did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#verkey"], - "keyAgreement": ["did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#key-agreement-1"], - "service": [ - { - "id": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#endpoint", - "type": "endpoint", - "serviceEndpoint": "https://agent.com" - }, - { - "id": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#did-communication", - "type": "did-communication", - "priority": 0, - "recipientKeys": ["did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#key-agreement-1"], - "routingKeys": ["routingKey1", "routingKey2"], - "accept": ["didcomm/aip2;env=rfc19"], - "serviceEndpoint": "https://agent.com" - }, - { - "id": "did:indy:pool1:WJz9mHyW9BZksioQnRsrAo#didcomm-1", - "type": "DIDComm", - "serviceEndpoint": "https://agent.com", - "accept": ["didcomm/v2"], - "routingKeys": ["routingKey1", "routingKey2"] - } - ] -} diff --git a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovR1xKJw17sUoXhejEpugMYJ.json b/packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovR1xKJw17sUoXhejEpugMYJ.json deleted file mode 100644 index 6a6e4ed706..0000000000 --- a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovR1xKJw17sUoXhejEpugMYJ.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "@context": [ - "https://w3id.org/did/v1", - "https://w3id.org/security/suites/ed25519-2018/v1", - "https://w3id.org/security/suites/x25519-2019/v1" - ], - "id": "did:sov:R1xKJw17sUoXhejEpugMYJ", - "verificationMethod": [ - { - "type": "Ed25519VerificationKey2018", - "controller": "did:sov:R1xKJw17sUoXhejEpugMYJ", - "id": "did:sov:R1xKJw17sUoXhejEpugMYJ#key-1", - "publicKeyBase58": "E6D1m3eERqCueX4ZgMCY14B4NceAr6XP2HyVqt55gDhu" - }, - { - "type": "X25519KeyAgreementKey2019", - "controller": "did:sov:R1xKJw17sUoXhejEpugMYJ", - "id": "did:sov:R1xKJw17sUoXhejEpugMYJ#key-agreement-1", - "publicKeyBase58": "Fbv17ZbnUSbafsiUBJbdGeC62M8v8GEscVMMcE59mRPt" - } - ], - "authentication": ["did:sov:R1xKJw17sUoXhejEpugMYJ#key-1"], - "assertionMethod": ["did:sov:R1xKJw17sUoXhejEpugMYJ#key-1"], - "keyAgreement": ["did:sov:R1xKJw17sUoXhejEpugMYJ#key-agreement-1"], - "service": [ - { - "id": "did:sov:R1xKJw17sUoXhejEpugMYJ#endpoint", - "type": "endpoint", - "serviceEndpoint": "https://ssi.com" - }, - { - "accept": ["didcomm/aip2;env=rfc19"], - "id": "did:sov:R1xKJw17sUoXhejEpugMYJ#did-communication", - "priority": 0, - "recipientKeys": ["did:sov:R1xKJw17sUoXhejEpugMYJ#key-agreement-1"], - "routingKeys": [], - "serviceEndpoint": "https://ssi.com", - "type": "did-communication" - }, - { - "id": "did:sov:R1xKJw17sUoXhejEpugMYJ#profile", - "serviceEndpoint": "https://profile.com", - "type": "profile" - }, - { - "id": "did:sov:R1xKJw17sUoXhejEpugMYJ#hub", - "serviceEndpoint": "https://hub.com", - "type": "hub" - } - ] -} diff --git a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovWJz9mHyW9BZksioQnRsrAo.json b/packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovWJz9mHyW9BZksioQnRsrAo.json deleted file mode 100644 index 7b74e0587f..0000000000 --- a/packages/indy-sdk/src/dids/__tests__/__fixtures__/didSovWJz9mHyW9BZksioQnRsrAo.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "@context": [ - "https://w3id.org/did/v1", - "https://w3id.org/security/suites/ed25519-2018/v1", - "https://w3id.org/security/suites/x25519-2019/v1", - "https://didcomm.org/messaging/contexts/v2" - ], - "id": "did:sov:WJz9mHyW9BZksioQnRsrAo", - "verificationMethod": [ - { - "type": "Ed25519VerificationKey2018", - "controller": "did:sov:WJz9mHyW9BZksioQnRsrAo", - "id": "did:sov:WJz9mHyW9BZksioQnRsrAo#key-1", - "publicKeyBase58": "GyYtYWU1vjwd5PFJM4VSX5aUiSV3TyZMuLBJBTQvfdF8" - }, - { - "type": "X25519KeyAgreementKey2019", - "controller": "did:sov:WJz9mHyW9BZksioQnRsrAo", - "id": "did:sov:WJz9mHyW9BZksioQnRsrAo#key-agreement-1", - "publicKeyBase58": "S3AQEEKkGYrrszT9D55ozVVX2XixYp8uynqVm4okbud" - } - ], - "authentication": ["did:sov:WJz9mHyW9BZksioQnRsrAo#key-1"], - "assertionMethod": ["did:sov:WJz9mHyW9BZksioQnRsrAo#key-1"], - "keyAgreement": ["did:sov:WJz9mHyW9BZksioQnRsrAo#key-agreement-1"], - "service": [ - { - "id": "did:sov:WJz9mHyW9BZksioQnRsrAo#endpoint", - "type": "endpoint", - "serviceEndpoint": "https://agent.com" - }, - { - "id": "did:sov:WJz9mHyW9BZksioQnRsrAo#did-communication", - "type": "did-communication", - "priority": 0, - "recipientKeys": ["did:sov:WJz9mHyW9BZksioQnRsrAo#key-agreement-1"], - "routingKeys": ["routingKey1", "routingKey2"], - "accept": ["didcomm/aip2;env=rfc19"], - "serviceEndpoint": "https://agent.com" - }, - { - "id": "did:sov:WJz9mHyW9BZksioQnRsrAo#didcomm-1", - "type": "DIDComm", - "serviceEndpoint": "https://agent.com", - "accept": ["didcomm/v2"], - "routingKeys": ["routingKey1", "routingKey2"] - } - ] -} diff --git a/packages/indy-sdk/src/dids/didIndyUtil.ts b/packages/indy-sdk/src/dids/didIndyUtil.ts deleted file mode 100644 index 7da10664b2..0000000000 --- a/packages/indy-sdk/src/dids/didIndyUtil.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { AgentContext } from '@aries-framework/core' - -import { - getKeyFromVerificationMethod, - AriesFrameworkError, - convertPublicKeyToX25519, - DidDocumentBuilder, - DidsApi, - TypedArrayEncoder, -} from '@aries-framework/core' - -// Create a base DIDDoc template according to https://hyperledger.github.io/indy-did-method/#base-diddoc-template -export function indyDidDocumentFromDid(did: string, publicKeyBase58: string) { - const verificationMethodId = `${did}#verkey` - - const builder = new DidDocumentBuilder(did) - .addContext('https://w3id.org/security/suites/ed25519-2018/v1') - .addVerificationMethod({ - controller: did, - id: verificationMethodId, - publicKeyBase58, - type: 'Ed25519VerificationKey2018', - }) - .addAuthentication(verificationMethodId) - - return builder -} - -export function createKeyAgreementKey(verkey: string) { - return TypedArrayEncoder.toBase58(convertPublicKeyToX25519(TypedArrayEncoder.fromBase58(verkey))) -} - -/** - * Fetches the verification key for a given did:indy did and returns the key as a {@link Key} object. - * - * @throws {@link AriesFrameworkError} if the did could not be resolved or the key could not be extracted - */ -export async function verificationKeyForIndyDid(agentContext: AgentContext, did: string) { - // FIXME: we should store the didDocument in the DidRecord so we don't have to fetch our own did - // from the ledger to know which key is associated with the did - const didsApi = agentContext.dependencyManager.resolve(DidsApi) - const didResult = await didsApi.resolve(did) - - if (!didResult.didDocument) { - throw new AriesFrameworkError( - `Could not resolve did ${did}. ${didResult.didResolutionMetadata.error} ${didResult.didResolutionMetadata.message}` - ) - } - - // did:indy dids MUST have a verificationMethod with #verkey - const verificationMethod = didResult.didDocument.dereferenceKey(`${did}#verkey`) - const key = getKeyFromVerificationMethod(verificationMethod) - - return key -} diff --git a/packages/indy-sdk/src/dids/didSovUtil.ts b/packages/indy-sdk/src/dids/didSovUtil.ts deleted file mode 100644 index 989e09f432..0000000000 --- a/packages/indy-sdk/src/dids/didSovUtil.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { - TypedArrayEncoder, - DidDocumentService, - DidDocumentBuilder, - DidCommV1Service, - DidCommV2Service, - convertPublicKeyToX25519, -} from '@aries-framework/core' - -import { getFullVerkey } from '../utils/did' - -export type DidCommServicesEndpointType = 'endpoint' | 'did-communication' | 'DIDComm' - -export interface IndyEndpointAttrib { - endpoint?: string - types?: Array<'endpoint' | 'did-communication' | 'DIDComm'> - routingKeys?: string[] - [key: string]: unknown -} - -/** - * Get a base did:sov did document based on the provided did and verkey - * https://sovrin-foundation.github.io/sovrin/spec/did-method-spec-template.html#crud-operation-definitions - */ -export function sovDidDocumentFromDid(fullDid: string, verkey: string) { - const verificationMethodId = `${fullDid}#key-1` - const keyAgreementId = `${fullDid}#key-agreement-1` - - const publicKeyBase58 = getFullVerkey(fullDid, verkey) - const publicKeyX25519 = TypedArrayEncoder.toBase58( - convertPublicKeyToX25519(TypedArrayEncoder.fromBase58(publicKeyBase58)) - ) - - const builder = new DidDocumentBuilder(fullDid) - .addContext('https://w3id.org/security/suites/ed25519-2018/v1') - .addContext('https://w3id.org/security/suites/x25519-2019/v1') - .addVerificationMethod({ - controller: fullDid, - id: verificationMethodId, - publicKeyBase58: publicKeyBase58, - type: 'Ed25519VerificationKey2018', - }) - .addVerificationMethod({ - controller: fullDid, - id: keyAgreementId, - publicKeyBase58: publicKeyX25519, - type: 'X25519KeyAgreementKey2019', - }) - .addAuthentication(verificationMethodId) - .addAssertionMethod(verificationMethodId) - .addKeyAgreement(keyAgreementId) - - return builder -} - -// Process Indy Attrib Endpoint Types according to: https://sovrin-foundation.github.io/sovrin/spec/did-method-spec-template.html > Read (Resolve) > DID Service Endpoint -function processEndpointTypes(types?: string[]) { - const expectedTypes = ['endpoint', 'did-communication', 'DIDComm'] - const defaultTypes = ['endpoint', 'did-communication'] - - // Return default types if types "is NOT present [or] empty" - if (!types || types.length <= 0) { - return defaultTypes - } - - // Return default types if types "contain any other values" - for (const type of types) { - if (!expectedTypes.includes(type)) { - return defaultTypes - } - } - - // Return provided types - return types -} - -export function addServicesFromEndpointsAttrib( - builder: DidDocumentBuilder, - did: string, - endpoints: IndyEndpointAttrib, - keyAgreementId: string -) { - const { endpoint, routingKeys, types, ...otherEndpoints } = endpoints - - if (endpoint) { - const processedTypes = processEndpointTypes(types) - - // If 'endpoint' included in types, add id to the services array - if (processedTypes.includes('endpoint')) { - builder.addService( - new DidDocumentService({ - id: `${did}#endpoint`, - serviceEndpoint: endpoint, - type: 'endpoint', - }) - ) - } - - // If 'did-communication' included in types, add DIDComm v1 entry - if (processedTypes.includes('did-communication')) { - builder.addService( - new DidCommV1Service({ - id: `${did}#did-communication`, - serviceEndpoint: endpoint, - priority: 0, - routingKeys: routingKeys ?? [], - recipientKeys: [keyAgreementId], - accept: ['didcomm/aip2;env=rfc19'], - }) - ) - - // If 'DIDComm' included in types, add DIDComm v2 entry - if (processedTypes.includes('DIDComm')) { - builder - .addService( - new DidCommV2Service({ - id: `${did}#didcomm-1`, - serviceEndpoint: endpoint, - routingKeys: routingKeys ?? [], - accept: ['didcomm/v2'], - }) - ) - .addContext('https://didcomm.org/messaging/contexts/v2') - } - } - } - - // Add other endpoint types - for (const [type, endpoint] of Object.entries(otherEndpoints)) { - builder.addService( - new DidDocumentService({ - id: `${did}#${type}`, - serviceEndpoint: endpoint as string, - type, - }) - ) - } -} diff --git a/packages/indy-sdk/src/dids/index.ts b/packages/indy-sdk/src/dids/index.ts deleted file mode 100644 index 8017bf8749..0000000000 --- a/packages/indy-sdk/src/dids/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { IndySdkIndyDidRegistrar, IndySdkIndyDidCreateOptions } from './IndySdkIndyDidRegistrar' -export { IndySdkSovDidResolver } from './IndySdkSovDidResolver' -export { IndySdkIndyDidResolver } from './IndySdkIndyDidResolver' diff --git a/packages/indy-sdk/src/error/IndySdkError.ts b/packages/indy-sdk/src/error/IndySdkError.ts deleted file mode 100644 index 4b67802a9a..0000000000 --- a/packages/indy-sdk/src/error/IndySdkError.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { IndyError } from './indyError' - -import { AriesFrameworkError } from '@aries-framework/core' - -export class IndySdkError extends AriesFrameworkError { - public constructor(indyError: IndyError, message?: string) { - const base = `${indyError.name}(${indyError.indyName}): ${indyError.message}` - - super(message ? `${message}: ${base}` : base, { cause: indyError }) - } -} diff --git a/packages/indy-sdk/src/error/index.ts b/packages/indy-sdk/src/error/index.ts deleted file mode 100644 index 5829a46d0a..0000000000 --- a/packages/indy-sdk/src/error/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './IndySdkError' -export * from './indyError' diff --git a/packages/indy-sdk/src/error/indyError.ts b/packages/indy-sdk/src/error/indyError.ts deleted file mode 100644 index c5d23f6093..0000000000 --- a/packages/indy-sdk/src/error/indyError.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { AriesFrameworkError } from '@aries-framework/core' - -export const indyErrors = { - 100: 'CommonInvalidParam1', - 101: 'CommonInvalidParam2', - 102: 'CommonInvalidParam3', - 103: 'CommonInvalidParam4', - 104: 'CommonInvalidParam5', - 105: 'CommonInvalidParam6', - 106: 'CommonInvalidParam7', - 107: 'CommonInvalidParam8', - 108: 'CommonInvalidParam9', - 109: 'CommonInvalidParam10', - 110: 'CommonInvalidParam11', - 111: 'CommonInvalidParam12', - 112: 'CommonInvalidState', - 113: 'CommonInvalidStructure', - 114: 'CommonIOError', - 115: 'CommonInvalidParam13', - 116: 'CommonInvalidParam14', - 200: 'WalletInvalidHandle', - 201: 'WalletUnknownTypeError', - 202: 'WalletTypeAlreadyRegisteredError', - 203: 'WalletAlreadyExistsError', - 204: 'WalletNotFoundError', - 205: 'WalletIncompatiblePoolError', - 206: 'WalletAlreadyOpenedError', - 207: 'WalletAccessFailed', - 208: 'WalletInputError', - 209: 'WalletDecodingError', - 210: 'WalletStorageError', - 211: 'WalletEncryptionError', - 212: 'WalletItemNotFound', - 213: 'WalletItemAlreadyExists', - 214: 'WalletQueryError', - 300: 'PoolLedgerNotCreatedError', - 301: 'PoolLedgerInvalidPoolHandle', - 302: 'PoolLedgerTerminated', - 303: 'LedgerNoConsensusError', - 304: 'LedgerInvalidTransaction', - 305: 'LedgerSecurityError', - 306: 'PoolLedgerConfigAlreadyExistsError', - 307: 'PoolLedgerTimeout', - 308: 'PoolIncompatibleProtocolVersion', - 309: 'LedgerNotFound', - 400: 'AnoncredsRevocationRegistryFullError', - 401: 'AnoncredsInvalidUserRevocId', - 404: 'AnoncredsMasterSecretDuplicateNameError', - 405: 'AnoncredsProofRejected', - 406: 'AnoncredsCredentialRevoked', - 407: 'AnoncredsCredDefAlreadyExistsError', - 500: 'UnknownCryptoTypeError', - 600: 'DidAlreadyExistsError', - 700: 'PaymentUnknownMethodError', - 701: 'PaymentIncompatibleMethodsError', - 702: 'PaymentInsufficientFundsError', - 703: 'PaymentSourceDoesNotExistError', - 704: 'PaymentOperationNotSupportedError', - 705: 'PaymentExtraFundsError', - 706: 'TransactionNotAllowedError', -} as const - -type IndyErrorValues = (typeof indyErrors)[keyof typeof indyErrors] - -export interface IndyError { - name: 'IndyError' - message: string - indyName?: string -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function isIndyError(error: any, errorName?: IndyErrorValues): error is IndyError { - if (typeof error !== 'object' || error === null) return false - - const indyError = error.name === 'IndyError' - - // if no specific indy error name is passed - // or the error is no indy error - // we can already return - if (!indyError || !errorName) return indyError - - // NodeJS Wrapper is missing some type names. When a type is missing it will - // only have the error code as string in the message field - // Until that is fixed we take that into account to make AFJ work with rn-indy-sdk - // See: https://github.com/AbsaOSS/rn-indy-sdk/pull/24 - // See: https://github.com/hyperledger/indy-sdk/pull/2283 - if (!error.indyName) { - const errorCode = Number(error.message) - if (!isNaN(errorCode) && Object.prototype.hasOwnProperty.call(indyErrors, errorCode)) { - // We already check if the property is set. We can safely ignore this typescript error - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return errorName === indyErrors[errorCode] - } - - throw new AriesFrameworkError(`Could not determine errorName of indyError ${error.message}`) - } - - return error.indyName === errorName -} diff --git a/packages/indy-sdk/src/index.ts b/packages/indy-sdk/src/index.ts deleted file mode 100644 index 5857f00da2..0000000000 --- a/packages/indy-sdk/src/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Dids -export * from './dids' - -// Ledger -export { IndySdkPoolConfig } from './ledger' - -// Wallet -export { IndySdkWallet } from './wallet' - -// Storage -export { IndySdkStorageService } from './storage' - -// AnonCreds -export { - IndySdkAnonCredsRegistry, - IndySdkHolderService, - IndySdkIssuerService, - IndySdkVerifierService, -} from './anoncreds' - -// Module -export { IndySdkModule } from './IndySdkModule' -export { IndySdkModuleConfig } from './IndySdkModuleConfig' diff --git a/packages/indy-sdk/src/ledger/IndySdkPool.ts b/packages/indy-sdk/src/ledger/IndySdkPool.ts deleted file mode 100644 index b784600416..0000000000 --- a/packages/indy-sdk/src/ledger/IndySdkPool.ts +++ /dev/null @@ -1,218 +0,0 @@ -import type { IndySdk } from '../types' -import type { FileSystem, Logger } from '@aries-framework/core' -import type { LedgerReadReplyResponse, LedgerRequest, LedgerWriteReplyResponse } from 'indy-sdk' -import type { Subject } from 'rxjs' - -import { AriesFrameworkError } from '@aries-framework/core' - -import { isIndyError, IndySdkError } from '../error' - -import { IndySdkPoolError } from './error' -import { isLedgerRejectResponse, isLedgerReqnackResponse } from './util' - -export interface TransactionAuthorAgreement { - version: `${number}.${number}` | `${number}` - acceptanceMechanism: string -} - -export interface IndySdkPoolConfig { - /** - * Optional id that influences the pool config that is created by the indy-sdk. - * Uses the indyNamespace as the pool identifier if not provided. - */ - id?: string - - genesisPath?: string - genesisTransactions?: string - - isProduction: boolean - indyNamespace: string - transactionAuthorAgreement?: TransactionAuthorAgreement - connectOnStartup?: boolean -} - -export class IndySdkPool { - private indySdk: IndySdk - private logger: Logger - private fileSystem: FileSystem - private poolConfig: IndySdkPoolConfig - private _poolHandle?: number - private poolConnected?: Promise - public authorAgreement?: AuthorAgreement | null - - public constructor( - poolConfig: IndySdkPoolConfig, - indySdk: IndySdk, - logger: Logger, - stop$: Subject, - fileSystem: FileSystem - ) { - this.indySdk = indySdk - this.fileSystem = fileSystem - this.poolConfig = poolConfig - this.logger = logger - - // Listen to stop$ (shutdown) and close pool - stop$.subscribe(async () => { - if (this._poolHandle) { - await this.close() - } - }) - } - - public get didIndyNamespace(): string { - return this.config.indyNamespace - } - - public get id() { - return this.poolConfig.id - } - - public get config() { - return this.poolConfig - } - - public async close() { - const poolHandle = this._poolHandle - - if (!poolHandle) { - return - } - - this._poolHandle = undefined - this.poolConnected = undefined - - await this.indySdk.closePoolLedger(poolHandle) - } - - public async delete() { - // Close the pool if currently open - if (this._poolHandle) { - await this.close() - } - - await this.indySdk.deletePoolLedgerConfig(this.poolConfig.indyNamespace) - } - - public async connect() { - if (!this.poolConnected) { - // Save the promise of connectToLedger to determine if we are done connecting - this.poolConnected = this.connectToLedger() - this.poolConnected.catch((error) => { - // Set poolConnected to undefined so we can retry connection upon failure - this.poolConnected = undefined - this.logger.error('Connection to pool: ' + this.poolConfig.genesisPath + ' failed.', { error }) - }) - return this.poolConnected - } else { - throw new AriesFrameworkError('Cannot attempt connection to ledger, already connecting.') - } - } - - private async connectToLedger() { - const poolName = this.poolConfig.id ?? this.poolConfig.indyNamespace - const genesisPath = await this.getGenesisPath() - - if (!genesisPath) { - throw new AriesFrameworkError('Cannot connect to ledger without genesis file') - } - - this.logger.debug(`Connecting to ledger pool '${poolName}'`, { genesisPath }) - await this.indySdk.setProtocolVersion(2) - - try { - this._poolHandle = await this.indySdk.openPoolLedger(poolName) - return - } catch (error) { - if (!isIndyError(error, 'PoolLedgerNotCreatedError')) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - this.logger.debug(`Pool '${poolName}' does not exist yet, creating.`, { - indyError: 'PoolLedgerNotCreatedError', - }) - try { - await this.indySdk.createPoolLedgerConfig(poolName, { genesis_txn: genesisPath }) - this._poolHandle = await this.indySdk.openPoolLedger(poolName) - return - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - private async submitRequest(request: LedgerRequest) { - return this.indySdk.submitRequest(await this.getPoolHandle(), request) - } - - public async submitReadRequest(request: LedgerRequest) { - const response = await this.submitRequest(request) - - if (isLedgerRejectResponse(response) || isLedgerReqnackResponse(response)) { - throw new IndySdkPoolError( - `Ledger '${this.didIndyNamespace}' rejected read transaction request: ${response.reason}` - ) - } - - return response as LedgerReadReplyResponse - } - - public async submitWriteRequest(request: LedgerRequest) { - const response = await this.submitRequest(request) - - if (isLedgerRejectResponse(response) || isLedgerReqnackResponse(response)) { - throw new IndySdkPoolError( - `Ledger '${this.didIndyNamespace}' rejected write transaction request: ${response.reason}` - ) - } - - return response as LedgerWriteReplyResponse - } - - private async getPoolHandle() { - if (this.poolConnected) { - // If we have tried to already connect to pool wait for it - try { - await this.poolConnected - } catch (error) { - this.logger.error('Connection to pool: ' + this.poolConfig.genesisPath + ' failed.', { error }) - } - } - - if (!this._poolHandle) await this.connect() - if (!this._poolHandle) throw new IndySdkPoolError('Pool handle not set after connection') - - return this._poolHandle - } - - private async getGenesisPath() { - // If the path is already provided return it - if (this.poolConfig.genesisPath) return this.poolConfig.genesisPath - - // Determine the genesisPath - const genesisPath = this.fileSystem.tempPath + `/genesis-${this.poolConfig.id ?? this.poolConfig.indyNamespace}.txn` - // Store genesis data if provided - if (this.poolConfig.genesisTransactions) { - await this.fileSystem.write(genesisPath, this.poolConfig.genesisTransactions) - this.poolConfig.genesisPath = genesisPath - return genesisPath - } - - // No genesisPath - return null - } -} - -export interface AuthorAgreement { - digest: string - version: string - text: string - ratification_ts: number - acceptanceMechanisms: AcceptanceMechanisms -} - -export interface AcceptanceMechanisms { - aml: Record - amlContext: string - version: string -} diff --git a/packages/indy-sdk/src/ledger/IndySdkPoolService.ts b/packages/indy-sdk/src/ledger/IndySdkPoolService.ts deleted file mode 100644 index bf632152bb..0000000000 --- a/packages/indy-sdk/src/ledger/IndySdkPoolService.ts +++ /dev/null @@ -1,357 +0,0 @@ -import type { AcceptanceMechanisms, AuthorAgreement } from './IndySdkPool' -import type { IndySdk } from '../types' -import type { AgentContext, Key } from '@aries-framework/core' -import type { GetNymResponse, LedgerReadReplyResponse, LedgerRequest, LedgerWriteReplyResponse } from 'indy-sdk' - -import { didIndyRegex } from '@aries-framework/anoncreds' -import { - TypedArrayEncoder, - CacheModuleConfig, - InjectionSymbols, - Logger, - injectable, - inject, - FileSystem, -} from '@aries-framework/core' -import { Subject } from 'rxjs' - -import { IndySdkModuleConfig } from '../IndySdkModuleConfig' -import { IndySdkError, isIndyError } from '../error' -import { assertIndySdkWallet } from '../utils/assertIndySdkWallet' -import { isLegacySelfCertifiedDid } from '../utils/did' -import { allSettled, onlyFulfilled, onlyRejected } from '../utils/promises' - -import { IndySdkPool } from './IndySdkPool' -import { IndySdkPoolError, IndySdkPoolNotConfiguredError, IndySdkPoolNotFoundError } from './error' -import { serializeRequestForSignature } from './serializeRequestForSignature' - -export interface CachedDidResponse { - nymResponse: GetNymResponse - indyNamespace: string -} - -@injectable() -export class IndySdkPoolService { - public pools: IndySdkPool[] = [] - private logger: Logger - private indySdk: IndySdk - private stop$: Subject - private fileSystem: FileSystem - private indySdkModuleConfig: IndySdkModuleConfig - - public constructor( - @inject(InjectionSymbols.Logger) logger: Logger, - @inject(InjectionSymbols.Stop$) stop$: Subject, - @inject(InjectionSymbols.FileSystem) fileSystem: FileSystem, - indySdkModuleConfig: IndySdkModuleConfig - ) { - this.logger = logger - this.indySdk = indySdkModuleConfig.indySdk - this.fileSystem = fileSystem - this.stop$ = stop$ - this.indySdkModuleConfig = indySdkModuleConfig - - this.pools = this.indySdkModuleConfig.networks.map( - (network) => new IndySdkPool(network, this.indySdk, this.logger, this.stop$, this.fileSystem) - ) - } - - /** - * 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 - * - * This method will optionally return a nym response when the did has been resolved to determine the ledger - * either now or in the past. The nymResponse can be used to prevent multiple ledger queries fetching the same - * did - */ - public async getPoolForDid( - agentContext: AgentContext, - did: string - ): Promise<{ pool: IndySdkPool; nymResponse?: GetNymResponse }> { - // Check if the did starts with did:indy - const match = did.match(didIndyRegex) - - if (match) { - const [, namespace] = match - - const pool = this.getPoolForNamespace(namespace) - - if (pool) return { pool } - - throw new IndySdkPoolError(`Pool for indy namespace '${namespace}' not found`) - } else { - return await this.getPoolForLegacyDid(agentContext, did) - } - } - - private async getPoolForLegacyDid( - agentContext: AgentContext, - did: string - ): Promise<{ pool: IndySdkPool; nymResponse: GetNymResponse }> { - const pools = this.pools - - if (pools.length === 0) { - throw new IndySdkPoolNotConfiguredError( - 'No indy ledgers configured. Provide at least one pool configuration in IndySdkModuleConfigOptions.networks' - ) - } - - const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache - const cacheKey = `IndySdkPoolService:${did}` - - const cachedNymResponse = await cache.get(agentContext, cacheKey) - const pool = this.pools.find((pool) => pool.didIndyNamespace === 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 '${pool.didIndyNamespace}' for did '${did}' in cache`) - return { nymResponse: cachedNymResponse.nymResponse, pool } - } - - const { successful, rejected } = await this.getSettledDidResponsesFromPools(did, pools) - - if (successful.length === 0) { - const allNotFound = rejected.every((e) => e.reason instanceof IndySdkPoolNotFoundError) - const rejectedOtherThanNotFound = rejected.filter((e) => !(e.reason instanceof IndySdkPoolNotFoundError)) - - // All ledgers returned response that the did was not found - if (allNotFound) { - throw new IndySdkPoolNotFoundError(`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 IndySdkPoolError( - `Unknown error retrieving did '${did}' from '${rejectedOtherThanNotFound.length}' of '${pools.length}' ledgers. ${rejectedOtherThanNotFound[0].reason}`, - { 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 - // IndySdkModuleConfigOptions.networks config as the order of preference of ledgers - let value = successful.find((response) => - isLegacySelfCertifiedDid(response.value.did.did, response.value.did.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 IndySdkModuleConfigOptions.networks - // config as the order of preference of ledgers - value = productionOrNonProduction[0].value - } - - await cache.set(agentContext, cacheKey, { - nymResponse: value.did, - indyNamespace: value.pool.didIndyNamespace, - } satisfies CachedDidResponse) - - return { pool: value.pool, nymResponse: value.did } - } - - private async getSettledDidResponsesFromPools(did: string, pools: IndySdkPool[]) { - 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 IndySdkPoolNotConfiguredError( - 'No indy ledgers configured. Provide at least one pool configuration in IndySdkModuleConfigOptions.networks' - ) - } - - 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.didIndyNamespace === indyNamespace) - - if (!pool) { - throw new IndySdkPoolNotFoundError(`No ledgers found for indy namespace '${indyNamespace}'.`) - } - - return pool - } - - public async submitWriteRequest( - agentContext: AgentContext, - pool: IndySdkPool, - request: LedgerRequest, - signingKey: Key - ): Promise { - try { - const requestWithTaa = await this.appendTaa(pool, request) - const signedRequestWithTaa = await this.signRequest(agentContext, signingKey, requestWithTaa) - - const response = await pool.submitWriteRequest(signedRequestWithTaa) - - return response - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async submitReadRequest(pool: IndySdkPool, request: LedgerRequest): Promise { - try { - const response = await pool.submitReadRequest(request) - - return response - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - private async signRequest(agentContext: AgentContext, key: Key, request: LedgerRequest): Promise { - assertIndySdkWallet(agentContext.wallet) - - try { - const signedPayload = await this.indySdk.cryptoSign( - agentContext.wallet.handle, - key.publicKeyBase58, - TypedArrayEncoder.fromString(serializeRequestForSignature(request)) - ) - - const signedRequest = { ...request, signature: TypedArrayEncoder.toBase58(signedPayload) } - return signedRequest - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - private async appendTaa(pool: IndySdkPool, request: LedgerRequest) { - try { - const authorAgreement = await this.getTransactionAuthorAgreement(pool) - const taa = pool.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 (!taa) { - throw new IndySdkPoolError( - `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 !== taa.version || - !(taa.acceptanceMechanism in authorAgreement.acceptanceMechanisms.aml) - ) { - // Throw an error with a helpful message - const errMessage = `Unable to satisfy matching TAA with mechanism ${JSON.stringify( - taa.acceptanceMechanism - )} and version ${JSON.stringify(taa.version)} in pool.\n Found ${JSON.stringify( - Object.keys(authorAgreement.acceptanceMechanisms.aml) - )} and version ${authorAgreement.version} in pool.` - throw new IndySdkPoolError(errMessage) - } - - const requestWithTaa = await this.indySdk.appendTxnAuthorAgreementAcceptanceToRequest( - request, - authorAgreement.text, - taa.version, - authorAgreement.digest, - taa.acceptanceMechanism, - // Current time since epoch - // We can't use ratification_ts, as it must be greater than 1499906902 - Math.floor(new Date().getTime() / 1000) - ) - - return requestWithTaa - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - private async getTransactionAuthorAgreement(pool: IndySdkPool): Promise { - try { - // TODO Replace this condition with memoization - if (pool.authorAgreement !== undefined) { - return pool.authorAgreement - } - - const taaRequest = await this.indySdk.buildGetTxnAuthorAgreementRequest(null) - const taaResponse = await this.submitReadRequest(pool, taaRequest) - const acceptanceMechanismRequest = await this.indySdk.buildGetAcceptanceMechanismsRequest(null) - const acceptanceMechanismResponse = await this.submitReadRequest(pool, acceptanceMechanismRequest) - - // TAA can be null - if (taaResponse.result.data == null) { - pool.authorAgreement = null - return null - } - - // If TAA is not null, we can be sure AcceptanceMechanisms is also not null - const authorAgreement = taaResponse.result.data as AuthorAgreement - const acceptanceMechanisms = acceptanceMechanismResponse.result.data as AcceptanceMechanisms - pool.authorAgreement = { - ...authorAgreement, - acceptanceMechanisms, - } - return pool.authorAgreement - } catch (error) { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - private async getDidFromPool(did: string, pool: IndySdkPool): Promise { - try { - this.logger.trace(`Get public did '${did}' from ledger '${pool.didIndyNamespace}'`) - const request = await this.indySdk.buildGetNymRequest(null, did) - - this.logger.trace(`Submitting get did request for did '${did}' to ledger '${pool.didIndyNamespace}'`) - const response = await pool.submitReadRequest(request) - - const result = await this.indySdk.parseGetNymResponse(response) - this.logger.trace(`Retrieved did '${did}' from ledger '${pool.didIndyNamespace}'`, result) - - return { - did: result, - pool, - response, - } - } catch (error) { - this.logger.trace(`Error retrieving did '${did}' from ledger '${pool.didIndyNamespace}'`, { - error, - did, - }) - if (isIndyError(error, 'LedgerNotFound')) { - throw new IndySdkPoolNotFoundError(`Did '${did}' not found on ledger ${pool.didIndyNamespace}`) - } else { - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - } -} - -export interface PublicDidRequest { - did: GetNymResponse - pool: IndySdkPool - response: LedgerReadReplyResponse -} diff --git a/packages/indy-sdk/src/ledger/__tests__/IndySdkPoolService.test.ts b/packages/indy-sdk/src/ledger/__tests__/IndySdkPoolService.test.ts deleted file mode 100644 index 20d79e0564..0000000000 --- a/packages/indy-sdk/src/ledger/__tests__/IndySdkPoolService.test.ts +++ /dev/null @@ -1,422 +0,0 @@ -import type { IndySdkPoolConfig } from '../IndySdkPool' -import type { CachedDidResponse } from '../IndySdkPoolService' - -import { - CacheModuleConfig, - InMemoryLruCache, - SigningProviderRegistry, - AriesFrameworkError, - Key, - KeyType, -} from '@aries-framework/core' -import indySdk from 'indy-sdk' -import { Subject } from 'rxjs' - -import { getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' -import { NodeFileSystem } from '../../../../node/src/NodeFileSystem' -import { IndySdkModuleConfig } from '../../IndySdkModuleConfig' -import { IndySdkWallet } from '../../wallet/IndySdkWallet' -import { IndySdkPoolService } from '../IndySdkPoolService' -import { IndySdkPoolError, IndySdkPoolNotConfiguredError, IndySdkPoolNotFoundError } from '../error' - -import { getDidResponsesForDid } from './didResponses' - -const pools: IndySdkPoolConfig[] = [ - { - indyNamespace: 'sovrin', - isProduction: true, - genesisTransactions: 'xxx', - transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' }, - }, - { - indyNamespace: 'sovrin:builder', - isProduction: false, - genesisTransactions: 'xxx', - transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' }, - }, - { - indyNamespace: 'sovrin:staging', - isProduction: false, - genesisTransactions: 'xxx', - transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' }, - }, - { - indyNamespace: 'indicio', - isProduction: true, - genesisTransactions: 'xxx', - transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' }, - }, - { - indyNamespace: 'bcovrin:test', - isProduction: false, - genesisTransactions: 'xxx', - transactionAuthorAgreement: { version: '1', acceptanceMechanism: 'accept' }, - }, -] - -const config = getAgentConfig('IndySdkPoolServiceTest') -const cache = new InMemoryLruCache({ limit: 1 }) - -const indySdkModule = new IndySdkModuleConfig({ indySdk, networks: pools }) -const wallet = new IndySdkWallet(indySdk, config.logger, new SigningProviderRegistry([])) - -const agentContext = getAgentContext({ - wallet, - registerInstances: [[CacheModuleConfig, new CacheModuleConfig({ cache })]], -}) - -const poolService = new IndySdkPoolService(config.logger, new Subject(), new NodeFileSystem(), indySdkModule) - -describe('IndySdkPoolService', () => { - beforeAll(async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await wallet.createAndOpen(config.walletConfig!) - }) - - afterAll(async () => { - await wallet.delete() - }) - - afterEach(() => { - cache.clear() - }) - - describe('getPoolForDid', () => { - it('should throw a IndySdkPoolNotConfiguredError error if no pools are configured on the pool service', async () => { - const oldPools = poolService.pools - poolService.pools = [] - - expect(poolService.getPoolForDid(agentContext, 'some-did')).rejects.toThrow(IndySdkPoolNotConfiguredError) - - poolService.pools = oldPools - }) - - it('should throw a IndySdkPoolError if all ledger requests throw an error other than NotFoundError', async () => { - const did = 'Y5bj4SjCiTM9PgeheKAiXx' - - poolService.pools.forEach((pool) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(() => Promise.reject(new AriesFrameworkError('Something went wrong'))) - }) - - expect(poolService.getPoolForDid(agentContext, did)).rejects.toThrowError(IndySdkPoolError) - }) - - it('should throw a IndySdkPoolNotFoundError if all pools did not find the did on the ledger', async () => { - const did = 'Y5bj4SjCiTM9PgeheKAiXx' - // Not found on any of the ledgers - const responses = getDidResponsesForDid(did, pools, {}) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(responses[index]) - }) - - expect(poolService.getPoolForDid(agentContext, did)).rejects.toThrowError(IndySdkPoolNotFoundError) - }) - - it('should return the pool based on namespace if did is a valid did:indy did', async () => { - const { pool } = await poolService.getPoolForDid(agentContext, 'did:indy:sovrin:Y5bj4SjCiTM9PgeheKAiXx') - - expect(pool.didIndyNamespace).toBe('sovrin') - }) - - it('should return the pool if the did was only found on one ledger', async () => { - const did = 'TL1EaPFCZ8Si5aUrqScBDt' - // Only found on one ledger - const responses = getDidResponsesForDid(did, pools, { - sovrin: '~43X4NhAFqREffK7eWdKgFH', - }) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(responses[index]) - }) - - const { pool } = await poolService.getPoolForDid(agentContext, did) - - expect(pool.config.indyNamespace).toBe('sovrin') - }) - - it('should return the first pool with a self certifying DID if at least one did is self certifying ', async () => { - const did = 'did:sov:q7ATwTYbQDgiigVijUAej' - // Found on one production and one non production ledger - const responses = getDidResponsesForDid(did, pools, { - indicio: '~43X4NhAFqREffK7eWdKgFH', - 'bcovrin:test': '43X4NhAFqREffK7eWdKgFH43X4NhAFqREffK7eWdKgFH', - 'sovrin:builder': '~43X4NhAFqREffK7eWdKgFH', - }) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(responses[index]) - }) - - const { pool } = await poolService.getPoolForDid(agentContext, did) - - expect(pool.config.indyNamespace).toBe('sovrin:builder') - }) - - it('should return the production pool if the did was found on one production and one non production ledger and both DIDs are not self certifying', async () => { - const did = 'V6ty6ttM3EjuCtosH6sGtW' - // Found on one production and one non production ledger - const responses = getDidResponsesForDid(did, pools, { - indicio: '43X4NhAFqREffK7eWdKgFH43X4NhAFqREffK7eWdKgFH', - 'sovrin:builder': '43X4NhAFqREffK7eWdKgFH43X4NhAFqREffK7eWdKgFH', - }) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(responses[index]) - }) - - const { pool } = await poolService.getPoolForDid(agentContext, did) - - expect(pool.config.indyNamespace).toBe('indicio') - }) - - it('should return the pool with the self certified did if the did was found on two production ledgers where one did is self certified', async () => { - const did = 'VsKV7grR1BUE29mG2Fm2kX' - // Found on two production ledgers. Sovrin is self certified - const responses = getDidResponsesForDid(did, pools, { - sovrin: '~43X4NhAFqREffK7eWdKgFH', - indicio: 'kqa2HyagzfMAq42H5f9u3UMwnSBPQx2QfrSyXbUPxMn', - }) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(responses[index]) - }) - - const { pool } = await poolService.getPoolForDid(agentContext, did) - - expect(pool.config.indyNamespace).toBe('sovrin') - }) - - it('should return the first pool with a self certified did if the did was found on three non production ledgers where two DIDs are self certified', async () => { - const did = 'HEi9QViXNThGQaDsQ3ptcw' - // Found on two non production ledgers. Sovrin is self certified - const responses = getDidResponsesForDid(did, pools, { - 'sovrin:builder': '~M9kv2Ez61cur7X39DXWh8W', - 'sovrin:staging': '~M9kv2Ez61cur7X39DXWh8W', - 'bcovrin:test': '3SeuRm3uYuQDYmHeuMLu1xNHozNTtzS3kbZRFMMCWrX4', - }) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(responses[index]) - }) - - const { pool } = await poolService.getPoolForDid(agentContext, did) - - expect(pool.config.indyNamespace).toBe('sovrin:builder') - }) - - it('should return the pool from the cache if the did was found in the cache', async () => { - const did = 'HEi9QViXNThGQaDsQ3ptcw' - - const expectedPool = pools[3] - - const didResponse: CachedDidResponse = { - nymResponse: { - did, - role: 'ENDORSER', - verkey: '~M9kv2Ez61cur7X39DXWh8W', - }, - indyNamespace: expectedPool.indyNamespace, - } - - await cache.set(agentContext, `IndySdkPoolService:${did}`, didResponse) - const { pool } = await poolService.getPoolForDid(agentContext, did) - - expect(pool.config.indyNamespace).toBe(pool.didIndyNamespace) - }) - - it('should set the indyNamespace in the cache if the did was not found in the cache, but resolved later on', async () => { - const did = 'HEi9QViXNThGQaDsQ3ptcw' - // Found on one ledger - const responses = getDidResponsesForDid(did, pools, { - 'sovrin:builder': '~M9kv2Ez61cur7X39DXWh8W', - }) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'submitReadRequest') - spy.mockImplementationOnce(responses[index]) - }) - - const { pool } = await poolService.getPoolForDid(agentContext, did) - - expect(pool.config.indyNamespace).toBe('sovrin:builder') - expect(pool.config.indyNamespace).toBe('sovrin:builder') - - expect(await cache.get(agentContext, `IndySdkPoolService:${did}`)).toEqual({ - nymResponse: { - did, - verkey: '~M9kv2Ez61cur7X39DXWh8W', - role: '0', - }, - indyNamespace: 'sovrin:builder', - }) - }) - }) - - describe('getPoolForNamespace', () => { - it('should throw a IndySdkPoolNotConfiguredError error if no pools are configured on the pool service', async () => { - const oldPools = poolService.pools - poolService.pools = [] - - expect(() => poolService.getPoolForNamespace()).toThrow(IndySdkPoolNotConfiguredError) - - poolService.pools = oldPools - }) - - it('should return the first pool if indyNamespace is not provided', async () => { - const expectedPool = pools[0] - - expect(poolService.getPoolForNamespace().didIndyNamespace).toEqual(expectedPool.indyNamespace) - }) - - it('should throw a IndySdkPoolNotFoundError error if any of the pools did not have the provided indyNamespace', async () => { - const indyNameSpace = 'test' - const responses = pools.map((pool) => pool.indyNamespace) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'didIndyNamespace', 'get') - spy.mockReturnValueOnce(responses[index]) - }) - - expect(() => poolService.getPoolForNamespace(indyNameSpace)).toThrow(IndySdkPoolNotFoundError) - }) - - it('should return the first pool that indyNamespace matches', async () => { - const expectedPool = pools[3] - const indyNameSpace = 'indicio' - const responses = pools.map((pool) => pool.indyNamespace) - - poolService.pools.forEach((pool, index) => { - const spy = jest.spyOn(pool, 'didIndyNamespace', 'get') - spy.mockReturnValueOnce(responses[index]) - }) - - const pool = poolService.getPoolForNamespace(indyNameSpace) - - expect(pool.didIndyNamespace).toEqual(expectedPool.indyNamespace) - }) - }) - - describe('submitWriteRequest', () => { - it('should throw an error if the config version does not match', async () => { - const pool = poolService.getPoolForNamespace() - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(poolService, 'getTransactionAuthorAgreement').mockResolvedValue({ - digest: 'abcde', - version: '2.0', - text: 'jhsdhbv', - ratification_ts: 12345678, - acceptanceMechanisms: { - aml: { accept: 'accept' }, - amlContext: 'accept', - version: '3', - }, - } as never) - await expect( - poolService.submitWriteRequest( - agentContext, - pool, - { - reqId: 1668174449192969000, - identifier: 'BBPoJqRKatdcfLEAFL7exC', - operation: { - type: '1', - dest: 'N8NQHLtCKfPmWMgCSdfa7h', - verkey: 'GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf', - alias: 'Heinz57', - }, - protocolVersion: 2, - }, - Key.fromPublicKeyBase58('GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf', KeyType.Ed25519) - ) - ).rejects.toThrowError( - 'Unable to satisfy matching TAA with mechanism "accept" and version "1" in pool.\n Found ["accept"] and version 2.0 in pool.' - ) - }) - - it('should throw an error if the config acceptance mechanism does not match', async () => { - const pool = poolService.getPoolForNamespace() - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(poolService, 'getTransactionAuthorAgreement').mockResolvedValue({ - digest: 'abcde', - version: '1.0', - text: 'jhsdhbv', - ratification_ts: 12345678, - acceptanceMechanisms: { - aml: { decline: 'accept' }, - amlContext: 'accept', - version: '1', - }, - } as never) - await expect( - poolService.submitWriteRequest( - agentContext, - pool, - { - reqId: 1668174449192969000, - identifier: 'BBPoJqRKatdcfLEAFL7exC', - operation: { - type: '1', - dest: 'N8NQHLtCKfPmWMgCSdfa7h', - verkey: 'GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf', - alias: 'Heinz57', - }, - protocolVersion: 2, - }, - Key.fromPublicKeyBase58('GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf', KeyType.Ed25519) - ) - ).rejects.toThrowError( - 'Unable to satisfy matching TAA with mechanism "accept" and version "1" in pool.\n Found ["decline"] and version 1.0 in pool.' - ) - }) - - it('should throw an error if no config is present', async () => { - const pool = poolService.getPoolForNamespace() - pool.authorAgreement = undefined - pool.config.transactionAuthorAgreement = undefined - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - jest.spyOn(poolService, 'getTransactionAuthorAgreement').mockResolvedValue({ - digest: 'abcde', - version: '1.0', - text: 'jhsdhbv', - ratification_ts: 12345678, - acceptanceMechanisms: { - aml: { accept: 'accept' }, - amlContext: 'accept', - version: '3', - }, - } as never) - await expect( - poolService.submitWriteRequest( - agentContext, - pool, - { - reqId: 1668174449192969000, - identifier: 'BBPoJqRKatdcfLEAFL7exC', - operation: { - type: '1', - dest: 'N8NQHLtCKfPmWMgCSdfa7h', - verkey: 'GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf', - alias: 'Heinz57', - }, - protocolVersion: 2, - }, - Key.fromPublicKeyBase58('GAb4NUvpBcHVCvtP45vTVa5Bp74vFg3iXzdp1Gbd68Wf', KeyType.Ed25519) - ) - ).rejects.toThrowError(/Please, specify a transaction author agreement with version and acceptance mechanism/) - }) - }) -}) diff --git a/packages/indy-sdk/src/ledger/__tests__/didResponses.ts b/packages/indy-sdk/src/ledger/__tests__/didResponses.ts deleted file mode 100644 index 4d3dac6596..0000000000 --- a/packages/indy-sdk/src/ledger/__tests__/didResponses.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { IndySdkPoolConfig } from '../IndySdkPool' -import type * as Indy from 'indy-sdk' - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -// eslint-disable-next-line import/no-extraneous-dependencies -import IndyError from 'indy-sdk/src/IndyError' - -export function getDidResponse({ did, verkey }: { did: string; verkey: string }) { - const response: Indy.LedgerReadReplyResponse = { - op: 'REPLY', - result: { - txnTime: 1632680963, - reqId: 1632681194706196000, - state_proof: { - multi_signature: { - participants: ['Node3', 'Node4', 'Node2'], - value: { - state_root_hash: 'AqMNuzJHeHduhggd8URobGyc1W89oGEjmohRXkB66JZo', - ledger_id: 1, - pool_state_root_hash: 'NCGqbfRWDWtLB2bDuL6TC5BhrRdQMc5MyKdXQqXii44', - timestamp: 1632680963, - txn_root_hash: 'AxqfyyDFuY74kiXcfvkYCWCVrHsrQutKaoi3ao4Vp8K7', - }, - signature: - 'QwkoPr9pwXyBdtMMUtJ841QjX3pTEQP6bumBpHCWiBCn4AduEW55SQXHjfQZd7EXEjArMfjNyDjgC3Qsvh51WAFGK74C3Tq7k5zYbm7kbVZdUse2i27XiDkMuB6sriroi7XHfnV3Bo55ig3APAFXD7mQrKTGE2ov17CF6yn1ns81vf', - }, - proof_nodes: - '+QHS+JygNttWkmVHYjZyCCk0TNJr5l7AJOnuLNU99qWyNhfBuWq4efh3uHV7ImlkZW50aWZpZXIiOiJWNFNHUlU4Nlo1OGQ2VFY3UEJVZTZmIiwicm9sZSI6IjAiLCJzZXFObyI6MTEsInR4blRpbWUiOjE2MzI2ODA5NjMsInZlcmtleSI6In40M1g0TmhBRnFSRWZmSzdlV2RLZ0ZIIn35ATGg09I/bgmxWmztC58rrZwebgwutUGli7VUyVOFwmuLFqOAoNrtARUl8FhzgOfGsZGlm8IVqgH1wB5KaoajR9sA53e2oJqauj70Qf++s0g43b1zvnQEyQJh2lfNqxFRtmaADvkwgKACG8f0w2NsuDibWYibc1TYySAgUKSeIevHF6wVZdMBL6BEAIIJs0un9jVqVEABbCWTkc0rybTVrFgaKU6LD6ciGYCAgICgJHIm3oUOYlDrQlw95UDkRdOc2tGIsE9g2r12AjpJiUKAoH0lXE47VtUlFvwnCC5rgY878m6TpeEZTJIKd4SUxXtqoBvSoTludXD0XkhTPm4YxfCcAdCaiDvkzM8w6O4v5/e1oDs6GXxRL8inD2b3RY1v/ufksDHNqfFKaK2MEIjNIZwagA==', - root_hash: 'AqMNuzJHeHduhggd8URobGyc1W89oGEjmohRXkB66JZo', - }, - seqNo: 11, - identifier: 'LibindyDid111111111111', - dest: did, - data: `{"dest":"${did}","identifier":"V4SGRU86Z58d6TV7PBUe6f","role":"0","seqNo":11,"txnTime":1632680963,"verkey":"${verkey}"}`, - type: '105', - }, - } - - return response -} - -export function getDidResponsesForDid( - did: string, - pools: IndySdkPoolConfig[], - responses: { [key: string]: string | undefined } -) { - return pools.map((pool) => { - const verkey = responses[pool.indyNamespace] - - if (verkey) { - return () => Promise.resolve(getDidResponse({ did, verkey })) - } - - // LedgerNotFound - return () => Promise.reject(new IndyError(309)) - }) -} diff --git a/packages/indy-sdk/src/ledger/__tests__/serializeRequestForSignature.test.ts b/packages/indy-sdk/src/ledger/__tests__/serializeRequestForSignature.test.ts deleted file mode 100644 index 7bf0c64a67..0000000000 --- a/packages/indy-sdk/src/ledger/__tests__/serializeRequestForSignature.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { serializeRequestForSignature } from '../serializeRequestForSignature' - -describe('serializeRequestForSignature', () => { - it('Should correctly serialize the json for signature input', () => { - const request = { - name: 'John Doe', - age: 43, - operation: { - dest: 54, - }, - phones: ['1234567', '2345678', { rust: 5, age: 1 }, 3], - } - - const expectedResult = 'age:43|name:John Doe|operation:dest:54|phones:1234567,2345678,age:1|rust:5,3' - - expect(serializeRequestForSignature(request)).toEqual(expectedResult) - }) - - it('Should correctly serialize the json for signature with skipped fields', () => { - const request = { - name: 'John Doe', - age: 43, - operation: { - type: '100', - hash: 'cool hash', - dest: 54, - }, - fees: 'fees1', - signature: 'sign1', - signatures: 'sign-m', - phones: ['1234567', '2345678', { rust: 5, age: 1 }, 3], - } - - const expectedResult = - 'age:43|name:John Doe|operation:dest:54|hash:46aa0c92129b33ee72ee1478d2ae62fa6e756869dedc6c858af3214a6fcf1904|type:100|phones:1234567,2345678,age:1|rust:5,3' - - expect(serializeRequestForSignature(request)).toEqual(expectedResult) - }) - - it('Should correctly serialize the json for signature with raw hash for attrib related types', () => { - const request = { - name: 'John Doe', - age: 43, - operation: { - type: '100', - hash: 'cool hash', - dest: 54, - raw: 'string for hash', - }, - phones: ['1234567', '2345678', { rust: 5, age: 1 }, 3], - } - - const expectedResult = - 'age:43|name:John Doe|operation:dest:54|hash:46aa0c92129b33ee72ee1478d2ae62fa6e756869dedc6c858af3214a6fcf1904|raw:1dcd0759ce38f57049344a6b3c5fc18144fca1724713090c2ceeffa788c02711|type:100|phones:1234567,2345678,age:1|rust:5,3' - - expect(serializeRequestForSignature(request)).toEqual(expectedResult) - }) - - it('Should correctly serialize the json for signature with raw hash for non-attrib related types', () => { - const request = { - name: 'John Doe', - age: 43, - operation: { - type: '101', - hash: 'cool hash', - dest: 54, - raw: 'string for hash', - }, - phones: ['1234567', '2345678', { rust: 5, age: 1 }, 3], - } - - const expectedResult = - 'age:43|name:John Doe|operation:dest:54|hash:cool hash|raw:string for hash|type:101|phones:1234567,2345678,age:1|rust:5,3' - - expect(serializeRequestForSignature(request)).toEqual(expectedResult) - }) - - it('Should correctly serialize the json for signature with null signature', () => { - const request = { - signature: null, - } - - const expectedResult = '' - - expect(serializeRequestForSignature(request)).toEqual(expectedResult) - }) -}) diff --git a/packages/indy-sdk/src/ledger/__tests__/util.test.ts b/packages/indy-sdk/src/ledger/__tests__/util.test.ts deleted file mode 100644 index 38976758ae..0000000000 --- a/packages/indy-sdk/src/ledger/__tests__/util.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { LedgerRejectResponse, LedgerReqnackResponse } from 'indy-sdk' - -import * as LedgerUtil from '../util' - -describe('LedgerUtils', () => { - // IsLedgerRejectResponse - it('Should return true if the response op is: REJECT', () => { - const ledgerResponse: LedgerRejectResponse = { - op: 'REJECT', - reqId: 1, - reason: 'Why not', - identifier: '123456', - } - expect(LedgerUtil.isLedgerRejectResponse(ledgerResponse)).toEqual(true) - }) - it('Should return false if the response op is not: REJECT', () => { - const ledgerResponse: LedgerReqnackResponse = { - op: 'REQNACK', - reqId: 1, - reason: 'Why not', - identifier: '123456', - } - expect(LedgerUtil.isLedgerRejectResponse(ledgerResponse)).toEqual(false) - }) - - // isLedgerReqnackResponse - it('Should return true if the response op is: REQNACK', () => { - const ledgerResponse: LedgerReqnackResponse = { - op: 'REQNACK', - reqId: 1, - reason: 'Why not', - identifier: '123456', - } - expect(LedgerUtil.isLedgerReqnackResponse(ledgerResponse)).toEqual(true) - }) - it('Should return false if the response op is NOT: REQNACK', () => { - const ledgerResponse: LedgerRejectResponse = { - op: 'REJECT', - reqId: 1, - reason: 'Why not', - identifier: '123456', - } - expect(LedgerUtil.isLedgerReqnackResponse(ledgerResponse)).toEqual(false) - }) -}) diff --git a/packages/indy-sdk/src/ledger/error/IndySdkPoolError.ts b/packages/indy-sdk/src/ledger/error/IndySdkPoolError.ts deleted file mode 100644 index fa6679d789..0000000000 --- a/packages/indy-sdk/src/ledger/error/IndySdkPoolError.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { AriesFrameworkError } from '@aries-framework/core' - -export class IndySdkPoolError extends AriesFrameworkError { - public constructor(message: string, { cause }: { cause?: Error } = {}) { - super(message, { cause }) - } -} diff --git a/packages/indy-sdk/src/ledger/error/IndySdkPoolNotConfiguredError.ts b/packages/indy-sdk/src/ledger/error/IndySdkPoolNotConfiguredError.ts deleted file mode 100644 index 91cd3c7199..0000000000 --- a/packages/indy-sdk/src/ledger/error/IndySdkPoolNotConfiguredError.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IndySdkPoolError } from './IndySdkPoolError' - -export class IndySdkPoolNotConfiguredError extends IndySdkPoolError { - public constructor(message: string, { cause }: { cause?: Error } = {}) { - super(message, { cause }) - } -} diff --git a/packages/indy-sdk/src/ledger/error/IndySdkPoolNotFoundError.ts b/packages/indy-sdk/src/ledger/error/IndySdkPoolNotFoundError.ts deleted file mode 100644 index 4977428cba..0000000000 --- a/packages/indy-sdk/src/ledger/error/IndySdkPoolNotFoundError.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IndySdkPoolError } from './IndySdkPoolError' - -export class IndySdkPoolNotFoundError extends IndySdkPoolError { - public constructor(message: string, { cause }: { cause?: Error } = {}) { - super(message, { cause }) - } -} diff --git a/packages/indy-sdk/src/ledger/error/index.ts b/packages/indy-sdk/src/ledger/error/index.ts deleted file mode 100644 index e2554abbdf..0000000000 --- a/packages/indy-sdk/src/ledger/error/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './IndySdkPoolError' -export * from './IndySdkPoolNotConfiguredError' -export * from './IndySdkPoolNotFoundError' diff --git a/packages/indy-sdk/src/ledger/index.ts b/packages/indy-sdk/src/ledger/index.ts deleted file mode 100644 index fe016abcec..0000000000 --- a/packages/indy-sdk/src/ledger/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './IndySdkPool' -export * from './IndySdkPoolService' diff --git a/packages/indy-sdk/src/ledger/serializeRequestForSignature.ts b/packages/indy-sdk/src/ledger/serializeRequestForSignature.ts deleted file mode 100644 index 630dcbab2b..0000000000 --- a/packages/indy-sdk/src/ledger/serializeRequestForSignature.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Hasher, TypedArrayEncoder } from '@aries-framework/core' - -const ATTRIB_TYPE = '100' -const GET_ATTR_TYPE = '104' - -/// Generate the normalized form of a ledger transaction request for signing -export function serializeRequestForSignature(v: any): string { - const type = v?.operation?.type - - return _serializeRequestForSignature(v, true, type != undefined ? `${type}` : undefined) -} - -/** - * Serialize an indy ledger request object for signing input. Based on the rust code. Indy SDK requires ledger requests to be signed using - * a did, however in AFJ's the wallet only creates keys, and we create custom did records. This allows us to remove the legacy createDid and - * publicDidSeed properties from the wallet, as we create the request payload ourselves. - * - * @see https://github.com/hyperledger/indy-shared-rs/blob/6af1e939586d1f16341dc03b62970cf28b32d118/indy-utils/src/txn_signature.rs#L10 - */ -function _serializeRequestForSignature(v: any, isTopLevel: boolean, _type?: string): string { - const vType = typeof v - - if (vType === 'boolean') return v ? 'True' : 'False' - if (vType === 'number') return v.toString() - if (vType === 'string') return v - - if (vType === 'object') { - if (Array.isArray(v)) { - return v.map((element) => _serializeRequestForSignature(element, false, _type)).join(',') - } - - let result = '' - let inMiddle = false - - for (const vKey of Object.keys(v).sort()) { - // Skip signature field at top level as in python code - if (isTopLevel && (vKey == 'signature' || vKey == 'fees' || vKey == 'signatures')) { - continue - } - - if (inMiddle) { - result += '|' - } - - let value = v[vKey] - if ((_type == ATTRIB_TYPE || _type == GET_ATTR_TYPE) && (vKey == 'raw' || vKey == 'hash' || vKey == 'enc')) { - // do it only for attribute related request - if (typeof value !== 'string') throw new Error('Value must be a string for hash') - const hash = Hasher.hash(TypedArrayEncoder.fromString(value), 'sha2-256') - value = Buffer.from(hash).toString('hex') - } - - result = `${result}${vKey}:${_serializeRequestForSignature(value, false, _type)}` - inMiddle = true - } - - return result - } - - return '' -} diff --git a/packages/indy-sdk/src/ledger/util.ts b/packages/indy-sdk/src/ledger/util.ts deleted file mode 100644 index d7b5fc2076..0000000000 --- a/packages/indy-sdk/src/ledger/util.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { LedgerResponse, LedgerRejectResponse, LedgerReqnackResponse } from 'indy-sdk' - -export function isLedgerRejectResponse(response: LedgerResponse): response is LedgerRejectResponse { - return response.op === 'REJECT' -} - -export function isLedgerReqnackResponse(response: LedgerResponse): response is LedgerReqnackResponse { - return response.op === 'REQNACK' -} diff --git a/packages/indy-sdk/src/storage/IndySdkStorageService.ts b/packages/indy-sdk/src/storage/IndySdkStorageService.ts deleted file mode 100644 index bfcb740d79..0000000000 --- a/packages/indy-sdk/src/storage/IndySdkStorageService.ts +++ /dev/null @@ -1,328 +0,0 @@ -import type { IndySdkWallet } from '../wallet/IndySdkWallet' -import type { - BaseRecordConstructor, - AgentContext, - BaseRecord, - TagsBase, - Query, - StorageService, -} from '@aries-framework/core' -import type { WalletQuery, WalletRecord, WalletSearchOptions } from 'indy-sdk' - -import { RecordDuplicateError, RecordNotFoundError, injectable, inject, JsonTransformer } from '@aries-framework/core' - -import { isIndyError, IndySdkError } from '../error' -import { IndySdk, IndySdkSymbol } from '../types' -import { assertIndySdkWallet } from '../utils/assertIndySdkWallet' - -@injectable() -export class IndySdkStorageService implements StorageService { - private indySdk: IndySdk - - private static DEFAULT_QUERY_OPTIONS = { - retrieveType: true, - retrieveTags: true, - } - - public constructor(@inject(IndySdkSymbol) indySdk: IndySdk) { - this.indySdk = indySdk - } - - private transformToRecordTagValues(tags: { [key: number]: string | undefined }): TagsBase { - const transformedTags: TagsBase = {} - - for (const [key, value] of Object.entries(tags)) { - // If the value is a boolean string ('1' or '0') - // use the boolean val - if (value === '1' && key?.includes(':')) { - const [tagName, tagValue] = key.split(':') - - const transformedValue = transformedTags[tagName] - - if (Array.isArray(transformedValue)) { - transformedTags[tagName] = [...transformedValue, tagValue] - } else { - transformedTags[tagName] = [tagValue] - } - } - // Transform '1' and '0' to boolean - else if (value === '1' || value === '0') { - transformedTags[key] = value === '1' - } - // If 1 or 0 is prefixed with 'n__' we need to remove it. This is to prevent - // casting the value to a boolean - else if (value === 'n__1' || value === 'n__0') { - transformedTags[key] = value === 'n__1' ? '1' : '0' - } - // Otherwise just use the value - else { - transformedTags[key] = value - } - } - - return transformedTags - } - - private transformFromRecordTagValues(tags: TagsBase): { [key: string]: string | undefined } { - const transformedTags: { [key: string]: string | undefined } = {} - - for (const [key, value] of Object.entries(tags)) { - // If the value is of type null we use the value undefined - // Indy doesn't support null as a value - if (value === null) { - transformedTags[key] = undefined - } - // If the value is a boolean use the indy - // '1' or '0' syntax - else if (typeof value === 'boolean') { - transformedTags[key] = value ? '1' : '0' - } - // If the value is 1 or 0, we need to add something to the value, otherwise - // the next time we deserialize the tag values it will be converted to boolean - else if (value === '1' || value === '0') { - transformedTags[key] = `n__${value}` - } - // If the value is an array we create a tag for each array - // item ("tagName:arrayItem" = "1") - else if (Array.isArray(value)) { - value.forEach((item) => { - const tagName = `${key}:${item}` - transformedTags[tagName] = '1' - }) - } - // Otherwise just use the value - else { - transformedTags[key] = value - } - } - - return transformedTags - } - - /** - * Transforms the search query into a wallet query compatible with indy WQL. - * - * The format used by AFJ is almost the same as the indy query, with the exception of - * the encoding of values, however this is handled by the {@link IndyStorageService.transformToRecordTagValues} - * method. - */ - private indyQueryFromSearchQuery(query: Query): Record { - // eslint-disable-next-line prefer-const - let { $and, $or, $not, ...tags } = query - - $and = ($and as Query[] | undefined)?.map((q) => this.indyQueryFromSearchQuery(q)) - $or = ($or as Query[] | undefined)?.map((q) => this.indyQueryFromSearchQuery(q)) - $not = $not ? this.indyQueryFromSearchQuery($not as Query) : undefined - - const indyQuery = { - ...this.transformFromRecordTagValues(tags as unknown as TagsBase), - $and, - $or, - $not, - } - - return indyQuery - } - - private recordToInstance(record: WalletRecord, recordClass: BaseRecordConstructor): T { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const instance = JsonTransformer.deserialize(record.value!, recordClass) - instance.id = record.id - - const tags = record.tags ? this.transformToRecordTagValues(record.tags) : {} - instance.replaceTags(tags) - - return instance - } - - /** @inheritDoc */ - public async save(agentContext: AgentContext, record: T) { - assertIndySdkWallet(agentContext.wallet) - - record.updatedAt = new Date() - - const value = JsonTransformer.serialize(record) - const tags = this.transformFromRecordTagValues(record.getTags()) as Record - - try { - await this.indySdk.addWalletRecord(agentContext.wallet.handle, record.type, record.id, value, tags) - } catch (error) { - // Record already exists - if (isIndyError(error, 'WalletItemAlreadyExists')) { - throw new RecordDuplicateError(`Record with id ${record.id} already exists`, { recordType: record.type }) - } - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - /** @inheritDoc */ - public async update(agentContext: AgentContext, record: T): Promise { - assertIndySdkWallet(agentContext.wallet) - - record.updatedAt = new Date() - - const value = JsonTransformer.serialize(record) - const tags = this.transformFromRecordTagValues(record.getTags()) as Record - - try { - await this.indySdk.updateWalletRecordValue(agentContext.wallet.handle, record.type, record.id, value) - await this.indySdk.updateWalletRecordTags(agentContext.wallet.handle, record.type, record.id, tags) - } catch (error) { - // Record does not exist - if (isIndyError(error, 'WalletItemNotFound')) { - throw new RecordNotFoundError(`record with id ${record.id} not found.`, { - recordType: record.type, - cause: error, - }) - } - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - /** @inheritDoc */ - public async delete(agentContext: AgentContext, record: T) { - assertIndySdkWallet(agentContext.wallet) - - try { - await this.indySdk.deleteWalletRecord(agentContext.wallet.handle, record.type, record.id) - } catch (error) { - // Record does not exist - if (isIndyError(error, 'WalletItemNotFound')) { - throw new RecordNotFoundError(`record with id ${record.id} not found.`, { - recordType: record.type, - cause: error, - }) - } - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - /** @inheritDoc */ - public async deleteById( - agentContext: AgentContext, - recordClass: BaseRecordConstructor, - id: string - ): Promise { - assertIndySdkWallet(agentContext.wallet) - - try { - await this.indySdk.deleteWalletRecord(agentContext.wallet.handle, recordClass.type, id) - } catch (error) { - if (isIndyError(error, 'WalletItemNotFound')) { - throw new RecordNotFoundError(`record with id ${id} not found.`, { - recordType: recordClass.type, - cause: error, - }) - } - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - /** @inheritDoc */ - public async getById(agentContext: AgentContext, recordClass: BaseRecordConstructor, id: string): Promise { - assertIndySdkWallet(agentContext.wallet) - - try { - const record = await this.indySdk.getWalletRecord( - agentContext.wallet.handle, - recordClass.type, - id, - IndySdkStorageService.DEFAULT_QUERY_OPTIONS - ) - return this.recordToInstance(record, recordClass) - } catch (error) { - if (isIndyError(error, 'WalletItemNotFound')) { - throw new RecordNotFoundError(`record with id ${id} not found.`, { - recordType: recordClass.type, - cause: error, - }) - } - - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - /** @inheritDoc */ - public async getAll(agentContext: AgentContext, recordClass: BaseRecordConstructor): Promise { - assertIndySdkWallet(agentContext.wallet) - - const recordIterator = this.search( - agentContext.wallet, - recordClass.type, - {}, - IndySdkStorageService.DEFAULT_QUERY_OPTIONS - ) - const records = [] - for await (const record of recordIterator) { - records.push(this.recordToInstance(record, recordClass)) - } - return records - } - - /** @inheritDoc */ - public async findByQuery( - agentContext: AgentContext, - recordClass: BaseRecordConstructor, - query: Query - ): Promise { - assertIndySdkWallet(agentContext.wallet) - - const indyQuery = this.indyQueryFromSearchQuery(query) - - const recordIterator = this.search( - agentContext.wallet, - recordClass.type, - indyQuery, - IndySdkStorageService.DEFAULT_QUERY_OPTIONS - ) - const records = [] - for await (const record of recordIterator) { - records.push(this.recordToInstance(record, recordClass)) - } - return records - } - - private async *search( - wallet: IndySdkWallet, - type: string, - query: WalletQuery, - { limit = Infinity, ...options }: WalletSearchOptions & { limit?: number } - ) { - try { - const searchHandle = await this.indySdk.openWalletSearch(wallet.handle, type, query, options) - - let records: WalletRecord[] = [] - - // Allow max of 256 per fetch operation - const chunk = limit ? Math.min(256, limit) : 256 - - // Loop while limit not reached (or no limit specified) - while (!limit || records.length < limit) { - // Retrieve records - const recordsJson = await this.indySdk.fetchWalletSearchNextRecords(wallet.handle, searchHandle, chunk) - - if (recordsJson.records) { - records = [...records, ...recordsJson.records] - - for (const record of recordsJson.records) { - yield record - } - } - - // If the number of records returned is less than chunk - // It means we reached the end of the iterator (no more records) - if (!records.length || !recordsJson.records || recordsJson.records.length < chunk) { - await this.indySdk.closeWalletSearch(searchHandle) - - return - } - } - } catch (error) { - throw new IndySdkError(error, `Searching '${type}' records for query '${JSON.stringify(query)}' failed`) - } - } -} diff --git a/packages/indy-sdk/src/storage/__tests__/IndySdkStorageService.test.ts b/packages/indy-sdk/src/storage/__tests__/IndySdkStorageService.test.ts deleted file mode 100644 index baa7207d7f..0000000000 --- a/packages/indy-sdk/src/storage/__tests__/IndySdkStorageService.test.ts +++ /dev/null @@ -1,314 +0,0 @@ -import type { IndySdk } from '../../types' -import type { TagsBase } from '@aries-framework/core' - -import { RecordDuplicateError, RecordNotFoundError, SigningProviderRegistry } from '@aries-framework/core' -import * as indySdk from 'indy-sdk' - -import { TestRecord } from '../../../../core/src/storage/__tests__/TestRecord' -import { getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' -import { IndySdkWallet } from '../../wallet/IndySdkWallet' -import { IndySdkStorageService } from '../IndySdkStorageService' - -const agentConfig = getAgentConfig('IndySdkStorageServiceTest') -const wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) - -const agentContext = getAgentContext({ - wallet, - agentConfig, -}) - -const storageService = new IndySdkStorageService(indySdk) -const startDate = Date.now() - -describe('IndySdkStorageService', () => { - beforeEach(async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await wallet.createAndOpen(agentConfig.walletConfig!) - }) - - afterEach(async () => { - await wallet.delete() - }) - - const insertRecord = async ({ id, tags }: { id?: string; tags?: TagsBase }) => { - const props = { - id, - foo: 'bar', - tags: tags ?? { myTag: 'foobar' }, - } - const record = new TestRecord(props) - await storageService.save(agentContext, record) - return record - } - - describe('tag transformation', () => { - it('should correctly transform tag values to string before storing', async () => { - const record = await insertRecord({ - id: 'test-id', - tags: { - someBoolean: true, - someOtherBoolean: false, - someStringValue: 'string', - anArrayValue: ['foo', 'bar'], - // booleans are stored as '1' and '0' so we store the string values '1' and '0' as 'n__1' and 'n__0' - someStringNumberValue: '1', - anotherStringNumberValue: '0', - }, - }) - - const retrieveRecord = await indySdk.getWalletRecord(wallet.handle, record.type, record.id, { - retrieveType: true, - retrieveTags: true, - }) - - expect(retrieveRecord.tags).toEqual({ - someBoolean: '1', - someOtherBoolean: '0', - someStringValue: 'string', - 'anArrayValue:foo': '1', - 'anArrayValue:bar': '1', - someStringNumberValue: 'n__1', - anotherStringNumberValue: 'n__0', - }) - }) - - it('should correctly transform tag values from string after retrieving', async () => { - await indySdk.addWalletRecord(wallet.handle, TestRecord.type, 'some-id', '{}', { - someBoolean: '1', - someOtherBoolean: '0', - someStringValue: 'string', - 'anArrayValue:foo': '1', - 'anArrayValue:bar': '1', - // booleans are stored as '1' and '0' so we store the string values '1' and '0' as 'n__1' and 'n__0' - someStringNumberValue: 'n__1', - anotherStringNumberValue: 'n__0', - }) - - const record = await storageService.getById(agentContext, TestRecord, 'some-id') - - expect(record.getTags()).toEqual({ - someBoolean: true, - someOtherBoolean: false, - someStringValue: 'string', - anArrayValue: expect.arrayContaining(['bar', 'foo']), - someStringNumberValue: '1', - anotherStringNumberValue: '0', - }) - }) - }) - - describe('save()', () => { - it('should throw RecordDuplicateError if a record with the id already exists', async () => { - const record = await insertRecord({ id: 'test-id' }) - - return expect(() => storageService.save(agentContext, record)).rejects.toThrowError(RecordDuplicateError) - }) - - it('should save the record', async () => { - const record = await insertRecord({ id: 'test-id' }) - const found = await storageService.getById(agentContext, TestRecord, 'test-id') - - expect(record).toEqual(found) - }) - - it('After a save the record should have update the updatedAt property', async () => { - const time = startDate - const record = await insertRecord({ id: 'test-updatedAt' }) - expect(record.updatedAt?.getTime()).toBeGreaterThan(time) - }) - }) - - describe('getById()', () => { - it('should throw RecordNotFoundError if the record does not exist', async () => { - return expect(() => storageService.getById(agentContext, TestRecord, 'does-not-exist')).rejects.toThrowError( - RecordNotFoundError - ) - }) - - it('should return the record by id', async () => { - const record = await insertRecord({ id: 'test-id' }) - const found = await storageService.getById(agentContext, TestRecord, 'test-id') - - expect(found).toEqual(record) - }) - }) - - describe('update()', () => { - it('should throw RecordNotFoundError if the record does not exist', async () => { - const record = new TestRecord({ - id: 'test-id', - foo: 'test', - tags: { some: 'tag' }, - }) - - return expect(() => storageService.update(agentContext, record)).rejects.toThrowError(RecordNotFoundError) - }) - - it('should update the record', async () => { - const record = await insertRecord({ id: 'test-id' }) - - record.replaceTags({ ...record.getTags(), foo: 'bar' }) - record.foo = 'foobaz' - await storageService.update(agentContext, record) - - const retrievedRecord = await storageService.getById(agentContext, TestRecord, record.id) - expect(retrievedRecord).toEqual(record) - }) - - it('After a record has been updated it should have updated the updatedAT property', async () => { - const time = startDate - const record = await insertRecord({ id: 'test-id' }) - - record.replaceTags({ ...record.getTags(), foo: 'bar' }) - record.foo = 'foobaz' - await storageService.update(agentContext, record) - - const retrievedRecord = await storageService.getById(agentContext, TestRecord, record.id) - expect(retrievedRecord.createdAt.getTime()).toBeGreaterThan(time) - }) - }) - - describe('delete()', () => { - it('should throw RecordNotFoundError if the record does not exist', async () => { - const record = new TestRecord({ - id: 'test-id', - foo: 'test', - tags: { some: 'tag' }, - }) - - return expect(() => storageService.delete(agentContext, record)).rejects.toThrowError(RecordNotFoundError) - }) - - it('should delete the record', async () => { - const record = await insertRecord({ id: 'test-id' }) - await storageService.delete(agentContext, record) - - return expect(() => storageService.getById(agentContext, TestRecord, record.id)).rejects.toThrowError( - RecordNotFoundError - ) - }) - }) - - describe('getAll()', () => { - it('should retrieve all records', async () => { - const createdRecords = await Promise.all( - Array(5) - .fill(undefined) - .map((_, index) => insertRecord({ id: `record-${index}` })) - ) - - const records = await storageService.getAll(agentContext, TestRecord) - - expect(records).toEqual(expect.arrayContaining(createdRecords)) - }) - }) - - describe('findByQuery()', () => { - it('should retrieve all records that match the query', async () => { - const expectedRecord = await insertRecord({ tags: { myTag: 'foobar' } }) - await insertRecord({ tags: { myTag: 'notfoobar' } }) - - const records = await storageService.findByQuery(agentContext, TestRecord, { myTag: 'foobar' }) - - expect(records.length).toBe(1) - expect(records[0]).toEqual(expectedRecord) - }) - - it('finds records using $and statements', async () => { - const expectedRecord = await insertRecord({ tags: { myTag: 'foo', anotherTag: 'bar' } }) - await insertRecord({ tags: { myTag: 'notfoobar' } }) - - const records = await storageService.findByQuery(agentContext, TestRecord, { - $and: [{ myTag: 'foo' }, { anotherTag: 'bar' }], - }) - - expect(records.length).toBe(1) - expect(records[0]).toEqual(expectedRecord) - }) - - it('finds records using $or statements', async () => { - const expectedRecord = await insertRecord({ tags: { myTag: 'foo' } }) - const expectedRecord2 = await insertRecord({ tags: { anotherTag: 'bar' } }) - await insertRecord({ tags: { myTag: 'notfoobar' } }) - - const records = await storageService.findByQuery(agentContext, TestRecord, { - $or: [{ myTag: 'foo' }, { anotherTag: 'bar' }], - }) - - expect(records.length).toBe(2) - expect(records).toEqual(expect.arrayContaining([expectedRecord, expectedRecord2])) - }) - - it('finds records using $not statements', async () => { - const expectedRecord = await insertRecord({ tags: { myTag: 'foo' } }) - const expectedRecord2 = await insertRecord({ tags: { anotherTag: 'bar' } }) - await insertRecord({ tags: { myTag: 'notfoobar' } }) - - const records = await storageService.findByQuery(agentContext, TestRecord, { - $not: { myTag: 'notfoobar' }, - }) - - expect(records.length).toBe(2) - expect(records).toEqual(expect.arrayContaining([expectedRecord, expectedRecord2])) - }) - - it('correctly transforms an advanced query into a valid WQL query', async () => { - const indySpy = jest.fn() - const storageServiceWithoutIndySdk = new IndySdkStorageService({ - openWalletSearch: indySpy, - fetchWalletSearchNextRecords: jest.fn(() => ({ records: undefined })), - closeWalletSearch: jest.fn(), - } as unknown as IndySdk) - - await storageServiceWithoutIndySdk.findByQuery(agentContext, TestRecord, { - $and: [ - { - $or: [{ myTag: true }, { myTag: false }], - }, - { - $and: [{ theNumber: '0' }, { theNumber: '1' }], - }, - ], - $or: [ - { - aValue: ['foo', 'bar'], - }, - ], - $not: { myTag: 'notfoobar' }, - }) - - const expectedQuery = { - $and: [ - { - $and: undefined, - $not: undefined, - $or: [ - { myTag: '1', $and: undefined, $or: undefined, $not: undefined }, - { myTag: '0', $and: undefined, $or: undefined, $not: undefined }, - ], - }, - { - $or: undefined, - $not: undefined, - $and: [ - { theNumber: 'n__0', $and: undefined, $or: undefined, $not: undefined }, - { theNumber: 'n__1', $and: undefined, $or: undefined, $not: undefined }, - ], - }, - ], - $or: [ - { - 'aValue:foo': '1', - 'aValue:bar': '1', - $and: undefined, - $or: undefined, - $not: undefined, - }, - ], - $not: { myTag: 'notfoobar', $and: undefined, $or: undefined, $not: undefined }, - } - - expect(indySpy).toBeCalledWith(expect.anything(), expect.anything(), expectedQuery, expect.anything()) - }) - }) -}) diff --git a/packages/indy-sdk/src/storage/index.ts b/packages/indy-sdk/src/storage/index.ts deleted file mode 100644 index ff59756cfa..0000000000 --- a/packages/indy-sdk/src/storage/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './IndySdkStorageService' diff --git a/packages/indy-sdk/src/types.ts b/packages/indy-sdk/src/types.ts deleted file mode 100644 index f6ac41c161..0000000000 --- a/packages/indy-sdk/src/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { default as _IndySdk } from 'indy-sdk' - -type IndySdk = typeof _IndySdk - -export const IndySdkSymbol = Symbol('IndySdk') -export type { IndySdk } diff --git a/packages/indy-sdk/src/utils/__tests__/did.test.ts b/packages/indy-sdk/src/utils/__tests__/did.test.ts deleted file mode 100644 index 222f9898fd..0000000000 --- a/packages/indy-sdk/src/utils/__tests__/did.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { isAbbreviatedVerkey, isFullVerkey, isLegacySelfCertifiedDid } from '../did' - -const validAbbreviatedVerkeys = [ - '~PKAYz8Ev4yoQgr2LaMAWFx', - '~Soy1augaQrQYtNZRRHsikB', - '~BUF7uxYTxZ6qYdZ4G9e1Gi', - '~DbZ4gkBqhFRVsT5P7BJqyZ', - '~4zmNTdG78iYyMAQdEQLrf8', -] - -const invalidAbbreviatedVerkeys = [ - '6YnVN5Qdb6mqimTRQcQmSXrHXKdTEdRn5YHZReezUTvt', - '8jG2Bim1HNSybCTdKBRppP4PCQSSijx1pBnreqsdo8JG', - 'ABUF7uxYTxZ6qYdZ4G9e1Gi', - '~Db3IgkBqhFRVsT5P7BJqyZ', - '~4zmNTlG78iYyMAQdEQLrf8', -] - -const validFullVerkeys = [ - '6YnVN5Qdb6mqimTRQcQmSXrHXKdTEdRn5YHZReezUTvt', - '8jG2Bim1HNSybCTdKBRppP4PCQSSijx1pBnreqsdo8JG', - '9wMLhw9SSxtTUyosrndMbvWY4TtDbVvRnMtzG2NysniP', - '6m2XT39vivJ7tLSxNPM8siMnhYCZcdMxbkTcJDSzAQTu', - 'CAgL85iEecPNQMmxQ1hgbqczwq7SAerQ8RbWTRtC7SoK', - 'MqXmB7cTsTXqyxDPBbrgu5EPqw61kouK1qjMvnoPa96', -] - -const invalidFullVerkeys = [ - '~PKAYz8Ev4yoQgr2LaMAWFx', - '~Soy1augaQrQYtNZRRHsikB', - '6YnVN5Qdb6mqimTRQcQmSXrHXKdTEdRn5YHZReezUTvta', - '6m2XT39vIvJ7tLSxNPM8siMnhYCZcdMxbkTcJDSzAQTu', - 'CAgL85iEecPNQMlxQ1hgbqczwq7SAerQ8RbWTRtC7SoK', -] - -describe('Utils | Did', () => { - describe('isSelfCertifiedDid()', () => { - test('returns true if the verkey is abbreviated', () => { - expect(isLegacySelfCertifiedDid('PW8ZHpNupeWXbmpPWog6Ki', '~QQ5jiH1dgXPAnvHdJvazn9')).toBe(true) - }) - - test('returns true if the verkey is not abbreviated and the did is generated from the verkey', () => { - expect(isLegacySelfCertifiedDid('Y8q4Aq6gRAcmB6jjKk3Z7t', 'HyEoPRNvC7q4jj5joUo8AWYtxbNccbEnTAeuMYkpmNS2')).toBe( - true - ) - }) - - test('returns false if the verkey is not abbreviated and the did is not generated from the verkey', () => { - expect(isLegacySelfCertifiedDid('Y8q4Aq6gRAcmB6jjKk3Z7t', 'AcU7DnRqoXGYATD6VqsRq4eHuz55gdM3uzFBEhFd6rGh')).toBe( - false - ) - }) - }) - - describe('isAbbreviatedVerkey()', () => { - test.each(validAbbreviatedVerkeys)('returns true when valid abbreviated verkey "%s" is passed in', (verkey) => { - expect(isAbbreviatedVerkey(verkey)).toBe(true) - }) - - test.each(invalidAbbreviatedVerkeys)( - 'returns false when invalid abbreviated verkey "%s" is passed in', - (verkey) => { - expect(isAbbreviatedVerkey(verkey)).toBe(false) - } - ) - }) - - describe('isFullVerkey()', () => { - test.each(validFullVerkeys)('returns true when valid full verkey "%s" is passed in', (verkey) => { - expect(isFullVerkey(verkey)).toBe(true) - }) - - test.each(invalidFullVerkeys)('returns false when invalid full verkey "%s" is passed in', (verkey) => { - expect(isFullVerkey(verkey)).toBe(false) - }) - }) -}) diff --git a/packages/indy-sdk/src/utils/assertIndySdkWallet.ts b/packages/indy-sdk/src/utils/assertIndySdkWallet.ts deleted file mode 100644 index 0b1914555f..0000000000 --- a/packages/indy-sdk/src/utils/assertIndySdkWallet.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Wallet } from '@aries-framework/core' - -import { AriesFrameworkError } from '@aries-framework/core' - -import { IndySdkWallet } from '../wallet/IndySdkWallet' - -export function assertIndySdkWallet(wallet: Wallet): asserts wallet is IndySdkWallet { - if (!(wallet instanceof IndySdkWallet)) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const walletClassName = (wallet as any).constructor?.name ?? 'unknown' - throw new AriesFrameworkError(`Expected wallet to be instance of IndySdkWallet, found ${walletClassName}`) - } -} diff --git a/packages/indy-sdk/src/utils/did.ts b/packages/indy-sdk/src/utils/did.ts deleted file mode 100644 index afb080696f..0000000000 --- a/packages/indy-sdk/src/utils/did.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * 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 { Buffer, 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}$/ - -/** - * 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 isLegacySelfCertifiedDid(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 = legacyIndyDidFromPublicKeyBase58(verkey) - - if (didFromVerkey === did) { - return true - } - - return false -} - -export function legacyIndyDidFromPublicKeyBase58(publicKeyBase58: string): string { - const buffer = TypedArrayEncoder.fromBase58(publicKeyBase58) - - const did = TypedArrayEncoder.toBase58(buffer.slice(0, 16)) - - return did -} - -export function getFullVerkey(did: string, verkey: string) { - if (isFullVerkey(verkey)) return verkey - - // Did could have did:xxx prefix, only take the last item after : - const id = did.split(':').pop() ?? did - // Verkey is prefixed with ~ if abbreviated - const verkeyWithoutTilde = verkey.slice(1) - - // Create base58 encoded public key (32 bytes) - return TypedArrayEncoder.toBase58( - Buffer.concat([ - // Take did identifier (16 bytes) - TypedArrayEncoder.fromBase58(id), - // Concat the abbreviated verkey (16 bytes) - TypedArrayEncoder.fromBase58(verkeyWithoutTilde), - ]) - ) -} - -/** - * Check a base58 encoded string against a regex expression to determine if it is a full valid verkey - * @param verkey Base58 encoded string representation of a verkey - * @return Boolean indicating if the string is a valid verkey - */ -export function isFullVerkey(verkey: string): boolean { - return FULL_VERKEY_REGEX.test(verkey) -} - -/** - * 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-sdk/src/utils/promises.ts b/packages/indy-sdk/src/utils/promises.ts deleted file mode 100644 index 0e843d73b5..0000000000 --- a/packages/indy-sdk/src/utils/promises.ts +++ /dev/null @@ -1,44 +0,0 @@ -// 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[] -} diff --git a/packages/indy-sdk/src/wallet/IndySdkWallet.ts b/packages/indy-sdk/src/wallet/IndySdkWallet.ts deleted file mode 100644 index 51177454c2..0000000000 --- a/packages/indy-sdk/src/wallet/IndySdkWallet.ts +++ /dev/null @@ -1,645 +0,0 @@ -import type { - Buffer, - EncryptedMessage, - KeyDerivationMethod, - KeyPair, - UnpackedMessageContext, - Wallet, - WalletConfig, - WalletConfigRekey, - WalletCreateKeyOptions, - WalletExportImportConfig, - WalletSignOptions, - WalletVerifyOptions, -} from '@aries-framework/core' -import type { OpenWalletCredentials, WalletConfig as IndySdkWalletConfig, WalletStorageConfig } from 'indy-sdk' - -// eslint-disable-next-line import/order -import { - AriesFrameworkError, - InjectionSymbols, - isValidPrivateKey, - isValidSeed, - JsonEncoder, - Key, - KeyType, - Logger, - RecordNotFoundError, - SigningProviderRegistry, - TypedArrayEncoder, - WalletDuplicateError, - WalletError, - WalletExportPathExistsError, - WalletInvalidKeyError, - WalletKeyExistsError, - WalletNotFoundError, -} from '@aries-framework/core' - -const isError = (error: unknown): error is Error => error instanceof Error - -import { inject, injectable } from 'tsyringe' - -import { IndySdkError, isIndyError } from '../error' -import { IndySdk, IndySdkSymbol } from '../types' - -@injectable() -export class IndySdkWallet implements Wallet { - private walletConfig?: WalletConfig - private walletHandle?: number - - private logger: Logger - private signingKeyProviderRegistry: SigningProviderRegistry - private indySdk: IndySdk - - public constructor( - @inject(IndySdkSymbol) indySdk: IndySdk, - @inject(InjectionSymbols.Logger) logger: Logger, - signingKeyProviderRegistry: SigningProviderRegistry - ) { - this.logger = logger - this.signingKeyProviderRegistry = signingKeyProviderRegistry - this.indySdk = indySdk - } - - public get isProvisioned() { - return this.walletConfig !== undefined - } - - public get isInitialized() { - return this.walletHandle !== undefined - } - - public get handle() { - if (!this.walletHandle) { - throw new AriesFrameworkError( - 'Wallet has not been initialized yet. Make sure to await agent.initialize() before using the agent.' - ) - } - - return this.walletHandle - } - - public get supportedKeyTypes() { - const walletSupportedKeyTypes = [KeyType.Ed25519] - const signingKeyProviderSupportedKeyTypes = this.signingKeyProviderRegistry.supportedKeyTypes - - return Array.from(new Set([...walletSupportedKeyTypes, ...signingKeyProviderSupportedKeyTypes])) - } - - /** - * Dispose method is called when an agent context is disposed. - */ - public async dispose() { - if (this.isInitialized) { - await this.close() - } - } - - private walletStorageConfig(walletConfig: WalletConfig): IndySdkWalletConfig { - const walletStorageConfig: IndySdkWalletConfig = { - id: walletConfig.id, - storage_type: walletConfig.storage?.type, - } - - if (walletConfig.storage?.config) { - walletStorageConfig.storage_config = walletConfig.storage?.config as WalletStorageConfig - } - - return walletStorageConfig - } - - private walletCredentials( - walletConfig: WalletConfig, - rekey?: string, - rekeyDerivation?: KeyDerivationMethod - ): OpenWalletCredentials { - const walletCredentials: OpenWalletCredentials = { - key: walletConfig.key, - key_derivation_method: walletConfig.keyDerivationMethod, - } - if (rekey) { - walletCredentials.rekey = rekey - } - if (rekeyDerivation) { - walletCredentials.rekey_derivation_method = rekeyDerivation - } - if (walletConfig.storage?.credentials) { - walletCredentials.storage_credentials = walletConfig.storage?.credentials as Record - } - - return walletCredentials - } - - /** - * @throws {WalletDuplicateError} if the wallet already exists - * @throws {WalletError} if another error occurs - */ - public async create(walletConfig: WalletConfig): Promise { - await this.createAndOpen(walletConfig) - await this.close() - } - - /** - * @throws {WalletDuplicateError} if the wallet already exists - * @throws {WalletError} if another error occurs - */ - public async createAndOpen(walletConfig: WalletConfig): Promise { - this.logger.debug(`Creating wallet '${walletConfig.id}' using SQLite storage`) - - try { - await this.indySdk.createWallet(this.walletStorageConfig(walletConfig), this.walletCredentials(walletConfig)) - this.walletConfig = walletConfig - - await this.open(walletConfig) - } catch (error) { - if (isIndyError(error, 'WalletAlreadyExistsError')) { - const errorMessage = `Wallet '${walletConfig.id}' already exists` - this.logger.debug(errorMessage) - - throw new WalletDuplicateError(errorMessage, { - walletType: 'IndySdkWallet', - cause: error, - }) - } else { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - const errorMessage = `Error creating wallet '${walletConfig.id}'` - this.logger.error(errorMessage, { - error, - errorMessage: error.message, - }) - - throw new WalletError(errorMessage, { cause: error }) - } - } - - this.logger.debug(`Successfully created wallet '${walletConfig.id}'`) - } - - /** - * @throws {WalletNotFoundError} if the wallet does not exist - * @throws {WalletError} if another error occurs - */ - public async open(walletConfig: WalletConfig): Promise { - await this._open(walletConfig) - } - - /** - * @throws {WalletNotFoundError} if the wallet does not exist - * @throws {WalletError} if another error occurs - */ - public async rotateKey(walletConfig: WalletConfigRekey): Promise { - if (!walletConfig.rekey) { - throw new WalletError('Wallet rekey undefined!. Please specify the new wallet key') - } - await this._open( - { - id: walletConfig.id, - key: walletConfig.key, - keyDerivationMethod: walletConfig.keyDerivationMethod, - }, - walletConfig.rekey, - walletConfig.rekeyDerivationMethod - ) - } - - /** - * @throws {WalletNotFoundError} if the wallet does not exist - * @throws {WalletError} if another error occurs - */ - private async _open( - walletConfig: WalletConfig, - rekey?: string, - rekeyDerivation?: KeyDerivationMethod - ): Promise { - if (this.walletHandle) { - throw new WalletError( - 'Wallet instance already opened. Close the currently opened wallet before re-opening the wallet' - ) - } - - try { - this.walletHandle = await this.indySdk.openWallet( - this.walletStorageConfig(walletConfig), - this.walletCredentials(walletConfig, rekey, rekeyDerivation) - ) - if (rekey) { - this.walletConfig = { ...walletConfig, key: rekey, keyDerivationMethod: rekeyDerivation } - } else { - this.walletConfig = walletConfig - } - } catch (error) { - if (isIndyError(error, 'WalletNotFoundError')) { - const errorMessage = `Wallet '${walletConfig.id}' not found` - this.logger.debug(errorMessage) - - throw new WalletNotFoundError(errorMessage, { - walletType: 'IndySdkWallet', - cause: error, - }) - } else if (isIndyError(error, 'WalletAccessFailed')) { - const errorMessage = `Incorrect key for wallet '${walletConfig.id}'` - this.logger.debug(errorMessage) - throw new WalletInvalidKeyError(errorMessage, { - walletType: 'IndySdkWallet', - cause: error, - }) - } else { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - const errorMessage = `Error opening wallet '${walletConfig.id}': ${error.message}` - this.logger.error(errorMessage, { - error, - errorMessage: error.message, - }) - - throw new WalletError(errorMessage, { cause: error }) - } - } - - this.logger.debug(`Wallet '${walletConfig.id}' opened with handle '${this.handle}'`) - } - - /** - * @throws {WalletNotFoundError} if the wallet does not exist - * @throws {WalletError} if another error occurs - */ - public async delete(): Promise { - if (!this.walletConfig) { - throw new WalletError( - 'Can not delete wallet that does not have wallet config set. Make sure to call create wallet before deleting the wallet' - ) - } - - this.logger.info(`Deleting wallet '${this.walletConfig.id}'`) - - if (this.walletHandle) { - await this.close() - } - - try { - await this.indySdk.deleteWallet( - this.walletStorageConfig(this.walletConfig), - this.walletCredentials(this.walletConfig) - ) - } catch (error) { - if (isIndyError(error, 'WalletNotFoundError')) { - const errorMessage = `Error deleting wallet: wallet '${this.walletConfig.id}' not found` - this.logger.debug(errorMessage) - - throw new WalletNotFoundError(errorMessage, { - walletType: 'IndySdkWallet', - cause: error, - }) - } else { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - const errorMessage = `Error deleting wallet '${this.walletConfig.id}': ${error.message}` - this.logger.error(errorMessage, { - error, - errorMessage: error.message, - }) - - throw new WalletError(errorMessage, { cause: error }) - } - } - } - - public async export(exportConfig: WalletExportImportConfig) { - try { - this.logger.debug(`Exporting wallet ${this.walletConfig?.id} to path ${exportConfig.path}`) - await this.indySdk.exportWallet(this.handle, exportConfig) - } catch (error) { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - - // Export path already exists - if (isIndyError(error, 'CommonIOError')) { - throw new WalletExportPathExistsError( - `Unable to create export, wallet export at path '${exportConfig.path}' already exists`, - { cause: error } - ) - } - - const errorMessage = `Error exporting wallet: ${error.message}` - this.logger.error(errorMessage, { - error, - }) - - throw new WalletError(errorMessage, { cause: error }) - } - } - - public async import(walletConfig: WalletConfig, importConfig: WalletExportImportConfig) { - try { - this.logger.debug(`Importing wallet ${walletConfig.id} from path ${importConfig.path}`) - await this.indySdk.importWallet( - { id: walletConfig.id }, - { key: walletConfig.key, key_derivation_method: walletConfig.keyDerivationMethod }, - importConfig - ) - } catch (error) { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - const errorMessage = `Error importing wallet': ${error.message}` - this.logger.error(errorMessage, { - error, - }) - - throw new WalletError(errorMessage, { cause: error }) - } - } - - /** - * @throws {WalletError} if the wallet is already closed or another error occurs - */ - public async close(): Promise { - this.logger.debug(`Closing wallet ${this.walletConfig?.id}`) - if (!this.walletHandle) { - throw new WalletError('Wallet is in invalid state, you are trying to close wallet that has no `walletHandle`.') - } - - try { - await this.indySdk.closeWallet(this.walletHandle) - this.walletHandle = undefined - } catch (error) { - if (isIndyError(error, 'WalletInvalidHandle')) { - const errorMessage = `Error closing wallet: wallet already closed` - this.logger.debug(errorMessage) - - throw new WalletError(errorMessage, { - cause: error, - }) - } else { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - const errorMessage = `Error closing wallet': ${error.message}` - this.logger.error(errorMessage, { - error, - errorMessage: error.message, - }) - - throw new WalletError(errorMessage, { cause: error }) - } - } - } - - /** - * Create a key with an optional private key and keyType. - * The keypair is also automatically stored in the wallet afterwards - * - * Bls12381g1g2 and X25519 are not supported. - */ - public async createKey({ seed, privateKey, keyType }: WalletCreateKeyOptions): Promise { - try { - if (seed && privateKey) { - throw new WalletError('Only one of seed and privateKey can be set') - } - - if (seed && !isValidSeed(seed, keyType)) { - throw new WalletError('Invalid seed provided') - } - - if (privateKey && !isValidPrivateKey(privateKey, keyType)) { - throw new WalletError('Invalid private key provided') - } - - // Ed25519 is supported natively in Indy wallet - if (keyType === KeyType.Ed25519) { - if (seed) { - throw new WalletError( - 'IndySdkWallet does not support seed. You may rather want to specify a private key for deterministic ed25519 key generation' - ) - } - try { - const verkey = await this.indySdk.createKey(this.handle, { - seed: privateKey?.toString(), - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - crypto_type: 'ed25519', - }) - - return Key.fromPublicKeyBase58(verkey, keyType) - } catch (error) { - // Handle case where key already exists - if (isIndyError(error, 'WalletItemAlreadyExists')) { - throw new WalletKeyExistsError('Key already exists') - } - - // Otherwise re-throw error - throw error - } - } - - // Check if there is a signing key provider for the specified key type. - if (this.signingKeyProviderRegistry.hasProviderForKeyType(keyType)) { - const signingKeyProvider = this.signingKeyProviderRegistry.getProviderForKeyType(keyType) - - const keyPair = await signingKeyProvider.createKeyPair({ seed, privateKey }) - await this.storeKeyPair(keyPair) - return Key.fromPublicKeyBase58(keyPair.publicKeyBase58, keyType) - } - } catch (error) { - // If already instance of `WalletError`, re-throw - if (error instanceof WalletError) throw error - - if (!isError(error)) { - throw new AriesFrameworkError(`Attempted to throw error, but it was not of type Error: ${error}`, { - cause: error, - }) - } - - throw new WalletError(`Error creating key with key type '${keyType}': ${error.message}`, { cause: error }) - } - - throw new WalletError(`Unsupported key type: '${keyType}' for wallet IndySdkWallet`) - } - - /** - * sign a Buffer with an instance of a Key class - * - * Bls12381g1g2, Bls12381g1 and X25519 are not supported. - * - * @param data Buffer The data that needs to be signed - * @param key Key The key that is used to sign the data - * - * @returns A signature for the data - */ - public async sign({ data, key }: WalletSignOptions): Promise { - try { - // Ed25519 is supported natively in Indy wallet - if (key.keyType === KeyType.Ed25519) { - // Checks to see if it is an not an Array of messages, but just a single one - if (!TypedArrayEncoder.isTypedArray(data)) { - throw new WalletError(`${KeyType.Ed25519} does not support multiple singing of multiple messages`) - } - return await this.indySdk.cryptoSign(this.handle, key.publicKeyBase58, data as Buffer) - } - - // Check if there is a signing key provider for the specified key type. - if (this.signingKeyProviderRegistry.hasProviderForKeyType(key.keyType)) { - const signingKeyProvider = this.signingKeyProviderRegistry.getProviderForKeyType(key.keyType) - - const keyPair = await this.retrieveKeyPair(key.publicKeyBase58) - const signed = await signingKeyProvider.sign({ - data, - privateKeyBase58: keyPair.privateKeyBase58, - publicKeyBase58: key.publicKeyBase58, - }) - - return signed - } - } catch (error) { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - throw new WalletError(`Error signing data with verkey ${key.publicKeyBase58}`, { cause: error }) - } - throw new WalletError(`Unsupported keyType: ${key.keyType}`) - } - - /** - * Verify the signature with the data and the used key - * - * Bls12381g1g2, Bls12381g1 and X25519 are not supported. - * - * @param data Buffer The data that has to be confirmed to be signed - * @param key Key The key that was used in the signing process - * @param signature Buffer The signature that was created by the signing process - * - * @returns A boolean whether the signature was created with the supplied data and key - * - * @throws {WalletError} When it could not do the verification - * @throws {WalletError} When an unsupported keytype is used - */ - public async verify({ data, key, signature }: WalletVerifyOptions): Promise { - try { - // Ed25519 is supported natively in Indy wallet - if (key.keyType === KeyType.Ed25519) { - // Checks to see if it is an not an Array of messages, but just a single one - if (!TypedArrayEncoder.isTypedArray(data)) { - throw new WalletError(`${KeyType.Ed25519} does not support multiple singing of multiple messages`) - } - return await this.indySdk.cryptoVerify(key.publicKeyBase58, data as Buffer, signature) - } - - // Check if there is a signing key provider for the specified key type. - if (this.signingKeyProviderRegistry.hasProviderForKeyType(key.keyType)) { - const signingKeyProvider = this.signingKeyProviderRegistry.getProviderForKeyType(key.keyType) - - const signed = await signingKeyProvider.verify({ - data, - signature, - publicKeyBase58: key.publicKeyBase58, - }) - - return signed - } - } catch (error) { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - throw new WalletError(`Error verifying signature of data signed with verkey ${key.publicKeyBase58}`, { - cause: error, - }) - } - throw new WalletError(`Unsupported keyType: ${key.keyType}`) - } - - public async pack( - payload: Record, - recipientKeys: string[], - senderVerkey?: string - ): Promise { - try { - const messageRaw = JsonEncoder.toBuffer(payload) - const packedMessage = await this.indySdk.packMessage(this.handle, messageRaw, recipientKeys, senderVerkey ?? null) - return JsonEncoder.fromBuffer(packedMessage) - } catch (error) { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - throw new WalletError('Error packing message', { cause: error }) - } - } - - public async unpack(messagePackage: EncryptedMessage): Promise { - try { - const unpackedMessageBuffer = await this.indySdk.unpackMessage(this.handle, JsonEncoder.toBuffer(messagePackage)) - const unpackedMessage = JsonEncoder.fromBuffer(unpackedMessageBuffer) - return { - senderKey: unpackedMessage.sender_verkey, - recipientKey: unpackedMessage.recipient_verkey, - plaintextMessage: JsonEncoder.fromString(unpackedMessage.message), - } - } catch (error) { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - throw new WalletError('Error unpacking message', { cause: error }) - } - } - - public async generateNonce(): Promise { - try { - return await this.indySdk.generateNonce() - } catch (error) { - if (!isError(error)) { - throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) - } - throw new WalletError('Error generating nonce', { cause: error }) - } - } - - private async retrieveKeyPair(publicKeyBase58: string): Promise { - try { - const { value } = await this.indySdk.getWalletRecord(this.handle, 'KeyPairRecord', `key-${publicKeyBase58}`, {}) - if (value) { - return JsonEncoder.fromString(value) as KeyPair - } else { - throw new WalletError(`No content found for record with public key: ${publicKeyBase58}`) - } - } catch (error) { - if (isIndyError(error, 'WalletItemNotFound')) { - throw new RecordNotFoundError(`KeyPairRecord not found for public key: ${publicKeyBase58}.`, { - recordType: 'KeyPairRecord', - cause: error, - }) - } - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - private async storeKeyPair(keyPair: KeyPair): Promise { - try { - await this.indySdk.addWalletRecord( - this.handle, - 'KeyPairRecord', - `key-${keyPair.publicKeyBase58}`, - JSON.stringify(keyPair), - { - keyType: keyPair.keyType, - } - ) - } catch (error) { - if (isIndyError(error, 'WalletItemAlreadyExists')) { - throw new WalletKeyExistsError('Key already exists') - } - throw isIndyError(error) ? new IndySdkError(error) : error - } - } - - public async generateWalletKey() { - try { - return await this.indySdk.generateWalletKey() - } catch (error) { - throw new WalletError('Error generating wallet key', { cause: error }) - } - } -} diff --git a/packages/indy-sdk/src/wallet/__tests__/IndySdkWallet.test.ts b/packages/indy-sdk/src/wallet/__tests__/IndySdkWallet.test.ts deleted file mode 100644 index 588a19ed7a..0000000000 --- a/packages/indy-sdk/src/wallet/__tests__/IndySdkWallet.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { SigningProvider, WalletConfig } from '@aries-framework/core' - -import { - Key, - WalletKeyExistsError, - KeyType, - SigningProviderRegistry, - TypedArrayEncoder, - KeyDerivationMethod, -} from '@aries-framework/core' -import indySdk from 'indy-sdk' - -import testLogger from '../../../../core/tests/logger' -import { IndySdkWallet } from '../IndySdkWallet' - -// use raw key derivation method to speed up wallet creating / opening / closing between tests -const walletConfig: WalletConfig = { - id: 'Wallet: IndySdkWalletTest', - // generated using indy.generateWalletKey - key: 'CwNJroKHTSSj3XvE7ZAnuKiTn2C4QkFvxEqfm5rzhNrb', - keyDerivationMethod: KeyDerivationMethod.Raw, -} - -const signingProvider = { - keyType: KeyType.X25519, - createKeyPair: () => Promise.resolve({ keyType: KeyType.X25519, privateKeyBase58: 'b', publicKeyBase58: 'a' }), -} satisfies Partial - -describe('IndySdkWallet', () => { - let indySdkWallet: IndySdkWallet - - const privateKey = TypedArrayEncoder.fromString('sample-seed') - const message = TypedArrayEncoder.fromString('sample-message') - - beforeEach(async () => { - indySdkWallet = new IndySdkWallet( - indySdk, - testLogger, - new SigningProviderRegistry([signingProvider as unknown as SigningProvider]) - ) - await indySdkWallet.createAndOpen(walletConfig) - }) - - afterEach(async () => { - await indySdkWallet.delete() - }) - - test('Get the wallet handle', () => { - expect(indySdkWallet.handle).toEqual(expect.any(Number)) - }) - - test('supportedKeyTypes', () => { - // indy supports ed25519, signing provider supports x25519 - expect(indySdkWallet.supportedKeyTypes).toEqual([KeyType.Ed25519, KeyType.X25519]) - }) - - test('Generate Nonce', async () => { - await expect(indySdkWallet.generateNonce()).resolves.toEqual(expect.any(String)) - }) - - test('Create ed25519 keypair from private key', async () => { - await expect( - indySdkWallet.createKey({ - privateKey: TypedArrayEncoder.fromString('2103de41b4ae37e8e28586d84a342b67'), - keyType: KeyType.Ed25519, - }) - ).resolves.toMatchObject({ - keyType: KeyType.Ed25519, - }) - }) - - test('throws WalletKeyExistsError when a key already exists', async () => { - const privateKey = TypedArrayEncoder.fromString('2103de41b4ae37e8e28586d84a342b68') - await expect(indySdkWallet.createKey({ privateKey, keyType: KeyType.Ed25519 })).resolves.toEqual(expect.any(Key)) - await expect(indySdkWallet.createKey({ privateKey, keyType: KeyType.Ed25519 })).rejects.toThrowError( - WalletKeyExistsError - ) - - // This should result in the signign provider being called twice, resulting in the record - // being stored twice - await expect(indySdkWallet.createKey({ privateKey, keyType: KeyType.X25519 })).resolves.toEqual(expect.any(Key)) - await expect(indySdkWallet.createKey({ privateKey, keyType: KeyType.X25519 })).rejects.toThrowError( - WalletKeyExistsError - ) - }) - - test('Fail to create ed25519 keypair from invalid private key', async () => { - await expect(indySdkWallet.createKey({ privateKey, keyType: KeyType.Ed25519 })).rejects.toThrowError( - /Invalid private key provided/ - ) - }) - - test('Fail to create x25519 keypair', async () => { - await expect(indySdkWallet.createKey({ keyType: KeyType.Bls12381g1 })).rejects.toThrowError(/Unsupported key type/) - }) - - test('Create a signature with a ed25519 keypair', async () => { - const ed25519Key = await indySdkWallet.createKey({ keyType: KeyType.Ed25519 }) - const signature = await indySdkWallet.sign({ - data: message, - key: ed25519Key, - }) - expect(signature.length).toStrictEqual(64) - }) - - test('Verify a signed message with a ed25519 publicKey', async () => { - const ed25519Key = await indySdkWallet.createKey({ keyType: KeyType.Ed25519 }) - const signature = await indySdkWallet.sign({ - data: message, - key: ed25519Key, - }) - await expect(indySdkWallet.verify({ key: ed25519Key, data: message, signature })).resolves.toStrictEqual(true) - }) -}) diff --git a/packages/indy-sdk/src/wallet/index.ts b/packages/indy-sdk/src/wallet/index.ts deleted file mode 100644 index b327ed63bf..0000000000 --- a/packages/indy-sdk/src/wallet/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { IndySdkWallet } from './IndySdkWallet' diff --git a/packages/indy-sdk/tests/__fixtures__/anoncreds.ts b/packages/indy-sdk/tests/__fixtures__/anoncreds.ts deleted file mode 100644 index eb978ec748..0000000000 --- a/packages/indy-sdk/tests/__fixtures__/anoncreds.ts +++ /dev/null @@ -1,30 +0,0 @@ -export const credentialDefinitionValue = { - primary: { - n: '96517142458750088826087901549537285521906361834839650465292394026155791790248920518228426560592477800345470631128393537910767968076647428853737338120375137978526133371095345886547568849980095910835456337942570110635942227498396677781945046904040000347997661394155645138402989185582727368743644878567330299129483548946710969360956979880962101169330048328620192831242584775824654760726417810662811409929761424969870024291961980782988854217354212087291593903213167261779548063894662259300608395552269380441482047725811646638173390809967510159302372018819245039226007682154490256871635806558216146474297742733244470144481', - s: '20992997088800769394205042281221010730843336204635587269131066142238627416871294692123680065003125450990475247419429111144686875080339959479648984195457400282722471552678361441816569115316390063503704185107464429408708889920969284364549487320740759452356010336698287092961864738455949515401889999320804333605635972368885179914619910494573144273759358510644118555354521660927445864167887629319425342133470781407706668100509422240127902573158722086763638357241708157836231326104213948080124231104027985997092193458353052131052627451830345602820935886233072722689872803371231173593216542422645374438328309647440653637339', - r: { - master_secret: - '96243300745227716230048295249700256382424379142767068560156597061550615821183969840133023439359733351013932957841392861447122785423145599004240865527901625751619237368187131360686977600247815596986496835118582544022443932674638843143227258367859921648385998241629365673854479167826898057354386557912400420925145402535066400276579674049751639901555837852972622061540154688641944145082381483273814616102862399655638465723909813901943343059991047747289931252070264205125933226649905593045675877143065756794349492159868513288280364195700788501708587588090219665708038121636837649207584981238653023213330207384929738192210', - name: '73301750658973501389860306433954162777688414647250690792688553201037736559940890441467927863421690990807820789906540409252803697381653459639864945429958798104818241892796218340966964349674689564019059435289373607451125919476002261041343187491848656595845611576458601110066647002078334660251906541846222115184239401618625285703919125402959929850028352261117167621349930047514115676870868726855651130262227714591240534532398809967792128535084773798290351459391475237061458901325844643172504167457543287673202618731404966555015061917662865397763636445953946274068384614117513804834235388565249331682010365807270858083546', - }, - rctxt: - '37788128721284563440858950515231840450431543928224096081933216180465915572829884228780081835462293611329848268384962871736884632087015070623933628853658097637604059748079512999518737243304794110313829761155878287344472916564970806851294430356498883927870926898737394894892797927804721407643833828162246495645836390303263072281761384240973982733122383052566872688887552226083782030670443318152427129452272570595367287061688769394567289624972332234661767648489253220495098949161964171486245324730862072203259801377135500275012560207100571502032523912388082460843991502336467718632746396226650194750972544436894286230063', - z: '43785356695890052462955676926428400928903479009358861113206349419200366390858322895540291303484939601128045362682307382393826375825484851021601464391509750565285197155653613669680662395620338416776539485377195826876505126073018100680273457526216247879013350460071029101583221000647494610122617904515744711339846577920055655093367012508192004131719432915903924789974568341538556528133188398290594619318653419602058489178526243446782729272985727332736198326183868783570550373552407121582843992983431205917273352230155794805507408743590383242904107596623095433284330566906935063373759426916339149701872288610119965287995', - }, - revocation: { - g: '1 0A84C28144BC8B677839038FFFA824AB5ADE517F8DD4A89F092FAF9A3560C62D 1 00FD708E112EEA5D89AF9D0559795E6DBCF56D3B8CDF79EFF34A72EB741F896F 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8', - g_dash: - '1 201F3E23CC7E9284F3EFCF9500F1E2537C398EAB2E94D2EB801AECC7FBFBDC01 1 08132C7723CF9861D4CC24B56555EF1CBD9AE746C97B3ADFA36C669F2DCE09B6 1 1B2397FB2A1ADE704E2A1E4C242612F4677F9F1BD09E6B14C2E77E25EDA4C62E 1 00CDC2CF5F278D699D52223577AB032C150A3CB4C8E8AB07AB9D592772910E95 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000', - h: '1 072E0A505004F2F32B4210E72FA18A2ADF17F31479BD2059B7A8C0BA58F2ACB3 1 05C70F039E60317003C41C319753ECACC629791FDB06D6ADC5B06DD94501B973 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8', - h0: '1 03CBE26D18118E9770D4A0B3E8607B3B3A8D3D3CA81FF8D41862430CC583156E 1 004A2A57E0A826AEFF007EDDAF89B02F054050843689167B10127FE9EDEEEDA9 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8', - h1: '1 10C9F9DE537994E4FEF2625AFA78342C8A096238A875F6899DD500230E6022E5 1 0C0A88F53D020557377B4ED9C3826E9B8F918DD03E23B0F8ECD922F8333359D3 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8', - h2: '1 017F748AEEC1DDE4E4C3FBAE771C041F0A6FAEAF34FD02AF773AC4B75025147B 1 1298DBD9A4BEE6AD54E060A57BCE932735B7738C30A9ADAEFE2F38E1858A0183 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8', - htilde: - '1 0C471F0451D6AC352E28B6ECDE8D7233B75530AE59276DF0F4B9A8B0C5C7E5DB 1 24CE4461910AA5D60C09C24EE0FE51E1B1600D8BA6E483E9050EF897CA3E3C8A 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8', - h_cap: - '1 225B2106DEBD353AABDFC4C7F7E8660D308FB514EA9DAE0533DDEB65CF796159 1 1F6093622F439FC22C64F157F4F35F7C592EC0169C6F0026BC44CD3E375974A7 1 142126FAC3657AD846D394E1F72FD01ECC15E84416713CD133980E324B24F4BC 1 0357995DBDCD4385E59E607761AB30AE8D9DDE005A777EE846EF51AE2816CD33 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000', - u: '1 00D8DDC2EB6536CA320EE035D099937E59B11678162C1BFEB30C58FCA9F84650 1 1557A5B05A1A30D63322E187D323C9CA431BC5E811E68D4703933D9DDA26D299 1 10E8AB93AA87839B757521742EBA23C3B257C91F61A93D37AEC4C0A011B5F073 1 1DA65E40406A7875DA8CFCE9FD7F283145C166382A937B72819BDC335FE9A734 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000', - pk: '1 1A7EBBE3E7F8ED50959851364B20997944FA8AE5E3FC0A2BB531BAA17179D320 1 02C55FE6F64A2A4FF49B37C513C39E56ECD565CFAD6CA46DC6D8095179351863 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8', - y: '1 1BF97F07270EC21A89E43BCA645D86A755F846B547238F1DA379E088CDD9B40D 1 146BB00F56FFC0DEF6541CEB484C718559B398DB1547B52850E46B23144161F1 1 079A1BEF8DFFA4E6352F701D476664340E7FBE5D3F46B897412BD2B5F10E33D7 1 02FDC508AEF90FB11961AF332BE4037973C76B954FFA48848F7E0588E93FCA8C 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000', - }, -} diff --git a/packages/indy-sdk/tests/indy-did-registrar.e2e.test.ts b/packages/indy-sdk/tests/indy-did-registrar.e2e.test.ts deleted file mode 100644 index 04781e2e62..0000000000 --- a/packages/indy-sdk/tests/indy-did-registrar.e2e.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -import type { IndySdkIndyDidCreateOptions } from '../src' - -import { Agent, TypedArrayEncoder, convertPublicKeyToX25519, JsonTransformer } from '@aries-framework/core' -import { generateKeyPairFromSeed } from '@stablelib/ed25519' - -import { getAgentOptions, importExistingIndyDidFromPrivateKey, publicDidSeed } from '../../core/tests' -import { legacyIndyDidFromPublicKeyBase58 } from '../src/utils/did' - -import { getIndySdkModules } from './setupIndySdkModule' - -const agentOptions = getAgentOptions('Indy Sdk Indy Did Registrar', {}, getIndySdkModules()) -const agent = new Agent(agentOptions) - -describe('Indy SDK Indy Did Registrar', () => { - beforeAll(async () => { - await agent.initialize() - }) - - afterAll(async () => { - await agent.shutdown() - await agent.wallet.delete() - }) - - it('should create a did:indy did', async () => { - // Add existing endorser did to the wallet - const unqualifiedSubmitterDid = await importExistingIndyDidFromPrivateKey( - agent, - TypedArrayEncoder.fromString(publicDidSeed) - ) - - // Generate a seed and the indy did. This allows us to create a new did every time - // but still check if the created output document is as expected. - const privateKey = TypedArrayEncoder.fromString( - Array(32 + 1) - .join((Math.random().toString(36) + '00000000000000000').slice(2, 18)) - .slice(0, 32) - ) - - const publicKeyEd25519 = generateKeyPairFromSeed(privateKey).publicKey - const x25519PublicKeyBase58 = TypedArrayEncoder.toBase58(convertPublicKeyToX25519(publicKeyEd25519)) - const ed25519PublicKeyBase58 = TypedArrayEncoder.toBase58(publicKeyEd25519) - const unqualifiedDid = legacyIndyDidFromPublicKeyBase58(ed25519PublicKeyBase58) - - const did = await agent.dids.create({ - method: 'indy', - options: { - submitterDid: `did:indy:pool:localtest:${unqualifiedSubmitterDid}`, - alias: 'Alias', - endpoints: { - endpoint: 'https://example.com/endpoint', - types: ['DIDComm', 'did-communication', 'endpoint'], - routingKeys: ['a-routing-key'], - }, - }, - secret: { - privateKey, - }, - }) - - expect(JsonTransformer.toJSON(did)).toMatchObject({ - didDocumentMetadata: {}, - didRegistrationMetadata: {}, - didState: { - state: 'finished', - did: `did:indy:pool:localtest:${unqualifiedDid}`, - didDocument: { - '@context': [ - 'https://w3id.org/did/v1', - 'https://w3id.org/security/suites/ed25519-2018/v1', - 'https://w3id.org/security/suites/x25519-2019/v1', - 'https://didcomm.org/messaging/contexts/v2', - ], - alsoKnownAs: undefined, - controller: undefined, - verificationMethod: [ - { - id: `did:indy:pool:localtest:${unqualifiedDid}#verkey`, - type: 'Ed25519VerificationKey2018', - controller: `did:indy:pool:localtest:${unqualifiedDid}`, - publicKeyBase58: ed25519PublicKeyBase58, - }, - { - id: `did:indy:pool:localtest:${unqualifiedDid}#key-agreement-1`, - type: 'X25519KeyAgreementKey2019', - controller: `did:indy:pool:localtest:${unqualifiedDid}`, - publicKeyBase58: x25519PublicKeyBase58, - }, - ], - service: [ - { - id: `did:indy:pool:localtest:${unqualifiedDid}#endpoint`, - serviceEndpoint: 'https://example.com/endpoint', - type: 'endpoint', - }, - { - accept: ['didcomm/aip2;env=rfc19'], - id: `did:indy:pool:localtest:${unqualifiedDid}#did-communication`, - priority: 0, - recipientKeys: [`did:indy:pool:localtest:${unqualifiedDid}#key-agreement-1`], - routingKeys: ['a-routing-key'], - serviceEndpoint: 'https://example.com/endpoint', - type: 'did-communication', - }, - { - accept: ['didcomm/v2'], - id: `did:indy:pool:localtest:${unqualifiedDid}#didcomm-1`, - routingKeys: ['a-routing-key'], - serviceEndpoint: 'https://example.com/endpoint', - type: 'DIDComm', - }, - ], - authentication: [`did:indy:pool:localtest:${unqualifiedDid}#verkey`], - assertionMethod: undefined, - keyAgreement: [`did:indy:pool:localtest:${unqualifiedDid}#key-agreement-1`], - capabilityInvocation: undefined, - capabilityDelegation: undefined, - id: `did:indy:pool:localtest:${unqualifiedDid}`, - }, - secret: { - privateKey, - }, - }, - }) - }) -}) diff --git a/packages/indy-sdk/tests/indy-did-resolver.e2e.test.ts b/packages/indy-sdk/tests/indy-did-resolver.e2e.test.ts deleted file mode 100644 index 839db5e4df..0000000000 --- a/packages/indy-sdk/tests/indy-did-resolver.e2e.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { IndySdkIndyDidCreateOptions } from '../src' - -import { Agent, AriesFrameworkError, JsonTransformer, TypedArrayEncoder } from '@aries-framework/core' - -import { getAgentOptions, importExistingIndyDidFromPrivateKey, publicDidSeed } from '../../core/tests/helpers' - -import { getIndySdkModules } from './setupIndySdkModule' - -const agent = new Agent(getAgentOptions('Indy SDK Indy DID resolver', {}, getIndySdkModules())) - -describe('Indy SDK Indy DID resolver', () => { - beforeAll(async () => { - await agent.initialize() - }) - - afterAll(async () => { - await agent.shutdown() - await agent.wallet.delete() - }) - - it('should resolve a did:indy did', async () => { - // Add existing endorser did to the wallet - const unqualifiedSubmitterDid = await importExistingIndyDidFromPrivateKey( - agent, - TypedArrayEncoder.fromString(publicDidSeed) - ) - - const createResult = await agent.dids.create({ - method: 'indy', - options: { - submitterDid: `did:indy:pool:localtest:${unqualifiedSubmitterDid}`, - alias: 'Alias', - role: 'TRUSTEE', - endpoints: { - endpoint: 'http://localhost:3000', - }, - }, - }) - - // Terrible, but the did can't be immediately resolved, so we need to wait a bit - await new Promise((res) => setTimeout(res, 1000)) - - if (!createResult.didState.did) throw new AriesFrameworkError('Unable to register did') - - const didResult = await agent.dids.resolve(createResult.didState.did) - - expect(JsonTransformer.toJSON(didResult)).toMatchObject({ - didDocument: { - '@context': [ - 'https://w3id.org/did/v1', - 'https://w3id.org/security/suites/ed25519-2018/v1', - 'https://w3id.org/security/suites/x25519-2019/v1', - ], - id: createResult.didState.did, - alsoKnownAs: undefined, - controller: undefined, - verificationMethod: [ - { - type: 'Ed25519VerificationKey2018', - controller: createResult.didState.did, - id: `${createResult.didState.did}#verkey`, - publicKeyBase58: expect.any(String), - }, - { - controller: createResult.didState.did, - type: 'X25519KeyAgreementKey2019', - id: `${createResult.didState.did}#key-agreement-1`, - publicKeyBase58: expect.any(String), - }, - ], - capabilityDelegation: undefined, - capabilityInvocation: undefined, - authentication: [`${createResult.didState.did}#verkey`], - assertionMethod: undefined, - keyAgreement: [`${createResult.didState.did}#key-agreement-1`], - service: [ - { - id: `${createResult.didState.did}#endpoint`, - serviceEndpoint: 'http://localhost:3000', - type: 'endpoint', - }, - { - id: `${createResult.didState.did}#did-communication`, - accept: ['didcomm/aip2;env=rfc19'], - priority: 0, - recipientKeys: [`${createResult.didState.did}#key-agreement-1`], - routingKeys: [], - serviceEndpoint: 'http://localhost:3000', - type: 'did-communication', - }, - ], - }, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, - }) - }) -}) diff --git a/packages/indy-sdk/tests/indy-sdk-anoncreds-registry.e2e.test.ts b/packages/indy-sdk/tests/indy-sdk-anoncreds-registry.e2e.test.ts deleted file mode 100644 index 0efa8d533d..0000000000 --- a/packages/indy-sdk/tests/indy-sdk-anoncreds-registry.e2e.test.ts +++ /dev/null @@ -1,345 +0,0 @@ -import { Agent, Key, KeyType, TypedArrayEncoder } from '@aries-framework/core' - -import { - agentDependencies, - getAgentConfig, - importExistingIndyDidFromPrivateKey, - publicDidSeed, -} from '../../core/tests/helpers' -import { IndySdkAnonCredsRegistry } from '../src/anoncreds/services/IndySdkAnonCredsRegistry' -import { IndySdkPoolService } from '../src/ledger' - -import { credentialDefinitionValue } from './__fixtures__/anoncreds' -import { getIndySdkModules, indySdk } from './setupIndySdkModule' - -const agentConfig = getAgentConfig('IndySdkAnonCredsRegistry') -const indySdkModules = getIndySdkModules() - -const agent = new Agent({ - config: agentConfig, - dependencies: agentDependencies, - modules: indySdkModules, -}) - -const indySdkAnonCredsRegistry = new IndySdkAnonCredsRegistry() -const indySdkPoolService = agent.dependencyManager.resolve(IndySdkPoolService) -const pool = indySdkPoolService.getPoolForNamespace('pool:localtest') - -describe('IndySdkAnonCredsRegistry', () => { - beforeAll(async () => { - await agent.initialize() - - // We need to import the endorser did/key into the wallet - await importExistingIndyDidFromPrivateKey(agent, TypedArrayEncoder.fromString(publicDidSeed)) - }) - - afterAll(async () => { - await agent.shutdown() - await agent.wallet.delete() - }) - - // TODO: use different issuer for schema and credential definition to catch possible bugs - // One test as the credential definition depends on the schema - test('register and resolve a schema and credential definition', async () => { - const dynamicVersion = `1.${Math.random() * 100}` - - const legacyIssuerId = 'TL1EaPFCZ8Si5aUrqScBDt' - const signingKey = Key.fromPublicKeyBase58('FMGcFuU3QwAQLywxvmEnSorQT3NwU9wgDMMTaDFtvswm', KeyType.Ed25519) - const didIndyIssuerId = 'did:indy:pool:localtest:TL1EaPFCZ8Si5aUrqScBDt' - - const legacySchemaId = `TL1EaPFCZ8Si5aUrqScBDt:2:test:${dynamicVersion}` - const didIndySchemaId = `did:indy:pool:localtest:TL1EaPFCZ8Si5aUrqScBDt/anoncreds/v0/SCHEMA/test/${dynamicVersion}` - - const schemaResult = await indySdkAnonCredsRegistry.registerSchema(agent.context, { - schema: { - attrNames: ['name'], - issuerId: didIndyIssuerId, - name: 'test', - version: dynamicVersion, - }, - options: {}, - }) - - expect(schemaResult).toMatchObject({ - schemaState: { - state: 'finished', - schema: { - attrNames: ['name'], - issuerId: didIndyIssuerId, - name: 'test', - version: dynamicVersion, - }, - schemaId: didIndySchemaId, - }, - registrationMetadata: {}, - schemaMetadata: { - indyLedgerSeqNo: expect.any(Number), - }, - }) - - // Wait some time before resolving credential definition object - await new Promise((res) => setTimeout(res, 1000)) - - // Resolve using legacy schema id - const legacySchema = await indySdkAnonCredsRegistry.getSchema(agent.context, legacySchemaId) - expect(legacySchema).toMatchObject({ - schema: { - attrNames: ['name'], - name: 'test', - version: dynamicVersion, - issuerId: 'TL1EaPFCZ8Si5aUrqScBDt', - }, - schemaId: `TL1EaPFCZ8Si5aUrqScBDt:2:test:${dynamicVersion}`, - resolutionMetadata: {}, - schemaMetadata: { - didIndyNamespace: 'pool:localtest', - indyLedgerSeqNo: expect.any(Number), - }, - }) - - // Resolve using did indy schema id - const didIndySchema = await indySdkAnonCredsRegistry.getSchema(agent.context, didIndySchemaId) - expect(didIndySchema).toMatchObject({ - schema: { - attrNames: ['name'], - name: 'test', - version: dynamicVersion, - issuerId: didIndyIssuerId, - }, - schemaId: didIndySchemaId, - resolutionMetadata: {}, - schemaMetadata: { - didIndyNamespace: 'pool:localtest', - indyLedgerSeqNo: expect.any(Number), - }, - }) - - const legacyCredentialDefinitionId = `TL1EaPFCZ8Si5aUrqScBDt:3:CL:${schemaResult.schemaMetadata.indyLedgerSeqNo}:TAG` - const didIndyCredentialDefinitionId = `did:indy:pool:localtest:TL1EaPFCZ8Si5aUrqScBDt/anoncreds/v0/CLAIM_DEF/${schemaResult.schemaMetadata.indyLedgerSeqNo}/TAG` - const credentialDefinitionResult = await indySdkAnonCredsRegistry.registerCredentialDefinition(agent.context, { - credentialDefinition: { - issuerId: didIndyIssuerId, - tag: 'TAG', - schemaId: didIndySchemaId, - type: 'CL', - value: credentialDefinitionValue, - }, - options: {}, - }) - - expect(credentialDefinitionResult).toMatchObject({ - credentialDefinitionMetadata: {}, - credentialDefinitionState: { - credentialDefinition: { - issuerId: didIndyIssuerId, - tag: 'TAG', - schemaId: didIndySchemaId, - type: 'CL', - value: credentialDefinitionValue, - }, - credentialDefinitionId: didIndyCredentialDefinitionId, - state: 'finished', - }, - registrationMetadata: {}, - }) - - // Wait some time before resolving credential definition object - await new Promise((res) => setTimeout(res, 1000)) - - // Resolve using legacy credential definition id - const legacyCredentialDefinition = await indySdkAnonCredsRegistry.getCredentialDefinition( - agent.context, - legacyCredentialDefinitionId - ) - expect(legacyCredentialDefinition).toMatchObject({ - credentialDefinitionId: legacyCredentialDefinitionId, - credentialDefinition: { - issuerId: legacyIssuerId, - schemaId: legacySchemaId, - tag: 'TAG', - type: 'CL', - value: credentialDefinitionValue, - }, - credentialDefinitionMetadata: { - didIndyNamespace: 'pool:localtest', - }, - resolutionMetadata: {}, - }) - - // resolve using did indy credential definition id - const didIndyCredentialDefinition = await indySdkAnonCredsRegistry.getCredentialDefinition( - agent.context, - didIndyCredentialDefinitionId - ) - - expect(didIndyCredentialDefinition).toMatchObject({ - credentialDefinitionId: didIndyCredentialDefinitionId, - credentialDefinition: { - issuerId: didIndyIssuerId, - schemaId: didIndySchemaId, - tag: 'TAG', - type: 'CL', - value: credentialDefinitionValue, - }, - credentialDefinitionMetadata: { - didIndyNamespace: 'pool:localtest', - }, - resolutionMetadata: {}, - }) - - // We don't support creating a revocation registry using AFJ yet, so we directly use indy-sdk to register the revocation registry - const legacyRevocationRegistryId = `TL1EaPFCZ8Si5aUrqScBDt:4:TL1EaPFCZ8Si5aUrqScBDt:3:CL:${schemaResult.schemaMetadata.indyLedgerSeqNo}:TAG:CL_ACCUM:tag` - const didIndyRevocationRegistryId = `did:indy:pool:localtest:TL1EaPFCZ8Si5aUrqScBDt/anoncreds/v0/REV_REG_DEF/${schemaResult.schemaMetadata.indyLedgerSeqNo}/TAG/tag` - const revocationRegistryRequest = await indySdk.buildRevocRegDefRequest('TL1EaPFCZ8Si5aUrqScBDt', { - id: legacyRevocationRegistryId, - credDefId: legacyCredentialDefinitionId, - revocDefType: 'CL_ACCUM', - tag: 'tag', - value: { - issuanceType: 'ISSUANCE_BY_DEFAULT', - maxCredNum: 100, - publicKeys: { - accumKey: { - z: '1 1812B206EB395D3AEBD4BBF53EBB0FFC3371D8BD6175316AB32C1C5F65452051 1 22A079D49C5351EFDC1410C81A1F6D8B2E3B79CFF20A30690C118FE2050F72CB 1 0FFC28B923A4654E261DB4CB5B9BABEFCB4DB189B20F52412B0CC9CCCBB8A3B2 1 1EE967C43EF1A3F487061D21B07076A26C126AAF7712E7B5CF5A53688DDD5CC0 1 009ED4D65879CA81DA8227D34CEA3B759B4627E1E2FFB273E9645CD4F3B10F19 1 1CF070212E1E213AEB472F56EDFC9D48009796C77B2D8CC16F2836E37B8715C2 1 04954F0B7B468781BAAE3291DD0E6FFA7F1AF66CAA4094D37B24363CC34606FB 1 115367CB755E9DB18781B3825CB1AEE2C334558B2C038E13DF57BB57CE1CF847 1 110D37EC05862EE2757A7DF39E814876FC97376FF8105D2D29619CB575537BDE 1 13C559A9563FCE083B3B39AE7E8FCA4099BEF3A4C8C6672E543D521F9DA88F96 1 137D87CC22ACC1B6B8C20EABE59F6ED456A58FE4CBEEFDFC4FA9B87E3EF32D17 1 00A2A9711737AAF0404F35AE502887AC6172B2B57D236BD4A40B45F659BFC696', - }, - }, - tailsHash: 'HLKresYcDSZYSKogq8wive4zyXNY84669MygftLFBG1i', - tailsLocation: '/var/folders/l3/xy8jzyvj4p5_d9g1123rt4bw0000gn/T/HLKresYcDSZYSKogq8wive4zyXNY84669MygftLFBG1i', - }, - ver: '1.0', - }) - - await indySdkPoolService.submitWriteRequest(agent.context, pool, revocationRegistryRequest, signingKey) - - // indySdk.buildRevRegEntry panics, so we just pass a custom request directly - const entryResponse = await indySdkPoolService.submitWriteRequest( - agent.context, - pool, - { - identifier: legacyIssuerId, - operation: { - revocDefType: 'CL_ACCUM', - revocRegDefId: legacyRevocationRegistryId, - type: '114', - value: { - accum: - '1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000', - }, - }, - protocolVersion: 2, - reqId: Math.floor(Math.random() * 1000000), - }, - signingKey - ) - - const legacyRevocationRegistryDefinition = await indySdkAnonCredsRegistry.getRevocationRegistryDefinition( - agent.context, - legacyRevocationRegistryId - ) - expect(legacyRevocationRegistryDefinition).toMatchObject({ - revocationRegistryDefinitionId: legacyRevocationRegistryId, - revocationRegistryDefinition: { - issuerId: legacyIssuerId, - revocDefType: 'CL_ACCUM', - value: { - maxCredNum: 100, - tailsHash: 'HLKresYcDSZYSKogq8wive4zyXNY84669MygftLFBG1i', - tailsLocation: - '/var/folders/l3/xy8jzyvj4p5_d9g1123rt4bw0000gn/T/HLKresYcDSZYSKogq8wive4zyXNY84669MygftLFBG1i', - publicKeys: { - accumKey: { - z: '1 1812B206EB395D3AEBD4BBF53EBB0FFC3371D8BD6175316AB32C1C5F65452051 1 22A079D49C5351EFDC1410C81A1F6D8B2E3B79CFF20A30690C118FE2050F72CB 1 0FFC28B923A4654E261DB4CB5B9BABEFCB4DB189B20F52412B0CC9CCCBB8A3B2 1 1EE967C43EF1A3F487061D21B07076A26C126AAF7712E7B5CF5A53688DDD5CC0 1 009ED4D65879CA81DA8227D34CEA3B759B4627E1E2FFB273E9645CD4F3B10F19 1 1CF070212E1E213AEB472F56EDFC9D48009796C77B2D8CC16F2836E37B8715C2 1 04954F0B7B468781BAAE3291DD0E6FFA7F1AF66CAA4094D37B24363CC34606FB 1 115367CB755E9DB18781B3825CB1AEE2C334558B2C038E13DF57BB57CE1CF847 1 110D37EC05862EE2757A7DF39E814876FC97376FF8105D2D29619CB575537BDE 1 13C559A9563FCE083B3B39AE7E8FCA4099BEF3A4C8C6672E543D521F9DA88F96 1 137D87CC22ACC1B6B8C20EABE59F6ED456A58FE4CBEEFDFC4FA9B87E3EF32D17 1 00A2A9711737AAF0404F35AE502887AC6172B2B57D236BD4A40B45F659BFC696', - }, - }, - }, - tag: 'tag', - credDefId: legacyCredentialDefinitionId, - }, - revocationRegistryDefinitionMetadata: { - issuanceType: 'ISSUANCE_BY_DEFAULT', - didIndyNamespace: 'pool:localtest', - }, - resolutionMetadata: {}, - }) - - const didIndyRevocationRegistryDefinition = await indySdkAnonCredsRegistry.getRevocationRegistryDefinition( - agent.context, - didIndyRevocationRegistryId - ) - expect(didIndyRevocationRegistryDefinition).toMatchObject({ - revocationRegistryDefinitionId: didIndyRevocationRegistryId, - revocationRegistryDefinition: { - issuerId: didIndyIssuerId, - revocDefType: 'CL_ACCUM', - value: { - maxCredNum: 100, - tailsHash: 'HLKresYcDSZYSKogq8wive4zyXNY84669MygftLFBG1i', - tailsLocation: - '/var/folders/l3/xy8jzyvj4p5_d9g1123rt4bw0000gn/T/HLKresYcDSZYSKogq8wive4zyXNY84669MygftLFBG1i', - publicKeys: { - accumKey: { - z: '1 1812B206EB395D3AEBD4BBF53EBB0FFC3371D8BD6175316AB32C1C5F65452051 1 22A079D49C5351EFDC1410C81A1F6D8B2E3B79CFF20A30690C118FE2050F72CB 1 0FFC28B923A4654E261DB4CB5B9BABEFCB4DB189B20F52412B0CC9CCCBB8A3B2 1 1EE967C43EF1A3F487061D21B07076A26C126AAF7712E7B5CF5A53688DDD5CC0 1 009ED4D65879CA81DA8227D34CEA3B759B4627E1E2FFB273E9645CD4F3B10F19 1 1CF070212E1E213AEB472F56EDFC9D48009796C77B2D8CC16F2836E37B8715C2 1 04954F0B7B468781BAAE3291DD0E6FFA7F1AF66CAA4094D37B24363CC34606FB 1 115367CB755E9DB18781B3825CB1AEE2C334558B2C038E13DF57BB57CE1CF847 1 110D37EC05862EE2757A7DF39E814876FC97376FF8105D2D29619CB575537BDE 1 13C559A9563FCE083B3B39AE7E8FCA4099BEF3A4C8C6672E543D521F9DA88F96 1 137D87CC22ACC1B6B8C20EABE59F6ED456A58FE4CBEEFDFC4FA9B87E3EF32D17 1 00A2A9711737AAF0404F35AE502887AC6172B2B57D236BD4A40B45F659BFC696', - }, - }, - }, - tag: 'tag', - credDefId: didIndyCredentialDefinitionId, - }, - revocationRegistryDefinitionMetadata: { - issuanceType: 'ISSUANCE_BY_DEFAULT', - didIndyNamespace: 'pool:localtest', - }, - resolutionMetadata: {}, - }) - - const legacyRevocationStatusList = await indySdkAnonCredsRegistry.getRevocationStatusList( - agent.context, - legacyRevocationRegistryId, - entryResponse.result.txnMetadata.txnTime - ) - - expect(legacyRevocationStatusList).toMatchObject({ - resolutionMetadata: {}, - revocationStatusList: { - issuerId: legacyIssuerId, - currentAccumulator: - '1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000', - revRegDefId: legacyRevocationRegistryId, - revocationList: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - timestamp: entryResponse.result.txnMetadata.txnTime, - }, - revocationStatusListMetadata: { - didIndyNamespace: 'pool:localtest', - }, - }) - - const didIndyRevocationStatusList = await indySdkAnonCredsRegistry.getRevocationStatusList( - agent.context, - didIndyRevocationRegistryId, - entryResponse.result.txnMetadata.txnTime - ) - - expect(didIndyRevocationStatusList).toMatchObject({ - resolutionMetadata: {}, - revocationStatusList: { - issuerId: didIndyIssuerId, - currentAccumulator: - '1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 2 095E45DDF417D05FB10933FFC63D474548B7FFFF7888802F07FFFFFF7D07A8A8 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000 1 0000000000000000000000000000000000000000000000000000000000000000', - revRegDefId: didIndyRevocationRegistryId, - revocationList: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - timestamp: entryResponse.result.txnMetadata.txnTime, - }, - revocationStatusListMetadata: { - didIndyNamespace: 'pool:localtest', - }, - }) - }) -}) diff --git a/packages/indy-sdk/tests/postgres.e2e.test.ts b/packages/indy-sdk/tests/postgres.e2e.test.ts deleted file mode 100644 index a59359f9d8..0000000000 --- a/packages/indy-sdk/tests/postgres.e2e.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import type { SubjectMessage } from '../../../tests/transport/SubjectInboundTransport' -import type { ConnectionRecord } from '../../core/src/modules/connections' -import type { IndySdkPostgresStorageConfig } from '../../node/src' - -import { Subject } from 'rxjs' - -import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' -import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { Agent } from '../../core/src/agent/Agent' -import { HandshakeProtocol } from '../../core/src/modules/connections' -import { waitForBasicMessage, getPostgresAgentOptions } from '../../core/tests/helpers' -import { loadIndySdkPostgresPlugin, IndySdkPostgresWalletScheme } from '../../node/src' - -import { getIndySdkModules } from './setupIndySdkModule' - -const alicePostgresAgentOptions = getPostgresAgentOptions( - 'AgentsAlice', - { - endpoints: ['rxjs:alice'], - }, - getIndySdkModules() -) - -const bobPostgresAgentOptions = getPostgresAgentOptions( - 'AgentsBob', - { - endpoints: ['rxjs:bob'], - }, - getIndySdkModules() -) - -describe('postgres agents', () => { - let aliceAgent: Agent - let bobAgent: Agent - let aliceConnection: ConnectionRecord - - afterAll(async () => { - await bobAgent.shutdown() - await bobAgent.wallet.delete() - await aliceAgent.shutdown() - await aliceAgent.wallet.delete() - }) - - test('make a connection between postgres agents', async () => { - const aliceMessages = new Subject() - const bobMessages = new Subject() - - const subjectMap = { - 'rxjs:alice': aliceMessages, - 'rxjs:bob': bobMessages, - } - - const storageConfig: IndySdkPostgresStorageConfig = { - type: 'postgres_storage', - config: { - url: 'localhost:5432', - wallet_scheme: IndySdkPostgresWalletScheme.DatabasePerWallet, - }, - credentials: { - account: 'postgres', - password: 'postgres', - admin_account: 'postgres', - admin_password: 'postgres', - }, - } - - // loading the postgres wallet plugin - loadIndySdkPostgresPlugin(storageConfig.config, storageConfig.credentials) - - aliceAgent = new Agent(alicePostgresAgentOptions) - aliceAgent.registerInboundTransport(new SubjectInboundTransport(aliceMessages)) - aliceAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) - await aliceAgent.initialize() - - bobAgent = new Agent(bobPostgresAgentOptions) - bobAgent.registerInboundTransport(new SubjectInboundTransport(bobMessages)) - bobAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) - await bobAgent.initialize() - - const aliceBobOutOfBandRecord = await aliceAgent.oob.createInvitation({ - handshakeProtocols: [HandshakeProtocol.Connections], - }) - - const { connectionRecord: bobConnectionAtBobAlice } = await bobAgent.oob.receiveInvitation( - aliceBobOutOfBandRecord.outOfBandInvitation - ) - await bobAgent.connections.returnWhenIsConnected(bobConnectionAtBobAlice!.id) - - const [aliceConnectionAtAliceBob] = await aliceAgent.connections.findAllByOutOfBandId(aliceBobOutOfBandRecord.id) - aliceConnection = await aliceAgent.connections.returnWhenIsConnected(aliceConnectionAtAliceBob!.id) - }) - - test('send a message to connection', async () => { - const message = 'hello, world' - await aliceAgent.basicMessages.sendMessage(aliceConnection.id, message) - - const basicMessage = await waitForBasicMessage(bobAgent, { - content: message, - }) - - expect(basicMessage.content).toBe(message) - }) - - test('can shutdown and re-initialize the same postgres agent', async () => { - expect(aliceAgent.isInitialized).toBe(true) - await aliceAgent.shutdown() - expect(aliceAgent.isInitialized).toBe(false) - await aliceAgent.initialize() - expect(aliceAgent.isInitialized).toBe(true) - }) -}) diff --git a/packages/indy-sdk/tests/setup.ts b/packages/indy-sdk/tests/setup.ts deleted file mode 100644 index 34e38c9705..0000000000 --- a/packages/indy-sdk/tests/setup.ts +++ /dev/null @@ -1 +0,0 @@ -jest.setTimeout(120000) diff --git a/packages/indy-sdk/tests/setupIndySdkModule.ts b/packages/indy-sdk/tests/setupIndySdkModule.ts deleted file mode 100644 index f4a2ca8c59..0000000000 --- a/packages/indy-sdk/tests/setupIndySdkModule.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { DidsModule, utils } from '@aries-framework/core' -import indySdk from 'indy-sdk' - -import { genesisPath, taaVersion, taaAcceptanceMechanism } from '../../core/tests/helpers' -import { - IndySdkModule, - IndySdkModuleConfig, - IndySdkIndyDidRegistrar, - IndySdkSovDidResolver, - IndySdkIndyDidResolver, -} from '../src' - -export { indySdk } - -export const getIndySdkModuleConfig = () => - new IndySdkModuleConfig({ - indySdk, - networks: [ - { - id: `localhost-${utils.uuid()}`, - isProduction: false, - genesisPath, - indyNamespace: 'pool:localtest', - transactionAuthorAgreement: { version: taaVersion, acceptanceMechanism: taaAcceptanceMechanism }, - }, - ], - }) - -export const getIndySdkModules = () => ({ - indySdk: new IndySdkModule(getIndySdkModuleConfig()), - dids: new DidsModule({ - registrars: [new IndySdkIndyDidRegistrar()], - resolvers: [new IndySdkSovDidResolver(), new IndySdkIndyDidResolver()], - }), -}) diff --git a/packages/indy-sdk/tests/sov-did-resolver.e2e.test.ts b/packages/indy-sdk/tests/sov-did-resolver.e2e.test.ts deleted file mode 100644 index d4c2af8e38..0000000000 --- a/packages/indy-sdk/tests/sov-did-resolver.e2e.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { IndySdkIndyDidCreateOptions } from '../src' - -import { parseIndyDid } from '@aries-framework/anoncreds' -import { Agent, AriesFrameworkError, JsonTransformer, TypedArrayEncoder } from '@aries-framework/core' - -import { getAgentOptions, importExistingIndyDidFromPrivateKey, publicDidSeed } from '../../core/tests/helpers' - -import { getIndySdkModules } from './setupIndySdkModule' - -const agent = new Agent(getAgentOptions('Indy SDK Sov DID resolver', {}, getIndySdkModules())) - -describe('Indy SDK Sov DID resolver', () => { - beforeAll(async () => { - await agent.initialize() - }) - - afterAll(async () => { - await agent.shutdown() - await agent.wallet.delete() - }) - - test('resolve a did:sov did', async () => { - // Add existing endorser did to the wallet - const unqualifiedSubmitterDid = await importExistingIndyDidFromPrivateKey( - agent, - TypedArrayEncoder.fromString(publicDidSeed) - ) - - const createResult = await agent.dids.create({ - method: 'indy', - options: { - submitterDid: `did:indy:pool:localtest:${unqualifiedSubmitterDid}`, - alias: 'Alias', - role: 'TRUSTEE', - endpoints: { - endpoint: 'http://localhost:3000', - }, - }, - }) - - // Terrible, but the did can't be immediately resolved, so we need to wait a bit - await new Promise((res) => setTimeout(res, 1000)) - - if (!createResult.didState.did) throw new AriesFrameworkError('Unable to register did') - - const { namespaceIdentifier } = parseIndyDid(createResult.didState.did) - const sovDid = `did:sov:${namespaceIdentifier}` - const didResult = await agent.dids.resolve(sovDid) - - expect(JsonTransformer.toJSON(didResult)).toMatchObject({ - didDocument: { - '@context': [ - 'https://w3id.org/did/v1', - 'https://w3id.org/security/suites/ed25519-2018/v1', - 'https://w3id.org/security/suites/x25519-2019/v1', - ], - id: sovDid, - alsoKnownAs: undefined, - controller: undefined, - verificationMethod: [ - { - type: 'Ed25519VerificationKey2018', - controller: sovDid, - id: `${sovDid}#key-1`, - publicKeyBase58: expect.any(String), - }, - { - controller: sovDid, - type: 'X25519KeyAgreementKey2019', - id: `${sovDid}#key-agreement-1`, - publicKeyBase58: expect.any(String), - }, - ], - capabilityDelegation: undefined, - capabilityInvocation: undefined, - authentication: [`${sovDid}#key-1`], - assertionMethod: [`${sovDid}#key-1`], - keyAgreement: [`${sovDid}#key-agreement-1`], - service: [ - { - id: `${sovDid}#endpoint`, - serviceEndpoint: 'http://localhost:3000', - type: 'endpoint', - }, - { - id: `${sovDid}#did-communication`, - accept: ['didcomm/aip2;env=rfc19'], - priority: 0, - recipientKeys: [`${sovDid}#key-agreement-1`], - routingKeys: [], - serviceEndpoint: 'http://localhost:3000', - type: 'did-communication', - }, - ], - }, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, - }) - }) -}) diff --git a/packages/indy-sdk/tsconfig.build.json b/packages/indy-sdk/tsconfig.build.json deleted file mode 100644 index 2b75d0adab..0000000000 --- a/packages/indy-sdk/tsconfig.build.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "outDir": "./build" - }, - "include": ["src/**/*"] -} diff --git a/packages/indy-sdk/tsconfig.json b/packages/indy-sdk/tsconfig.json deleted file mode 100644 index 46efe6f721..0000000000 --- a/packages/indy-sdk/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "types": ["jest"] - } -} 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 e3dab42a4b..ffcb2519ab 100644 --- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts @@ -3,10 +3,10 @@ import type { Key } from '@aries-framework/core' import { TypedArrayEncoder, KeyType, SigningProviderRegistry } from '@aries-framework/core' import { GetNymRequest, NymRequest, SchemaRequest, CredentialDefinitionRequest } from '@hyperledger/indy-vdr-shared' +import { RegisteredAskarTestWallet } from '../../askar/tests/helpers' import { genesisTransactions, getAgentConfig, getAgentContext } from '../../core/tests/helpers' import testLogger from '../../core/tests/logger' -import { IndySdkWallet } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' +import { NodeFileSystem } from '../../node/src/NodeFileSystem' import { IndyVdrPool } from '../src/pool' import { IndyVdrPoolService } from '../src/pool/IndyVdrPoolService' import { indyDidFromPublicKeyBase58 } from '../src/utils/did' @@ -14,7 +14,7 @@ import { indyDidFromPublicKeyBase58 } from '../src/utils/did' import { indyVdrModuleConfig } from './helpers' const indyVdrPoolService = new IndyVdrPoolService(testLogger, indyVdrModuleConfig) -const wallet = new IndySdkWallet(indySdk, testLogger, new SigningProviderRegistry([])) +const wallet = new RegisteredAskarTestWallet(testLogger, new NodeFileSystem(), new SigningProviderRegistry([])) const agentConfig = getAgentConfig('IndyVdrPoolService') const agentContext = getAgentContext({ wallet, agentConfig }) diff --git a/packages/node/src/PostgresPlugin.ts b/packages/node/src/PostgresPlugin.ts deleted file mode 100644 index 22478d2b0a..0000000000 --- a/packages/node/src/PostgresPlugin.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { Library } from '@2060.io/ffi-napi' -import { types } from '@2060.io/ref-napi' -import fs from 'fs' -import os from 'os' -import path from 'path' - -const LIBNAME = 'indystrgpostgres' -const ENV_VAR = 'LIB_INDY_STRG_POSTGRES' - -type Platform = 'darwin' | 'linux' | 'win32' - -type ExtensionMap = Record - -const extensions: ExtensionMap = { - darwin: { prefix: 'lib', extension: '.dylib' }, - linux: { prefix: 'lib', extension: '.so' }, - win32: { extension: '.dll' }, -} - -const libPaths: Record> = { - darwin: ['/usr/local/lib/', '/usr/lib/', '/opt/homebrew/opt/'], - linux: ['/usr/lib/', '/usr/local/lib/'], - win32: ['c:\\windows\\system32\\'], -} - -// Alias for a simple function to check if the path exists -const doesPathExist = fs.existsSync - -const getLibrary = () => { - // Detect OS; darwin, linux and windows are only supported - const platform = os.platform() - - if (platform !== 'linux' && platform !== 'win32' && platform !== 'darwin') - throw new Error(`Unsupported platform: ${platform}. linux, win32 and darwin are supported.`) - - // Get a potential path from the environment variable - const pathFromEnvironment = process.env[ENV_VAR] - - // Get the paths specific to the users operating system - const platformPaths = libPaths[platform] - - // Check if the path from the environment variable is supplied and add it - // We use unshift here so that when we want to get a valid library path this will be the first to resolve - if (pathFromEnvironment) platformPaths.unshift(pathFromEnvironment) - - // Create the path + file - const libraries = platformPaths.map((p) => - path.join(p, `${extensions[platform].prefix ?? ''}${LIBNAME}${extensions[platform].extension}`) - ) - - // Gaurd so we quit if there is no valid path for the library - if (!libraries.some(doesPathExist)) - throw new Error(`Could not find ${LIBNAME} with these paths: ${libraries.join(' ')}`) - - // Get the first valid library - // Casting here as a string because there is a guard of none of the paths - // would be valid - const validLibraryPath = libraries.find((l) => doesPathExist(l)) as string - - return Library(validLibraryPath, { - postgresstorage_init: [types.int, []], - init_storagetype: [types.int, ['string', 'string']], - }) -} - -type NativeIndyPostgres = { - postgresstorage_init: () => number - init_storagetype: (arg0: string, arg1: string) => number -} - -let indyPostgresStorage: NativeIndyPostgres | undefined - -export interface IndySdkPostgresWalletStorageConfig { - url: string - wallet_scheme: IndySdkPostgresWalletScheme - path?: string -} - -export interface IndySdkPostgresWalletStorageCredentials { - account: string - password: string - admin_account: string - admin_password: string -} - -export enum IndySdkPostgresWalletScheme { - DatabasePerWallet = 'DatabasePerWallet', - MultiWalletSingleTable = 'MultiWalletSingleTable', - MultiWalletSingleTableSharedPool = 'MultiWalletSingleTableSharedPool', -} - -export interface IndySdkPostgresStorageConfig { - type: 'postgres_storage' - config: IndySdkPostgresWalletStorageConfig - credentials: IndySdkPostgresWalletStorageCredentials -} - -export function loadIndySdkPostgresPlugin( - config: IndySdkPostgresWalletStorageConfig, - credentials: IndySdkPostgresWalletStorageCredentials -) { - if (!indyPostgresStorage) { - indyPostgresStorage = getLibrary() - } - - indyPostgresStorage.postgresstorage_init() - indyPostgresStorage.init_storagetype(JSON.stringify(config), JSON.stringify(credentials)) -} diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index b457802722..a5ca793e14 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -4,7 +4,6 @@ import { EventEmitter } from 'events' import WebSocket from 'ws' import { NodeFileSystem } from './NodeFileSystem' -import { IndySdkPostgresStorageConfig, loadIndySdkPostgresPlugin, IndySdkPostgresWalletScheme } from './PostgresPlugin' import { HttpInboundTransport } from './transport/HttpInboundTransport' import { WsInboundTransport } from './transport/WsInboundTransport' @@ -15,11 +14,4 @@ const agentDependencies: AgentDependencies = { WebSocketClass: WebSocket, } -export { - agentDependencies, - HttpInboundTransport, - WsInboundTransport, - loadIndySdkPostgresPlugin, - IndySdkPostgresStorageConfig, - IndySdkPostgresWalletScheme, -} +export { agentDependencies, HttpInboundTransport, WsInboundTransport } diff --git a/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts b/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts index 4a21491d36..4e9364bcf9 100644 --- a/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts +++ b/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts @@ -5,9 +5,9 @@ import { EventEmitter, SigningProviderRegistry, InboundMessageContext, DidExchan import { agentDependencies } from '@aries-framework/node' import { Subject } from 'rxjs' +import { RegisteredAskarTestWallet } from '../../../askar/tests/helpers' import { getAgentConfig, getAgentContext, getMockConnection, mockFunction } from '../../../core/tests/helpers' -import { IndySdkWallet } from '../../../indy-sdk/src' -import { indySdk } from '../../../indy-sdk/tests/setupIndySdkModule' +import { NodeFileSystem } from '../../../node/src/NodeFileSystem' import { QuestionAnswerRecord, @@ -61,7 +61,7 @@ describe('QuestionAnswerService', () => { beforeAll(async () => { agentConfig = getAgentConfig('QuestionAnswerServiceTest') - wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) + wallet = new RegisteredAskarTestWallet(agentConfig.logger, new NodeFileSystem(), new SigningProviderRegistry([])) agentContext = getAgentContext() // eslint-disable-next-line @typescript-eslint/no-non-null-assertion await wallet.createAndOpen(agentConfig.walletConfig!) diff --git a/packages/question-answer/tests/question-answer.e2e.test.ts b/packages/question-answer/tests/question-answer.e2e.test.ts index af3373de88..37e3d11fde 100644 --- a/packages/question-answer/tests/question-answer.e2e.test.ts +++ b/packages/question-answer/tests/question-answer.e2e.test.ts @@ -2,8 +2,8 @@ import type { ConnectionRecord } from '@aries-framework/core' import { Agent } from '@aries-framework/core' -import { indySdk, setupSubjectTransports, testLogger, getAgentOptions, makeConnection } from '../../core/tests' -import { IndySdkModule } from '../../indy-sdk/src' +import { askarModule } from '../../askar/tests/helpers' +import { setupSubjectTransports, testLogger, getAgentOptions, makeConnection } from '../../core/tests' import { waitForQuestionAnswerRecord } from './helpers' @@ -11,9 +11,7 @@ import { QuestionAnswerModule, QuestionAnswerRole, QuestionAnswerState } from '@ const modules = { questionAnswer: new QuestionAnswerModule(), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, } const bobAgentOptions = getAgentOptions( diff --git a/packages/react-native/jest.config.ts b/packages/react-native/jest.config.ts index 6426c5d8b8..2556d19c61 100644 --- a/packages/react-native/jest.config.ts +++ b/packages/react-native/jest.config.ts @@ -7,10 +7,6 @@ import packageJson from './package.json' const config: Config.InitialOptions = { ...base, displayName: packageJson.name, - moduleNameMapper: { - ...base.moduleNameMapper, - 'indy-sdk-react-native': 'indy-sdk', - }, } export default config diff --git a/yarn.lock b/yarn.lock index 2afc180e9f..e7d386a4ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,6 +32,20 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@aries-framework/indy-sdk@*", "@aries-framework/indy-sdk@0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@aries-framework/indy-sdk/-/indy-sdk-0.4.2.tgz#ec6a6a97e200390d5759575612922ae44bac62f8" + integrity sha512-ne+SnDTpNQ4bQYYpyYhF0W7c5dlG/UVIdUysFgz/ZTD78tsc+Z7EiXnbz5gKVbqqgxpjiHfNsb4SQJcNUBy8bQ== + dependencies: + "@aries-framework/anoncreds" "0.4.2" + "@aries-framework/core" "0.4.2" + "@stablelib/ed25519" "^1.0.3" + "@types/indy-sdk" "1.16.27" + class-transformer "0.5.1" + class-validator "0.14.0" + rxjs "^7.2.0" + tsyringe "^4.8.0" + "@azure/core-asynciterator-polyfill@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz#0dd3849fb8d97f062a39db0e5cadc9ffaf861fec" From dd390fbb5708271223b24221b99151f950d68391 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Tue, 7 Nov 2023 12:37:55 +0700 Subject: [PATCH 02/19] refactor: remove indy-sdk Signed-off-by: Timo Glastra --- Dockerfile | 66 +----- demo/package.json | 2 +- demo/src/Alice.ts | 2 +- demo/src/BaseAgent.ts | 13 +- demo/src/Faber.ts | 2 +- package.json | 2 +- .../action-menu/tests/action-menu.e2e.test.ts | 8 +- packages/anoncreds-rs/package.json | 6 +- packages/anoncreds-rs/src/index.ts | 1 + .../legacy-indy-format-services.test.ts | 73 +++--- .../v1-connectionless-proofs.e2e.test.ts | 10 +- .../src/updates/__tests__/0.3.test.ts | 15 +- .../tests/InMemoryAnonCredsRegistry.ts | 5 +- packages/anoncreds/tests/anoncreds.test.ts | 11 +- .../anoncreds/tests/legacyAnonCredsSetup.ts | 63 +---- .../tests/bbs-signatures.e2e.test.ts | 11 +- .../tests/bbs-signing-provider.e2e.test.ts | 10 +- packages/core/src/agent/Agent.ts | 4 +- .../core/src/agent/__tests__/Agent.test.ts | 8 +- .../signature/SignatureDecoratorUtils.test.ts | 11 +- .../__tests__/basic-messages.e2e.test.ts | 6 +- .../__tests__/ConnectionService.test.ts | 10 +- .../__tests__/connection-manual.e2e.test.ts | 8 +- .../v2-connectionless-credentials.e2e.test.ts | 6 +- ...f.credentials.propose-offerED25519.test.ts | 38 +-- .../oob/__tests__/implicit.e2e.test.ts | 40 +++- .../v2-indy-connectionless-proofs.e2e.test.ts | 8 +- .../routing/__tests__/mediation.test.ts | 8 +- .../vc/__tests__/W3cCredentialService.test.ts | 10 +- .../vc/__tests__/W3cCredentialsApi.test.ts | 8 +- .../W3cJsonLdCredentialService.test.ts | 11 +- .../storage/migration/__tests__/0.1.test.ts | 24 +- .../storage/migration/__tests__/0.2.test.ts | 19 +- .../storage/migration/__tests__/0.3.test.ts | 9 +- .../__tests__/UpdateAssistant.test.ts | 9 +- .../migration/__tests__/backup.test.ts | 4 +- packages/core/tests/agents.test.ts | 6 +- packages/core/tests/connections.test.ts | 10 +- packages/core/tests/generic-records.test.ts | 4 +- packages/core/tests/helpers.ts | 45 +--- packages/core/tests/index.ts | 1 - packages/core/tests/indySdk.ts | 3 - packages/core/tests/jsonld.ts | 7 +- packages/core/tests/migration.test.ts | 4 +- .../core/tests/multi-protocol-version.test.ts | 6 +- .../tests/oob-mediation-provision.test.ts | 8 +- packages/core/tests/oob-mediation.test.ts | 8 +- packages/core/tests/oob.test.ts | 10 +- packages/core/tests/wallet.test.ts | 6 +- .../indy-sdk-to-askar-migration/package.json | 2 - .../src/IndySdkToAskarMigrationUpdater.ts | 2 +- .../tests/indy-sdk-040-wallet.db | Bin 0 -> 57344 bytes .../tests/migrate.test.ts | 87 +++---- .../src/anoncreds/IndyVdrAnonCredsRegistry.ts | 8 +- .../src/anoncreds/utils/identifiers.ts | 5 - .../__tests__/IndyVdrIndyDidRegistrar.test.ts | 10 +- .../indy-vdr-anoncreds-registry.e2e.test.ts | 11 +- .../tests/indy-vdr-did-registrar.e2e.test.ts | 11 +- .../indy-vdr-indy-did-resolver.e2e.test.ts | 7 +- .../indy-vdr-sov-did-resolver.e2e.test.ts | 7 +- .../tenants/src/__tests__/TenantAgent.test.ts | 5 +- .../tenants/src/__tests__/TenantsApi.test.ts | 6 +- .../tenants/tests/tenant-sessions.e2e.test.ts | 6 +- packages/tenants/tests/tenants.e2e.test.ts | 8 +- samples/extension-module/package.json | 4 +- .../extension-module/tests/dummy.e2e.test.ts | 8 +- ...> e2e-askar-indy-vdr-anoncreds-rs.test.ts} | 9 +- tests/e2e-http.test.ts | 8 +- tests/e2e-subject.test.ts | 8 +- tests/e2e-ws-pickup-v2.test.ts | 8 +- tests/e2e-ws.test.ts | 8 +- yarn.lock | 216 ++---------------- 72 files changed, 350 insertions(+), 753 deletions(-) delete mode 100644 packages/core/tests/indySdk.ts create mode 100644 packages/indy-sdk-to-askar-migration/tests/indy-sdk-040-wallet.db rename tests/{e2e-askar-indy-sdk-wallet-subject.test.ts => e2e-askar-indy-vdr-anoncreds-rs.test.ts} (94%) diff --git a/Dockerfile b/Dockerfile index c89fc3504d..83236c6e63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,66 +1,4 @@ -## Stage 1: Build indy-sdk and postgres plugin - -FROM ubuntu:22.04 as base - -# Set this value only during build -ARG DEBIAN_FRONTEND noninteractive - -# Define packages to install -ENV PACKAGES software-properties-common ca-certificates \ - curl build-essential git \ - libzmq3-dev libsodium-dev pkg-config gnupg - -# Combined update and install to ensure Docker caching works correctly -RUN apt-get update -y \ - && apt-get install -y $PACKAGES - -RUN curl http://security.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1-1ubuntu2.1~18.04.23_amd64.deb -o libssl1.1.deb \ - # libssl1.1 (required by libindy) - && dpkg -i libssl1.1.deb \ - && curl http://security.ubuntu.com/ubuntu/pool/main/o/openssl/libssl-dev_1.1.1-1ubuntu2.1~18.04.23_amd64.deb -o libssl-dev1.1.deb \ - # libssl-dev1.1 (required to compile libindy with posgres plugin) - && dpkg -i libssl-dev1.1.deb - -# Add APT sources -RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CE7709D068DB5E88 \ - && add-apt-repository "deb https://repo.sovrin.org/sdk/deb bionic stable" \ - && mkdir -p /etc/apt/keyrings \ - && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ - && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \ - && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ - && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list - -# Install libindy, NodeJS and yarn -RUN apt-get update -y \ - # Install libindy - && apt-get install -y --allow-unauthenticated libindy \ - && apt-get install -y nodejs \ - && apt-get install -y --no-install-recommends yarn \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean -y - -# postgres plugin setup -# install rust and set up rustup -RUN curl https://sh.rustup.rs -sSf | bash -s -- -y -ENV PATH="/root/.cargo/bin:${PATH}" - -# cargo build failing on latest release of rust due to socket2 dependency in the plugin https://users.rust-lang.org/t/build-broken-with-parse-quote-spanned-is-ambiguous/80280/2 so pointing rust version to 1.63.0 -RUN rustup default 1.63.0 - -# clone indy-sdk and build postgres plugin -RUN git clone https://github.com/hyperledger/indy-sdk.git -WORKDIR /indy-sdk/experimental/plugins/postgres_storage/ -RUN cargo build --release - -# set up library path for postgres plugin -ENV LIB_INDY_STRG_POSTGRES="/indy-sdk/experimental/plugins/postgres_storage/target/release" - -## Stage 2: Build Aries Framework JavaScript - -FROM base as final - -# Set environment variables -ENV RUN_MODE="docker" +FROM node:18 # Set working directory WORKDIR /www @@ -71,3 +9,5 @@ COPY . . # Run yarn install and build RUN yarn install --frozen-lockfile \ && yarn build + +entrypoint ["yarn", "run-mediator"] \ No newline at end of file diff --git a/demo/package.json b/demo/package.json index 096f60cfbd..61cca53f31 100644 --- a/demo/package.json +++ b/demo/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@hyperledger/indy-vdr-nodejs": "^0.2.0-dev.5", - "@hyperledger/anoncreds-nodejs": "^0.2.0-dev.4", + "@hyperledger/anoncreds-nodejs": "^0.2.0-dev.5", "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1", "inquirer": "^8.2.5" }, diff --git a/demo/src/Alice.ts b/demo/src/Alice.ts index 2de378d8c1..9052654925 100644 --- a/demo/src/Alice.ts +++ b/demo/src/Alice.ts @@ -8,7 +8,7 @@ export class Alice extends BaseAgent { public connectionRecordFaberId?: string public constructor(port: number, name: string) { - super({ port, name, useLegacyIndySdk: true }) + super({ port, name }) this.connected = false } diff --git a/demo/src/BaseAgent.ts b/demo/src/BaseAgent.ts index 8c174a7fe6..67f5e274cd 100644 --- a/demo/src/BaseAgent.ts +++ b/demo/src/BaseAgent.ts @@ -58,17 +58,8 @@ export class BaseAgent { public name: string public config: InitConfig public agent: DemoAgent - public useLegacyIndySdk: boolean - public constructor({ - port, - name, - useLegacyIndySdk = false, - }: { - port: number - name: string - useLegacyIndySdk?: boolean - }) { + public constructor({ port, name }: { port: number; name: string }) { this.name = name this.port = port @@ -83,8 +74,6 @@ export class BaseAgent { this.config = config - this.useLegacyIndySdk = useLegacyIndySdk - this.agent = new Agent({ config, dependencies: agentDependencies, diff --git a/demo/src/Faber.ts b/demo/src/Faber.ts index 91befb8918..c8c454ec96 100644 --- a/demo/src/Faber.ts +++ b/demo/src/Faber.ts @@ -24,7 +24,7 @@ export class Faber extends BaseAgent { public ui: BottomBar public constructor(port: number, name: string) { - super({ port, name, useLegacyIndySdk: true }) + super({ port, name }) this.ui = new ui.BottomBar() } diff --git a/package.json b/package.json index 7a6f393934..376b186055 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "node": ">=18" }, "dependencies": { - "@hyperledger/aries-askar-nodejs": "^0.1.0" + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1" } } diff --git a/packages/action-menu/tests/action-menu.e2e.test.ts b/packages/action-menu/tests/action-menu.e2e.test.ts index a32b13df49..6737aaed69 100644 --- a/packages/action-menu/tests/action-menu.e2e.test.ts +++ b/packages/action-menu/tests/action-menu.e2e.test.ts @@ -2,8 +2,8 @@ import type { ConnectionRecord } from '@aries-framework/core' import { Agent } from '@aries-framework/core' -import { getAgentOptions, makeConnection, testLogger, setupSubjectTransports, indySdk } from '../../core/tests' -import { IndySdkModule } from '../../indy-sdk/src' +import { askarModule } from '../../askar/tests/helpers' +import { getAgentOptions, makeConnection, testLogger, setupSubjectTransports } from '../../core/tests' import { waitForActionMenuRecord } from './helpers' @@ -17,9 +17,7 @@ import { const modules = { actionMenu: new ActionMenuModule(), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, } const faberAgentOptions = getAgentOptions( diff --git a/packages/anoncreds-rs/package.json b/packages/anoncreds-rs/package.json index aaafaf228d..494d899a09 100644 --- a/packages/anoncreds-rs/package.json +++ b/packages/anoncreds-rs/package.json @@ -32,8 +32,8 @@ "tsyringe": "^4.8.0" }, "devDependencies": { - "@hyperledger/anoncreds-nodejs": "^0.2.0-dev.4", - "@hyperledger/anoncreds-shared": "^0.2.0-dev.4", + "@hyperledger/anoncreds-nodejs": "^0.2.0-dev.5", + "@hyperledger/anoncreds-shared": "^0.2.0-dev.5", "@types/ref-array-di": "^1.2.6", "@types/ref-struct-di": "^1.1.10", "reflect-metadata": "^0.1.13", @@ -41,6 +41,6 @@ "typescript": "~4.9.5" }, "peerDependencies": { - "@hyperledger/anoncreds-shared": "^0.2.0-dev.4" + "@hyperledger/anoncreds-shared": "^0.2.0-dev.5" } } diff --git a/packages/anoncreds-rs/src/index.ts b/packages/anoncreds-rs/src/index.ts index 5fdd9486c7..952884c8c5 100644 --- a/packages/anoncreds-rs/src/index.ts +++ b/packages/anoncreds-rs/src/index.ts @@ -3,3 +3,4 @@ export * from './services' // Module export { AnonCredsRsModule } from './AnonCredsRsModule' +export { AnonCredsRsModuleConfig } from './AnonCredsRsModuleConfig' diff --git a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts index a05a6d4199..7aa3dcf564 100644 --- a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts +++ b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts @@ -10,20 +10,20 @@ import { ProofState, EventEmitter, } from '@aries-framework/core' -import * as indySdk from 'indy-sdk' import { Subject } from 'rxjs' -import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' import { - IndySdkHolderService, - IndySdkIssuerService, - IndySdkModuleConfig, - IndySdkStorageService, - IndySdkVerifierService, - IndySdkWallet, -} from '../../../../indy-sdk/src' -import { IndySdkRevocationService } from '../../../../indy-sdk/src/anoncreds/services/IndySdkRevocationService' -import { legacyIndyDidFromPublicKeyBase58 } from '../../../../indy-sdk/src/utils/did' + AnonCredsRsHolderService, + AnonCredsRsIssuerService, + AnonCredsRsModuleConfig, + AnonCredsRsVerifierService, +} from '../../../../anoncreds-rs/src' +import { anoncreds } from '../../../../anoncreds-rs/tests/helpers' +import { AskarStorageService } from '../../../../askar/src' +import { AskarModuleConfig } from '../../../../askar/src/AskarModuleConfig' +import { askarModuleConfig, RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' +import { indyDidFromPublicKeyBase58 } from '../../../../core/src/utils/did' +import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' import { InMemoryAnonCredsRegistry } from '../../../tests/InMemoryAnonCredsRegistry' import { AnonCredsModuleConfig } from '../../AnonCredsModuleConfig' import { AnonCredsLinkSecretRecord, AnonCredsLinkSecretRepository } from '../../repository' @@ -48,12 +48,15 @@ const anonCredsModuleConfig = new AnonCredsModuleConfig({ }) const agentConfig = getAgentConfig('LegacyIndyFormatServicesTest') -const anonCredsRevocationService = new IndySdkRevocationService(indySdk) -const anonCredsVerifierService = new IndySdkVerifierService(indySdk) -const anonCredsHolderService = new IndySdkHolderService(anonCredsRevocationService, indySdk) -const anonCredsIssuerService = new IndySdkIssuerService(indySdk) -const wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) -const storageService = new IndySdkStorageService(indySdk) +const anonCredsVerifierService = new AnonCredsRsVerifierService() +const anonCredsHolderService = new AnonCredsRsHolderService() +const anonCredsIssuerService = new AnonCredsRsIssuerService() +const wallet = new RegisteredAskarTestWallet( + agentConfig.logger, + new agentDependencies.FileSystem(), + new SigningProviderRegistry([]) +) +const storageService = new AskarStorageService() const eventEmitter = new EventEmitter(agentDependencies, new Subject()) const anonCredsLinkSecretRepository = new AnonCredsLinkSecretRepository(storageService, eventEmitter) const agentContext = getAgentContext({ @@ -64,7 +67,14 @@ const agentContext = getAgentContext({ [AnonCredsRegistryService, new AnonCredsRegistryService()], [AnonCredsModuleConfig, anonCredsModuleConfig], [AnonCredsLinkSecretRepository, anonCredsLinkSecretRepository], - [IndySdkModuleConfig, new IndySdkModuleConfig({ indySdk, autoCreateLinkSecret: false })], + [AskarModuleConfig, askarModuleConfig], + [ + AnonCredsRsModuleConfig, + new AnonCredsRsModuleConfig({ + anoncreds, + autoCreateLinkSecret: false, + }), + ], ], agentConfig, wallet, @@ -87,7 +97,7 @@ describe('Legacy indy format services', () => { test('issuance and verification flow starting from proposal without negotiation and without revocation', async () => { // This is just so we don't have to register an actual indy did (as we don't have the indy did registrar configured) const key = await wallet.createKey({ keyType: KeyType.Ed25519 }) - const unqualifiedIndyDid = legacyIndyDidFromPublicKeyBase58(key.publicKeyBase58) + const unqualifiedIndyDid = indyDidFromPublicKeyBase58(key.publicKeyBase58) const indyDid = `did:indy:pool1:${unqualifiedIndyDid}` // Create link secret @@ -107,27 +117,18 @@ describe('Legacy indy format services', () => { version: '1.0.0', }) - const { schemaState, schemaMetadata } = await registry.registerSchema(agentContext, { + const { schemaState } = await registry.registerSchema(agentContext, { schema, options: {}, }) - const { credentialDefinition } = await anonCredsIssuerService.createCredentialDefinition( - agentContext, - { - issuerId: indyDid, - schemaId: schemaState.schemaId as string, - schema, - tag: 'Employee Credential', - supportRevocation: false, - }, - { - // NOTE: indy-sdk support has been removed from main repo, but keeping - // this in place to allow the indy-sdk to still be used as a custom package - // Need to pass this as the indy-sdk MUST have the seqNo - indyLedgerSchemaSeqNo: schemaMetadata.indyLedgerSeqNo as number, - } - ) + const { credentialDefinition } = await anonCredsIssuerService.createCredentialDefinition(agentContext, { + issuerId: indyDid, + schemaId: schemaState.schemaId as string, + schema, + tag: 'Employee Credential', + supportRevocation: false, + }) const { credentialDefinitionState } = await registry.registerCredentialDefinition(agentContext, { credentialDefinition, diff --git a/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts b/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts index 57127b9269..b06b6af89b 100644 --- a/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts +++ b/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts @@ -5,6 +5,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../../tests/transport/SubjectOutboundTransport' +import { askarModule } from '../../../../../../askar/tests/helpers' import { CredentialEventTypes, Agent, @@ -27,9 +28,8 @@ import { makeConnection, setupEventReplaySubjects, } from '../../../../../../core/tests' -import { getIndySdkModules } from '../../../../../../indy-sdk/tests/setupIndySdkModule' import { - getLegacyAnonCredsModules, + getAskarAnonCredsIndyModules, issueLegacyAnonCredsCredential, prepareForAnonCredsIssuance, setupAnonCredsTests, @@ -365,7 +365,7 @@ describe('V1 Proofs - Connectionless - Indy', () => { endpoints: ['rxjs:mediator'], }, { - ...getIndySdkModules(), + askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true, }), @@ -395,7 +395,7 @@ describe('V1 Proofs - Connectionless - Indy', () => { `Connectionless proofs with mediator Faber-${unique}`, {}, { - ...getLegacyAnonCredsModules({ + ...getAskarAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ @@ -411,7 +411,7 @@ describe('V1 Proofs - Connectionless - Indy', () => { `Connectionless proofs with mediator Alice-${unique}`, {}, { - ...getLegacyAnonCredsModules({ + ...getAskarAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ diff --git a/packages/anoncreds/src/updates/__tests__/0.3.test.ts b/packages/anoncreds/src/updates/__tests__/0.3.test.ts index 7ad829c3f9..a2542f7694 100644 --- a/packages/anoncreds/src/updates/__tests__/0.3.test.ts +++ b/packages/anoncreds/src/updates/__tests__/0.3.test.ts @@ -3,9 +3,8 @@ import { readFileSync } from 'fs' import path from 'path' import { InMemoryStorageService } from '../../../../../tests/InMemoryStorageService' -import { indySdk, agentDependencies } from '../../../../core/tests' -import { IndySdkWallet } from '../../../../indy-sdk/src' -import { IndySdkSymbol } from '../../../../indy-sdk/src/types' +import { RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' +import { agentDependencies } from '../../../../core/tests' import { InMemoryAnonCredsRegistry } from '../../../tests/InMemoryAnonCredsRegistry' import { AnonCredsModule } from '../../AnonCredsModule' import { @@ -32,9 +31,8 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) dependencyManager.registerInstance(AnonCredsIssuerServiceSymbol, {}) dependencyManager.registerInstance(AnonCredsHolderServiceSymbol, {}) dependencyManager.registerInstance(AnonCredsVerifierServiceSymbol, {}) @@ -108,9 +106,8 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) dependencyManager.registerInstance(AnonCredsIssuerServiceSymbol, {}) dependencyManager.registerInstance(AnonCredsHolderServiceSymbol, {}) dependencyManager.registerInstance(AnonCredsVerifierServiceSymbol, {}) diff --git a/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts b/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts index 9cb3a9adf3..00919127bf 100644 --- a/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts +++ b/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts @@ -19,7 +19,7 @@ import type { AgentContext } from '@aries-framework/core' import { Hasher, TypedArrayEncoder } from '@aries-framework/core' import BigNumber from 'bn.js' -import { getDidIndyCredentialDefinitionId, getDidIndySchemaId } from '../../indy-sdk/src/anoncreds/utils/identifiers' +import { getDidIndyCredentialDefinitionId, getDidIndySchemaId } from '../../indy-vdr/src/anoncreds/utils/identifiers' import { getUnqualifiedCredentialDefinitionId, getUnqualifiedSchemaId, parseIndyDid, parseIndySchemaId } from '../src' /** @@ -28,9 +28,6 @@ import { getUnqualifiedCredentialDefinitionId, getUnqualifiedSchemaId, parseIndy export class InMemoryAnonCredsRegistry implements AnonCredsRegistry { public readonly methodName = 'inMemory' - // Roughly match that the identifier starts with an unqualified indy did. Once the - // anoncreds tests are not based on the indy-sdk anymore, we can use any identifier - // we want, but the indy-sdk is picky about the identifier format. public readonly supportedIdentifier = /.+/ private schemas: Record diff --git a/packages/anoncreds/tests/anoncreds.test.ts b/packages/anoncreds/tests/anoncreds.test.ts index d56dc4b630..5778a8d737 100644 --- a/packages/anoncreds/tests/anoncreds.test.ts +++ b/packages/anoncreds/tests/anoncreds.test.ts @@ -1,8 +1,9 @@ import { Agent, KeyDerivationMethod, KeyType, TypedArrayEncoder } from '@aries-framework/core' import { agentDependencies } from '@aries-framework/node' -import * as indySdk from 'indy-sdk' -import { IndySdkModule } from '../../indy-sdk/src/IndySdkModule' +import { AnonCredsRsModule } from '../../anoncreds-rs/src' +import { anoncreds } from '../../anoncreds-rs/tests/helpers' +import { askarModule } from '../../askar/tests/helpers' import { AnonCredsModule } from '../src' import { InMemoryAnonCredsRegistry } from './InMemoryAnonCredsRegistry' @@ -81,10 +82,8 @@ const agent = new Agent({ }, }, modules: { - indySdk: new IndySdkModule({ - indySdk, - autoCreateLinkSecret: false, - }), + anoncredsRs: new AnonCredsRsModule({ anoncreds, autoCreateLinkSecret: false }), + askar: askarModule, anoncreds: new AnonCredsModule({ registries: [ new InMemoryAnonCredsRegistry({ diff --git a/packages/anoncreds/tests/legacyAnonCredsSetup.ts b/packages/anoncreds/tests/legacyAnonCredsSetup.ts index 39e9b53c47..366089c3cd 100644 --- a/packages/anoncreds/tests/legacyAnonCredsSetup.ts +++ b/packages/anoncreds/tests/legacyAnonCredsSetup.ts @@ -44,14 +44,6 @@ import { waitForProofExchangeRecordSubject, } from '../../core/tests/helpers' import testLogger from '../../core/tests/logger' -import { - IndySdkAnonCredsRegistry, - IndySdkIndyDidRegistrar, - IndySdkIndyDidResolver, - IndySdkModule, - IndySdkSovDidResolver, -} from '../../indy-sdk/src' -import { getIndySdkModuleConfig } from '../../indy-sdk/tests/setupIndySdkModule' import { IndyVdrAnonCredsRegistry, IndyVdrSovDidResolver, @@ -73,52 +65,9 @@ import { } from '../src' // Helper type to get the type of the agents (with the custom modules) for the credential tests -export type AnonCredsTestsAgent = - | Agent & { mediationRecipient?: any; mediator?: any }> - | Agent & { mediationRecipient?: any; mediator?: any }> - -export const getLegacyAnonCredsModules = ({ - autoAcceptCredentials, - autoAcceptProofs, -}: { autoAcceptCredentials?: AutoAcceptCredential; autoAcceptProofs?: AutoAcceptProof } = {}) => { - const indyCredentialFormat = new LegacyIndyCredentialFormatService() - const indyProofFormat = new LegacyIndyProofFormatService() - - // Register the credential and proof protocols - const modules = { - credentials: new CredentialsModule({ - autoAcceptCredentials, - credentialProtocols: [ - new V1CredentialProtocol({ indyCredentialFormat }), - new V2CredentialProtocol({ - credentialFormats: [indyCredentialFormat], - }), - ], - }), - proofs: new ProofsModule({ - autoAcceptProofs, - proofProtocols: [ - new V1ProofProtocol({ indyProofFormat }), - new V2ProofProtocol({ - proofFormats: [indyProofFormat], - }), - ], - }), - anoncreds: new AnonCredsModule({ - registries: [new IndySdkAnonCredsRegistry()], - }), - dids: new DidsModule({ - resolvers: [new IndySdkSovDidResolver(), new IndySdkIndyDidResolver()], - registrars: [new IndySdkIndyDidRegistrar()], - }), - indySdk: new IndySdkModule(getIndySdkModuleConfig()), - cache: new CacheModule({ - cache: new InMemoryLruCache({ limit: 100 }), - }), - } as const - - return modules -} +export type AnonCredsTestsAgent = Agent< + ReturnType & { mediationRecipient?: any; mediator?: any } +> export const getAskarAnonCredsIndyModules = ({ autoAcceptCredentials, @@ -357,7 +306,7 @@ export async function setupAnonCredsTests< { endpoints: ['rxjs:issuer'], }, - getLegacyAnonCredsModules({ + getAskarAnonCredsIndyModules({ autoAcceptCredentials, autoAcceptProofs, }) @@ -370,7 +319,7 @@ export async function setupAnonCredsTests< { endpoints: ['rxjs:holder'], }, - getLegacyAnonCredsModules({ + getAskarAnonCredsIndyModules({ autoAcceptCredentials, autoAcceptProofs, }) @@ -384,7 +333,7 @@ export async function setupAnonCredsTests< { endpoints: ['rxjs:verifier'], }, - getLegacyAnonCredsModules({ + getAskarAnonCredsIndyModules({ autoAcceptCredentials, autoAcceptProofs, }) diff --git a/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts b/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts index 6aa8db303f..555737505b 100644 --- a/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts +++ b/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts @@ -20,14 +20,13 @@ import { W3cJsonLdVerifiableCredential, } from '@aries-framework/core' +import { RegisteredAskarTestWallet } from '../../askar/tests/helpers' import { W3cCredentialsModuleConfig } from '../../core/src/modules/vc/W3cCredentialsModuleConfig' import { SignatureSuiteRegistry } from '../../core/src/modules/vc/data-integrity/SignatureSuiteRegistry' import { W3cJsonLdCredentialService } from '../../core/src/modules/vc/data-integrity/W3cJsonLdCredentialService' import { customDocumentLoader } from '../../core/src/modules/vc/data-integrity/__tests__/documentLoader' import { LinkedDataProof } from '../../core/src/modules/vc/data-integrity/models/LinkedDataProof' -import { getAgentConfig, getAgentContext } from '../../core/tests/helpers' -import { IndySdkWallet } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' +import { agentDependencies, getAgentConfig, getAgentContext } from '../../core/tests/helpers' import { BbsBlsSignature2020, BbsBlsSignatureProof2020, Bls12381g2SigningProvider } from '../src' import { BbsBlsSignature2020Fixtures } from './fixtures' @@ -70,7 +69,11 @@ describeSkipNode17And18('BBS W3cCredentialService', () => { const privateKey = TypedArrayEncoder.fromString('testseed000000000000000000000001') beforeAll(async () => { - wallet = new IndySdkWallet(indySdk, agentConfig.logger, signingProviderRegistry) + wallet = new RegisteredAskarTestWallet( + agentConfig.logger, + new agentDependencies.FileSystem(), + signingProviderRegistry + ) await wallet.createAndOpen(agentConfig.walletConfig) agentContext = getAgentContext({ agentConfig, diff --git a/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts b/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts index 67e2112e96..2350dd32b2 100644 --- a/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts +++ b/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts @@ -7,11 +7,11 @@ import { TypedArrayEncoder, SigningProviderRegistry, } from '@aries-framework/core' +import { agentDependencies } from '@aries-framework/core/tests' import { BBS_SIGNATURE_LENGTH } from '@mattrglobal/bbs-signatures' +import { RegisteredAskarTestWallet } from '../../askar/tests/helpers' import testLogger from '../../core/tests/logger' -import { IndySdkWallet } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' import { Bls12381g2SigningProvider } from '../src' import { describeSkipNode17And18 } from './util' @@ -30,7 +30,11 @@ describeSkipNode17And18('BBS Signing Provider', () => { const message = TypedArrayEncoder.fromString('sample-message') beforeEach(async () => { - wallet = new IndySdkWallet(indySdk, testLogger, new SigningProviderRegistry([new Bls12381g2SigningProvider()])) + wallet = new RegisteredAskarTestWallet( + testLogger, + new agentDependencies.FileSystem(), + new SigningProviderRegistry([new Bls12381g2SigningProvider()]) + ) await wallet.createAndOpen(walletConfig) }) diff --git a/packages/core/src/agent/Agent.ts b/packages/core/src/agent/Agent.ts index 952e610c82..9c25006433 100644 --- a/packages/core/src/agent/Agent.ts +++ b/packages/core/src/agent/Agent.ts @@ -79,7 +79,7 @@ export class Agent extends BaseAge // Register possibly already defined services if (!dependencyManager.isRegistered(InjectionSymbols.Wallet)) { throw new AriesFrameworkError( - "Missing required dependency: 'Wallet'. You can register it using one of the provided modules such as the AskarModule or the IndySdkModule, or implement your own." + "Missing required dependency: 'Wallet'. You can register it using the AskarModule, or implement your own." ) } if (!dependencyManager.isRegistered(InjectionSymbols.Logger)) { @@ -87,7 +87,7 @@ export class Agent extends BaseAge } if (!dependencyManager.isRegistered(InjectionSymbols.StorageService)) { throw new AriesFrameworkError( - "Missing required dependency: 'StorageService'. You can register it using one of the provided modules such as the AskarModule or the IndySdkModule, or implement your own." + "Missing required dependency: 'StorageService'. You can register it using the AskarModule, or implement your own." ) } if (!dependencyManager.isRegistered(InjectionSymbols.MessageRepository)) { diff --git a/packages/core/src/agent/__tests__/Agent.test.ts b/packages/core/src/agent/__tests__/Agent.test.ts index d11331d6ff..82c7f656f4 100644 --- a/packages/core/src/agent/__tests__/Agent.test.ts +++ b/packages/core/src/agent/__tests__/Agent.test.ts @@ -2,7 +2,7 @@ import type { DependencyManager, Module } from '../../plugins' import { injectable } from 'tsyringe' -import { getIndySdkModules } from '../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../askar/tests/helpers' import { getAgentOptions } from '../../../tests/helpers' import { InjectionSymbols } from '../../constants' import { BasicMessageRepository, BasicMessageService } from '../../modules/basic-messages' @@ -33,7 +33,7 @@ import { FeatureRegistry } from '../FeatureRegistry' import { MessageReceiver } from '../MessageReceiver' import { MessageSender } from '../MessageSender' -const agentOptions = getAgentOptions('Agent Class Test', {}, getIndySdkModules()) +const agentOptions = getAgentOptions('Agent Class Test', {}, { askar: askarModule }) const myModuleMethod = jest.fn() @injectable() @@ -61,7 +61,7 @@ describe('Agent', () => { ...agentOptions, modules: { myModule: new MyModule(), - ...getIndySdkModules(), + askar: askarModule, }, }) @@ -79,7 +79,7 @@ describe('Agent', () => { mediationRecipient: new MediationRecipientModule({ maximumMessagePickup: 42, }), - ...getIndySdkModules(), + askar: askarModule, }, }) diff --git a/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts b/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts index 93d3610f29..c4b943a5e1 100644 --- a/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts +++ b/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts @@ -1,8 +1,7 @@ import type { Wallet } from '../../wallet' -import { IndySdkWallet } from '../../../../indy-sdk/src' -import { indySdk } from '../../../../indy-sdk/tests/setupIndySdkModule' -import { getAgentConfig } from '../../../tests/helpers' +import { RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' +import { agentDependencies, getAgentConfig } from '../../../tests/helpers' import { KeyType } from '../../crypto' import { SigningProviderRegistry } from '../../crypto/signing-provider' import { TypedArrayEncoder } from '../../utils' @@ -47,7 +46,11 @@ describe('Decorators | Signature | SignatureDecoratorUtils', () => { beforeAll(async () => { const config = getAgentConfig('SignatureDecoratorUtilsTest') - wallet = new IndySdkWallet(indySdk, config.logger, new SigningProviderRegistry([])) + wallet = new RegisteredAskarTestWallet( + config.logger, + new agentDependencies.FileSystem(), + new SigningProviderRegistry([]) + ) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion await wallet.createAndOpen(config.walletConfig!) }) diff --git a/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts b/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts index 77f746030c..ae6ca1a29c 100644 --- a/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts +++ b/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts @@ -6,7 +6,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions, makeConnection, waitForBasicMessage } from '../../../../tests/helpers' import testLogger from '../../../../tests/logger' import { Agent } from '../../../agent/Agent' @@ -19,7 +19,7 @@ const faberConfig = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getIndySdkModules() + { askar: askarModule } ) const aliceConfig = getAgentOptions( @@ -27,7 +27,7 @@ const aliceConfig = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getIndySdkModules() + { askar: askarModule } ) describe('Basic Messages E2E', () => { diff --git a/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts b/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts index 378596a888..78ff3c9b7d 100644 --- a/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts +++ b/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts @@ -5,9 +5,9 @@ import type { Routing } from '../services/ConnectionService' import { Subject } from 'rxjs' -import { IndySdkWallet } from '../../../../../indy-sdk/src' -import { indySdk } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' import { + agentDependencies, getAgentConfig, getAgentContext, getMockConnection, @@ -92,7 +92,11 @@ describe('ConnectionService', () => { let agentContext: AgentContext beforeAll(async () => { - wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) + wallet = new RegisteredAskarTestWallet( + agentConfig.logger, + new agentDependencies.FileSystem(), + new SigningProviderRegistry([]) + ) agentContext = getAgentContext({ wallet, agentConfig, diff --git a/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts b/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts index 9e029a27df..e784c6983e 100644 --- a/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts +++ b/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts @@ -4,7 +4,7 @@ import type { ConnectionStateChangedEvent } from '../ConnectionEvents' import { firstValueFrom } from 'rxjs' import { filter, first, map, timeout } from 'rxjs/operators' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' import { getAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' @@ -53,7 +53,7 @@ describe('Manual Connection Flow', () => { endpoints: ['rxjs:alice'], }, { - ...getIndySdkModules(), + askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, }), @@ -66,7 +66,7 @@ describe('Manual Connection Flow', () => { endpoints: ['rxjs:bob'], }, { - ...getIndySdkModules(), + askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, }), @@ -78,7 +78,7 @@ describe('Manual Connection Flow', () => { endpoints: ['rxjs:faber'], }, { - ...getIndySdkModules(), + askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, }), diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts index 7fdb14f74a..9e1c5a7f0c 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts @@ -8,7 +8,7 @@ import { ReplaySubject, Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../../../tests/transport/SubjectOutboundTransport' import { - getLegacyAnonCredsModules, + getAskarAnonCredsIndyModules, prepareForAnonCredsIssuance, } from '../../../../../../../anoncreds/tests/legacyAnonCredsSetup' import { waitForCredentialRecordSubject, getAgentOptions } from '../../../../../../tests/helpers' @@ -25,7 +25,7 @@ const faberAgentOptions = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getLegacyAnonCredsModules() + getAskarAnonCredsIndyModules() ) const aliceAgentOptions = getAgentOptions( @@ -33,7 +33,7 @@ const aliceAgentOptions = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getLegacyAnonCredsModules() + getAskarAnonCredsIndyModules() ) const credentialPreview = V2CredentialPreview.fromRecord({ diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts index 860b29a43e..296e2bc863 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts @@ -1,29 +1,18 @@ import type { EventReplaySubject } from '../../../../../../tests' -import { randomUUID } from 'crypto' - import { LegacyIndyCredentialFormatService, LegacyIndyProofFormatService, V1CredentialProtocol, V1ProofProtocol, - AnonCredsModule, } from '../../../../../../../anoncreds/src' -import { prepareForAnonCredsIssuance } from '../../../../../../../anoncreds/tests/legacyAnonCredsSetup' import { - IndySdkAnonCredsRegistry, - IndySdkIndyDidRegistrar, - IndySdkIndyDidResolver, - IndySdkModule, - IndySdkSovDidResolver, -} from '../../../../../../../indy-sdk/src' -import { indySdk } from '../../../../../../../indy-sdk/tests/setupIndySdkModule' + getAskarAnonCredsIndyModules, + prepareForAnonCredsIssuance, +} from '../../../../../../../anoncreds/tests/legacyAnonCredsSetup' import { setupEventReplaySubjects, setupSubjectTransports, - genesisPath, - taaAcceptanceMechanism, - taaVersion, getAgentOptions, waitForCredentialRecordSubject, testLogger, @@ -34,7 +23,6 @@ import { KeyType } from '../../../../../crypto' import { TypedArrayEncoder } from '../../../../../utils' import { JsonTransformer } from '../../../../../utils/JsonTransformer' import { CacheModule, InMemoryLruCache } from '../../../../cache' -import { DidsModule } from '../../../../dids' import { ProofEventTypes, ProofsModule, V2ProofProtocol } from '../../../../proofs' import { W3cCredentialsModule } from '../../../../vc' import { customDocumentLoader } from '../../../../vc/data-integrity/__tests__/documentLoader' @@ -88,6 +76,7 @@ const indyProofFormat = new LegacyIndyProofFormatService() const getIndyJsonLdModules = () => ({ + ...getAskarAnonCredsIndyModules(), credentials: new CredentialsModule({ credentialProtocols: [ new V1CredentialProtocol({ indyCredentialFormat }), @@ -104,25 +93,6 @@ const getIndyJsonLdModules = () => }), ], }), - anoncreds: new AnonCredsModule({ - registries: [new IndySdkAnonCredsRegistry()], - }), - dids: new DidsModule({ - resolvers: [new IndySdkSovDidResolver(), new IndySdkIndyDidResolver()], - registrars: [new IndySdkIndyDidRegistrar()], - }), - indySdk: new IndySdkModule({ - indySdk, - networks: [ - { - isProduction: false, - genesisPath, - id: randomUUID(), - indyNamespace: `pool:localtest`, - transactionAuthorAgreement: { version: taaVersion, acceptanceMechanism: taaAcceptanceMechanism }, - }, - ], - }), cache: new CacheModule({ cache: new InMemoryLruCache({ limit: 100 }), }), diff --git a/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts b/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts index 2453b55e6c..5f35965917 100644 --- a/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts +++ b/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import type { IndySdkIndyDidCreateOptions } from '@aries-framework/indy-sdk' +import type { IndyVdrDidCreateOptions } from '@aries-framework/indy-vdr' -import { getLegacyAnonCredsModules } from '../../../../../anoncreds/tests/legacyAnonCredsSetup' +import { getAskarAnonCredsIndyModules } from '../../../../../anoncreds/tests/legacyAnonCredsSetup' import { setupSubjectTransports } from '../../../../tests' import { getAgentOptions, @@ -13,20 +13,21 @@ import { Agent } from '../../../agent/Agent' import { TypedArrayEncoder } from '../../../utils' import { sleep } from '../../../utils/sleep' import { DidExchangeState, HandshakeProtocol } from '../../connections' +import { DidCommV1Service, DidCommV2Service, DidDocumentService } from '../../dids' const faberAgentOptions = getAgentOptions( 'Faber Agent OOB Implicit', { endpoints: ['rxjs:faber'], }, - getLegacyAnonCredsModules() + getAskarAnonCredsIndyModules() ) const aliceAgentOptions = getAgentOptions( 'Alice Agent OOB Implicit', { endpoints: ['rxjs:alice'], }, - getLegacyAnonCredsModules() + getAskarAnonCredsIndyModules() ) describe('out of band implicit', () => { @@ -230,15 +231,34 @@ describe('out of band implicit', () => { }) async function createPublicDid(agent: Agent, unqualifiedSubmitterDid: string, endpoint: string) { - const createResult = await agent.dids.create({ + const createResult = await agent.dids.create({ method: 'indy', options: { - submitterDid: `did:indy:pool:localtest:${unqualifiedSubmitterDid}`, + endorserMode: 'internal', + endorserDid: `did:indy:pool:localtest:${unqualifiedSubmitterDid}`, + useEndpointAttrib: true, + services: [ + new DidDocumentService({ + id: `#endpoint`, + serviceEndpoint: endpoint, + type: 'endpoint', + }), + new DidCommV1Service({ + id: `#did-communication`, + priority: 0, + recipientKeys: [`#key-agreement-1`], + routingKeys: ['a-routing-key'], + serviceEndpoint: endpoint, + accept: ['didcomm/aip2;env=rfc19'], + }), + new DidCommV2Service({ + accept: ['didcomm/v2'], + id: `#didcomm-1`, + routingKeys: ['a-routing-key'], + serviceEndpoint: endpoint, + }), + ], alias: 'Alias', - endpoints: { - endpoint, - types: ['DIDComm', 'did-communication', 'endpoint'], - }, }, }) diff --git a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts index e83dc5809a..db1bbbe965 100644 --- a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts +++ b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts @@ -7,7 +7,7 @@ import { SubjectInboundTransport } from '../../../../../../../../tests/transport import { SubjectOutboundTransport } from '../../../../../../../../tests/transport/SubjectOutboundTransport' import { V1CredentialPreview } from '../../../../../../../anoncreds/src' import { - getLegacyAnonCredsModules, + getAskarAnonCredsIndyModules, issueLegacyAnonCredsCredential, prepareForAnonCredsIssuance, setupAnonCredsTests, @@ -271,7 +271,7 @@ describe('V2 Connectionless Proofs - Indy', () => { endpoints: ['rxjs:mediator'], }, { - ...getLegacyAnonCredsModules({ + ...getAskarAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediator: new MediatorModule({ @@ -303,7 +303,7 @@ describe('V2 Connectionless Proofs - Indy', () => { `Connectionless proofs with mediator Faber-${unique}`, {}, { - ...getLegacyAnonCredsModules({ + ...getAskarAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ @@ -319,7 +319,7 @@ describe('V2 Connectionless Proofs - Indy', () => { `Connectionless proofs with mediator Alice-${unique}`, {}, { - ...getLegacyAnonCredsModules({ + ...getAskarAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ diff --git a/packages/core/src/modules/routing/__tests__/mediation.test.ts b/packages/core/src/modules/routing/__tests__/mediation.test.ts index 574f999297..063a27e8d5 100644 --- a/packages/core/src/modules/routing/__tests__/mediation.test.ts +++ b/packages/core/src/modules/routing/__tests__/mediation.test.ts @@ -8,7 +8,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions, waitForBasicMessage } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { sleep } from '../../../utils/sleep' @@ -18,14 +18,14 @@ import { MediatorModule } from '../MediatorModule' import { MediatorPickupStrategy } from '../MediatorPickupStrategy' import { MediationState } from '../models/MediationState' -const recipientAgentOptions = getAgentOptions('Mediation: Recipient', {}, getIndySdkModules()) +const recipientAgentOptions = getAgentOptions('Mediation: Recipient', {}, { askar: askarModule }) const mediatorAgentOptions = getAgentOptions( 'Mediation: Mediator', { endpoints: ['rxjs:mediator'], }, { - ...getIndySdkModules(), + askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true, }), @@ -37,7 +37,7 @@ const senderAgentOptions = getAgentOptions( { endpoints: ['rxjs:sender'], }, - getIndySdkModules() + { askar: askarModule } ) describe('mediator establishment', () => { diff --git a/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts b/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts index 2a3961fa89..99c73e17c5 100644 --- a/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts +++ b/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts @@ -1,8 +1,8 @@ import type { AgentContext } from '../../../agent' import type { Wallet } from '../../../wallet' -import { IndySdkWallet } from '../../../../../indy-sdk/src' -import { getAgentConfig, indySdk, getAgentContext, mockFunction } from '../../../../tests' +import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' +import { agentDependencies, getAgentConfig, getAgentContext, mockFunction } from '../../../../tests' import { SigningProviderRegistry, JwsService } from '../../../crypto' import { JsonTransformer, asArray } from '../../../utils' import { W3cCredentialService } from '../W3cCredentialService' @@ -48,7 +48,11 @@ describe('W3cCredentialsService', () => { let w3cCredentialsRepository: W3cCredentialRepository beforeAll(async () => { - wallet = new IndySdkWallet(indySdk, agentConfig.logger, signingProviderRegistry) + wallet = new RegisteredAskarTestWallet( + agentConfig.logger, + new agentDependencies.FileSystem(), + signingProviderRegistry + ) await wallet.createAndOpen(agentConfig.walletConfig) agentContext = getAgentContext({ agentConfig, diff --git a/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts b/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts index 01a67407cf..f374f09593 100644 --- a/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts +++ b/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts @@ -1,5 +1,5 @@ -import { IndySdkModule } from '../../../../../indy-sdk/src' -import { getAgentOptions, indySdk } from '../../../../tests' +import { askarModule } from '../../../../../askar/tests/helpers' +import { getAgentOptions } from '../../../../tests' import { Agent } from '../../../agent/Agent' import { JsonTransformer } from '../../../utils' import { W3cCredentialService } from '../W3cCredentialService' @@ -10,9 +10,7 @@ import { W3cJsonLdVerifiableCredential } from '../data-integrity/models' import { W3cCredentialRepository } from '../repository' const modules = { - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, w3cCredentials: new W3cCredentialsModule({ documentLoader: customDocumentLoader, }), diff --git a/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts b/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts index 80f4e42526..e980c81e3c 100644 --- a/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts +++ b/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts @@ -1,9 +1,8 @@ import type { AgentContext } from '../../../../agent' import type { Wallet } from '../../../../wallet' -import { IndySdkWallet } from '../../../../../../indy-sdk/src' -import { indySdk } from '../../../../../../indy-sdk/tests/setupIndySdkModule' -import { getAgentConfig, getAgentContext } from '../../../../../tests/helpers' +import { RegisteredAskarTestWallet } from '../../../../../../askar/tests/helpers' +import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../../tests/helpers' import { KeyType } from '../../../../crypto' import { SigningProviderRegistry } from '../../../../crypto/signing-provider' import { asArray, TypedArrayEncoder } from '../../../../utils' @@ -51,7 +50,11 @@ describe('W3cJsonLdCredentialsService', () => { const privateKey = TypedArrayEncoder.fromString('testseed000000000000000000000001') beforeAll(async () => { - wallet = new IndySdkWallet(indySdk, agentConfig.logger, signingProviderRegistry) + wallet = new RegisteredAskarTestWallet( + agentConfig.logger, + new agentDependencies.FileSystem(), + signingProviderRegistry + ) await wallet.createAndOpen(agentConfig.walletConfig) agentContext = getAgentContext({ agentConfig, diff --git a/packages/core/src/storage/migration/__tests__/0.1.test.ts b/packages/core/src/storage/migration/__tests__/0.1.test.ts index ff2033f3ba..67c9aabed0 100644 --- a/packages/core/src/storage/migration/__tests__/0.1.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.1.test.ts @@ -4,9 +4,7 @@ import { readFileSync } from 'fs' import path from 'path' import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' -import { IndySdkWallet } from '../../../../../indy-sdk/src' -import { IndySdkSymbol } from '../../../../../indy-sdk/src/types' -import { indySdk } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' import { Agent } from '../../../../src' import { agentDependencies as dependencies } from '../../../../tests/helpers' import { InjectionSymbols } from '../../../constants' @@ -40,9 +38,8 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) const agent = new Agent( { @@ -99,9 +96,8 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) const agent = new Agent( { @@ -160,9 +156,8 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) const agent = new Agent( { @@ -221,9 +216,8 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) const agent = new Agent( { diff --git a/packages/core/src/storage/migration/__tests__/0.2.test.ts b/packages/core/src/storage/migration/__tests__/0.2.test.ts index a66ef7c832..e79919750d 100644 --- a/packages/core/src/storage/migration/__tests__/0.2.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.2.test.ts @@ -2,10 +2,8 @@ import { readFileSync } from 'fs' import path from 'path' import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' -import { IndySdkWallet } from '../../../../../indy-sdk/src' -import { IndySdkSymbol } from '../../../../../indy-sdk/src/types' +import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' import { Agent } from '../../../../src' -import { indySdk } from '../../../../tests' import { agentDependencies } from '../../../../tests/helpers' import { InjectionSymbols } from '../../../constants' import { DependencyManager } from '../../../plugins' @@ -34,9 +32,8 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) const agent = new Agent( { @@ -103,9 +100,8 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) const agent = new Agent( { @@ -150,9 +146,8 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) const agent = new Agent( diff --git a/packages/core/src/storage/migration/__tests__/0.3.test.ts b/packages/core/src/storage/migration/__tests__/0.3.test.ts index e8479803fc..25f0a2a219 100644 --- a/packages/core/src/storage/migration/__tests__/0.3.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.3.test.ts @@ -2,9 +2,7 @@ import { readFileSync } from 'fs' import path from 'path' import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' -import { IndySdkWallet } from '../../../../../indy-sdk/src' -import { IndySdkSymbol } from '../../../../../indy-sdk/src/types' -import { indySdk } from '../../../../tests' +import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' import { agentDependencies } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { InjectionSymbols } from '../../../constants' @@ -34,9 +32,8 @@ describe('UpdateAssistant | v0.3.1 - v0.4', () => { const dependencyManager = new DependencyManager() const storageService = new InMemoryStorageService() dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) const agent = new Agent( { diff --git a/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts b/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts index 2f9e3e80a3..e437b36c6b 100644 --- a/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts +++ b/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts @@ -1,9 +1,7 @@ import type { BaseRecord } from '../../BaseRecord' import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' -import { IndySdkWallet } from '../../../../../indy-sdk/src' -import { IndySdkSymbol } from '../../../../../indy-sdk/src/types' -import { indySdk } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' import { getAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { InjectionSymbols } from '../../../constants' @@ -21,9 +19,8 @@ describe('UpdateAssistant', () => { beforeEach(async () => { const dependencyManager = new DependencyManager() storageService = new InMemoryStorageService() - // If we register the IndySdkModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, IndySdkWallet) - dependencyManager.registerInstance(IndySdkSymbol, indySdk) + // If we register the AskarModule it will register the storage service, but we use in memory storage here + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) agent = new Agent(agentOptions, dependencyManager) diff --git a/packages/core/src/storage/migration/__tests__/backup.test.ts b/packages/core/src/storage/migration/__tests__/backup.test.ts index e582263b57..15cf8ff031 100644 --- a/packages/core/src/storage/migration/__tests__/backup.test.ts +++ b/packages/core/src/storage/migration/__tests__/backup.test.ts @@ -4,7 +4,7 @@ import type { StorageUpdateError } from '../error/StorageUpdateError' import { readFileSync, unlinkSync } from 'fs' import path from 'path' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { InjectionSymbols } from '../../../constants' @@ -14,7 +14,7 @@ import { JsonTransformer } from '../../../utils' import { StorageUpdateService } from '../StorageUpdateService' import { UpdateAssistant } from '../UpdateAssistant' -const agentOptions = getAgentOptions('UpdateAssistant | Backup', {}, getIndySdkModules()) +const agentOptions = getAgentOptions('UpdateAssistant | Backup', {}, { askar: askarModule }) const aliceCredentialRecordsString = readFileSync( path.join(__dirname, '__fixtures__/alice-4-credentials-0.1.json'), diff --git a/packages/core/tests/agents.test.ts b/packages/core/tests/agents.test.ts index 9bded8ba18..9f8dd40b97 100644 --- a/packages/core/tests/agents.test.ts +++ b/packages/core/tests/agents.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { ConnectionRecord } from '../src/modules/connections' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { HandshakeProtocol } from '../src/modules/connections' @@ -13,14 +13,14 @@ const aliceAgentOptions = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getIndySdkModules() + { askar: askarModule } ) const bobAgentOptions = getAgentOptions( 'Agents Bob', { endpoints: ['rxjs:bob'], }, - getIndySdkModules() + { askar: askarModule } ) describe('agents', () => { diff --git a/packages/core/tests/connections.test.ts b/packages/core/tests/connections.test.ts index 0f64b31d2c..09760187a8 100644 --- a/packages/core/tests/connections.test.ts +++ b/packages/core/tests/connections.test.ts @@ -3,7 +3,7 @@ import type { AgentMessageProcessedEvent, KeylistUpdate } from '../src' import { filter, firstValueFrom, map, timeout } from 'rxjs' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { MediatorModule, Key, @@ -32,21 +32,21 @@ describe('connections', () => { { endpoints: ['rxjs:faber'], }, - getIndySdkModules() + { askar: askarModule } ) const aliceAgentOptions = getAgentOptions( 'Alice Agent Connections', { endpoints: ['rxjs:alice'], }, - getIndySdkModules() + { askar: askarModule } ) const acmeAgentOptions = getAgentOptions( 'Acme Agent Connections', { endpoints: ['rxjs:acme'], }, - getIndySdkModules() + { askar: askarModule } ) const mediatorAgentOptions = getAgentOptions( 'Mediator Agent Connections', @@ -54,7 +54,7 @@ describe('connections', () => { endpoints: ['rxjs:mediator'], }, { - ...getIndySdkModules(), + askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true, }), diff --git a/packages/core/tests/generic-records.test.ts b/packages/core/tests/generic-records.test.ts index 3d37def0ed..6da9f6f8ce 100644 --- a/packages/core/tests/generic-records.test.ts +++ b/packages/core/tests/generic-records.test.ts @@ -1,6 +1,6 @@ import type { GenericRecord } from '../src/modules/generic-records/repository/GenericRecord' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { RecordNotFoundError } from '../src/error' @@ -11,7 +11,7 @@ const aliceAgentOptions = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getIndySdkModules() + { askar: askarModule } ) describe('genericRecords', () => { diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts index 517c53a274..81cfcdcfde 100644 --- a/packages/core/tests/helpers.ts +++ b/packages/core/tests/helpers.ts @@ -26,7 +26,7 @@ import path from 'path' import { lastValueFrom, firstValueFrom, ReplaySubject } from 'rxjs' import { catchError, filter, map, take, timeout } from 'rxjs/operators' -import { agentDependencies, IndySdkPostgresWalletScheme } from '../../node/src' +import { agentDependencies } from '../../node/src' import { OutOfBandDidCommService, ConnectionsModule, @@ -100,49 +100,6 @@ export function getAgentOptions( - name: string, - extraConfig: Partial = {}, - inputModules?: AgentModules -) { - const random = uuid().slice(0, 4) - const config: InitConfig = { - label: `Agent: ${name} - ${random}`, - walletConfig: { - // NOTE: IndySDK Postgres database per wallet doesn't support special characters/spaces in the wallet name - id: `PostgresWallet${name}${random}`, - key: `Key${name}`, - storage: { - type: 'postgres_storage', - config: { - url: 'localhost:5432', - wallet_scheme: IndySdkPostgresWalletScheme.DatabasePerWallet, - }, - credentials: { - account: 'postgres', - password: 'postgres', - admin_account: 'postgres', - admin_password: 'postgres', - }, - }, - }, - autoUpdateStorageOnStartup: false, - logger: TestLogger.fromLogger(testLogger, name), - ...extraConfig, - } - - const m = (inputModules ?? {}) as AgentModulesInput - const modules = { - ...m, - // Make sure connections module is always defined so we can set autoAcceptConnections - connections: m.connections ?? new ConnectionsModule({}), - } - - modules.connections.config.autoAcceptConnections = true - - return { config, dependencies: agentDependencies, modules: modules as AgentModules } as const -} - export async function importExistingIndyDidFromPrivateKey(agent: Agent, privateKey: Buffer) { const key = await agent.wallet.createKey({ keyType: KeyType.Ed25519, diff --git a/packages/core/tests/index.ts b/packages/core/tests/index.ts index 2822fb23e1..b8ea2ca430 100644 --- a/packages/core/tests/index.ts +++ b/packages/core/tests/index.ts @@ -2,7 +2,6 @@ export * from './jsonld' export * from './transport' export * from './events' export * from './helpers' -export * from './indySdk' import testLogger from './logger' diff --git a/packages/core/tests/indySdk.ts b/packages/core/tests/indySdk.ts deleted file mode 100644 index b5e5a3075d..0000000000 --- a/packages/core/tests/indySdk.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' - -export { indySdk } diff --git a/packages/core/tests/jsonld.ts b/packages/core/tests/jsonld.ts index 9b0f211097..f996794e57 100644 --- a/packages/core/tests/jsonld.ts +++ b/packages/core/tests/jsonld.ts @@ -1,9 +1,8 @@ import type { EventReplaySubject } from './events' import type { AutoAcceptCredential, AutoAcceptProof, ConnectionRecord } from '../src' +import { askarModule } from '../../askar/tests/helpers' import { BbsModule } from '../../bbs-signatures/src/BbsModule' -import { IndySdkModule } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' import { CacheModule, CredentialEventTypes, @@ -42,9 +41,7 @@ export const getJsonLdModules = ({ cache: new CacheModule({ cache: new InMemoryLruCache({ limit: 100 }), }), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, bbs: new BbsModule(), } as const) diff --git a/packages/core/tests/migration.test.ts b/packages/core/tests/migration.test.ts index ac898caa73..bc39a9382a 100644 --- a/packages/core/tests/migration.test.ts +++ b/packages/core/tests/migration.test.ts @@ -1,12 +1,12 @@ import type { VersionString } from '../src/utils/version' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { UpdateAssistant } from '../src/storage/migration/UpdateAssistant' import { getAgentOptions } from './helpers' -const agentOptions = getAgentOptions('Migration', {}, getIndySdkModules()) +const agentOptions = getAgentOptions('Migration', {}, { askar: askarModule }) describe('migration', () => { test('manually initiating the update assistant to perform an update', async () => { diff --git a/packages/core/tests/multi-protocol-version.test.ts b/packages/core/tests/multi-protocol-version.test.ts index 4f7596d5ff..b14db97215 100644 --- a/packages/core/tests/multi-protocol-version.test.ts +++ b/packages/core/tests/multi-protocol-version.test.ts @@ -2,7 +2,7 @@ import type { AgentMessageProcessedEvent } from '../src/agent/Events' import { filter, firstValueFrom, timeout } from 'rxjs' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { parseMessageType, MessageSender, AgentMessage, IsValidMessageType } from '../src' import { Agent } from '../src/agent/Agent' import { AgentEventTypes } from '../src/agent/Events' @@ -16,14 +16,14 @@ const aliceAgentOptions = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getIndySdkModules() + { askar: askarModule } ) const bobAgentOptions = getAgentOptions( 'Multi Protocol Versions - Bob', { endpoints: ['rxjs:bob'], }, - getIndySdkModules() + { askar: askarModule } ) describe('multi version protocols', () => { diff --git a/packages/core/tests/oob-mediation-provision.test.ts b/packages/core/tests/oob-mediation-provision.test.ts index 5e18f36197..610f27fdfd 100644 --- a/packages/core/tests/oob-mediation-provision.test.ts +++ b/packages/core/tests/oob-mediation-provision.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { OutOfBandInvitation } from '../src/modules/oob/messages' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { DidExchangeState, HandshakeProtocol } from '../src/modules/connections' import { @@ -19,7 +19,7 @@ const faberAgentOptions = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getIndySdkModules() + { askar: askarModule } ) const aliceAgentOptions = getAgentOptions( 'OOB mediation provision - Alice Recipient Agent', @@ -27,7 +27,7 @@ const aliceAgentOptions = getAgentOptions( endpoints: ['rxjs:alice'], }, { - ...getIndySdkModules(), + askar: askarModule, mediationRecipient: new MediationRecipientModule({ // FIXME: discover features returns that we support this protocol, but we don't support all roles // we should return that we only support the mediator role so we don't have to explicitly declare this @@ -40,7 +40,7 @@ const mediatorAgentOptions = getAgentOptions( { endpoints: ['rxjs:mediator'], }, - { ...getIndySdkModules(), mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } + { askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } ) describe('out of band with mediation set up with provision method', () => { diff --git a/packages/core/tests/oob-mediation.test.ts b/packages/core/tests/oob-mediation.test.ts index 272c468d3b..ea39333bc2 100644 --- a/packages/core/tests/oob-mediation.test.ts +++ b/packages/core/tests/oob-mediation.test.ts @@ -7,7 +7,7 @@ import { filter, firstValueFrom, map, Subject, timeout } from 'rxjs' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { AgentEventTypes } from '../src/agent/Events' import { DidExchangeState, HandshakeProtocol } from '../src/modules/connections' @@ -29,7 +29,7 @@ const faberAgentOptions = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getIndySdkModules() + { askar: askarModule } ) const aliceAgentOptions = getAgentOptions( 'OOB mediation - Alice Recipient Agent', @@ -37,7 +37,7 @@ const aliceAgentOptions = getAgentOptions( endpoints: ['rxjs:alice'], }, { - ...getIndySdkModules(), + askar: askarModule, mediationRecipient: new MediationRecipientModule({ // FIXME: discover features returns that we support this protocol, but we don't support all roles // we should return that we only support the mediator role so we don't have to explicitly declare this @@ -50,7 +50,7 @@ const mediatorAgentOptions = getAgentOptions( { endpoints: ['rxjs:mediator'], }, - { ...getIndySdkModules(), mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } + { askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } ) describe('out of band with mediation', () => { diff --git a/packages/core/tests/oob.test.ts b/packages/core/tests/oob.test.ts index 2911d9d406..35b323af93 100644 --- a/packages/core/tests/oob.test.ts +++ b/packages/core/tests/oob.test.ts @@ -8,7 +8,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { getLegacyAnonCredsModules, prepareForAnonCredsIssuance } from '../../anoncreds/tests/legacyAnonCredsSetup' +import { getAskarAnonCredsIndyModules, prepareForAnonCredsIssuance } from '../../anoncreds/tests/legacyAnonCredsSetup' import { Agent } from '../src/agent/Agent' import { Key } from '../src/crypto' import { DidExchangeState, HandshakeProtocol } from '../src/modules/connections' @@ -29,7 +29,7 @@ const faberAgentOptions = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getLegacyAnonCredsModules({ + getAskarAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }) ) @@ -38,7 +38,7 @@ const aliceAgentOptions = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getLegacyAnonCredsModules({ + getAskarAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }) ) @@ -63,8 +63,8 @@ describe('out of band', () => { autoAcceptConnection: false, } - let faberAgent: Agent> - let aliceAgent: Agent> + let faberAgent: Agent> + let aliceAgent: Agent> let credentialTemplate: CreateCredentialOfferOptions<[V1CredentialProtocol]> beforeAll(async () => { diff --git a/packages/core/tests/wallet.test.ts b/packages/core/tests/wallet.test.ts index 78e089482a..e7815cf4e4 100644 --- a/packages/core/tests/wallet.test.ts +++ b/packages/core/tests/wallet.test.ts @@ -1,7 +1,7 @@ import { tmpdir } from 'os' import path from 'path' -import { getIndySdkModules } from '../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { BasicMessageRepository, BasicMessageRecord, BasicMessageRole } from '../src/modules/basic-messages' import { KeyDerivationMethod } from '../src/types' @@ -12,8 +12,8 @@ import { WalletNotFoundError } from '../src/wallet/error/WalletNotFoundError' import { getAgentOptions } from './helpers' -const aliceAgentOptions = getAgentOptions('wallet-tests-Alice', {}, getIndySdkModules()) -const bobAgentOptions = getAgentOptions('wallet-tests-Bob', {}, getIndySdkModules()) +const aliceAgentOptions = getAgentOptions('wallet-tests-Alice', {}, { askar: askarModule }) +const bobAgentOptions = getAgentOptions('wallet-tests-Bob', {}, { askar: askarModule }) describe('wallet', () => { let aliceAgent: Agent diff --git a/packages/indy-sdk-to-askar-migration/package.json b/packages/indy-sdk-to-askar-migration/package.json index a8e1c6e0a4..81ecd826df 100644 --- a/packages/indy-sdk-to-askar-migration/package.json +++ b/packages/indy-sdk-to-askar-migration/package.json @@ -30,10 +30,8 @@ "@aries-framework/node": "0.4.2" }, "devDependencies": { - "@aries-framework/indy-sdk": "0.4.2", "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1", "@hyperledger/aries-askar-shared": "^0.2.0-dev.1", - "indy-sdk": "^1.16.0-dev-1655", "rimraf": "^4.4.0", "typescript": "~4.9.5" }, diff --git a/packages/indy-sdk-to-askar-migration/src/IndySdkToAskarMigrationUpdater.ts b/packages/indy-sdk-to-askar-migration/src/IndySdkToAskarMigrationUpdater.ts index 0af8f27508..50382c0a18 100644 --- a/packages/indy-sdk-to-askar-migration/src/IndySdkToAskarMigrationUpdater.ts +++ b/packages/indy-sdk-to-askar-migration/src/IndySdkToAskarMigrationUpdater.ts @@ -119,7 +119,7 @@ export class IndySdkToAskarMigrationUpdater { /** * Location of the new wallet */ - private get newWalletPath() { + public get newWalletPath() { return `${this.fs.dataPath}/wallet/${this.walletConfig.id}/sqlite.db` } diff --git a/packages/indy-sdk-to-askar-migration/tests/indy-sdk-040-wallet.db b/packages/indy-sdk-to-askar-migration/tests/indy-sdk-040-wallet.db new file mode 100644 index 0000000000000000000000000000000000000000..1fc1e28b4080b86ad51c7bed7e72af3cf8c2c817 GIT binary patch literal 57344 zcmeI4X;f3!7RQqqWezPxQWY@{P|{u{_a=lytcnmB1q@P^Dv=>b1VLsHQ34ckU@3^G zloq9Gg(^?<30jA$l@^>=eRhecsMJ|Ro>kvdD{r45u_)H{zW9OeySU`$oPGB2`|ljR zH%kL1`)Cr?f{57oxgm)HG3z}Rhr=2#5U^M*4xBtVyABh$;C8)%SN5N--*m}gjq+Py z#`9#E8CI~&lX*LMlTAf?wh0;b(oAXDlihj6dp(b2_OL^fCP{L5_p|Jl9>U2 zoRFH@Z}J&&l>{9gv@;< zp6OfSkrh3JBg4Y1(MAS*p^%;9kQfpg{fgu6Wf{K+GsR_skK$Ea#)21zE|{<16oGG` zj}N6E?yULs@fVmupeYJ>g;Makg}>5sl8bV>z*{lho;arjUDCYtKG9F9@O1ap*>uh7 zLzBdmiirxP!q-(1pj(|_uL&1+Gk^wgQ}`&LRa{*HTwUB0ug(VgyOBov^Q_R>xF6q7 z$Y$x3N{EYw(5jH6#8}!-UG>DAWH zyzFO#p88pDr+V4X`Z2?|1nu6>`epVn`ng|E{j9fA5lwYy^g{-3iKlC^u1~Cfm99CU zpSiE~v)-h8n7*&~v)p3~FYkPj(mh`dC-kvO{1Vjv>)`erh=kwWFA-XL~H?RBE zr<-0Km!vA8AA>Mn~dj3!Cqtt0VIQjGb)wSygwFYbh{@}rEZD$SS6A%uUU9X&O zm2`~?UUubQR`aI4w#Q7&Kr*(eoCQC4AOR$R1dsp{Kmter2_OL^fCPFbu-J{wWvwtx z9|pHQ3ByKzPCGFaLo*cZD5WIuB9l|JlbB*0B@``kgln3jr7#RHPI8K&#Bd=NQ8WXm z3?}4YBbHENCzzK}QVB&YC9qfw&O}m*5s4`oyp<4p83pd7GK!`hAt+5T5D0=WUP9<@1&LsuApl_l{6IveQxhTv$%6r%oE#~FK@KNPG6p}8JWYa90D`1M zRzcBF3Hc$0a0AD98*b;k!f>Z`+ zf+vVbz|#zrL^Ob8U_=Cyy3UYOAUqKtnv0PT0|+jLVnA~mq=#10$mTAs_Evhtw!+-tL@c_+t6$DOBqEDXy(IXg0AgsLEJfK}WO&8>BtT3zp$7j0Q( z|KTRJ%%uAKf+dFDH)kr<4OJJfY5$nxa?6v`V4YNESC(?Qb*|PWcU)vkm6gYw^7OLI z-`6=gUvF+wf3c?F;d;N)o8Px>jJTP0U0pSHU%sZK+5PH2!eaanht~8RIR5LKb|)gd zE-PzR&b#fm?8)AFoD_Ngyu7KrD^c;DyDS~#5h2e9)Eu{B4zeSoa(J#8kFD!7H;XJp z+gTf?a_pKo-=qd#s@peuQmtL$G}(?tyY?I#>*y}1U-IbK-4nx0?pJ5q9Bz@c6!lTTJA3dyP zCA&@3;lJ5D++?>g`pES!iz|I&yl#ur?tQmF`h8W7^`xx@hqSYvWPiU-wRE`u)A#Of z+VkK`b<@oGgA-N$rlx-G=h8pOwGj>c=&<2OmvgVy zb!>GwZZp~IN#0~9Md|3&M?dD61dbXJSNXGMjD75&hohC@;{wXoE{-}n^z8bm8F|Aq zHg}w}jci@NZ2GVp%WYCl)gQ4ud9J{h9kH`-+pT++S6gD%&uS_h)lxaTYVf*BzE+~K zowj84>>s@A!imrYc5y~UOA_Z|=D(U)7VXH2<`}U)(^_Y)Kh{68$hLN~(9JDqVN3e% zz#-ep1CKk;&%fyvp8BBJ?9BOxm-^iG$ZH%}kTk=cef8sIRW}YSG)%tK)>2`caPxyv zDQ6aL4&0VuQy6EuBHyCcI-}inUqQ>YoSh>Bw{KXw$Nkj3{I&tX@qs%-KfLtqREwXl z#dWl=x^cI?IB;Ub%#p|I7AxB(m_IvL7ZtY;{Th zbinM>yLOak{&!5lousk-fA?x@b@v!*rOeKqySI6G>~HnSdpOD0ciE=2{dy>Jsw6#%b)j;{wt$KCJcE9<2X@Y@sfdmc zRu3M$;>@x_A7l8_jmz_3nHQT6 { test('indy-sdk sqlite to aries-askar sqlite successful migration', async () => { const indySdkAndAskarConfig: InitConfig = { - label: `indy | indy-sdk sqlite to aries-askar sqlite successful migration | ${utils.uuid()}`, + label: `indy | indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, walletConfig: { - id: `indy-sdk sqlite to aries-askar sqlite successful migration | ${utils.uuid()}`, + id: `indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, key: 'GfwU1DC7gEZNs3w41tjBiZYj7BNToDoFEqKY6wZXqs1A', keyDerivationMethod: KeyDerivationMethod.Raw, }, } - const indySdkAgent = new Agent({ - config: indySdkAndAskarConfig, - modules: { indySdk: new IndySdkModule({ indySdk: indy }) }, - dependencies: agentDependencies, - }) - const indySdkAgentDbPath = `${homedir()}/.indy_client/wallet/${indySdkAndAskarConfig.walletConfig?.id}/sqlite.db` - - const genericRecordContent = { foo: 'bar' } - - await indySdkAgent.initialize() - - const record = await indySdkAgent.genericRecords.save({ content: genericRecordContent }) - - await indySdkAgent.shutdown() - + const indySdkWalletTestPath = path.join(__dirname, 'indy-sdk-040-wallet.db') const askarAgent = new Agent({ config: indySdkAndAskarConfig, modules: { askar: askarModule }, dependencies: agentDependencies, }) - const updater = await IndySdkToAskarMigrationUpdater.initialize({ dbPath: indySdkAgentDbPath, agent: askarAgent }) - await updater.update() + // Remove new wallet path (if exists) + unlinkSync(updater.newWalletPath) + + // Create old wallet path and copy test wallet + mkdirSync(path.dirname(indySdkAgentDbPath), { recursive: true }) + copyFileSync(indySdkWalletTestPath, indySdkAgentDbPath) + + await updater.update() await askarAgent.initialize() - await expect(askarAgent.genericRecords.findById(record.id)).resolves.toMatchObject({ - content: genericRecordContent, - }) + await expect(askarAgent.genericRecords.getAll()).resolves.toMatchObject([ + { + content: { + foo: 'bar', + }, + }, + ]) await askarAgent.shutdown() }) @@ -64,36 +60,21 @@ describe('Indy SDK To Askar Migration', () => { */ test('indy-sdk sqlite to aries-askar sqlite fails and restores', async () => { const indySdkAndAskarConfig: InitConfig = { - label: `indy | indy-sdk sqlite to aries-askar sqlite fails and restores | ${utils.uuid()}`, + label: `indy | indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, walletConfig: { - id: `indy-sdk sqlite to aries-askar sqlite fails and restores | ${utils.uuid()}`, - key: 'GfwU1DC7gEZNs3w41tjBiZYj7BNToDoFEqKY6wZXqs1A', + id: `indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, + // NOTE: wrong key passed + key: 'wrong-key', keyDerivationMethod: KeyDerivationMethod.Raw, }, } - const indySdkAgent = new Agent({ - config: indySdkAndAskarConfig, - modules: { indySdk: new IndySdkModule({ indySdk: indy }) }, - dependencies: agentDependencies, - }) - const indySdkAgentDbPath = `${homedir()}/.indy_client/wallet/${indySdkAndAskarConfig.walletConfig?.id}/sqlite.db` - - const genericRecordContent = { foo: 'bar' } - - await indySdkAgent.initialize() - - const record = await indySdkAgent.genericRecords.save({ content: genericRecordContent }) - - await indySdkAgent.shutdown() + const indySdkWalletTestPath = path.join(__dirname, 'indy-sdk-040-wallet.db') const askarAgent = new Agent({ - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - config: { ...indySdkAndAskarConfig, walletConfig: { ...indySdkAndAskarConfig.walletConfig!, key: 'wrong-key' } }, - modules: { - askar: askarModule, - }, + config: indySdkAndAskarConfig, + modules: { askar: askarModule }, dependencies: agentDependencies, }) @@ -102,12 +83,14 @@ describe('Indy SDK To Askar Migration', () => { agent: askarAgent, }) - await expect(updater.update()).rejects.toThrowError(IndySdkToAskarMigrationError) + // Remove new wallet path (if exists) + unlinkSync(updater.newWalletPath) - await indySdkAgent.initialize() + // Create old wallet path and copy test wallet + mkdirSync(path.dirname(indySdkAgentDbPath), { recursive: true }) + copyFileSync(indySdkWalletTestPath, indySdkAgentDbPath) - await expect(indySdkAgent.genericRecords.findById(record.id)).resolves.toMatchObject({ - content: genericRecordContent, - }) + await expect(updater.update()).rejects.toThrowError(IndySdkToAskarMigrationError) + expect(existsSync(indySdkWalletTestPath)).toBe(true) }) }) diff --git a/packages/indy-vdr/src/anoncreds/IndyVdrAnonCredsRegistry.ts b/packages/indy-vdr/src/anoncreds/IndyVdrAnonCredsRegistry.ts index fbfaa49a0a..4a83e318df 100644 --- a/packages/indy-vdr/src/anoncreds/IndyVdrAnonCredsRegistry.ts +++ b/packages/indy-vdr/src/anoncreds/IndyVdrAnonCredsRegistry.ts @@ -444,11 +444,11 @@ export class IndyVdrAnonCredsRegistry implements AnonCredsRegistry { revocationRegistryDefinitionId: string ): Promise { try { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndyVdrPoolService) + const indyVdrPoolService = agentContext.dependencyManager.resolve(IndyVdrPoolService) const { did, namespaceIdentifier, credentialDefinitionTag, revocationRegistryTag, schemaSeqNo } = parseIndyRevocationRegistryId(revocationRegistryDefinitionId) - const { pool } = await indySdkPoolService.getPoolForDid(agentContext, did) + const { pool } = await indyVdrPoolService.getPoolForDid(agentContext, did) agentContext.config.logger.debug( `Using ledger '${pool.indyNamespace}' to retrieve revocation registry definition '${revocationRegistryDefinitionId}'` @@ -555,11 +555,11 @@ export class IndyVdrAnonCredsRegistry implements AnonCredsRegistry { timestamp: number ): Promise { try { - const indySdkPoolService = agentContext.dependencyManager.resolve(IndyVdrPoolService) + const indyVdrPoolService = agentContext.dependencyManager.resolve(IndyVdrPoolService) const { did, namespaceIdentifier, schemaSeqNo, credentialDefinitionTag, revocationRegistryTag } = parseIndyRevocationRegistryId(revocationRegistryId) - const { pool } = await indySdkPoolService.getPoolForDid(agentContext, did) + const { pool } = await indyVdrPoolService.getPoolForDid(agentContext, did) agentContext.config.logger.debug( `Using ledger '${pool.indyNamespace}' to retrieve revocation registry deltas with revocation registry definition id '${revocationRegistryId}' until ${timestamp}` diff --git a/packages/indy-vdr/src/anoncreds/utils/identifiers.ts b/packages/indy-vdr/src/anoncreds/utils/identifiers.ts index 1e9d6a8fd3..9c0afcd960 100644 --- a/packages/indy-vdr/src/anoncreds/utils/identifiers.ts +++ b/packages/indy-vdr/src/anoncreds/utils/identifiers.ts @@ -1,8 +1,3 @@ -/** - * NOTE: this file is availalbe in both the indy-sdk and indy-vdr packages. If making changes to - * this file, make sure to update both files if applicable. - */ - import { unqualifiedSchemaIdRegex, unqualifiedCredentialDefinitionIdRegex, diff --git a/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts b/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts index a3762dc96b..ee80d713e5 100644 --- a/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts +++ b/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts @@ -21,8 +21,8 @@ import { import { Subject } from 'rxjs' import { InMemoryStorageService } from '../../../../../tests/InMemoryStorageService' -import { agentDependencies, getAgentConfig, getAgentContext, indySdk, mockProperty } from '../../../../core/tests' -import { IndySdkWallet } from '../../../../indy-sdk/src' +import { RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' +import { agentDependencies, getAgentConfig, getAgentContext, mockProperty } from '../../../../core/tests' import { IndyVdrPool, IndyVdrPoolService } from '../../pool' import { IndyVdrIndyDidRegistrar } from '../IndyVdrIndyDidRegistrar' @@ -33,7 +33,11 @@ mockProperty(poolMock, 'indyNamespace', 'ns1') const agentConfig = getAgentConfig('IndyVdrIndyDidRegistrar') -const wallet = new IndySdkWallet(indySdk, agentConfig.logger, new SigningProviderRegistry([])) +const wallet = new RegisteredAskarTestWallet( + agentConfig.logger, + new agentDependencies.FileSystem(), + new SigningProviderRegistry([]) +) jest .spyOn(wallet, 'createKey') diff --git a/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts index c98a807b91..310bd0a3f1 100644 --- a/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts @@ -10,9 +10,8 @@ import { RevocationRegistryEntryRequest, } from '@hyperledger/indy-vdr-shared' +import { askarModule } from '../../askar/tests/helpers' import { agentDependencies, getAgentConfig, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' -import { IndySdkModule } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' import { IndyVdrIndyDidResolver, IndyVdrModule, IndyVdrSovDidResolver } from '../src' import { IndyVdrAnonCredsRegistry } from '../src/anoncreds/IndyVdrAnonCredsRegistry' import { IndyVdrIndyDidRegistrar } from '../src/dids/IndyVdrIndyDidRegistrar' @@ -35,9 +34,7 @@ const endorser = new Agent({ indyVdr, networks: indyVdrModuleConfig.networks, }), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrSovDidResolver(), new IndyVdrIndyDidResolver()], @@ -53,9 +50,7 @@ const agent = new Agent({ indyVdr, networks: indyVdrModuleConfig.networks, }), - indySdk: new IndySdkModule({ - indySdk, - }), + asakar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrSovDidResolver(), new IndyVdrIndyDidResolver()], diff --git a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts index 526391871f..51e2b0d428 100644 --- a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts @@ -15,10 +15,9 @@ import { import { indyVdr } from '@hyperledger/indy-vdr-nodejs' import { convertPublicKeyToX25519, generateKeyPairFromSeed } from '@stablelib/ed25519' +import { askarModule } from '../../askar/tests/helpers' import { sleep } from '../../core/src/utils/sleep' import { getAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' -import { IndySdkModule } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' import { IndyVdrModule, IndyVdrSovDidResolver } from '../src' import { IndyVdrIndyDidRegistrar } from '../src/dids/IndyVdrIndyDidRegistrar' import { IndyVdrIndyDidResolver } from '../src/dids/IndyVdrIndyDidResolver' @@ -35,9 +34,7 @@ const endorser = new Agent( networks: indyVdrModuleConfig.networks, indyVdr, }), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], @@ -54,9 +51,7 @@ const agent = new Agent( indyVdr, networks: indyVdrModuleConfig.networks, }), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], diff --git a/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts index 92068e5690..69dc27891d 100644 --- a/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts @@ -1,9 +1,8 @@ import { DidsModule, Agent, TypedArrayEncoder, JsonTransformer } from '@aries-framework/core' import { indyVdr } from '@hyperledger/indy-vdr-nodejs' +import { askarModule } from '../../askar/tests/helpers' import { getAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' -import { IndySdkModule } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' import { IndyVdrModule } from '../src' import { IndyVdrIndyDidRegistrar, IndyVdrIndyDidResolver, IndyVdrSovDidResolver } from '../src/dids' @@ -18,9 +17,7 @@ const agent = new Agent( indyVdr, networks: indyVdrModuleConfig.networks, }), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], diff --git a/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts index cc987e7888..370cdc68a0 100644 --- a/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts @@ -2,9 +2,8 @@ import { parseIndyDid } from '@aries-framework/anoncreds' import { DidsModule, Agent, TypedArrayEncoder, JsonTransformer } from '@aries-framework/core' import { indyVdr } from '@hyperledger/indy-vdr-nodejs' +import { askarModule } from '../../askar/tests/helpers' import { getAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' -import { IndySdkModule } from '../../indy-sdk/src' -import { indySdk } from '../../indy-sdk/tests/setupIndySdkModule' import { IndyVdrModule } from '../src' import { IndyVdrIndyDidRegistrar, IndyVdrIndyDidResolver, IndyVdrSovDidResolver } from '../src/dids' @@ -19,9 +18,7 @@ const agent = new Agent( indyVdr, networks: indyVdrModuleConfig.networks, }), - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], diff --git a/packages/tenants/src/__tests__/TenantAgent.test.ts b/packages/tenants/src/__tests__/TenantAgent.test.ts index 1c3bb05cc3..70172cf17b 100644 --- a/packages/tenants/src/__tests__/TenantAgent.test.ts +++ b/packages/tenants/src/__tests__/TenantAgent.test.ts @@ -1,8 +1,7 @@ import { Agent, AgentContext } from '@aries-framework/core' -import { indySdk } from '../../../core/tests' +import { askarModule } from '../../../askar/tests/helpers' import { agentDependencies, getAgentConfig, getAgentContext } from '../../../core/tests/helpers' -import { IndySdkModule } from '../../../indy-sdk/src' import { TenantAgent } from '../TenantAgent' describe('TenantAgent', () => { @@ -17,7 +16,7 @@ describe('TenantAgent', () => { }, dependencies: agentDependencies, modules: { - indySdk: new IndySdkModule({ indySdk }), + askar: askarModule, }, }) diff --git a/packages/tenants/src/__tests__/TenantsApi.test.ts b/packages/tenants/src/__tests__/TenantsApi.test.ts index 213e0cfda3..80d506631d 100644 --- a/packages/tenants/src/__tests__/TenantsApi.test.ts +++ b/packages/tenants/src/__tests__/TenantsApi.test.ts @@ -1,7 +1,7 @@ import { Agent, AgentContext, InjectionSymbols } from '@aries-framework/core' -import { indySdk, getAgentContext, getAgentOptions, mockFunction } from '../../../core/tests' -import { IndySdkModule } from '../../../indy-sdk/src' +import { askarModule } from '../../../askar/tests/helpers' +import { getAgentContext, getAgentOptions, mockFunction } from '../../../core/tests' import { TenantAgent } from '../TenantAgent' import { TenantsApi } from '../TenantsApi' import { TenantAgentContextProvider } from '../context/TenantAgentContextProvider' @@ -16,7 +16,7 @@ const AgentContextProviderMock = TenantAgentContextProvider as jest.Mock Date: Fri, 17 Nov 2023 13:35:50 +0700 Subject: [PATCH 03/19] test: fixed a lot of tests Signed-off-by: Timo Glastra --- .devcontainer/Dockerfile | 18 --- .devcontainer/devcontainer.json | 4 +- .github/actions/setup-cheqd/action.yml | 14 --- .github/actions/setup-indy-pool/action.yml | 36 ------ .github/actions/setup-libindy/action.yml | 18 --- .github/actions/setup-postgres/action.yml | 12 -- .github/workflows/continuous-deployment.yml | 8 -- .github/workflows/continuous-integration.yml | 30 +---- DEVREADME.md | 105 +++--------------- docker-compose.arm.yml | 32 ++++++ docker-compose.yml | 32 ++++++ docker/docker-compose-mediators-ngrok.yml | 19 ---- docker/docker-compose-mediators.yml | 16 --- packages/anoncreds/src/AnonCredsApi.ts | 2 +- .../legacy-indy-format-services.test.ts | 82 ++++++++++++-- .../anoncreds/tests/legacyAnonCredsSetup.ts | 7 +- packages/askar/tests/helpers.ts | 1 + .../tests/bbs-signing-provider.e2e.test.ts | 3 +- .../v2-credentials-auto-accept.e2e.test.ts | 14 ++- .../modules/dids/__tests__/DidsApi.test.ts | 7 +- .../dids/__tests__/dids-registrar.e2e.test.ts | 7 +- .../dids/__tests__/dids-resolver.e2e.test.ts | 7 +- .../modules/dids/__tests__/peer-did.test.ts | 11 +- .../v1-discover-features.e2e.test.ts | 10 +- .../v2-discover-features.e2e.test.ts | 10 +- .../__tests__/pickup.test.ts" | 14 ++- .../oob/__tests__/connect-to-self.e2e.test.ts | 6 +- packages/core/tests/helpers.ts | 35 ++++++ .../tests/migrate.test.ts | 12 +- .../tenants/src/__tests__/TenantsApi.test.ts | 9 ++ .../tenants/tests/tenant-sessions.e2e.test.ts | 10 +- 31 files changed, 277 insertions(+), 314 deletions(-) delete mode 100644 .devcontainer/Dockerfile delete mode 100644 .github/actions/setup-cheqd/action.yml delete mode 100644 .github/actions/setup-indy-pool/action.yml delete mode 100644 .github/actions/setup-libindy/action.yml delete mode 100644 .github/actions/setup-postgres/action.yml create mode 100644 docker-compose.arm.yml create mode 100644 docker-compose.yml delete mode 100644 docker/docker-compose-mediators-ngrok.yml delete mode 100644 docker/docker-compose-mediators.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 3d51f0a5a0..0000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -# arm + amd compatible Dockerfile -FROM ghcr.io/findy-network/findy-base:indy-1.16.ubuntu-18.04 AS indy-base - -FROM ubuntu:18.04 - -# install indy deps and files from base -RUN apt-get update && apt-get install -y libsodium23 libssl1.1 libzmq5 git zsh - -COPY --from=indy-base /usr/include/indy /usr/include/indy -COPY --from=indy-base /usr/lib/libindy.a /usr/lib/libindy.a -COPY --from=indy-base /usr/lib/libindy.so /usr/lib/libindy.so - -RUN apt-get install -y curl python3 build-essential ca-certificates && \ - curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash && \ - export NVM_DIR="$HOME/.nvm" && \ - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \ - nvm install v16 && \ - npm install yarn -g diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1728c1a7cc..61745b0bc6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,5 @@ { - "build": { - "dockerfile": "Dockerfile" - }, + "image": "node:18", "runArgs": ["--env-file", ".devcontainer/devcontainer.env"], "workspaceMount": "source=${localWorkspaceFolder},target=/work,type=bind", "workspaceFolder": "/work" diff --git a/.github/actions/setup-cheqd/action.yml b/.github/actions/setup-cheqd/action.yml deleted file mode 100644 index e8a64207e7..0000000000 --- a/.github/actions/setup-cheqd/action.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Setup cheqd -description: Setup a cheqd network to perform tests -author: 'daev@cheqd.io' - -runs: - using: composite - steps: - - name: Start cheqd localnet - run: docker run --rm -d -p 26657:26657 ghcr.io/cheqd/cheqd-testnet:latest - shell: bash - -branding: - icon: scissors - color: purple diff --git a/.github/actions/setup-indy-pool/action.yml b/.github/actions/setup-indy-pool/action.yml deleted file mode 100644 index 23e1ebd8cf..0000000000 --- a/.github/actions/setup-indy-pool/action.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Setup Indy Pool -description: Setup an Indy ledger pool and register test did on the ledger -author: 'timo@animo.id' - -inputs: - seed: - description: Seed to register on the ledger - required: true - endorserSeed: - description: Endorser seed to register on the ledger - required: true - -runs: - using: composite - steps: - - name: Start indy pool - run: | - docker build -f network/indy-pool.dockerfile -t indy-pool . - docker run -d --name indy-pool -p 9701-9708:9701-9708 indy-pool - shell: bash - - - name: Setup Indy CLI - run: docker exec indy-pool indy-cli-setup - shell: bash - - - name: Register Trustee DID on ledger - run: docker exec indy-pool add-did-from-seed ${{ inputs.seed }} TRUSTEE - shell: bash - - - name: Register Endorser DID on ledger - run: docker exec indy-pool add-did-from-seed ${{ inputs.endorserSeed }} ENDORSER - shell: bash - -branding: - icon: scissors - color: purple diff --git a/.github/actions/setup-libindy/action.yml b/.github/actions/setup-libindy/action.yml deleted file mode 100644 index 086635ee6c..0000000000 --- a/.github/actions/setup-libindy/action.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Setup Libindy -description: Download and install the libindy binary from the sovrin repository -author: 'timo@animo.id' - -runs: - using: composite - steps: - - name: Setup Indy - run: | - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CE7709D068DB5E88 - sudo add-apt-repository "deb https://repo.sovrin.org/sdk/deb bionic stable" - sudo apt-get update -y - sudo apt-get install -y --allow-unauthenticated libindy - shell: bash - -branding: - icon: scissors - color: purple diff --git a/.github/actions/setup-postgres/action.yml b/.github/actions/setup-postgres/action.yml deleted file mode 100644 index 6e69e6574f..0000000000 --- a/.github/actions/setup-postgres/action.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Setup Postgres -description: Setup Postgres -author: 'sairanjit.tummalapalli@ayanworks.com' - -runs: - using: composite - steps: - - name: Setup Postgres - run: | - docker pull postgres - docker run --name postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres - shell: bash diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index c7e209bfda..bb02c6e9d6 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -20,10 +20,6 @@ jobs: # pulls all commits (needed for lerna to correctly version) fetch-depth: 0 - # setup dependencies - - name: Setup Libindy - uses: ./.github/actions/setup-libindy - - name: Setup NodeJS uses: actions/setup-node@v3 with: @@ -69,10 +65,6 @@ jobs: - name: Checkout aries-framework-javascript uses: actions/checkout@v4 - # setup dependencies - - name: Setup Libindy - uses: ./.github/actions/setup-libindy - - name: Setup NodeJS uses: actions/setup-node@v3 with: diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index f004beee36..5a78ffffff 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -9,9 +9,6 @@ on: workflow_dispatch: env: - TEST_AGENT_PUBLIC_DID_SEED: 000000000000000000000000Trustee9 - ENDORSER_AGENT_PUBLIC_DID_SEED: 00000000000000000000000Endorser9 - GENESIS_TXN_PATH: network/genesis/local-genesis.txn NODE_OPTIONS: --max_old_space_size=6144 # Make sure we're not running multiple release steps at the same time as this can give issues with determining the next npm version to release. @@ -52,10 +49,6 @@ jobs: - name: Checkout aries-framework-javascript uses: actions/checkout@v4 - # setup dependencies - - name: Setup Libindy - uses: ./.github/actions/setup-libindy - - name: Setup NodeJS uses: actions/setup-node@v3 with: @@ -90,21 +83,8 @@ jobs: uses: actions/checkout@v4 # setup dependencies - - - name: Setup Libindy - uses: ./.github/actions/setup-libindy - - - name: Setup Indy Pool - uses: ./.github/actions/setup-indy-pool - with: - seed: ${TEST_AGENT_PUBLIC_DID_SEED} - endorserSeed: ${ENDORSER_AGENT_PUBLIC_DID_SEED} - - - name: Setup Cheqd - uses: ./.github/actions/setup-cheqd - - - name: Setup Postgres - uses: ./.github/actions/setup-postgres + - name: Setup services + run: docker compose up -d - name: Setup NodeJS uses: actions/setup-node@v3 @@ -116,7 +96,7 @@ jobs: run: yarn install --frozen-lockfile - name: Run tests - run: TEST_AGENT_PUBLIC_DID_SEED=${TEST_AGENT_PUBLIC_DID_SEED} ENDORSER_AGENT_PUBLIC_DID_SEED=${ENDORSER_AGENT_PUBLIC_DID_SEED} GENESIS_TXN_PATH=${GENESIS_TXN_PATH} yarn test --coverage --forceExit --bail + run: yarn test --coverage --forceExit --bail - uses: codecov/codecov-action@v3 if: always() @@ -134,10 +114,6 @@ jobs: fetch-depth: 0 persist-credentials: false - # setup dependencies - - name: Setup Libindy - uses: ./.github/actions/setup-libindy - - name: Setup NodeJS uses: actions/setup-node@v3 with: diff --git a/DEVREADME.md b/DEVREADME.md index 01581a0ea7..345955c60e 100644 --- a/DEVREADME.md +++ b/DEVREADME.md @@ -20,72 +20,18 @@ GENESIS_TXN_PATH=/work/network/genesis/local-genesis.txn Test are executed using jest. Some test require either the **mediator agents** or the **ledger** to be running. When running tests that require a connection to the ledger pool, you need to set the `TEST_AGENT_PUBLIC_DID_SEED`, `ENDORSER_AGENT_PUBLIC_DID_SEED` and `GENESIS_TXN_PATH` environment variables. -### Setting environment variables - -If you're using the setup as described in this document, you don't need to provide any environment variables as the default will be sufficient. - -- `GENESIS_TXN_PATH`: The path to the genesis transaction that allows us to connect to the indy pool. - - `GENESIS_TXN_PATH=network/genesis/local-genesis.txn` - default. Works with the [ledger setup](#setup-indy-ledger) from the previous step. - - `GENESIS_TXN_PATH=network/genesis/builder-net-genesis.txn` - Sovrin BuilderNet genesis. - - `GENESIS_TXN_PATH=/path/to/any/ledger/you/like` -- `TEST_AGENT_PUBLIC_DID_SEED`: The seed to use for the public DID. This will be used to do public write operations to the ledger. You should use a seed for a DID that is already registered on the ledger. - - If using the local or default genesis, use the same seed you used for the `add-did-from-seed` command from the [ledger setup](#setup-indy-ledger) in the previous step. (default is `000000000000000000000000Trustee9`) - - If using the BuilderNet genesis, make sure your seed is registered on the BuilderNet using [selfserve.sovrin.org](https://selfserve.sovrin.org/) and you have read and accepted the associated [Transaction Author Agreement](https://github.com/sovrin-foundation/sovrin/blob/master/TAA/TAA.md). We are not responsible for any unwanted consequences of using the BuilderNet. -- `ENDORSER_AGENT_PUBLIC_DID_SEED`: The seed to use for the public Endorser DID. This will be used to endorse transactions. You should use a seed for a DID that is already registered on the ledger. - - If using the local or default genesis, use the same seed you used for the `add-did-from-seed` command from the [ledger setup](#setup-indy-ledger) in the previous step. (default is `00000000000000000000000Endorser9`) - - If using the BuilderNet genesis, make sure your seed is registered on the BuilderNet using [selfserve.sovrin.org](https://selfserve.sovrin.org/) and you have read and accepted the associated [Transaction Author Agreement](https://github.com/sovrin-foundation/sovrin/blob/master/TAA/TAA.md). We are not responsible for any unwanted consequences of using the BuilderNet. - -### Setup Postgres - -> Note: Setup the postgres plugin first by following the [docs](https://aries.js.org/) - -```sh -# Get postgres docker image -docker pull postgres - -# Run postgres in docker -docker run --name postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres -``` - -### Setup Indy Ledger - -For testing we've added a setup to this repo that allows you to quickly setup an indy ledger. - -```sh -# Build indy pool -docker build -f network/indy-pool.dockerfile -t indy-pool . --platform linux/amd64 - -# NOTE: If you are on an ARM (M1) mac use the `network/indy-pool-arm.dockerfile` instead -# docker build -f network/indy-pool-arm.dockerfile -t indy-pool . --platform linux/arm64/v8 - -# Start indy pool -docker run -d --rm --name indy-pool -p 9701-9708:9701-9708 indy-pool - -# Setup CLI. This creates a wallet, connects to the ledger and sets the Transaction Author Agreement -docker exec indy-pool indy-cli-setup - -# DID and Verkey from seed. Set 'ENDORSER' role in order to be able to register public DIDs -docker exec indy-pool add-did-from-seed 00000000000000000000000Endorser9 ENDORSER - -# DID and Verkey from seed. Set 'Trustee' -docker exec indy-pool add-did-from-seed 000000000000000000000000Trustee9 TRUSTEE - -# If you want to register using the DID/Verkey you can use -# docker exec indy-pool add-did "NkGXDEPgpFGjQKMYmz6SyF" "CrSA1WbYYWLJoHm16Xw1VEeWxFvXtWjtsfEzMsjB5vDT" -``` - -### Setup Cheqd Ledger +### Quick Setup -In addition, there's also a docker command to run a cheqd test network. +To quickly set up all services needed to run tests (Postgres, Hyperledger Indy Ledger, and Cheqd Ledger), run the following command: ```sh -docker run --rm -d -p 26657:26657 ghcr.io/cheqd/cheqd-testnet:latest +docker compose up -d ``` -If you want to run tests without the cheqd ledger, you can use the following ignore pattern: +If you're running on an ARM based machine (such as Apple Silicon), you can use the `docker-compose.arm.yml` file instead: ```sh -yarn test --testPathIgnorePatterns packages/cheqd +docker compose -f docker-compose.arm.yml up -d ``` ### Run all tests @@ -96,34 +42,17 @@ You can run the tests using the following command. yarn test ``` -If you're not using the ledger setup from above, make sure you pass the correct environment variables from [Setting environment variables](#setting-environment-variables) for connecting to the indy **ledger** pool. - -```sh -GENESIS_TXN_PATH=network/genesis/local-genesis.txn TEST_AGENT_PUBLIC_DID_SEED=000000000000000000000000Trustee9 ENDORSER_AGENT_PUBLIC_DID_SEED=00000000000000000000000Endorser9 yarn test -``` - -Locally, you might want to run the tests without postgres tests. You can do that by ignoring the tests: - -```sh -yarn test --testPathIgnorePatterns postgres.e2e.test.ts -``` - -In case you run into trouble running the tests, e.g. complaining about snapshots not being up-to-date, you can try and remove the data stored for the indy-client or AFJ. Note this removes all wallets and data, so make sure you're okay with all data being removed. On a Unix system with default setup you achieve this by running: - -```sh -rm -rf ~/.indy-client ~/.afj -``` - -## Usage with Docker - -If you don't want to install the libindy dependencies yourself, or want a clean environment when running the framework or tests you can use docker. - -Make sure you followed the [local ledger setup](#setup-indy-ledger) to setup a local indy pool inside docker. +### Setting environment variables -```sh -# Builds the framework docker image with all dependencies installed -docker build -t aries-framework-javascript . +If you're using the setup as described in this document, you don't need to provide any environment variables as the default will be sufficient. -# Run test with ledger pool -docker run -it --rm --network host aries-framework-javascript yarn test -``` +- `GENESIS_TXN_PATH`: The path to the genesis transaction that allows us to connect to the indy pool. + - `GENESIS_TXN_PATH=network/genesis/local-genesis.txn` - default. Works with the [ledger setup](#setup-indy-ledger) from the previous step. + - `GENESIS_TXN_PATH=network/genesis/builder-net-genesis.txn` - Sovrin BuilderNet genesis. + - `GENESIS_TXN_PATH=/path/to/any/ledger/you/like` +- `TEST_AGENT_PUBLIC_DID_SEED`: The seed to use for the public DID. This will be used to do public write operations to the ledger. You should use a seed for a DID that is already registered on the ledger. + - If using the local or default genesis, use the same seed you used for the `add-did-from-seed` command from the [ledger setup](#setup-indy-ledger) in the previous step. (default is `000000000000000000000000Trustee9`) + - If using the BuilderNet genesis, make sure your seed is registered on the BuilderNet using [selfserve.sovrin.org](https://selfserve.sovrin.org/) and you have read and accepted the associated [Transaction Author Agreement](https://github.com/sovrin-foundation/sovrin/blob/master/TAA/TAA.md). We are not responsible for any unwanted consequences of using the BuilderNet. +- `ENDORSER_AGENT_PUBLIC_DID_SEED`: The seed to use for the public Endorser DID. This will be used to endorse transactions. You should use a seed for a DID that is already registered on the ledger. + - If using the local or default genesis, use the same seed you used for the `add-did-from-seed` command from the [ledger setup](#setup-indy-ledger) in the previous step. (default is `00000000000000000000000Endorser9`) + - If using the BuilderNet genesis, make sure your seed is registered on the BuilderNet using [selfserve.sovrin.org](https://selfserve.sovrin.org/) and you have read and accepted the associated [Transaction Author Agreement](https://github.com/sovrin-foundation/sovrin/blob/master/TAA/TAA.md). We are not responsible for any unwanted consequences of using the BuilderNet. diff --git a/docker-compose.arm.yml b/docker-compose.arm.yml new file mode 100644 index 0000000000..263f77baf2 --- /dev/null +++ b/docker-compose.arm.yml @@ -0,0 +1,32 @@ +version: '3' +services: + postgres: + image: postgres:15-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - '5432:5432' + + indy-pool: + build: + context: . + dockerfile: network/indy-pool-arm.dockerfile + platform: linux/arm64/v8 + ports: + - '9701-9708:9701-9708' + # Start supervisord in bg, run commands, bring supervisor to fg + command: > + /bin/bash -c " + /usr/bin/supervisord & + indy-cli-setup && + add-did-from-seed 00000000000000000000000Endorser9 ENDORSER && + add-did-from-seed 000000000000000000000000Trustee9 TRUSTEE && + /usr/bin/supervisord -n + " + + cheqd-ledger: + image: ghcr.io/cheqd/cheqd-testnet:latest + platform: linux/amd64 + ports: + - '26657:26657' diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..dc08922877 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3' +services: + postgres: + image: postgres:15-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - '5432:5432' + + indy-pool: + build: + context: . + dockerfile: network/indy-pool.dockerfile + target: linux/amd64 + ports: + - '9701-9708:9701-9708' + # Start supervisord in bg, run commands, bring supervisor to fg + command: > + /bin/bash -c " + /usr/bin/supervisord & + indy-cli-setup && + add-did-from-seed 00000000000000000000000Endorser9 ENDORSER && + add-did-from-seed 000000000000000000000000Trustee9 TRUSTEE && + /usr/bin/supervisord -n + " + + cheqd-ledger: + image: ghcr.io/cheqd/cheqd-testnet:latest + platform: linux/amd64 + ports: + - '26657:26657' diff --git a/docker/docker-compose-mediators-ngrok.yml b/docker/docker-compose-mediators-ngrok.yml deleted file mode 100644 index 36c5899b36..0000000000 --- a/docker/docker-compose-mediators-ngrok.yml +++ /dev/null @@ -1,19 +0,0 @@ -version: '3' - -# This file extends docker-compose-mediators.yml - -services: - mediator: - environment: - NGROK_NAME: mediator-ngrok - entrypoint: ./scripts/ngrok-wait.sh - depends_on: [mediator-ngrok] - - mediator-ngrok: - image: wernight/ngrok - command: ngrok http -bind-tls=true --log stdout mediator:3001 - networks: - - hyperledger - -networks: - hyperledger: diff --git a/docker/docker-compose-mediators.yml b/docker/docker-compose-mediators.yml deleted file mode 100644 index ad5f9294c5..0000000000 --- a/docker/docker-compose-mediators.yml +++ /dev/null @@ -1,16 +0,0 @@ -version: '3' - -services: - mediator: - build: .. - image: aries-framework-javascript - container_name: afj-mediator - command: yarn run-mediator - platform: linux/amd64 - networks: - - hyperledger - ports: - - 3001:3001 - -networks: - hyperledger: diff --git a/packages/anoncreds/src/AnonCredsApi.ts b/packages/anoncreds/src/AnonCredsApi.ts index 36aaf7fa19..9270bb0de3 100644 --- a/packages/anoncreds/src/AnonCredsApi.ts +++ b/packages/anoncreds/src/AnonCredsApi.ts @@ -262,7 +262,7 @@ export class AnonCredsApi { schema: schemaResult.schema, }, // NOTE: indy-sdk support has been removed from main repo, but keeping - // this in place to allow the indy-sdk to still be used as a custom package + // this in place to allow the indy-sdk to still be used as a custom package for some time // FIXME: Indy SDK requires the schema seq no to be passed in here. This is not ideal. { indyLedgerSchemaSeqNo: schemaResult.schemaMetadata.indyLedgerSeqNo, diff --git a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts index 7aa3dcf564..1185a7ee98 100644 --- a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts +++ b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts @@ -9,6 +9,7 @@ import { ProofExchangeRecord, ProofState, EventEmitter, + InjectionSymbols, } from '@aries-framework/core' import { Subject } from 'rxjs' @@ -26,7 +27,17 @@ import { indyDidFromPublicKeyBase58 } from '../../../../core/src/utils/did' import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' import { InMemoryAnonCredsRegistry } from '../../../tests/InMemoryAnonCredsRegistry' import { AnonCredsModuleConfig } from '../../AnonCredsModuleConfig' -import { AnonCredsLinkSecretRecord, AnonCredsLinkSecretRepository } from '../../repository' +import { + AnonCredsCredentialDefinitionPrivateRecord, + AnonCredsCredentialDefinitionPrivateRepository, + AnonCredsCredentialDefinitionRecord, + AnonCredsCredentialDefinitionRepository, + AnonCredsCredentialRepository, + AnonCredsKeyCorrectnessProofRecord, + AnonCredsKeyCorrectnessProofRepository, + AnonCredsLinkSecretRecord, + AnonCredsLinkSecretRepository, +} from '../../repository' import { AnonCredsHolderServiceSymbol, AnonCredsIssuerServiceSymbol, @@ -56,9 +67,19 @@ const wallet = new RegisteredAskarTestWallet( new agentDependencies.FileSystem(), new SigningProviderRegistry([]) ) -const storageService = new AskarStorageService() +const storageService = new AskarStorageService() const eventEmitter = new EventEmitter(agentDependencies, new Subject()) const anonCredsLinkSecretRepository = new AnonCredsLinkSecretRepository(storageService, eventEmitter) +const anonCredsCredentialDefinitionRepository = new AnonCredsCredentialDefinitionRepository( + storageService, + eventEmitter +) +const anonCredsCredentialDefinitionPrivateRepository = new AnonCredsCredentialDefinitionPrivateRepository( + storageService, + eventEmitter +) +const anonCredsCredentialRepository = new AnonCredsCredentialRepository(storageService, eventEmitter) +const anonCredsKeyCorrectnessProofRepository = new AnonCredsKeyCorrectnessProofRepository(storageService, eventEmitter) const agentContext = getAgentContext({ registerInstances: [ [AnonCredsIssuerServiceSymbol, anonCredsIssuerService], @@ -67,7 +88,12 @@ const agentContext = getAgentContext({ [AnonCredsRegistryService, new AnonCredsRegistryService()], [AnonCredsModuleConfig, anonCredsModuleConfig], [AnonCredsLinkSecretRepository, anonCredsLinkSecretRepository], + [AnonCredsCredentialDefinitionRepository, anonCredsCredentialDefinitionRepository], + [AnonCredsCredentialDefinitionPrivateRepository, anonCredsCredentialDefinitionPrivateRepository], + [AnonCredsCredentialRepository, anonCredsCredentialRepository], + [AnonCredsKeyCorrectnessProofRepository, anonCredsKeyCorrectnessProofRepository], [AskarModuleConfig, askarModuleConfig], + [InjectionSymbols.StorageService, storageService], [ AnonCredsRsModuleConfig, new AnonCredsRsModuleConfig({ @@ -101,11 +127,12 @@ describe('Legacy indy format services', () => { const indyDid = `did:indy:pool1:${unqualifiedIndyDid}` // Create link secret - await anonCredsHolderService.createLinkSecret(agentContext, { + const { linkSecretValue } = await anonCredsHolderService.createLinkSecret(agentContext, { linkSecretId: 'link-secret-id', }) const anonCredsLinkSecret = new AnonCredsLinkSecretRecord({ linkSecretId: 'link-secret-id', + value: linkSecretValue, }) anonCredsLinkSecret.setTag('isDefault', true) await anonCredsLinkSecretRepository.save(agentContext, anonCredsLinkSecret) @@ -122,13 +149,14 @@ describe('Legacy indy format services', () => { options: {}, }) - const { credentialDefinition } = await anonCredsIssuerService.createCredentialDefinition(agentContext, { - issuerId: indyDid, - schemaId: schemaState.schemaId as string, - schema, - tag: 'Employee Credential', - supportRevocation: false, - }) + const { credentialDefinition, credentialDefinitionPrivate, keyCorrectnessProof } = + await anonCredsIssuerService.createCredentialDefinition(agentContext, { + issuerId: indyDid, + schemaId: schemaState.schemaId as string, + schema, + tag: 'Employee Credential', + supportRevocation: false, + }) const { credentialDefinitionState } = await registry.registerCredentialDefinition(agentContext, { credentialDefinition, @@ -144,6 +172,35 @@ describe('Legacy indy format services', () => { throw new Error('Failed to create schema or credential definition') } + await anonCredsCredentialDefinitionRepository.save( + agentContext, + new AnonCredsCredentialDefinitionRecord({ + credentialDefinition, + credentialDefinitionId: credentialDefinitionState.credentialDefinitionId, + methodName: 'indy', + }) + ) + + if (!keyCorrectnessProof || !credentialDefinitionPrivate) { + throw new Error('Failed to create credential definition private or key correctness proof') + } + + await anonCredsKeyCorrectnessProofRepository.save( + agentContext, + new AnonCredsKeyCorrectnessProofRecord({ + credentialDefinitionId: credentialDefinitionState.credentialDefinitionId, + value: keyCorrectnessProof, + }) + ) + + await anonCredsCredentialDefinitionPrivateRepository.save( + agentContext, + new AnonCredsCredentialDefinitionPrivateRecord({ + credentialDefinitionId: credentialDefinitionState.credentialDefinitionId, + value: credentialDefinitionPrivate, + }) + ) + const holderCredentialRecord = new CredentialExchangeRecord({ protocolVersion: 'v1', state: CredentialState.ProposalSent, @@ -249,9 +306,10 @@ describe('Legacy indy format services', () => { }, schemaId: legacySchemaId, credentialDefinitionId: legacyCredentialDefinitionId, + // FIXME: We should be consistent in using null vs undefined revocationRegistryId: null, - credentialRevocationId: null, - methodName: 'indy', + credentialRevocationId: undefined, + methodName: 'inMemory', }) expect(holderCredentialRecord.metadata.data).toEqual({ diff --git a/packages/anoncreds/tests/legacyAnonCredsSetup.ts b/packages/anoncreds/tests/legacyAnonCredsSetup.ts index 366089c3cd..d6286b7174 100644 --- a/packages/anoncreds/tests/legacyAnonCredsSetup.ts +++ b/packages/anoncreds/tests/legacyAnonCredsSetup.ts @@ -11,6 +11,7 @@ import type { import type { AutoAcceptProof, ConnectionRecord } from '@aries-framework/core' import { + AgentEventTypes, TypedArrayEncoder, CacheModule, InMemoryLruCache, @@ -344,7 +345,11 @@ export async function setupAnonCredsTests< setupSubjectTransports(verifierAgent ? [issuerAgent, holderAgent, verifierAgent] : [issuerAgent, holderAgent]) const [issuerReplay, holderReplay, verifierReplay] = setupEventReplaySubjects( verifierAgent ? [issuerAgent, holderAgent, verifierAgent] : [issuerAgent, holderAgent], - [CredentialEventTypes.CredentialStateChanged, ProofEventTypes.ProofStateChanged] + [ + CredentialEventTypes.CredentialStateChanged, + ProofEventTypes.ProofStateChanged, + AgentEventTypes.AgentMessageProcessed, + ] ) await issuerAgent.initialize() diff --git a/packages/askar/tests/helpers.ts b/packages/askar/tests/helpers.ts index cc6d1cfeed..efae6afc68 100644 --- a/packages/askar/tests/helpers.ts +++ b/packages/askar/tests/helpers.ts @@ -16,6 +16,7 @@ import { AskarWallet } from '../src/wallet' export const askarModuleConfig = new AskarModuleConfig({ ariesAskar }) registerAriesAskar({ askar: askarModuleConfig.ariesAskar }) export const askarModule = new AskarModule(askarModuleConfig) +export { ariesAskar } // When using the AskarWallet directly, the native dependency won't be loaded by default. // So in tests depending on Askar, we import this wallet so we're sure the native dependency is loaded. diff --git a/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts b/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts index 2350dd32b2..69c6ebeb3c 100644 --- a/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts +++ b/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts @@ -7,11 +7,10 @@ import { TypedArrayEncoder, SigningProviderRegistry, } from '@aries-framework/core' -import { agentDependencies } from '@aries-framework/core/tests' import { BBS_SIGNATURE_LENGTH } from '@mattrglobal/bbs-signatures' import { RegisteredAskarTestWallet } from '../../askar/tests/helpers' -import testLogger from '../../core/tests/logger' +import { testLogger, agentDependencies } from '../../core/tests' import { Bls12381g2SigningProvider } from '../src' import { describeSkipNode17And18 } from './util' diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts index 88422a79c4..0fb3cf3e78 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts @@ -2,11 +2,16 @@ import type { AnonCredsTestsAgent } from '../../../../../../../anoncreds/tests/l import type { EventReplaySubject } from '../../../../../../tests' import { setupAnonCredsTests } from '../../../../../../../anoncreds/tests/legacyAnonCredsSetup' -import { waitForCredentialRecord, waitForCredentialRecordSubject } from '../../../../../../tests/helpers' +import { + waitForCredentialRecord, + waitForCredentialRecordSubject, + waitForMessageProcessedSubject, +} from '../../../../../../tests/helpers' import testLogger from '../../../../../../tests/logger' import { AutoAcceptCredential } from '../../../models/CredentialAutoAcceptType' import { CredentialState } from '../../../models/CredentialState' import { CredentialExchangeRecord } from '../../../repository/CredentialExchangeRecord' +import { V2ProposeCredentialMessage } from '../messages' import { V2CredentialPreview } from '../messages/V2CredentialPreview' describe('V2 Credentials Auto Accept', () => { @@ -435,6 +440,13 @@ describe('V2 Credentials Auto Accept', () => { state: CredentialState.ProposalReceived, threadId: aliceCredentialRecord.threadId, }) + + // ProposalReceived is emitted before the whole message is finished processing + // So to not get errors when shutting down the agent, we wait for the message to be processed + await waitForMessageProcessedSubject(faberReplay, { + threadId: aliceCredentialRecord.threadId, + messageClass: V2ProposeCredentialMessage, + }) }) }) }) diff --git a/packages/core/src/modules/dids/__tests__/DidsApi.test.ts b/packages/core/src/modules/dids/__tests__/DidsApi.test.ts index 41993e9d43..4e207b1a64 100644 --- a/packages/core/src/modules/dids/__tests__/DidsApi.test.ts +++ b/packages/core/src/modules/dids/__tests__/DidsApi.test.ts @@ -1,5 +1,4 @@ -import { IndySdkModule } from '../../../../../indy-sdk/src' -import { indySdk } from '../../../../tests' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' @@ -9,9 +8,7 @@ const agentOptions = getAgentOptions( 'DidsApi', {}, { - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, } ) diff --git a/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts b/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts index 590933f882..dc214cbae8 100644 --- a/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts +++ b/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts @@ -1,8 +1,7 @@ import type { KeyDidCreateOptions } from '../methods/key/KeyDidRegistrar' import type { PeerDidNumAlgo0CreateOptions } from '../methods/peer/PeerDidRegistrar' -import { IndySdkModule } from '../../../../../indy-sdk/src' -import { indySdk } from '../../../../tests' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { KeyType } from '../../../crypto' @@ -14,9 +13,7 @@ const agentOptions = getAgentOptions( 'Faber Dids Registrar', {}, { - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, } ) diff --git a/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts b/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts index 3e46ada4f0..dcb6f8ff20 100644 --- a/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts +++ b/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts @@ -1,5 +1,4 @@ -import { IndySdkModule } from '../../../../../indy-sdk/src' -import { indySdk } from '../../../../tests' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { JsonTransformer } from '../../../utils' @@ -9,9 +8,7 @@ const agent = new Agent( 'Faber Dids', {}, { - indySdk: new IndySdkModule({ - indySdk, - }), + askar: askarModule, } ) ) diff --git a/packages/core/src/modules/dids/__tests__/peer-did.test.ts b/packages/core/src/modules/dids/__tests__/peer-did.test.ts index 566e580d17..67a873c5ca 100644 --- a/packages/core/src/modules/dids/__tests__/peer-did.test.ts +++ b/packages/core/src/modules/dids/__tests__/peer-did.test.ts @@ -4,9 +4,8 @@ import type { Wallet } from '../../../wallet' import { Subject } from 'rxjs' import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' -import { IndySdkWallet } from '../../../../../indy-sdk/src' -import { indySdk } from '../../../../../indy-sdk/tests/setupIndySdkModule' -import { getAgentConfig, getAgentContext } from '../../../../tests/helpers' +import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' +import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../tests/helpers' import { EventEmitter } from '../../../agent/EventEmitter' import { InjectionSymbols } from '../../../constants' import { Key, KeyType } from '../../../crypto' @@ -41,7 +40,11 @@ describe('peer dids', () => { let eventEmitter: EventEmitter beforeEach(async () => { - wallet = new IndySdkWallet(indySdk, config.logger, new SigningProviderRegistry([])) + wallet = new RegisteredAskarTestWallet( + config.logger, + new agentDependencies.FileSystem(), + new SigningProviderRegistry([]) + ) const storageService = new InMemoryStorageService() eventEmitter = new EventEmitter(config.agentDependencies, new Subject()) didRepository = new DidRepository(storageService, eventEmitter) diff --git a/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts b/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts index 68fb1a0103..4b5ddd9fb3 100644 --- a/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts +++ b/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts @@ -6,7 +6,7 @@ import type { import { ReplaySubject } from 'rxjs' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' import { getAgentOptions, makeConnection } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' @@ -19,7 +19,9 @@ const faberAgentOptions = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getIndySdkModules() + { + askar: askarModule, + } ) const aliceAgentOptions = getAgentOptions( @@ -27,7 +29,9 @@ const aliceAgentOptions = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getIndySdkModules() + { + askar: askarModule, + } ) describe('v1 discover features', () => { diff --git a/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts b/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts index f5a4b9f782..00f0c5cfb1 100644 --- a/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts +++ b/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts @@ -6,7 +6,7 @@ import type { import { ReplaySubject } from 'rxjs' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' import { getAgentOptions, makeConnection } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' @@ -20,7 +20,9 @@ const faberAgentOptions = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getIndySdkModules() + { + askar: askarModule, + } ) const aliceAgentOptions = getAgentOptions( @@ -28,7 +30,9 @@ const aliceAgentOptions = getAgentOptions( { endpoints: ['rxjs:alice'], }, - getIndySdkModules() + { + askar: askarModule, + } ) describe('v2 discover features', () => { diff --git "a/packages/core/src/modules/message-p\303\254ckup/__tests__/pickup.test.ts" "b/packages/core/src/modules/message-p\303\254ckup/__tests__/pickup.test.ts" index 6285f2828d..d772960b31 100644 --- "a/packages/core/src/modules/message-p\303\254ckup/__tests__/pickup.test.ts" +++ "b/packages/core/src/modules/message-p\303\254ckup/__tests__/pickup.test.ts" @@ -5,18 +5,26 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions, waitForBasicMessage, waitForTrustPingReceivedEvent } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { HandshakeProtocol } from '../../connections' -const recipientOptions = getAgentOptions('Mediation: Recipient Pickup', {}, getIndySdkModules()) +const recipientOptions = getAgentOptions( + 'Mediation: Recipient Pickup', + {}, + { + askar: askarModule, + } +) const mediatorOptions = getAgentOptions( 'Mediation: Mediator Pickup', { endpoints: ['wss://mediator'], }, - getIndySdkModules() + { + askar: askarModule, + } ) describe('E2E Pick Up protocol', () => { diff --git a/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts b/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts index 59ea798c98..a9c0cd37d1 100644 --- a/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts +++ b/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts @@ -5,7 +5,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions } from '../../../../tests/helpers' import { HandshakeProtocol, DidExchangeState } from '../../connections' import { OutOfBandState } from '../domain/OutOfBandState' @@ -17,7 +17,9 @@ const faberAgentOptions = getAgentOptions( { endpoints: ['rxjs:faber'], }, - getIndySdkModules() + { + askar: askarModule, + } ) describe('out of band', () => { diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts index 81cfcdcfde..fdde8fb551 100644 --- a/packages/core/tests/helpers.ts +++ b/packages/core/tests/helpers.ts @@ -14,7 +14,9 @@ import type { CredentialState, ConnectionStateChangedEvent, Buffer, + AgentMessageProcessedEvent, } from '../src' +import type { ConstructableAgentMessage } from '../src/agent/AgentMessage' import type { AgentModulesInput, EmptyModuleMap } from '../src/agent/AgentModules' import type { TrustPingReceivedEvent, TrustPingResponseReceivedEvent } from '../src/modules/connections/TrustPingEvents' import type { ProofState } from '../src/modules/proofs/models/ProofState' @@ -28,6 +30,8 @@ import { catchError, filter, map, take, timeout } from 'rxjs/operators' import { agentDependencies } from '../../node/src' import { + AgentEventTypes, + parseMessageType, OutOfBandDidCommService, ConnectionsModule, ConnectionEventTypes, @@ -52,6 +56,7 @@ import { OutOfBandState } from '../src/modules/oob/domain/OutOfBandState' import { OutOfBandInvitation } from '../src/modules/oob/messages' import { OutOfBandRecord } from '../src/modules/oob/repository' import { KeyDerivationMethod } from '../src/types' +import { supportsIncomingMessageType } from '../src/utils/messageType' import { uuid } from '../src/utils/uuid' import testLogger, { TestLogger } from './logger' @@ -300,6 +305,36 @@ export function waitForTrustPingResponseReceivedEventSubject( ) } +export function waitForMessageProcessedSubject( + subject: ReplaySubject | Observable, + { + threadId, + messageClass, + timeoutMs = 10000, + }: { + threadId?: string + messageClass: ConstructableAgentMessage + timeoutMs?: number + } +) { + const observable = subject instanceof ReplaySubject ? subject.asObservable() : subject + + return firstValueFrom( + observable.pipe( + filter((e): e is AgentMessageProcessedEvent => e.type === AgentEventTypes.AgentMessageProcessed), + filter((e) => threadId === undefined || e.payload.message.threadId === threadId), + filter((e) => supportsIncomingMessageType(parseMessageType(e.payload.message.type), messageClass.type)), + timeout(timeoutMs), + catchError(() => { + throw new Error(`AgentMessageProcessed event not emitted within specified timeout: { + previousState: ${messageClass.type.messageTypeUri}, + threadId: ${threadId} +}`) + }) + ) + ) +} + export function waitForCredentialRecordSubject( subject: ReplaySubject | Observable, { diff --git a/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts b/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts index d82d9cdf53..2f5ad21b8e 100644 --- a/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts +++ b/packages/indy-sdk-to-askar-migration/tests/migrate.test.ts @@ -13,9 +13,9 @@ import { IndySdkToAskarMigrationError } from '../src/errors/IndySdkToAskarMigrat describe('Indy SDK To Askar Migration', () => { test('indy-sdk sqlite to aries-askar sqlite successful migration', async () => { const indySdkAndAskarConfig: InitConfig = { - label: `indy | indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, + label: `indy | indy-sdk sqlite to aries-askar sqlite successful migration`, walletConfig: { - id: `indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, + id: `indy-sdk sqlite to aries-askar sqlite successful migration`, key: 'GfwU1DC7gEZNs3w41tjBiZYj7BNToDoFEqKY6wZXqs1A', keyDerivationMethod: KeyDerivationMethod.Raw, }, @@ -31,7 +31,7 @@ describe('Indy SDK To Askar Migration', () => { const updater = await IndySdkToAskarMigrationUpdater.initialize({ dbPath: indySdkAgentDbPath, agent: askarAgent }) // Remove new wallet path (if exists) - unlinkSync(updater.newWalletPath) + if (existsSync(updater.newWalletPath)) unlinkSync(updater.newWalletPath) // Create old wallet path and copy test wallet mkdirSync(path.dirname(indySdkAgentDbPath), { recursive: true }) @@ -60,9 +60,9 @@ describe('Indy SDK To Askar Migration', () => { */ test('indy-sdk sqlite to aries-askar sqlite fails and restores', async () => { const indySdkAndAskarConfig: InitConfig = { - label: `indy | indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, + label: `indy | indy-sdk sqlite to aries-askar sqlite fails and restores`, walletConfig: { - id: `indy-sdk sqlite to aries-askar sqlite successful migration | e9484a22-6f8c-4e35-88c5-83cc1a7f77b4`, + id: `indy-sdk sqlite to aries-askar sqlite fails and restores`, // NOTE: wrong key passed key: 'wrong-key', keyDerivationMethod: KeyDerivationMethod.Raw, @@ -84,7 +84,7 @@ describe('Indy SDK To Askar Migration', () => { }) // Remove new wallet path (if exists) - unlinkSync(updater.newWalletPath) + if (existsSync(updater.newWalletPath)) unlinkSync(updater.newWalletPath) // Create old wallet path and copy test wallet mkdirSync(path.dirname(indySdkAgentDbPath), { recursive: true }) diff --git a/packages/tenants/src/__tests__/TenantsApi.test.ts b/packages/tenants/src/__tests__/TenantsApi.test.ts index 80d506631d..9dbad0f527 100644 --- a/packages/tenants/src/__tests__/TenantsApi.test.ts +++ b/packages/tenants/src/__tests__/TenantsApi.test.ts @@ -47,6 +47,9 @@ describe('TenantsApi', () => { expect(tenantAgent.wallet.walletConfig).toEqual({ id: 'Wallet: TenantsApi: tenant-id', key: 'Wallet: TenantsApi: tenant-id', + storage: { + type: 'sqlite', + }, }) expect(agentContextProvider.getAgentContextForContextCorrelationId).toBeCalledWith('tenant-id') @@ -85,6 +88,9 @@ describe('TenantsApi', () => { expect(tenantAgent.wallet.walletConfig).toEqual({ id: 'Wallet: TenantsApi: tenant-id', key: 'Wallet: TenantsApi: tenant-id', + storage: { + type: 'sqlite', + }, }) expect(agentContextProvider.getAgentContextForContextCorrelationId).toBeCalledWith('tenant-id') @@ -124,6 +130,9 @@ describe('TenantsApi', () => { expect(tenantAgent.wallet.walletConfig).toEqual({ id: 'Wallet: TenantsApi: tenant-id', key: 'Wallet: TenantsApi: tenant-id', + storage: { + type: 'sqlite', + }, }) expect(agentContextProvider.getAgentContextForContextCorrelationId).toBeCalledWith('tenant-id') diff --git a/packages/tenants/tests/tenant-sessions.e2e.test.ts b/packages/tenants/tests/tenant-sessions.e2e.test.ts index ad77d8a42f..9f4841e05b 100644 --- a/packages/tenants/tests/tenant-sessions.e2e.test.ts +++ b/packages/tenants/tests/tenant-sessions.e2e.test.ts @@ -3,7 +3,8 @@ import type { InitConfig } from '@aries-framework/core' import { ConnectionsModule, Agent } from '@aries-framework/core' import { agentDependencies } from '@aries-framework/node' -import { askarModule } from '../../askar/tests/helpers' +import { AskarModule, AskarMultiWalletDatabaseScheme } from '../../askar/src' +import { ariesAskar } from '../../askar/tests/helpers' import { testLogger } from '../../core/tests' import { TenantsModule } from '@aries-framework/tenants' @@ -24,7 +25,10 @@ const agent = new Agent({ dependencies: agentDependencies, modules: { tenants: new TenantsModule({ sessionAcquireTimeout: 10000 }), - askar: askarModule, + askar: new AskarModule({ + ariesAskar, + multiWalletDatabaseScheme: AskarMultiWalletDatabaseScheme.ProfilePerWallet, + }), connections: new ConnectionsModule({ autoAcceptConnections: true, }), @@ -61,6 +65,8 @@ describe('Tenants Sessions E2E', () => { await Promise.all(tenantAgents.map((tenantAgent) => tenantAgent.endSession())) }) + // FIXME: this test is somehow failing? It first creates the TenantRecord, + // and then it can't fine the profile (of the root wallet) when it fetches it? test('create 5 sessions each for 20 tenants in parallel and close them', async () => { const numberOfTenants = 20 const numberOfSessions = 5 From 762667a6498e19753b931701582ef498dbd9bfc2 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Tue, 12 Dec 2023 22:29:29 +0700 Subject: [PATCH 04/19] lot more updates Signed-off-by: Timo Glastra --- DEVREADME.md | 4 +- .../src/updates/__tests__/0.3.test.ts | 12 +- .../__tests__/__snapshots__/0.3.test.ts.snap | 8 +- packages/anoncreds/tests/anoncreds.test.ts | 49 +++-- .../askar/src/storage/AskarStorageService.ts | 2 +- packages/askar/src/utils/askarWalletConfig.ts | 44 +++-- packages/askar/src/wallet/AskarWallet.ts | 9 +- .../AskarWalletPostgresStorageConfig.ts | 22 --- .../src/wallet/AskarWalletStorageConfig.ts | 47 +++++ packages/askar/src/wallet/index.ts | 2 +- .../askar/tests/askar-postgres.e2e.test.ts | 18 +- packages/askar/tests/helpers.ts | 11 ++ .../message-pickup/__tests__/pickup.test.ts | 14 +- .../routing/__tests__/mediation.test.ts | 12 +- .../storage/migration/__tests__/0.2.test.ts | 2 +- .../__tests__/__snapshots__/0.2.test.ts.snap | 22 +-- .../migration/__tests__/backup-askar.test.ts | 6 +- .../migration/__tests__/backup.test.ts | 14 +- packages/core/tests/helpers.ts | 30 ++- packages/core/tests/wallet.test.ts | 186 ------------------ .../src/__tests__/SdJwtVcService.test.ts | 27 +-- packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts | 29 +-- .../TenantSessionCoordinator.test.ts | 20 +- .../tenants/tests/tenant-sessions.e2e.test.ts | 21 +- .../tests/tenants-askar-profiles.e2e.test.ts | 12 +- packages/tenants/tests/tenants.e2e.test.ts | 12 +- 26 files changed, 263 insertions(+), 372 deletions(-) delete mode 100644 packages/askar/src/wallet/AskarWalletPostgresStorageConfig.ts create mode 100644 packages/askar/src/wallet/AskarWalletStorageConfig.ts delete mode 100644 packages/core/tests/wallet.test.ts diff --git a/DEVREADME.md b/DEVREADME.md index 345955c60e..2f47a96fb3 100644 --- a/DEVREADME.md +++ b/DEVREADME.md @@ -18,7 +18,9 @@ GENESIS_TXN_PATH=/work/network/genesis/local-genesis.txn ## Running tests -Test are executed using jest. Some test require either the **mediator agents** or the **ledger** to be running. When running tests that require a connection to the ledger pool, you need to set the `TEST_AGENT_PUBLIC_DID_SEED`, `ENDORSER_AGENT_PUBLIC_DID_SEED` and `GENESIS_TXN_PATH` environment variables. +Test are executed using jest. Some test require the **indy ledger**, **cheqd ledger** or **postgres database** to be running. + +When running tests that require a connection to the indy ledger pool, you can set the `TEST_AGENT_PUBLIC_DID_SEED`, `ENDORSER_AGENT_PUBLIC_DID_SEED` and `GENESIS_TXN_PATH` environment variables. ### Quick Setup diff --git a/packages/anoncreds/src/updates/__tests__/0.3.test.ts b/packages/anoncreds/src/updates/__tests__/0.3.test.ts index a2542f7694..666b6fb7c6 100644 --- a/packages/anoncreds/src/updates/__tests__/0.3.test.ts +++ b/packages/anoncreds/src/updates/__tests__/0.3.test.ts @@ -4,7 +4,7 @@ import path from 'path' import { InMemoryStorageService } from '../../../../../tests/InMemoryStorageService' import { RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' -import { agentDependencies } from '../../../../core/tests' +import { agentDependencies, getAskarWalletConfig } from '../../../../core/tests' import { InMemoryAnonCredsRegistry } from '../../../tests/InMemoryAnonCredsRegistry' import { AnonCredsModule } from '../../AnonCredsModule' import { @@ -41,10 +41,7 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { { config: { label: 'Test Agent', - walletConfig: { - id: `Wallet: 0.3 Update AnonCreds - Holder`, - key: `Key: 0.3 Update AnonCreds - Holder`, - }, + walletConfig: getAskarWalletConfig('0.3 Update AnonCreds - Holder', { inMemory: false, random: 'static' }), }, dependencies: agentDependencies, modules: { @@ -116,10 +113,7 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { { config: { label: 'Test Agent', - walletConfig: { - id: `Wallet: 0.3 Update AnonCreds - Issuer`, - key: `Key: 0.3 Update AnonCreds - Issuer`, - }, + walletConfig: getAskarWalletConfig('0.3 Update AnonCreds - Issuer', { inMemory: false, random: 'static' }), }, dependencies: agentDependencies, modules: { diff --git a/packages/anoncreds/src/updates/__tests__/__snapshots__/0.3.test.ts.snap b/packages/anoncreds/src/updates/__tests__/__snapshots__/0.3.test.ts.snap index d6061e5889..5deeb55c0d 100644 --- a/packages/anoncreds/src/updates/__tests__/__snapshots__/0.3.test.ts.snap +++ b/packages/anoncreds/src/updates/__tests__/__snapshots__/0.3.test.ts.snap @@ -6,7 +6,7 @@ exports[`UpdateAssistant | AnonCreds | v0.3.1 - v0.4 should correctly update the "id": "1-4e4f-41d9-94c4-f49351b811f1", "tags": { "isDefault": true, - "linkSecretId": "Wallet: 0.3 Update AnonCreds - Holder", + "linkSecretId": "Wallet: 0.3 Update AnonCreds - Holder - static", }, "type": "AnonCredsLinkSecretRecord", "value": { @@ -14,7 +14,7 @@ exports[`UpdateAssistant | AnonCreds | v0.3.1 - v0.4 should correctly update the "isDefault": true, }, "id": "1-4e4f-41d9-94c4-f49351b811f1", - "linkSecretId": "Wallet: 0.3 Update AnonCreds - Holder", + "linkSecretId": "Wallet: 0.3 Update AnonCreds - Holder - static", "metadata": {}, "updatedAt": "2023-03-19T22:50:20.522Z", "value": undefined, @@ -345,7 +345,7 @@ exports[`UpdateAssistant | AnonCreds | v0.3.1 - v0.4 should correctly update the "id": "1-4e4f-41d9-94c4-f49351b811f1", "tags": { "isDefault": true, - "linkSecretId": "Wallet: 0.3 Update AnonCreds - Issuer", + "linkSecretId": "Wallet: 0.3 Update AnonCreds - Issuer - static", }, "type": "AnonCredsLinkSecretRecord", "value": { @@ -353,7 +353,7 @@ exports[`UpdateAssistant | AnonCreds | v0.3.1 - v0.4 should correctly update the "isDefault": true, }, "id": "1-4e4f-41d9-94c4-f49351b811f1", - "linkSecretId": "Wallet: 0.3 Update AnonCreds - Issuer", + "linkSecretId": "Wallet: 0.3 Update AnonCreds - Issuer - static", "metadata": {}, "updatedAt": "2023-03-19T22:50:20.522Z", "value": undefined, diff --git a/packages/anoncreds/tests/anoncreds.test.ts b/packages/anoncreds/tests/anoncreds.test.ts index 1671d3c7b2..4a0a9603e1 100644 --- a/packages/anoncreds/tests/anoncreds.test.ts +++ b/packages/anoncreds/tests/anoncreds.test.ts @@ -1,9 +1,9 @@ -import { Agent, KeyDerivationMethod, KeyType, TypedArrayEncoder } from '@aries-framework/core' -import { agentDependencies } from '@aries-framework/node' +import { Agent, KeyType, TypedArrayEncoder } from '@aries-framework/core' import { AnonCredsRsModule } from '../../anoncreds-rs/src' import { anoncreds } from '../../anoncreds-rs/tests/helpers' import { askarModule } from '../../askar/tests/helpers' +import { getAgentOptions } from '../../core/tests' import { AnonCredsModule } from '../src' import { InMemoryAnonCredsRegistry } from './InMemoryAnonCredsRegistry' @@ -72,31 +72,26 @@ const existingRevocationStatusLists = { }, } -const agent = new Agent({ - config: { - label: '@aries-framework/anoncreds', - walletConfig: { - id: '@aries-framework/anoncreds', - key: 'CwNJroKHTSSj3XvE7ZAnuKiTn2C4QkFvxEqfm5rzhNrb', - keyDerivationMethod: KeyDerivationMethod.Raw, - }, - }, - modules: { - anoncredsRs: new AnonCredsRsModule({ anoncreds, autoCreateLinkSecret: false }), - askar: askarModule, - anoncreds: new AnonCredsModule({ - registries: [ - new InMemoryAnonCredsRegistry({ - existingSchemas, - existingCredentialDefinitions, - existingRevocationRegistryDefinitions, - existingRevocationStatusLists, - }), - ], - }), - }, - dependencies: agentDependencies, -}) +const agent = new Agent( + getAgentOptions( + 'aries-framework-anoncreds-package', + {}, + { + anoncredsRs: new AnonCredsRsModule({ anoncreds, autoCreateLinkSecret: false }), + askar: askarModule, + anoncreds: new AnonCredsModule({ + registries: [ + new InMemoryAnonCredsRegistry({ + existingSchemas, + existingCredentialDefinitions, + existingRevocationRegistryDefinitions, + existingRevocationStatusLists, + }), + ], + }), + } + ) +) describe('AnonCreds API', () => { beforeEach(async () => { diff --git a/packages/askar/src/storage/AskarStorageService.ts b/packages/askar/src/storage/AskarStorageService.ts index 17bec8917a..2a987193d5 100644 --- a/packages/askar/src/storage/AskarStorageService.ts +++ b/packages/askar/src/storage/AskarStorageService.ts @@ -116,7 +116,7 @@ export class AskarStorageService implements StorageService return recordToInstance(record, recordClass) } catch (error) { if (error instanceof RecordNotFoundError) throw error - throw new WalletError(`Error getting record`, { cause: error }) + throw new WalletError(`Error getting record ${recordClass.name}`, { cause: error }) } } diff --git a/packages/askar/src/utils/askarWalletConfig.ts b/packages/askar/src/utils/askarWalletConfig.ts index 50424bcd84..ffa096b026 100644 --- a/packages/askar/src/utils/askarWalletConfig.ts +++ b/packages/askar/src/utils/askarWalletConfig.ts @@ -1,9 +1,13 @@ -import type { AskarWalletPostgresStorageConfig } from '../wallet/AskarWalletPostgresStorageConfig' import type { WalletConfig } from '@aries-framework/core' import { KeyDerivationMethod, WalletError } from '@aries-framework/core' import { KdfMethod, StoreKeyMethod } from '@hyperledger/aries-askar-shared' +import { + isAskarWalletPostgresStorageConfig, + isAskarWalletSqliteStorageConfig, +} from '../wallet/AskarWalletStorageConfig' + export const keyDerivationMethodToStoreKeyMethod = (keyDerivationMethod: KeyDerivationMethod) => { const correspondenceTable = { [KeyDerivationMethod.Raw]: KdfMethod.Raw, @@ -32,33 +36,27 @@ export const uriFromWalletConfig = ( walletConfig.storage = { type: 'sqlite' } } - if (walletConfig.storage.type === 'sqlite') { - if (walletConfig.storage.inMemory) { + const urlParams = [] + + const storageConfig = walletConfig.storage + if (isAskarWalletSqliteStorageConfig(storageConfig)) { + if (storageConfig.config?.inMemory) { uri = 'sqlite://:memory:' } else { - path = (walletConfig.storage.path as string) ?? `${afjDataPath}/wallet/${walletConfig.id}/sqlite.db` + path = storageConfig.config?.path ?? `${afjDataPath}/wallet/${walletConfig.id}/sqlite.db` uri = `sqlite://${path}` } - } else if (walletConfig.storage.type === 'postgres') { - const storageConfig = walletConfig.storage as unknown as AskarWalletPostgresStorageConfig - + } else if (isAskarWalletPostgresStorageConfig(storageConfig)) { if (!storageConfig.config || !storageConfig.credentials) { throw new WalletError('Invalid storage configuration for postgres wallet') } - const urlParams = [] if (storageConfig.config.connectTimeout !== undefined) { urlParams.push(`connect_timeout=${encodeURIComponent(storageConfig.config.connectTimeout)}`) } if (storageConfig.config.idleTimeout !== undefined) { urlParams.push(`idle_timeout=${encodeURIComponent(storageConfig.config.idleTimeout)}`) } - if (storageConfig.config.maxConnections !== undefined) { - urlParams.push(`max_connections=${encodeURIComponent(storageConfig.config.maxConnections)}`) - } - if (storageConfig.config.minConnections !== undefined) { - urlParams.push(`min_connections=${encodeURIComponent(storageConfig.config.minConnections)}`) - } if (storageConfig.credentials.adminAccount !== undefined) { urlParams.push(`admin_account=${encodeURIComponent(storageConfig.credentials.adminAccount)}`) } @@ -69,12 +67,20 @@ export const uriFromWalletConfig = ( uri = `postgres://${encodeURIComponent(storageConfig.credentials.account)}:${encodeURIComponent( storageConfig.credentials.password )}@${storageConfig.config.host}/${encodeURIComponent(walletConfig.id)}` - - if (urlParams.length > 0) { - uri = `${uri}?${urlParams.join('&')}` - } } else { - throw new WalletError(`Storage type not supported: ${walletConfig.storage.type}`) + throw new WalletError(`Storage type not supported: ${storageConfig.type}`) + } + + // Common config options + if (storageConfig.config?.maxConnections !== undefined) { + urlParams.push(`max_connections=${encodeURIComponent(storageConfig.config.maxConnections)}`) + } + if (storageConfig.config?.minConnections !== undefined) { + urlParams.push(`min_connections=${encodeURIComponent(storageConfig.config.minConnections)}`) + } + + if (urlParams.length > 0) { + uri = `${uri}?${urlParams.join('&')}` } return { uri, path } diff --git a/packages/askar/src/wallet/AskarWallet.ts b/packages/askar/src/wallet/AskarWallet.ts index d284dbaf65..6dd3176265 100644 --- a/packages/askar/src/wallet/AskarWallet.ts +++ b/packages/askar/src/wallet/AskarWallet.ts @@ -23,6 +23,7 @@ import { AskarErrorCode, isAskarError, keyDerivationMethodToStoreKeyMethod, uriF import { AskarBaseWallet } from './AskarBaseWallet' import { AskarProfileWallet } from './AskarProfileWallet' +import { isAskarWalletSqliteStorageConfig } from './AskarWalletStorageConfig' /** * @todo: rename after 0.5.0, as we now have multiple types of AskarWallet @@ -218,7 +219,9 @@ export class AskarWallet extends AskarBaseWallet { if ( isAskarError(error) && (error.code === AskarErrorCode.NotFound || - (error.code === AskarErrorCode.Backend && walletConfig.storage?.inMemory)) + (error.code === AskarErrorCode.Backend && + isAskarWalletSqliteStorageConfig(walletConfig.storage) && + walletConfig.storage.config?.inMemory)) ) { const errorMessage = `Wallet '${walletConfig.id}' not found` this.logger.debug(errorMessage) @@ -281,6 +284,10 @@ export class AskarWallet extends AskarBaseWallet { const { path: destinationPath, key: exportKey } = exportConfig const { path: sourcePath } = uriFromWalletConfig(this.walletConfig, this.fileSystem.dataPath) + + if (isAskarWalletSqliteStorageConfig(this.walletConfig.storage) && this.walletConfig.storage?.inMemory) { + throw new WalletError('Export is not supported for in memory wallet') + } if (!sourcePath) { throw new WalletError('Export is only supported for SQLite backend') } diff --git a/packages/askar/src/wallet/AskarWalletPostgresStorageConfig.ts b/packages/askar/src/wallet/AskarWalletPostgresStorageConfig.ts deleted file mode 100644 index 2ca48f0c56..0000000000 --- a/packages/askar/src/wallet/AskarWalletPostgresStorageConfig.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { WalletStorageConfig } from '@aries-framework/core' - -export interface AskarWalletPostgresConfig { - host: string - connectTimeout?: number - idleTimeout?: number - maxConnections?: number - minConnections?: number -} - -export interface AskarWalletPostgresCredentials { - account: string - password: string - adminAccount?: string - adminPassword?: string -} - -export interface AskarWalletPostgresStorageConfig extends WalletStorageConfig { - type: 'postgres' - config: AskarWalletPostgresConfig - credentials: AskarWalletPostgresCredentials -} diff --git a/packages/askar/src/wallet/AskarWalletStorageConfig.ts b/packages/askar/src/wallet/AskarWalletStorageConfig.ts new file mode 100644 index 0000000000..5a3ab4733d --- /dev/null +++ b/packages/askar/src/wallet/AskarWalletStorageConfig.ts @@ -0,0 +1,47 @@ +import type { WalletStorageConfig } from '@aries-framework/core' + +export interface AskarWalletPostgresConfig { + host: string + connectTimeout?: number + idleTimeout?: number + maxConnections?: number + minConnections?: number +} + +export interface AskarWalletSqliteConfig { + // TODO: add other sqlite config options + maxConnections?: number + minConnections?: number + inMemory?: boolean + path?: string +} + +export interface AskarWalletPostgresCredentials { + account: string + password: string + adminAccount?: string + adminPassword?: string +} + +export interface AskarWalletPostgresStorageConfig extends WalletStorageConfig { + type: 'postgres' + config: AskarWalletPostgresConfig + credentials: AskarWalletPostgresCredentials +} + +export interface AskarWalletSqliteStorageConfig extends WalletStorageConfig { + type: 'sqlite' + config?: AskarWalletSqliteConfig +} + +export function isAskarWalletSqliteStorageConfig( + config?: WalletStorageConfig +): config is AskarWalletSqliteStorageConfig { + return config?.type === 'sqlite' +} + +export function isAskarWalletPostgresStorageConfig( + config?: WalletStorageConfig +): config is AskarWalletPostgresStorageConfig { + return config?.type === 'postgres' +} diff --git a/packages/askar/src/wallet/index.ts b/packages/askar/src/wallet/index.ts index fb71764d57..49e1da0a79 100644 --- a/packages/askar/src/wallet/index.ts +++ b/packages/askar/src/wallet/index.ts @@ -1,3 +1,3 @@ export { AskarWallet } from './AskarWallet' export { AskarProfileWallet } from './AskarProfileWallet' -export * from './AskarWalletPostgresStorageConfig' +export * from './AskarWalletStorageConfig' diff --git a/packages/askar/tests/askar-postgres.e2e.test.ts b/packages/askar/tests/askar-postgres.e2e.test.ts index a88a8a8a22..d2b87b79c4 100644 --- a/packages/askar/tests/askar-postgres.e2e.test.ts +++ b/packages/askar/tests/askar-postgres.e2e.test.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { SubjectMessage } from '../../../tests/transport/SubjectInboundTransport' -import type { AskarWalletPostgresStorageConfig } from '../src/wallet' import { Agent } from '@aries-framework/core' import { Subject } from 'rxjs' @@ -8,23 +7,12 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { e2eTest, getPostgresAgentOptions } from './helpers' +import { askarPostgresStorageConfig, e2eTest, getPostgresAgentOptions } from './helpers' -const storageConfig: AskarWalletPostgresStorageConfig = { - type: 'postgres', - config: { - host: 'localhost:5432', - }, - credentials: { - account: 'postgres', - password: 'postgres', - }, -} - -const alicePostgresAgentOptions = getPostgresAgentOptions('AgentsAlice', storageConfig, { +const alicePostgresAgentOptions = getPostgresAgentOptions('AgentsAlice', askarPostgresStorageConfig, { endpoints: ['rxjs:alice'], }) -const bobPostgresAgentOptions = getPostgresAgentOptions('AgentsBob', storageConfig, { +const bobPostgresAgentOptions = getPostgresAgentOptions('AgentsBob', askarPostgresStorageConfig, { endpoints: ['rxjs:bob'], }) diff --git a/packages/askar/tests/helpers.ts b/packages/askar/tests/helpers.ts index efae6afc68..7162ae5d52 100644 --- a/packages/askar/tests/helpers.ts +++ b/packages/askar/tests/helpers.ts @@ -28,6 +28,17 @@ export const genesisPath = process.env.GENESIS_TXN_PATH export const publicDidSeed = process.env.TEST_AGENT_PUBLIC_DID_SEED ?? '000000000000000000000000Trustee9' +export const askarPostgresStorageConfig: AskarWalletPostgresStorageConfig = { + type: 'postgres', + config: { + host: 'localhost:5432', + }, + credentials: { + account: 'postgres', + password: 'postgres', + }, +} + export function getPostgresAgentOptions( name: string, storageConfig: AskarWalletPostgresStorageConfig, diff --git a/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts b/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts index d772960b31..c035dd63fe 100644 --- a/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts +++ b/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts @@ -6,13 +6,21 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions, waitForBasicMessage, waitForTrustPingReceivedEvent } from '../../../../tests/helpers' +import { + getAgentOptions, + getAskarWalletConfig, + waitForBasicMessage, + waitForTrustPingReceivedEvent, +} from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { HandshakeProtocol } from '../../connections' const recipientOptions = getAgentOptions( 'Mediation: Recipient Pickup', - {}, + { + // Agent is shutdown during test, so we can't use in-memory wallet + walletConfig: getAskarWalletConfig('Mediation: Recipient Pickup', { inMemory: false }), + }, { askar: askarModule, } @@ -20,6 +28,8 @@ const recipientOptions = getAgentOptions( const mediatorOptions = getAgentOptions( 'Mediation: Mediator Pickup', { + // Agent is shutdown during test, so we can't use in-memory wallet + walletConfig: getAskarWalletConfig('Mediation: Mediator Pickup', { inMemory: false }), endpoints: ['wss://mediator'], }, { diff --git a/packages/core/src/modules/routing/__tests__/mediation.test.ts b/packages/core/src/modules/routing/__tests__/mediation.test.ts index 063a27e8d5..2965ad08c8 100644 --- a/packages/core/src/modules/routing/__tests__/mediation.test.ts +++ b/packages/core/src/modules/routing/__tests__/mediation.test.ts @@ -9,7 +9,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions, waitForBasicMessage } from '../../../../tests/helpers' +import { getAgentOptions, getAskarWalletConfig, waitForBasicMessage } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { sleep } from '../../../utils/sleep' import { ConnectionRecord, HandshakeProtocol } from '../../connections' @@ -18,11 +18,18 @@ import { MediatorModule } from '../MediatorModule' import { MediatorPickupStrategy } from '../MediatorPickupStrategy' import { MediationState } from '../models/MediationState' -const recipientAgentOptions = getAgentOptions('Mediation: Recipient', {}, { askar: askarModule }) +const recipientAgentOptions = getAgentOptions( + 'Mediation: Recipient', + { + walletConfig: getAskarWalletConfig('Mediation: Recipient', { inMemory: false }), + }, + { askar: askarModule } +) const mediatorAgentOptions = getAgentOptions( 'Mediation: Mediator', { endpoints: ['rxjs:mediator'], + walletConfig: getAskarWalletConfig('Mediation: Mediator', { inMemory: false }), }, { askar: askarModule, @@ -36,6 +43,7 @@ const senderAgentOptions = getAgentOptions( 'Mediation: Sender', { endpoints: ['rxjs:sender'], + walletConfig: getAskarWalletConfig('Mediation: Sender', { inMemory: false }), }, { askar: askarModule } ) diff --git a/packages/core/src/storage/migration/__tests__/0.2.test.ts b/packages/core/src/storage/migration/__tests__/0.2.test.ts index e79919750d..95ed841a1b 100644 --- a/packages/core/src/storage/migration/__tests__/0.2.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.2.test.ts @@ -10,7 +10,7 @@ import { DependencyManager } from '../../../plugins' import * as uuid from '../../../utils/uuid' import { UpdateAssistant } from '../UpdateAssistant' -const backupDate = new Date('2022-01-21T22:50:20.522Z') +const backupDate = new Date('2023-01-21T22:50:20.522Z') jest.useFakeTimers().setSystemTime(backupDate) const walletConfig = { diff --git a/packages/core/src/storage/migration/__tests__/__snapshots__/0.2.test.ts.snap b/packages/core/src/storage/migration/__tests__/__snapshots__/0.2.test.ts.snap index c4767da0c1..cf2fb076af 100644 --- a/packages/core/src/storage/migration/__tests__/__snapshots__/0.2.test.ts.snap +++ b/packages/core/src/storage/migration/__tests__/__snapshots__/0.2.test.ts.snap @@ -122,7 +122,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update proof records a "id": "STORAGE_VERSION_RECORD_ID", "metadata": {}, "storageVersion": "0.4", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "ea840186-3c77-45f4-a2e6-349811ad8994": { @@ -303,7 +303,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "1-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "created", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "2-4e4f-41d9-94c4-f49351b811f1": { @@ -366,7 +366,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "2-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "received", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "3-4e4f-41d9-94c4-f49351b811f1": { @@ -429,7 +429,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "3-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "created", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "4-4e4f-41d9-94c4-f49351b811f1": { @@ -494,7 +494,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "4-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "created", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "5-4e4f-41d9-94c4-f49351b811f1": { @@ -557,7 +557,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "5-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "received", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "6-4e4f-41d9-94c4-f49351b811f1": { @@ -620,7 +620,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "6-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "received", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "7-4e4f-41d9-94c4-f49351b811f1": { @@ -683,7 +683,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "7-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "received", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "8-4e4f-41d9-94c4-f49351b811f1": { @@ -746,7 +746,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "8-4e4f-41d9-94c4-f49351b811f1", "metadata": {}, "role": "created", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "STORAGE_VERSION_RECORD_ID": { @@ -758,7 +758,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the did records "id": "STORAGE_VERSION_RECORD_ID", "metadata": {}, "storageVersion": "0.4", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, } @@ -886,7 +886,7 @@ exports[`UpdateAssistant | v0.2 - v0.3.1 should correctly update the proofs reco "id": "STORAGE_VERSION_RECORD_ID", "metadata": {}, "storageVersion": "0.4", - "updatedAt": "2022-01-21T22:50:20.522Z", + "updatedAt": "2023-01-21T22:50:20.522Z", }, }, "ea840186-3c77-45f4-a2e6-349811ad8994": { diff --git a/packages/core/src/storage/migration/__tests__/backup-askar.test.ts b/packages/core/src/storage/migration/__tests__/backup-askar.test.ts index 1b83777bdd..97f5450983 100644 --- a/packages/core/src/storage/migration/__tests__/backup-askar.test.ts +++ b/packages/core/src/storage/migration/__tests__/backup-askar.test.ts @@ -6,7 +6,7 @@ import path from 'path' import { AskarModule } from '../../../../../askar/src' import { askarModuleConfig } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests/helpers' +import { getAgentOptions, getAskarWalletConfig } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { InjectionSymbols } from '../../../constants' import { AriesFrameworkError } from '../../../error' @@ -17,7 +17,9 @@ import { UpdateAssistant } from '../UpdateAssistant' const agentOptions = getAgentOptions( 'UpdateAssistant | Backup | Aries Askar', - {}, + { + walletConfig: getAskarWalletConfig('UpdateAssistant | Backup | Aries Askar', { inMemory: false }), + }, { askar: new AskarModule(askarModuleConfig), } diff --git a/packages/core/src/storage/migration/__tests__/backup.test.ts b/packages/core/src/storage/migration/__tests__/backup.test.ts index 15cf8ff031..6001ac2a99 100644 --- a/packages/core/src/storage/migration/__tests__/backup.test.ts +++ b/packages/core/src/storage/migration/__tests__/backup.test.ts @@ -5,7 +5,7 @@ import { readFileSync, unlinkSync } from 'fs' import path from 'path' import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests/helpers' +import { getAgentOptions, getAskarWalletConfig } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { InjectionSymbols } from '../../../constants' import { AriesFrameworkError } from '../../../error' @@ -14,7 +14,17 @@ import { JsonTransformer } from '../../../utils' import { StorageUpdateService } from '../StorageUpdateService' import { UpdateAssistant } from '../UpdateAssistant' -const agentOptions = getAgentOptions('UpdateAssistant | Backup', {}, { askar: askarModule }) +const agentOptions = getAgentOptions( + 'UpdateAssistant | Backup', + { + walletConfig: getAskarWalletConfig('UpdateAssistant | Backup', { + inMemory: false, + }), + }, + { askar: askarModule } +) +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +agentOptions.config.walletConfig!.storage!.inMemory = false const aliceCredentialRecordsString = readFileSync( path.join(__dirname, '__fixtures__/alice-4-credentials-0.1.json'), diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts index c61697956c..c299b48481 100644 --- a/packages/core/tests/helpers.ts +++ b/packages/core/tests/helpers.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ +import type { AskarWalletSqliteStorageConfig } from '../../askar/src/wallet' import type { AgentDependencies, BaseEvent, @@ -73,6 +74,29 @@ export const taaVersion = (process.env.TEST_AGENT_TAA_VERSION ?? '1') as `${numb export const taaAcceptanceMechanism = process.env.TEST_AGENT_TAA_ACCEPTANCE_MECHANISM ?? 'accept' export { agentDependencies } +export function getAskarWalletConfig( + name: string, + { + inMemory = true, + random = uuid().slice(0, 4), + maxConnections, + }: { inMemory?: boolean; random?: string; maxConnections?: number } = {} +) { + return { + id: `Wallet: ${name} - ${random}`, + key: 'DZ9hPqFWTPxemcGea72C1X1nusqk5wFNLq6QPjwXGqAa', // generated using indy.generateWalletKey + keyDerivationMethod: KeyDerivationMethod.Raw, + // Use in memory by default + storage: { + type: 'sqlite', + config: { + inMemory, + maxConnections, + }, + } satisfies AskarWalletSqliteStorageConfig, + } satisfies WalletConfig +} + export function getAgentOptions( name: string, extraConfig: Partial = {}, @@ -81,11 +105,7 @@ export function getAgentOptions { - let aliceAgent: Agent - let bobAgent: Agent - - beforeEach(async () => { - aliceAgent = new Agent(aliceAgentOptions) - bobAgent = new Agent(bobAgentOptions) - }) - - afterEach(async () => { - await aliceAgent.shutdown() - await bobAgent.shutdown() - - if (aliceAgent.wallet.isProvisioned) { - await aliceAgent.wallet.delete() - } - - if (bobAgent.wallet.isProvisioned) { - await bobAgent.wallet.delete() - } - }) - - test('open, create and open wallet with different wallet key that it is in agent config', async () => { - const walletConfig = { - id: 'mywallet', - key: 'mysecretwalletkey', - } - - try { - await aliceAgent.wallet.open(walletConfig) - } catch (error) { - if (error instanceof WalletNotFoundError) { - await aliceAgent.wallet.create(walletConfig) - await aliceAgent.wallet.open(walletConfig) - } - } - - await aliceAgent.initialize() - - expect(aliceAgent.isInitialized).toBe(true) - }) - - test('when creating already existing wallet throw WalletDuplicateError', async () => { - const walletConfig = { - id: 'mywallet', - key: 'mysecretwalletkey', - } - - await aliceAgent.wallet.create(walletConfig) - - await expect(aliceAgent.wallet.create(walletConfig)).rejects.toThrowError(WalletDuplicateError) - }) - - test('when opening non-existing wallet throw WalletNotFoundError', async () => { - const walletConfig = { - id: 'mywallet', - key: 'mysecretwalletkey', - } - - await expect(aliceAgent.wallet.open(walletConfig)).rejects.toThrowError(WalletNotFoundError) - }) - - test('when opening wallet with invalid key throw WalletInvalidKeyError', async () => { - const walletConfig = { - id: 'mywallet', - key: 'mysecretwalletkey', - } - - await aliceAgent.wallet.create(walletConfig) - await expect(aliceAgent.wallet.open({ ...walletConfig, key: 'abcd' })).rejects.toThrowError(WalletInvalidKeyError) - }) - - test('when create wallet and shutdown, wallet is closed', async () => { - const walletConfig = { - id: 'mywallet', - key: 'mysecretwalletkey', - } - - await aliceAgent.wallet.create(walletConfig) - - await aliceAgent.shutdown() - - await expect(aliceAgent.wallet.open(walletConfig)).resolves.toBeUndefined() - }) - - test('create wallet with custom key derivation method', async () => { - const walletConfig = { - id: 'mywallet', - key: 'mysecretwalletkey', - keyDerivationMethod: KeyDerivationMethod.Argon2IInt, - } - - await aliceAgent.wallet.createAndOpen(walletConfig) - - expect(aliceAgent.wallet.isInitialized).toBe(true) - }) - - test('when exporting and importing a wallet, content is copied', async () => { - await bobAgent.initialize() - const bobBasicMessageRepository = bobAgent.dependencyManager.resolve(BasicMessageRepository) - - const basicMessageRecord = new BasicMessageRecord({ - id: 'some-id', - connectionId: 'connId', - content: 'hello', - role: BasicMessageRole.Receiver, - sentTime: 'sentIt', - }) - - // Save in wallet - await bobBasicMessageRepository.save(bobAgent.context, basicMessageRecord) - - if (!bobAgent.config.walletConfig) { - throw new Error('No wallet config on bobAgent') - } - - const backupKey = 'someBackupKey' - const backupWalletName = `backup-${uuid()}` - const backupPath = path.join(tmpdir(), backupWalletName) - - // Create backup and delete wallet - await bobAgent.wallet.export({ path: backupPath, key: backupKey }) - await bobAgent.wallet.delete() - - // Initialize the wallet again and assert record does not exist - // This should create a new wallet - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await bobAgent.wallet.initialize(bobAgentOptions.config.walletConfig!) - expect(await bobBasicMessageRepository.findById(bobAgent.context, basicMessageRecord.id)).toBeNull() - await bobAgent.wallet.delete() - - // Import backup with different wallet id and initialize - await bobAgent.wallet.import({ id: backupWalletName, key: backupWalletName }, { path: backupPath, key: backupKey }) - await bobAgent.wallet.initialize({ id: backupWalletName, key: backupWalletName }) - - // Expect same basic message record to exist in new wallet - expect(await bobBasicMessageRepository.getById(bobAgent.context, basicMessageRecord.id)).toMatchObject({ - id: basicMessageRecord.id, - connectionId: basicMessageRecord.connectionId, - content: basicMessageRecord.content, - createdAt: basicMessageRecord.createdAt, - updatedAt: basicMessageRecord.updatedAt, - type: basicMessageRecord.type, - }) - }) - - test('changing wallet key', async () => { - const walletConfig = { - id: 'mywallet', - key: 'mysecretwalletkey', - } - - await aliceAgent.wallet.createAndOpen(walletConfig) - await aliceAgent.initialize() - - //Close agent - const walletConfigRekey = { - id: 'mywallet', - key: 'mysecretwalletkey', - rekey: '123', - } - - await aliceAgent.shutdown() - await aliceAgent.wallet.rotateKey(walletConfigRekey) - await aliceAgent.initialize() - - expect(aliceAgent.isInitialized).toBe(true) - }) -}) diff --git a/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts b/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts index a0347e3c46..a083e91816 100644 --- a/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts +++ b/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts @@ -7,14 +7,13 @@ import { DidsModule, KeyDidRegistrar, KeyDidResolver, - utils, KeyType, Agent, TypedArrayEncoder, } from '@aries-framework/core' import { ariesAskar } from '@hyperledger/aries-askar-nodejs' -import { agentDependencies } from '../../../core/tests' +import { getAgentOptions } from '../../../core/tests' import { SdJwtVcService } from '../SdJwtVcService' import { SdJwtVcRepository } from '../repository' @@ -27,17 +26,19 @@ import { simpleJwtVcPresentation, } from './sdjwtvc.fixtures' -const agent = new Agent({ - config: { label: 'sdjwtvcserviceagent', walletConfig: { id: utils.uuid(), key: utils.uuid() } }, - modules: { - askar: new AskarModule({ ariesAskar }), - dids: new DidsModule({ - resolvers: [new KeyDidResolver()], - registrars: [new KeyDidRegistrar()], - }), - }, - dependencies: agentDependencies, -}) +const agent = new Agent( + getAgentOptions( + 'sdjwtvcserviceagent', + {}, + { + askar: new AskarModule({ ariesAskar }), + dids: new DidsModule({ + resolvers: [new KeyDidResolver()], + registrars: [new KeyDidRegistrar()], + }), + } + ) +) const logger = jest.fn() as unknown as Logger agent.context.wallet.generateNonce = jest.fn(() => Promise.resolve('salt')) diff --git a/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts b/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts index 9db27d97fe..f75ac85219 100644 --- a/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts +++ b/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts @@ -9,26 +9,27 @@ import { KeyDidResolver, KeyType, TypedArrayEncoder, - utils, } from '@aries-framework/core' import { ariesAskar } from '@hyperledger/aries-askar-nodejs' -import { agentDependencies } from '../../core/tests' +import { getAgentOptions } from '../../core/tests' import { SdJwtVcModule } from '../src' const getAgent = (label: string) => - new Agent({ - config: { label, walletConfig: { id: utils.uuid(), key: utils.uuid() } }, - modules: { - sdJwt: new SdJwtVcModule(), - askar: new AskarModule({ ariesAskar }), - dids: new DidsModule({ - resolvers: [new KeyDidResolver()], - registrars: [new KeyDidRegistrar()], - }), - }, - dependencies: agentDependencies, - }) + new Agent( + getAgentOptions( + label, + {}, + { + sdJwt: new SdJwtVcModule(), + askar: new AskarModule({ ariesAskar }), + dids: new DidsModule({ + resolvers: [new KeyDidResolver()], + registrars: [new KeyDidRegistrar()], + }), + } + ) + ) describe('sd-jwt-vc end to end test', () => { const issuer = getAgent('sdjwtvcissueragent') diff --git a/packages/tenants/src/context/__tests__/TenantSessionCoordinator.test.ts b/packages/tenants/src/context/__tests__/TenantSessionCoordinator.test.ts index 6744ef0359..eb1706fc14 100644 --- a/packages/tenants/src/context/__tests__/TenantSessionCoordinator.test.ts +++ b/packages/tenants/src/context/__tests__/TenantSessionCoordinator.test.ts @@ -96,9 +96,15 @@ describe('TenantSessionCoordinator', () => { const tenantAgentContext = await tenantSessionCoordinator.getContextForSession(tenantRecord) - expect(wallet.initialize).toHaveBeenCalledWith(tenantRecord.config.walletConfig) + expect(wallet.initialize).toHaveBeenCalledWith({ + ...tenantRecord.config.walletConfig, + storage: { config: { inMemory: true }, type: 'sqlite' }, + }) expect(tenantSessionMutexMock.acquireSession).toHaveBeenCalledTimes(1) - expect(extendSpy).toHaveBeenCalledWith(tenantRecord.config) + expect(extendSpy).toHaveBeenCalledWith({ + ...tenantRecord.config, + walletConfig: { ...tenantRecord.config.walletConfig, storage: { config: { inMemory: true }, type: 'sqlite' } }, + }) expect(createChildSpy).toHaveBeenCalledWith() expect(tenantDependencyManager.registerInstance).toHaveBeenCalledWith(AgentContext, expect.any(AgentContext)) expect(tenantDependencyManager.registerInstance).toHaveBeenCalledWith(AgentConfig, expect.any(AgentConfig)) @@ -136,7 +142,10 @@ describe('TenantSessionCoordinator', () => { await expect(tenantSessionCoordinator.getContextForSession(tenantRecord)).rejects.toThrowError('Test error') - expect(wallet.initialize).toHaveBeenCalledWith(tenantRecord.config.walletConfig) + expect(wallet.initialize).toHaveBeenCalledWith({ + ...tenantRecord.config.walletConfig, + storage: { config: { inMemory: true }, type: 'sqlite' }, + }) expect(tenantSessionMutexMock.acquireSession).toHaveBeenCalledTimes(1) expect(tenantSessionMutexMock.releaseSession).toHaveBeenCalledTimes(1) }) @@ -192,7 +201,10 @@ describe('TenantSessionCoordinator', () => { }) // Initialize should only be called once - expect(wallet.initialize).toHaveBeenCalledWith(tenantRecord.config.walletConfig) + expect(wallet.initialize).toHaveBeenCalledWith({ + ...tenantRecord.config.walletConfig, + storage: { config: { inMemory: true }, type: 'sqlite' }, + }) expect(wallet.initialize).toHaveBeenCalledTimes(1) expect(tenantAgentContext1).toBe(tenantAgentContext2) diff --git a/packages/tenants/tests/tenant-sessions.e2e.test.ts b/packages/tenants/tests/tenant-sessions.e2e.test.ts index 9f4841e05b..aae44c9f25 100644 --- a/packages/tenants/tests/tenant-sessions.e2e.test.ts +++ b/packages/tenants/tests/tenant-sessions.e2e.test.ts @@ -5,16 +5,13 @@ import { agentDependencies } from '@aries-framework/node' import { AskarModule, AskarMultiWalletDatabaseScheme } from '../../askar/src' import { ariesAskar } from '../../askar/tests/helpers' -import { testLogger } from '../../core/tests' +import { getAskarWalletConfig, testLogger } from '../../core/tests' import { TenantsModule } from '@aries-framework/tenants' const agentConfig: InitConfig = { label: 'Tenant Agent 1', - walletConfig: { - id: 'Wallet: tenant sessions e2e agent 1', - key: 'Wallet: tenant sessions e2e agent 1', - }, + walletConfig: getAskarWalletConfig('tenant sessions e2e agent 1', { inMemory: false, maxConnections: 100 }), logger: testLogger, endpoints: ['rxjs:tenant-agent1'], } @@ -65,25 +62,25 @@ describe('Tenants Sessions E2E', () => { await Promise.all(tenantAgents.map((tenantAgent) => tenantAgent.endSession())) }) - // FIXME: this test is somehow failing? It first creates the TenantRecord, - // and then it can't fine the profile (of the root wallet) when it fetches it? + // FIXME: when creating the 100 tenants in parallel, it will error out with askar. + // For now I've fixed it by creating the tenants sequentially, but still opening all + // the sessions in parallel. However it should be fine to create the tenants in parallel + // as well, and this should be fixed in askar / AFJs wallet implementation around askar test('create 5 sessions each for 20 tenants in parallel and close them', async () => { const numberOfTenants = 20 const numberOfSessions = 5 - const tenantRecordPromises = [] + const tenantRecords = [] for (let tenantNo = 0; tenantNo < numberOfTenants; tenantNo++) { - const tenantRecord = agent.modules.tenants.createTenant({ + const tenantRecord = await agent.modules.tenants.createTenant({ config: { label: 'Agent 1 Tenant 1', }, }) - tenantRecordPromises.push(tenantRecord) + tenantRecords.push(tenantRecord) } - const tenantRecords = await Promise.all(tenantRecordPromises) - const tenantAgentPromises = [] for (const tenantRecord of tenantRecords) { for (let session = 0; session < numberOfSessions; session++) { diff --git a/packages/tenants/tests/tenants-askar-profiles.e2e.test.ts b/packages/tenants/tests/tenants-askar-profiles.e2e.test.ts index afe8bb9692..5e8607f8c9 100644 --- a/packages/tenants/tests/tenants-askar-profiles.e2e.test.ts +++ b/packages/tenants/tests/tenants-askar-profiles.e2e.test.ts @@ -5,7 +5,7 @@ import { agentDependencies } from '@aries-framework/node' import { AskarModule, AskarMultiWalletDatabaseScheme, AskarProfileWallet, AskarWallet } from '../../askar/src' import { askarModuleConfig } from '../../askar/tests/helpers' -import { testLogger } from '../../core/tests' +import { getAskarWalletConfig, testLogger } from '../../core/tests' import { TenantsModule } from '@aries-framework/tenants' @@ -13,10 +13,7 @@ describe('Tenants Askar database schemes E2E', () => { test('uses AskarWallet for all wallets and tenants when database schema is DatabasePerWallet', async () => { const agentConfig: InitConfig = { label: 'Tenant Agent 1', - walletConfig: { - id: 'Wallet: askar tenants without profiles e2e agent 1', - key: 'Wallet: askar tenants without profiles e2e agent 1', - }, + walletConfig: getAskarWalletConfig('askar tenants without profiles e2e agent 1', { inMemory: false }), logger: testLogger, } @@ -74,10 +71,7 @@ describe('Tenants Askar database schemes E2E', () => { test('uses AskarWallet for main agent, and ProfileAskarWallet for tenants', async () => { const agentConfig: InitConfig = { label: 'Tenant Agent 1', - walletConfig: { - id: 'Wallet: askar tenants with profiles e2e agent 1', - key: 'Wallet: askar tenants with profiles e2e agent 1', - }, + walletConfig: getAskarWalletConfig('askar tenants with profiles e2e agent 1'), logger: testLogger, } diff --git a/packages/tenants/tests/tenants.e2e.test.ts b/packages/tenants/tests/tenants.e2e.test.ts index 364382399c..e4daab37cf 100644 --- a/packages/tenants/tests/tenants.e2e.test.ts +++ b/packages/tenants/tests/tenants.e2e.test.ts @@ -6,26 +6,20 @@ import { agentDependencies } from '@aries-framework/node' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' import { askarModule } from '../../askar/tests/helpers' -import { testLogger } from '../../core/tests' +import { getAskarWalletConfig, testLogger } from '../../core/tests' import { TenantsModule } from '@aries-framework/tenants' const agent1Config: InitConfig = { label: 'Tenant Agent 1', - walletConfig: { - id: 'Wallet: tenants e2e agent 1', - key: 'Wallet: tenants e2e agent 1', - }, + walletConfig: getAskarWalletConfig('tenants e2e agent 1'), logger: testLogger, endpoints: ['rxjs:tenant-agent1'], } const agent2Config: InitConfig = { label: 'Tenant Agent 2', - walletConfig: { - id: 'Wallet: tenants e2e agent 2', - key: 'Wallet: tenants e2e agent 2', - }, + walletConfig: getAskarWalletConfig('tenants e2e agent 2'), logger: testLogger, endpoints: ['rxjs:tenant-agent2'], } From 770ae2f5ea91e353c5d60c820655d90d870ddb34 Mon Sep 17 00:00:00 2001 From: Ariel Gentile Date: Thu, 14 Dec 2023 11:04:06 -0300 Subject: [PATCH 05/19] fix: askar export storage config Signed-off-by: Ariel Gentile --- packages/askar/src/wallet/AskarWallet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/askar/src/wallet/AskarWallet.ts b/packages/askar/src/wallet/AskarWallet.ts index 6dd3176265..839def9699 100644 --- a/packages/askar/src/wallet/AskarWallet.ts +++ b/packages/askar/src/wallet/AskarWallet.ts @@ -302,7 +302,7 @@ export class AskarWallet extends AskarBaseWallet { const exportedWalletConfig = await this.getAskarWalletConfig({ ...this.walletConfig, key: exportKey, - storage: { type: 'sqlite', path: destinationPath }, + storage: { type: 'sqlite', config: { path: destinationPath } }, }) // Make sure destination path exists From 18e17866e1bc17c88fae331f388984cdb9704632 Mon Sep 17 00:00:00 2001 From: Ariel Gentile Date: Thu, 14 Dec 2023 11:04:43 -0300 Subject: [PATCH 06/19] test: invalid sample routing keys did Signed-off-by: Ariel Gentile --- packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts b/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts index 5f35965917..4ba9e1293c 100644 --- a/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts +++ b/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts @@ -247,14 +247,14 @@ async function createPublicDid(agent: Agent, unqualifiedSubmitterDid: string, en id: `#did-communication`, priority: 0, recipientKeys: [`#key-agreement-1`], - routingKeys: ['a-routing-key'], + routingKeys: [], serviceEndpoint: endpoint, accept: ['didcomm/aip2;env=rfc19'], }), new DidCommV2Service({ accept: ['didcomm/v2'], id: `#didcomm-1`, - routingKeys: ['a-routing-key'], + routingKeys: [], serviceEndpoint: endpoint, }), ], From e9d0863f811e699fbca829253def81bdc3d6d386 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Thu, 21 Dec 2023 15:09:09 +0700 Subject: [PATCH 07/19] temp Signed-off-by: Timo Glastra --- demo/package.json | 2 +- package.json | 5 +-- .../tests/InMemoryAnonCredsRegistry.ts | 39 +++++++++++++++---- packages/askar/package.json | 6 +-- .../indy-sdk-to-askar-migration/package.json | 6 +-- packages/sd-jwt-vc/package.json | 1 - packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts | 5 +-- .../tenants/tests/tenant-sessions.e2e.test.ts | 14 +++++-- samples/extension-module/package.json | 2 +- yarn.lock | 18 ++++----- 10 files changed, 62 insertions(+), 36 deletions(-) diff --git a/demo/package.json b/demo/package.json index 61cca53f31..c6bcb44dad 100644 --- a/demo/package.json +++ b/demo/package.json @@ -16,7 +16,7 @@ "dependencies": { "@hyperledger/indy-vdr-nodejs": "^0.2.0-dev.5", "@hyperledger/anoncreds-nodejs": "^0.2.0-dev.5", - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", "inquirer": "^8.2.5" }, "devDependencies": { diff --git a/package.json b/package.json index 376b186055..84b96b089a 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "next-version-bump": "ts-node ./scripts/get-next-bump.ts" }, "devDependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", "@types/cors": "^2.8.10", "@types/eslint": "^8.21.2", "@types/express": "^4.17.13", @@ -64,8 +64,5 @@ }, "engines": { "node": ">=18" - }, - "dependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1" } } diff --git a/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts b/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts index 2d3209b824..96d64bc656 100644 --- a/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts +++ b/packages/anoncreds/tests/InMemoryAnonCredsRegistry.ts @@ -1,18 +1,41 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import type { AgentContext } from '@aries-framework/core' import type { - AnonCredsCredentialDefinition, AnonCredsRegistry, AnonCredsRevocationRegistryDefinition, AnonCredsRevocationStatusList, AnonCredsSchema, GetCredentialDefinitionReturn, GetRevocationRegistryDefinitionReturn, - GetRevocationStatusListReturn, GetSchemaReturn, RegisterCredentialDefinitionOptions, - RegisterCredentialDefinitionReturn, RegisterRevocationRegistryDefinitionOptions, - RegisterRevocationRegistryDefinitionReturn, RegisterRevocationStatusListOptions, RegisterRevocationStatusListReturn, RegisterSchemaOptions, - RegisterSchemaReturn + AnonCredsCredentialDefinition, + AnonCredsRegistry, + AnonCredsRevocationRegistryDefinition, + AnonCredsRevocationStatusList, + AnonCredsSchema, + GetCredentialDefinitionReturn, + GetRevocationRegistryDefinitionReturn, + GetRevocationStatusListReturn, + GetSchemaReturn, + RegisterCredentialDefinitionOptions, + RegisterCredentialDefinitionReturn, + RegisterRevocationRegistryDefinitionOptions, + RegisterRevocationRegistryDefinitionReturn, + RegisterRevocationStatusListOptions, + RegisterRevocationStatusListReturn, + RegisterSchemaOptions, + RegisterSchemaReturn, } from '../src' +import type { AgentContext } from '@aries-framework/core' import { Hasher, TypedArrayEncoder } from '@aries-framework/core' import BigNumber from 'bn.js' -import { getDidIndyCredentialDefinitionId, getDidIndyRevocationRegistryId, getDidIndySchemaId } from '../../indy-vdr/src/anoncreds/utils/identifiers' -import { getUnqualifiedCredentialDefinitionId, getUnqualifiedRevocationRegistryId, getUnqualifiedSchemaId, parseIndyCredentialDefinitionId, parseIndyDid, parseIndySchemaId } from '../src' +import { + getDidIndyCredentialDefinitionId, + getDidIndyRevocationRegistryId, + getDidIndySchemaId, +} from '../../indy-vdr/src/anoncreds/utils/identifiers' +import { + getUnqualifiedCredentialDefinitionId, + getUnqualifiedRevocationRegistryId, + getUnqualifiedSchemaId, + parseIndyCredentialDefinitionId, + parseIndyDid, + parseIndySchemaId, +} from '../src' import { dateToTimestamp } from '../src/utils/timestamp' /** diff --git a/packages/askar/package.json b/packages/askar/package.json index 6a88bf3449..9df8ee2230 100644 --- a/packages/askar/package.json +++ b/packages/askar/package.json @@ -32,8 +32,8 @@ "tsyringe": "^4.8.0" }, "devDependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1", - "@hyperledger/aries-askar-shared": "^0.2.0-dev.1", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", + "@hyperledger/aries-askar-shared": "^0.2.0-dev.4", "@types/bn.js": "^5.1.0", "@types/ref-array-di": "^1.2.6", "@types/ref-struct-di": "^1.1.10", @@ -42,6 +42,6 @@ "typescript": "~4.9.5" }, "peerDependencies": { - "@hyperledger/aries-askar-shared": "^0.2.0-dev.1" + "@hyperledger/aries-askar-shared": "^0.2.0-dev.4" } } diff --git a/packages/indy-sdk-to-askar-migration/package.json b/packages/indy-sdk-to-askar-migration/package.json index 81ecd826df..db823020a9 100644 --- a/packages/indy-sdk-to-askar-migration/package.json +++ b/packages/indy-sdk-to-askar-migration/package.json @@ -30,12 +30,12 @@ "@aries-framework/node": "0.4.2" }, "devDependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1", - "@hyperledger/aries-askar-shared": "^0.2.0-dev.1", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", + "@hyperledger/aries-askar-shared": "^0.2.0-dev.4", "rimraf": "^4.4.0", "typescript": "~4.9.5" }, "peerDependencies": { - "@hyperledger/aries-askar-shared": "^0.2.0-dev.1" + "@hyperledger/aries-askar-shared": "^0.2.0-dev.4" } } diff --git a/packages/sd-jwt-vc/package.json b/packages/sd-jwt-vc/package.json index df62927318..49efb1e07b 100644 --- a/packages/sd-jwt-vc/package.json +++ b/packages/sd-jwt-vc/package.json @@ -31,7 +31,6 @@ "jwt-sd": "^0.1.2" }, "devDependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1", "reflect-metadata": "^0.1.13", "rimraf": "^4.4.0", "typescript": "~4.9.5" diff --git a/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts b/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts index f75ac85219..47dc44055c 100644 --- a/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts +++ b/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts @@ -1,6 +1,5 @@ import type { Key } from '@aries-framework/core' -import { AskarModule } from '@aries-framework/askar' import { Agent, DidKey, @@ -10,8 +9,8 @@ import { KeyType, TypedArrayEncoder, } from '@aries-framework/core' -import { ariesAskar } from '@hyperledger/aries-askar-nodejs' +import { askarModule } from '../../askar/tests/helpers' import { getAgentOptions } from '../../core/tests' import { SdJwtVcModule } from '../src' @@ -22,7 +21,7 @@ const getAgent = (label: string) => {}, { sdJwt: new SdJwtVcModule(), - askar: new AskarModule({ ariesAskar }), + askar: askarModule, dids: new DidsModule({ resolvers: [new KeyDidResolver()], registrars: [new KeyDidRegistrar()], diff --git a/packages/tenants/tests/tenant-sessions.e2e.test.ts b/packages/tenants/tests/tenant-sessions.e2e.test.ts index aae44c9f25..1ee9f16e33 100644 --- a/packages/tenants/tests/tenant-sessions.e2e.test.ts +++ b/packages/tenants/tests/tenant-sessions.e2e.test.ts @@ -1,4 +1,5 @@ import type { InitConfig } from '@aries-framework/core' +import type { TenantRecord } from '@aries-framework/tenants' import { ConnectionsModule, Agent } from '@aries-framework/core' import { agentDependencies } from '@aries-framework/node' @@ -70,17 +71,24 @@ describe('Tenants Sessions E2E', () => { const numberOfTenants = 20 const numberOfSessions = 5 - const tenantRecords = [] + const tenantRecordPromises = [] for (let tenantNo = 0; tenantNo < numberOfTenants; tenantNo++) { - const tenantRecord = await agent.modules.tenants.createTenant({ + const tenantRecordPromise = agent.modules.tenants.createTenant({ config: { label: 'Agent 1 Tenant 1', }, }) - tenantRecords.push(tenantRecord) + tenantRecordPromises.push(tenantRecordPromise) } + let tenantRecords: TenantRecord[] = [] + try { + tenantRecords = await Promise.all(tenantRecordPromises) + } catch (error) { + console.log(error.cause.code) + throw error + } const tenantAgentPromises = [] for (const tenantRecord of tenantRecords) { for (let session = 0; session < numberOfSessions; session++) { diff --git a/samples/extension-module/package.json b/samples/extension-module/package.json index fd362b0de2..26dfdf265c 100644 --- a/samples/extension-module/package.json +++ b/samples/extension-module/package.json @@ -24,6 +24,6 @@ "@types/ws": "^8.5.4", "class-validator": "0.14.0", "rxjs": "^7.2.0", - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.1" + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4" } } diff --git a/yarn.lock b/yarn.lock index 02ed7c136f..84c0e136e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1222,23 +1222,23 @@ resolved "https://registry.yarnpkg.com/@hyperledger/anoncreds-shared/-/anoncreds-shared-0.2.0-dev.5.tgz#1d6da9db5cc16ba8766fb4db1166dbe5af63e96e" integrity sha512-YtVju8WBKj3tdZbPWGjwdx7jkE5ePPfspPCvbcjIia00CWPES7UUkfjn8NVk82rq/Gi7IoWR3Jdpfv8rPe0fEA== -"@hyperledger/aries-askar-nodejs@^0.2.0-dev.1": - version "0.2.0-dev.1" - resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-nodejs/-/aries-askar-nodejs-0.2.0-dev.1.tgz#5b0fffe88438108e7ae34ac2f1f59fd31b9f1bc0" - integrity sha512-Ie1lw/4GNI1sGwNZ5ak6yV2dnhRLs7tPf1Q3CLPTsq1NtjPofsAAcwTfwDE2pYIdxCTXalC2ecy3VvXgtpllFA== +"@hyperledger/aries-askar-nodejs@^0.2.0-dev.4": + version "0.2.0-dev.4" + resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-nodejs/-/aries-askar-nodejs-0.2.0-dev.4.tgz#b43e396c5142aa84b5b2bfe2ab32245315d31265" + integrity sha512-0+UNnuHV2Tu1mN21JHuohvu47hqej8kp0dD3hk9usQMH7yAV0PW/Qkq4GVgqeoOuS3+lLuPFlnwCcsyNqMjhmg== dependencies: "@2060.io/ffi-napi" "4.0.8" "@2060.io/ref-napi" "3.0.6" - "@hyperledger/aries-askar-shared" "0.2.0-dev.1" + "@hyperledger/aries-askar-shared" "0.2.0-dev.4" "@mapbox/node-pre-gyp" "^1.0.10" node-cache "^5.1.2" ref-array-di "^1.2.2" ref-struct-di "^1.1.1" -"@hyperledger/aries-askar-shared@0.2.0-dev.1", "@hyperledger/aries-askar-shared@^0.2.0-dev.1": - version "0.2.0-dev.1" - resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-shared/-/aries-askar-shared-0.2.0-dev.1.tgz#08c36f39355cc780cc3198e1cf5fc16d871ece91" - integrity sha512-I92Aflknb2HjDuT6UOcLqJjbZLQ6nP5E2Y4F9wreTIrk+nsN++UTvbuhuIz7PFddWfrT+mFtVG3E4cHaNU10pw== +"@hyperledger/aries-askar-shared@0.2.0-dev.4", "@hyperledger/aries-askar-shared@^0.2.0-dev.4": + version "0.2.0-dev.4" + resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-shared/-/aries-askar-shared-0.2.0-dev.4.tgz#40e34d907ed4f8d59279dfba209066a1f656a9bf" + integrity sha512-GmjNH+aWCOKtw8KRaZW+MOFx8w32cIxeZ6JuB1vxpQCdH13Ac5+/rIj9T0IGgDN5u0sn9R1HV164F+LUKQjn4w== dependencies: buffer "^6.0.3" From d08a9910d1f2bf9fd4885a5380bfa2a93d16206d Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Thu, 21 Dec 2023 16:38:57 +0700 Subject: [PATCH 08/19] updates Signed-off-by: Timo Glastra --- demo/package.json | 2 +- package.json | 2 +- packages/askar/package.json | 6 +- packages/core/tests/helpers.ts | 24 +++ .../indy-sdk-to-askar-migration/package.json | 6 +- .../tests/indy-vdr-did-registrar.e2e.test.ts | 194 +++++++++--------- .../src/__tests__/SdJwtVcService.test.ts | 5 +- .../tenants/tests/tenant-sessions.e2e.test.ts | 13 +- samples/extension-module/package.json | 2 +- yarn.lock | 18 +- 10 files changed, 137 insertions(+), 135 deletions(-) diff --git a/demo/package.json b/demo/package.json index c6bcb44dad..2c28070b83 100644 --- a/demo/package.json +++ b/demo/package.json @@ -16,7 +16,7 @@ "dependencies": { "@hyperledger/indy-vdr-nodejs": "^0.2.0-dev.5", "@hyperledger/anoncreds-nodejs": "^0.2.0-dev.5", - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5", "inquirer": "^8.2.5" }, "devDependencies": { diff --git a/package.json b/package.json index 84b96b089a..c8833b3498 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "next-version-bump": "ts-node ./scripts/get-next-bump.ts" }, "devDependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5", "@types/cors": "^2.8.10", "@types/eslint": "^8.21.2", "@types/express": "^4.17.13", diff --git a/packages/askar/package.json b/packages/askar/package.json index 9df8ee2230..dbce742314 100644 --- a/packages/askar/package.json +++ b/packages/askar/package.json @@ -32,8 +32,8 @@ "tsyringe": "^4.8.0" }, "devDependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", - "@hyperledger/aries-askar-shared": "^0.2.0-dev.4", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5", + "@hyperledger/aries-askar-shared": "^0.2.0-dev.5", "@types/bn.js": "^5.1.0", "@types/ref-array-di": "^1.2.6", "@types/ref-struct-di": "^1.1.10", @@ -42,6 +42,6 @@ "typescript": "~4.9.5" }, "peerDependencies": { - "@hyperledger/aries-askar-shared": "^0.2.0-dev.4" + "@hyperledger/aries-askar-shared": "^0.2.0-dev.5" } } diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts index c299b48481..a5da390712 100644 --- a/packages/core/tests/helpers.ts +++ b/packages/core/tests/helpers.ts @@ -59,6 +59,7 @@ import { OutOfBandInvitation } from '../src/modules/oob/messages' import { OutOfBandRecord } from '../src/modules/oob/repository' import { KeyDerivationMethod } from '../src/types' import { supportsIncomingMessageType } from '../src/utils/messageType' +import { sleep } from '../src/utils/sleep' import { uuid } from '../src/utils/uuid' import testLogger, { TestLogger } from './logger' @@ -616,3 +617,26 @@ export function mockFunction any>(fn: T): jest.Moc export function mockProperty(object: T, property: K, value: T[K]) { Object.defineProperty(object, property, { get: () => value }) } + +export async function retryUntilResult Promise>( + method: M, + { + intervalMs = 500, + delay = 1000, + maxAttempts = 5, + }: { + intervalMs?: number + delay?: number + maxAttempts?: number + } = {} +): Promise { + await sleep(delay) + + for (let i = 0; i < maxAttempts; i++) { + const result = await method() + if (result) return result + await sleep(intervalMs) + } + + throw new Error(`Unable to get result from method in ${maxAttempts} attempts`) +} diff --git a/packages/indy-sdk-to-askar-migration/package.json b/packages/indy-sdk-to-askar-migration/package.json index db823020a9..6f04fc5510 100644 --- a/packages/indy-sdk-to-askar-migration/package.json +++ b/packages/indy-sdk-to-askar-migration/package.json @@ -30,12 +30,12 @@ "@aries-framework/node": "0.4.2" }, "devDependencies": { - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4", - "@hyperledger/aries-askar-shared": "^0.2.0-dev.4", + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5", + "@hyperledger/aries-askar-shared": "^0.2.0-dev.5", "rimraf": "^4.4.0", "typescript": "~4.9.5" }, "peerDependencies": { - "@hyperledger/aries-askar-shared": "^0.2.0-dev.4" + "@hyperledger/aries-askar-shared": "^0.2.0-dev.5" } } diff --git a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts index 51e2b0d428..48a2981db7 100644 --- a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts @@ -16,8 +16,7 @@ import { indyVdr } from '@hyperledger/indy-vdr-nodejs' import { convertPublicKeyToX25519, generateKeyPairFromSeed } from '@stablelib/ed25519' import { askarModule } from '../../askar/tests/helpers' -import { sleep } from '../../core/src/utils/sleep' -import { getAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' +import { getAgentOptions, importExistingIndyDidFromPrivateKey, retryUntilResult } from '../../core/tests/helpers' import { IndyVdrModule, IndyVdrSovDidResolver } from '../src' import { IndyVdrIndyDidRegistrar } from '../src/dids/IndyVdrIndyDidRegistrar' import { IndyVdrIndyDidResolver } from '../src/dids/IndyVdrIndyDidResolver' @@ -120,33 +119,31 @@ describe('Indy VDR Indy Did Registrar', () => { const did = didRegistrationResult.didState.did if (!did) throw Error('did not defined') - // Wait some time pass to let ledger settle the object - await sleep(1000) - - const didResolutionResult = await endorser.dids.resolve(did) - expect(JsonTransformer.toJSON(didResolutionResult)).toMatchObject({ - didDocument: { - '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], - id: did, - alsoKnownAs: undefined, - controller: undefined, - verificationMethod: [ - { - type: 'Ed25519VerificationKey2018', - controller: did, - id: `${did}#verkey`, - publicKeyBase58: expect.any(String), - }, - ], - capabilityDelegation: undefined, - capabilityInvocation: undefined, - authentication: [`${did}#verkey`], - service: undefined, - }, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, + // Tries to call it in an interval until it succeeds (with maxAttempts) + // As the ledger write is not always consistent in how long it takes + // to write the data, we need to retry until we get a result. + const didDocument = await retryUntilResult(async () => { + const result = await endorser.dids.resolve(did) + return result.didDocument + }) + + expect(JsonTransformer.toJSON(didDocument)).toMatchObject({ + '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], + id: did, + alsoKnownAs: undefined, + controller: undefined, + verificationMethod: [ + { + type: 'Ed25519VerificationKey2018', + controller: did, + id: `${did}#verkey`, + publicKeyBase58: expect.any(String), + }, + ], + capabilityDelegation: undefined, + capabilityInvocation: undefined, + authentication: [`${did}#verkey`], + service: undefined, }) }) @@ -232,33 +229,31 @@ describe('Indy VDR Indy Did Registrar', () => { }, }) - // Wait some time pass to let ledger settle the object - await sleep(1000) - - const didResult = await endorser.dids.resolve(did) - expect(JsonTransformer.toJSON(didResult)).toMatchObject({ - didDocument: { - '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], - id: did, - alsoKnownAs: undefined, - controller: undefined, - verificationMethod: [ - { - type: 'Ed25519VerificationKey2018', - controller: did, - id: `${did}#verkey`, - publicKeyBase58: ed25519PublicKeyBase58, - }, - ], - capabilityDelegation: undefined, - capabilityInvocation: undefined, - authentication: [`${did}#verkey`], - service: undefined, - }, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, + // Tries to call it in an interval until it succeeds (with maxAttempts) + // As the ledger write is not always consistent in how long it takes + // to write the data, we need to retry until we get a result. + const didDocument = await retryUntilResult(async () => { + const result = await endorser.dids.resolve(did) + return result.didDocument + }) + + expect(JsonTransformer.toJSON(didDocument)).toMatchObject({ + '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], + id: did, + alsoKnownAs: undefined, + controller: undefined, + verificationMethod: [ + { + type: 'Ed25519VerificationKey2018', + controller: did, + id: `${did}#verkey`, + publicKeyBase58: ed25519PublicKeyBase58, + }, + ], + capabilityDelegation: undefined, + capabilityInvocation: undefined, + authentication: [`${did}#verkey`], + service: undefined, }) }) @@ -312,33 +307,31 @@ describe('Indy VDR Indy Did Registrar', () => { }, }) - // Wait some time pass to let ledger settle the object - await sleep(1000) - - const didResult = await endorser.dids.resolve(did) - expect(JsonTransformer.toJSON(didResult)).toMatchObject({ - didDocument: { - '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], - id: did, - alsoKnownAs: undefined, - controller: undefined, - verificationMethod: [ - { - type: 'Ed25519VerificationKey2018', - controller: did, - id: `${did}#verkey`, - publicKeyBase58: ed25519PublicKeyBase58, - }, - ], - capabilityDelegation: undefined, - capabilityInvocation: undefined, - authentication: [`${did}#verkey`], - service: undefined, - }, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, + // Tries to call it in an interval until it succeeds (with maxAttempts) + // As the ledger write is not always consistent in how long it takes + // to write the data, we need to retry until we get a result. + const didDocument = await retryUntilResult(async () => { + const result = await endorser.dids.resolve(did) + return result.didDocument + }) + + expect(JsonTransformer.toJSON(didDocument)).toMatchObject({ + '@context': ['https://w3id.org/did/v1', 'https://w3id.org/security/suites/ed25519-2018/v1'], + id: did, + alsoKnownAs: undefined, + controller: undefined, + verificationMethod: [ + { + type: 'Ed25519VerificationKey2018', + controller: did, + id: `${did}#verkey`, + publicKeyBase58: ed25519PublicKeyBase58, + }, + ], + capabilityDelegation: undefined, + capabilityInvocation: undefined, + authentication: [`${did}#verkey`], + service: undefined, }) }) @@ -453,17 +446,15 @@ describe('Indy VDR Indy Did Registrar', () => { }, }) - // Wait some time pass to let ledger settle the object - await sleep(1000) - - const didResult = await endorser.dids.resolve(did) - expect(JsonTransformer.toJSON(didResult)).toMatchObject({ - didDocument: expectedDidDocument, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, + // Tries to call it in an interval until it succeeds (with maxAttempts) + // As the ledger write is not always consistent in how long it takes + // to write the data, we need to retry until we get a result. + const didDocument = await retryUntilResult(async () => { + const result = await endorser.dids.resolve(did) + return result.didDocument }) + + expect(JsonTransformer.toJSON(didDocument)).toMatchObject(expectedDidDocument) }) test('can register an endorsed did:indy with services - did and verkey specified - using attrib endpoint', async () => { @@ -602,16 +593,15 @@ describe('Indy VDR Indy Did Registrar', () => { didDocument: expectedDidDocument, }, }) - // Wait some time pass to let ledger settle the object - await sleep(1000) - const didResult = await endorser.dids.resolve(did) - expect(JsonTransformer.toJSON(didResult)).toMatchObject({ - didDocument: expectedDidDocument, - didDocumentMetadata: {}, - didResolutionMetadata: { - contentType: 'application/did+ld+json', - }, + // Tries to call it in an interval until it succeeds (with maxAttempts) + // As the ledger write is not always consistent in how long it takes + // to write the data, we need to retry until we get a result. + const didDocument = await retryUntilResult(async () => { + const result = await endorser.dids.resolve(did) + return result.didDocument }) + + expect(JsonTransformer.toJSON(didDocument)).toMatchObject(expectedDidDocument) }) }) diff --git a/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts b/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts index a083e91816..03ca20b38a 100644 --- a/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts +++ b/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts @@ -1,6 +1,5 @@ import type { Key, Logger } from '@aries-framework/core' -import { AskarModule } from '@aries-framework/askar' import { getJwkFromKey, DidKey, @@ -11,8 +10,8 @@ import { Agent, TypedArrayEncoder, } from '@aries-framework/core' -import { ariesAskar } from '@hyperledger/aries-askar-nodejs' +import { askarModule } from '../../../askar/tests/helpers' import { getAgentOptions } from '../../../core/tests' import { SdJwtVcService } from '../SdJwtVcService' import { SdJwtVcRepository } from '../repository' @@ -31,7 +30,7 @@ const agent = new Agent( 'sdjwtvcserviceagent', {}, { - askar: new AskarModule({ ariesAskar }), + askar: askarModule, dids: new DidsModule({ resolvers: [new KeyDidResolver()], registrars: [new KeyDidRegistrar()], diff --git a/packages/tenants/tests/tenant-sessions.e2e.test.ts b/packages/tenants/tests/tenant-sessions.e2e.test.ts index 1ee9f16e33..1171ccd590 100644 --- a/packages/tenants/tests/tenant-sessions.e2e.test.ts +++ b/packages/tenants/tests/tenant-sessions.e2e.test.ts @@ -1,5 +1,4 @@ import type { InitConfig } from '@aries-framework/core' -import type { TenantRecord } from '@aries-framework/tenants' import { ConnectionsModule, Agent } from '@aries-framework/core' import { agentDependencies } from '@aries-framework/node' @@ -63,10 +62,6 @@ describe('Tenants Sessions E2E', () => { await Promise.all(tenantAgents.map((tenantAgent) => tenantAgent.endSession())) }) - // FIXME: when creating the 100 tenants in parallel, it will error out with askar. - // For now I've fixed it by creating the tenants sequentially, but still opening all - // the sessions in parallel. However it should be fine to create the tenants in parallel - // as well, and this should be fixed in askar / AFJs wallet implementation around askar test('create 5 sessions each for 20 tenants in parallel and close them', async () => { const numberOfTenants = 20 const numberOfSessions = 5 @@ -82,13 +77,7 @@ describe('Tenants Sessions E2E', () => { tenantRecordPromises.push(tenantRecordPromise) } - let tenantRecords: TenantRecord[] = [] - try { - tenantRecords = await Promise.all(tenantRecordPromises) - } catch (error) { - console.log(error.cause.code) - throw error - } + const tenantRecords = await Promise.all(tenantRecordPromises) const tenantAgentPromises = [] for (const tenantRecord of tenantRecords) { for (let session = 0; session < numberOfSessions; session++) { diff --git a/samples/extension-module/package.json b/samples/extension-module/package.json index 26dfdf265c..26cf9181fa 100644 --- a/samples/extension-module/package.json +++ b/samples/extension-module/package.json @@ -24,6 +24,6 @@ "@types/ws": "^8.5.4", "class-validator": "0.14.0", "rxjs": "^7.2.0", - "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.4" + "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5" } } diff --git a/yarn.lock b/yarn.lock index 84c0e136e0..02088b7657 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1222,23 +1222,23 @@ resolved "https://registry.yarnpkg.com/@hyperledger/anoncreds-shared/-/anoncreds-shared-0.2.0-dev.5.tgz#1d6da9db5cc16ba8766fb4db1166dbe5af63e96e" integrity sha512-YtVju8WBKj3tdZbPWGjwdx7jkE5ePPfspPCvbcjIia00CWPES7UUkfjn8NVk82rq/Gi7IoWR3Jdpfv8rPe0fEA== -"@hyperledger/aries-askar-nodejs@^0.2.0-dev.4": - version "0.2.0-dev.4" - resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-nodejs/-/aries-askar-nodejs-0.2.0-dev.4.tgz#b43e396c5142aa84b5b2bfe2ab32245315d31265" - integrity sha512-0+UNnuHV2Tu1mN21JHuohvu47hqej8kp0dD3hk9usQMH7yAV0PW/Qkq4GVgqeoOuS3+lLuPFlnwCcsyNqMjhmg== +"@hyperledger/aries-askar-nodejs@^0.2.0-dev.5": + version "0.2.0-dev.5" + resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-nodejs/-/aries-askar-nodejs-0.2.0-dev.5.tgz#e831648d75ebde8e3f583e531710a21b08252f8d" + integrity sha512-C/17MpOP5jZdIHEAUnkQ0DymiQAPFACiw1tmBFOVhHTF7PZDtSXzzp+orewaKsXcFL5Qc1FoEyves5ougftAbw== dependencies: "@2060.io/ffi-napi" "4.0.8" "@2060.io/ref-napi" "3.0.6" - "@hyperledger/aries-askar-shared" "0.2.0-dev.4" + "@hyperledger/aries-askar-shared" "0.2.0-dev.5" "@mapbox/node-pre-gyp" "^1.0.10" node-cache "^5.1.2" ref-array-di "^1.2.2" ref-struct-di "^1.1.1" -"@hyperledger/aries-askar-shared@0.2.0-dev.4", "@hyperledger/aries-askar-shared@^0.2.0-dev.4": - version "0.2.0-dev.4" - resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-shared/-/aries-askar-shared-0.2.0-dev.4.tgz#40e34d907ed4f8d59279dfba209066a1f656a9bf" - integrity sha512-GmjNH+aWCOKtw8KRaZW+MOFx8w32cIxeZ6JuB1vxpQCdH13Ac5+/rIj9T0IGgDN5u0sn9R1HV164F+LUKQjn4w== +"@hyperledger/aries-askar-shared@0.2.0-dev.5", "@hyperledger/aries-askar-shared@^0.2.0-dev.5": + version "0.2.0-dev.5" + resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-shared/-/aries-askar-shared-0.2.0-dev.5.tgz#81881eee427ee3f4ae2f56d248f83a6425ea79b8" + integrity sha512-H5yQEWDUL+G4rN85CyJe30dSeW7cSFHnFXaC1g9xkTXCom7eT4XxT8TpY5D/QBr3KWf26KECc/I1roZOTJQQJQ== dependencies: buffer "^6.0.3" From 39dfdb5bdda23a56c06fe1d4d7b5374f0e54ba56 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Thu, 21 Dec 2023 16:53:13 +0700 Subject: [PATCH 09/19] updates Signed-off-by: Timo Glastra --- .../src/services/AnonCredsRsHolderService.ts | 12 ++++++------ .../services/__tests__/AnonCredsRsServices.test.ts | 4 ++-- .../anoncreds-rs/src/services/__tests__/helpers.ts | 2 ++ packages/anoncreds-rs/tests/anoncredsSetup.ts | 10 +++++++--- packages/anoncreds-rs/tests/indy-flow.test.ts | 2 +- .../tests/v2-credential-revocation.e2e.test.ts | 4 ++-- packages/anoncreds-rs/tests/v2-proofs.e2e.test.ts | 2 +- .../src/formats/AnonCredsCredentialFormatService.ts | 4 ++-- .../src/formats/LegacyIndyCredentialFormatService.ts | 4 ++-- .../__tests__/legacy-indy-format-services.test.ts | 3 +-- packages/anoncreds/src/models/internal.ts | 4 ++-- 11 files changed, 28 insertions(+), 23 deletions(-) diff --git a/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts b/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts index 7249da2662..29964425e6 100644 --- a/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts +++ b/packages/anoncreds-rs/src/services/AnonCredsRsHolderService.ts @@ -317,8 +317,8 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { credentialDefinitionId: credentialRecord.credential.cred_def_id, credentialId: credentialRecord.credentialId, schemaId: credentialRecord.credential.schema_id, - credentialRevocationId: credentialRecord.credentialRevocationId, - revocationRegistryId: credentialRecord.credential.rev_reg_id, + credentialRevocationId: credentialRecord.credentialRevocationId ?? null, + revocationRegistryId: credentialRecord.credential.rev_reg_id ?? null, methodName: credentialRecord.methodName, } } @@ -346,8 +346,8 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { credentialDefinitionId: credentialRecord.credential.cred_def_id, credentialId: credentialRecord.credentialId, schemaId: credentialRecord.credential.schema_id, - credentialRevocationId: credentialRecord.credentialRevocationId, - revocationRegistryId: credentialRecord.credential.rev_reg_id, + credentialRevocationId: credentialRecord.credentialRevocationId ?? null, + revocationRegistryId: credentialRecord.credential.rev_reg_id ?? null, methodName: credentialRecord.methodName, })) } @@ -412,8 +412,8 @@ export class AnonCredsRsHolderService implements AnonCredsHolderService { credentialDefinitionId: credentialRecord.credential.cred_def_id, credentialId: credentialRecord.credentialId, schemaId: credentialRecord.credential.schema_id, - credentialRevocationId: credentialRecord.credentialRevocationId, - revocationRegistryId: credentialRecord.credential.rev_reg_id, + credentialRevocationId: credentialRecord.credentialRevocationId ?? null, + revocationRegistryId: credentialRecord.credential.rev_reg_id ?? null, methodName: credentialRecord.methodName, }, interval: proofRequest.non_revoked, diff --git a/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts b/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts index e8c28fa31e..895ab770ca 100644 --- a/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts +++ b/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts @@ -190,7 +190,7 @@ describe('AnonCredsRsServices', () => { schemaId: schemaState.schemaId, credentialDefinitionId: credentialDefinitionState.credentialDefinitionId, revocationRegistryId: null, - credentialRevocationId: undefined, // Should it be null in this case? + credentialRevocationId: null, methodName: 'inMemory', }) @@ -398,7 +398,7 @@ describe('AnonCredsRsServices', () => { schemaId: unqualifiedSchemaId, credentialDefinitionId: unqualifiedCredentialDefinitionId, revocationRegistryId: null, - credentialRevocationId: undefined, // Should it be null in this case? + credentialRevocationId: null, methodName: 'inMemory', }) diff --git a/packages/anoncreds-rs/src/services/__tests__/helpers.ts b/packages/anoncreds-rs/src/services/__tests__/helpers.ts index 47af6c909c..765b4e7c89 100644 --- a/packages/anoncreds-rs/src/services/__tests__/helpers.ts +++ b/packages/anoncreds-rs/src/services/__tests__/helpers.ts @@ -160,6 +160,8 @@ export function createCredentialForHolder(options: { credentialId, schemaId, methodName: 'inMemory', + credentialRevocationId: null, + revocationRegistryId: null, } const returnObj = { credential: credentialObj.toJson() as unknown as AnonCredsCredential, diff --git a/packages/anoncreds-rs/tests/anoncredsSetup.ts b/packages/anoncreds-rs/tests/anoncredsSetup.ts index 2ce0a49fee..84121c92f8 100644 --- a/packages/anoncreds-rs/tests/anoncredsSetup.ts +++ b/packages/anoncreds-rs/tests/anoncredsSetup.ts @@ -201,7 +201,7 @@ export async function issueAnonCredsCredential({ holderReplay: EventReplaySubject issuerHolderConnectionId: string - revocationRegistryDefinitionId?: string + revocationRegistryDefinitionId: string | null offer: AnonCredsOfferCredentialFormat }) { let issuerCredentialExchangeRecord = await issuerAgent.credentials.offerCredential({ @@ -209,7 +209,11 @@ export async function issueAnonCredsCredential({ connectionId: issuerHolderConnectionId, protocolVersion: 'v2', credentialFormats: { - anoncreds: { ...offer, revocationRegistryDefinitionId, revocationRegistryIndex: 1 }, + anoncreds: { + ...offer, + revocationRegistryDefinitionId: revocationRegistryDefinitionId ?? undefined, + revocationRegistryIndex: 1, + }, }, autoAcceptCredential: AutoAcceptCredential.ContentApproved, }) @@ -267,7 +271,7 @@ interface SetupAnonCredsTestsReturn { schemaId: unqualifiedSchemaId, credentialDefinitionId: unqualifiedCredentialDefinitionId, revocationRegistryId: null, - credentialRevocationId: undefined, // FIXME: should be null? + credentialRevocationId: null, methodName: 'inMemory', }) diff --git a/packages/anoncreds-rs/tests/v2-credential-revocation.e2e.test.ts b/packages/anoncreds-rs/tests/v2-credential-revocation.e2e.test.ts index f3db7e54cf..888a15c2a5 100644 --- a/packages/anoncreds-rs/tests/v2-credential-revocation.e2e.test.ts +++ b/packages/anoncreds-rs/tests/v2-credential-revocation.e2e.test.ts @@ -28,7 +28,7 @@ describe('IC v2 credential revocation', () => { let faberAgent: AnonCredsTestsAgent let aliceAgent: AnonCredsTestsAgent let credentialDefinitionId: string - let revocationRegistryDefinitionId: string | undefined + let revocationRegistryDefinitionId: string | null let aliceConnectionId: string let faberReplay: EventReplaySubject @@ -105,7 +105,7 @@ describe('IC v2 credential revocation', () => { anoncreds: { credentialDefinitionId: credentialDefinitionId, attributes: credentialPreview.attributes, - revocationRegistryDefinitionId, + revocationRegistryDefinitionId: revocationRegistryDefinitionId ?? undefined, revocationRegistryIndex: 1, }, }, diff --git a/packages/anoncreds-rs/tests/v2-proofs.e2e.test.ts b/packages/anoncreds-rs/tests/v2-proofs.e2e.test.ts index b304ef5e73..ecd79a502e 100644 --- a/packages/anoncreds-rs/tests/v2-proofs.e2e.test.ts +++ b/packages/anoncreds-rs/tests/v2-proofs.e2e.test.ts @@ -28,7 +28,7 @@ describe('PP V2 AnonCreds Proofs', () => { let aliceAgent: AnonCredsTestsAgent let aliceReplay: EventReplaySubject let credentialDefinitionId: string - let revocationRegistryDefinitionId: string | undefined + let revocationRegistryDefinitionId: string | null let aliceConnectionId: string let faberConnectionId: string let faberProofExchangeRecord: ProofExchangeRecord diff --git a/packages/anoncreds/src/formats/AnonCredsCredentialFormatService.ts b/packages/anoncreds/src/formats/AnonCredsCredentialFormatService.ts index 9a53590d12..bd8cb17300 100644 --- a/packages/anoncreds/src/formats/AnonCredsCredentialFormatService.ts +++ b/packages/anoncreds/src/formats/AnonCredsCredentialFormatService.ts @@ -468,8 +468,8 @@ export class AnonCredsCredentialFormatService implements CredentialFormatService const credential = await anonCredsHolderService.getCredential(agentContext, { credentialId }) credentialRecord.metadata.add(AnonCredsCredentialMetadataKey, { - credentialRevocationId: credential.credentialRevocationId, - revocationRegistryId: credential.revocationRegistryId, + credentialRevocationId: credential.credentialRevocationId ?? undefined, + revocationRegistryId: credential.revocationRegistryId ?? undefined, }) credentialRecord.setTags({ anonCredsRevocationRegistryId: credential.revocationRegistryId, diff --git a/packages/anoncreds/src/formats/LegacyIndyCredentialFormatService.ts b/packages/anoncreds/src/formats/LegacyIndyCredentialFormatService.ts index 98a45b70bc..831a2e6ebb 100644 --- a/packages/anoncreds/src/formats/LegacyIndyCredentialFormatService.ts +++ b/packages/anoncreds/src/formats/LegacyIndyCredentialFormatService.ts @@ -434,8 +434,8 @@ export class LegacyIndyCredentialFormatService implements CredentialFormatServic const credential = await anonCredsHolderService.getCredential(agentContext, { credentialId }) credentialRecord.metadata.add(AnonCredsCredentialMetadataKey, { - credentialRevocationId: credential.credentialRevocationId, - revocationRegistryId: credential.revocationRegistryId, + credentialRevocationId: credential.credentialRevocationId ?? undefined, + revocationRegistryId: credential.revocationRegistryId ?? undefined, }) credentialRecord.setTags({ anonCredsRevocationRegistryId: credential.revocationRegistryId, diff --git a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts index 1185a7ee98..9b1e013628 100644 --- a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts +++ b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts @@ -306,9 +306,8 @@ describe('Legacy indy format services', () => { }, schemaId: legacySchemaId, credentialDefinitionId: legacyCredentialDefinitionId, - // FIXME: We should be consistent in using null vs undefined revocationRegistryId: null, - credentialRevocationId: undefined, + credentialRevocationId: null, methodName: 'inMemory', }) diff --git a/packages/anoncreds/src/models/internal.ts b/packages/anoncreds/src/models/internal.ts index 8aacc72a52..112a0fb128 100644 --- a/packages/anoncreds/src/models/internal.ts +++ b/packages/anoncreds/src/models/internal.ts @@ -5,8 +5,8 @@ export interface AnonCredsCredentialInfo { } schemaId: string credentialDefinitionId: string - revocationRegistryId?: string | undefined - credentialRevocationId?: string | undefined + revocationRegistryId: string | null + credentialRevocationId: string | null methodName: string } From 6a83ea8fdb0d3bbbc9cc8e74d90b60f0787dcb95 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Thu, 21 Dec 2023 17:01:00 +0700 Subject: [PATCH 10/19] updates Signed-off-by: Timo Glastra --- packages/anoncreds-rs/tests/v2-credentials.e2e.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/anoncreds-rs/tests/v2-credentials.e2e.test.ts b/packages/anoncreds-rs/tests/v2-credentials.e2e.test.ts index e198a16828..63fc1d6fb9 100644 --- a/packages/anoncreds-rs/tests/v2-credentials.e2e.test.ts +++ b/packages/anoncreds-rs/tests/v2-credentials.e2e.test.ts @@ -239,6 +239,7 @@ describe('IC V2 AnonCreds credentials', () => { credentialDefinitionId: credentialDefinitionId, attributes: credentialPreview.attributes, }, + revocationRegistryDefinitionId: null, }) // test that delete credential removes from both repository and wallet From b762641237caccd27b5d408008528a8ba57417a7 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Thu, 21 Dec 2023 17:27:05 +0700 Subject: [PATCH 11/19] fix Signed-off-by: Timo Glastra --- packages/anoncreds-rs/tests/anoncreds-flow.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/anoncreds-rs/tests/anoncreds-flow.test.ts b/packages/anoncreds-rs/tests/anoncreds-flow.test.ts index 06481055f4..465395147c 100644 --- a/packages/anoncreds-rs/tests/anoncreds-flow.test.ts +++ b/packages/anoncreds-rs/tests/anoncreds-flow.test.ts @@ -355,7 +355,7 @@ async function anonCredsFlowTest(options: { issuerId: string; revocable: boolean schemaId: schemaState.schemaId, credentialDefinitionId: credentialDefinitionState.credentialDefinitionId, revocationRegistryId: revocable ? revocationRegistryDefinitionId : null, - credentialRevocationId: revocable ? '1' : undefined, + credentialRevocationId: revocable ? '1' : null, methodName: 'inMemory', }) From 80bdf48959f94b1d15e7e4ac16e2e4f589c00d16 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Fri, 22 Dec 2023 13:14:58 +0700 Subject: [PATCH 12/19] test: make it work for now Signed-off-by: Timo Glastra --- .../proofs/protocol/v2/__tests__/v2-indy-proofs.e2e.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-proofs.e2e.test.ts b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-proofs.e2e.test.ts index 29a7fce4c8..a942e4744f 100644 --- a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-proofs.e2e.test.ts +++ b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-proofs.e2e.test.ts @@ -345,11 +345,16 @@ describe('Present Proof', () => { presentation: { indy: { proof: { + // FIXME: Indy SDK only had one proof: https://github.com/hyperledger/anoncreds-rs/issues/292 proofs: [ { primary_proof: expect.any(Object), non_revoc_proof: null, }, + { + primary_proof: expect.any(Object), + non_revoc_proof: null, + }, ], aggregated_proof: { c_hash: expect.any(String), From 8ea72987ff3a99090db24a86bb1289046f38021e Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Fri, 22 Dec 2023 13:25:51 +0700 Subject: [PATCH 13/19] updates Signed-off-by: Timo Glastra --- docker-compose.yml | 1 - packages/anoncreds-rs/tests/anoncredsSetup.ts | 1 + .../formats/__tests__/legacy-indy-format-services.test.ts | 1 + packages/anoncreds/src/models/exchange.ts | 1 + packages/anoncreds/tests/legacyAnonCredsSetup.ts | 1 + .../connections/__tests__/didexchange-numalgo.e2e.test.ts | 6 +++--- .../core/src/modules/vc/data-integrity/deriveProof.ts | 1 + .../vc/data-integrity/proof-purposes/ProofPurpose.ts | 1 + samples/extension-module/package.json | 8 ++++---- 9 files changed, 13 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index dc08922877..f7dea20d37 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,7 +12,6 @@ services: build: context: . dockerfile: network/indy-pool.dockerfile - target: linux/amd64 ports: - '9701-9708:9701-9708' # Start supervisord in bg, run commands, bring supervisor to fg diff --git a/packages/anoncreds-rs/tests/anoncredsSetup.ts b/packages/anoncreds-rs/tests/anoncredsSetup.ts index 84121c92f8..daf58ae8bb 100644 --- a/packages/anoncreds-rs/tests/anoncredsSetup.ts +++ b/packages/anoncreds-rs/tests/anoncredsSetup.ts @@ -55,6 +55,7 @@ import { LocalDidResolver } from './LocalDidResolver' // Helper type to get the type of the agents (with the custom modules) for the credential tests export type AnonCredsTestsAgent = Agent< + // eslint-disable-next-line @typescript-eslint/no-explicit-any ReturnType & { mediationRecipient?: any; mediator?: any } > diff --git a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts index 9b1e013628..e7a9fe5b20 100644 --- a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts +++ b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts @@ -67,6 +67,7 @@ const wallet = new RegisteredAskarTestWallet( new agentDependencies.FileSystem(), new SigningProviderRegistry([]) ) +// eslint-disable-next-line @typescript-eslint/no-explicit-any const storageService = new AskarStorageService() const eventEmitter = new EventEmitter(agentDependencies, new Subject()) const anonCredsLinkSecretRepository = new AnonCredsLinkSecretRepository(storageService, eventEmitter) diff --git a/packages/anoncreds/src/models/exchange.ts b/packages/anoncreds/src/models/exchange.ts index 5213153ff9..7d483a602f 100644 --- a/packages/anoncreds/src/models/exchange.ts +++ b/packages/anoncreds/src/models/exchange.ts @@ -90,6 +90,7 @@ export interface AnonCredsProof { predicates: Record } // TODO: extend types for proof property + // eslint-disable-next-line @typescript-eslint/no-explicit-any proof: any identifiers: Array<{ schema_id: string diff --git a/packages/anoncreds/tests/legacyAnonCredsSetup.ts b/packages/anoncreds/tests/legacyAnonCredsSetup.ts index 2ee7e8dc7e..1455800db9 100644 --- a/packages/anoncreds/tests/legacyAnonCredsSetup.ts +++ b/packages/anoncreds/tests/legacyAnonCredsSetup.ts @@ -67,6 +67,7 @@ import { // Helper type to get the type of the agents (with the custom modules) for the credential tests export type AnonCredsTestsAgent = Agent< + // eslint-disable-next-line @typescript-eslint/no-explicit-any ReturnType & { mediationRecipient?: any; mediator?: any } > diff --git a/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts b/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts index 0c6c1c657b..63eb58f7fc 100644 --- a/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts +++ b/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts @@ -4,7 +4,7 @@ import type { ConnectionStateChangedEvent } from '../ConnectionEvents' import { firstValueFrom } from 'rxjs' import { filter, first, map, timeout } from 'rxjs/operators' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' +import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' import { getAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' @@ -103,7 +103,7 @@ async function didExchangeNumAlgoBaseTest(options: { endpoints: ['rxjs:alice'], }, { - ...getIndySdkModules(), + askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, peerNumAlgoForDidExchangeRequests: options.requesterNumAlgoSetting, @@ -117,7 +117,7 @@ async function didExchangeNumAlgoBaseTest(options: { endpoints: ['rxjs:faber'], }, { - ...getIndySdkModules(), + askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, peerNumAlgoForDidExchangeRequests: options.responderNumAlgoSetting, diff --git a/packages/core/src/modules/vc/data-integrity/deriveProof.ts b/packages/core/src/modules/vc/data-integrity/deriveProof.ts index a98bf1a064..78e13826de 100644 --- a/packages/core/src/modules/vc/data-integrity/deriveProof.ts +++ b/packages/core/src/modules/vc/data-integrity/deriveProof.ts @@ -38,6 +38,7 @@ export interface W3cJsonLdDeriveProofOptions { export const deriveProof = async ( proofDocument: JsonObject, revealDocument: JsonObject, + // eslint-disable-next-line @typescript-eslint/no-explicit-any { suite, skipProofCompaction, documentLoader, expansionMap, nonce }: any ): Promise => { if (!suite) { diff --git a/packages/core/src/modules/vc/data-integrity/proof-purposes/ProofPurpose.ts b/packages/core/src/modules/vc/data-integrity/proof-purposes/ProofPurpose.ts index 2695f3276c..af04ec9f41 100644 --- a/packages/core/src/modules/vc/data-integrity/proof-purposes/ProofPurpose.ts +++ b/packages/core/src/modules/vc/data-integrity/proof-purposes/ProofPurpose.ts @@ -1 +1,2 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type ProofPurpose = any diff --git a/samples/extension-module/package.json b/samples/extension-module/package.json index 26cf9181fa..da23943672 100644 --- a/samples/extension-module/package.json +++ b/samples/extension-module/package.json @@ -16,12 +16,12 @@ "@aries-framework/core": "*", "@aries-framework/node": "*", "@aries-framework/askar": "*", - "ts-node": "^10.4.0" - }, - "dependencies": { + "ts-node": "^10.4.0", "@types/express": "^4.17.13", "@types/uuid": "^9.0.1", - "@types/ws": "^8.5.4", + "@types/ws": "^8.5.4" + }, + "dependencies": { "class-validator": "0.14.0", "rxjs": "^7.2.0", "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5" From 0c9d6195d3026a796ef2954075d6dcacbdc19914 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Fri, 22 Dec 2023 13:43:17 +0700 Subject: [PATCH 14/19] stop message pickup Signed-off-by: Timo Glastra --- DEVREADME.md | 2 +- packages/core/src/modules/routing/__tests__/mediation.test.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/DEVREADME.md b/DEVREADME.md index 2f47a96fb3..bfd3e87e9e 100644 --- a/DEVREADME.md +++ b/DEVREADME.md @@ -18,7 +18,7 @@ GENESIS_TXN_PATH=/work/network/genesis/local-genesis.txn ## Running tests -Test are executed using jest. Some test require the **indy ledger**, **cheqd ledger** or **postgres database** to be running. +Test are executed using jest. Some test require the **indy ledger**, **cheqd ledger** or **postgres database** to be running. When running tests that require a connection to the indy ledger pool, you can set the `TEST_AGENT_PUBLIC_DID_SEED`, `ENDORSER_AGENT_PUBLIC_DID_SEED` and `GENESIS_TXN_PATH` environment variables. diff --git a/packages/core/src/modules/routing/__tests__/mediation.test.ts b/packages/core/src/modules/routing/__tests__/mediation.test.ts index 2965ad08c8..ae29aaf80b 100644 --- a/packages/core/src/modules/routing/__tests__/mediation.test.ts +++ b/packages/core/src/modules/routing/__tests__/mediation.test.ts @@ -253,6 +253,8 @@ describe('mediator establishment', () => { expect(recipientMediator?.state).toBe(MediationState.Granted) + await recipientAgent.mediationRecipient.stopMessagePickup() + // Restart recipient agent await recipientAgent.shutdown() recipientAgent = new Agent({ From 068fcacfd69c3c9b66e6792d773c1ba1a2aa85d5 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Wed, 31 Jan 2024 15:54:03 +0700 Subject: [PATCH 15/19] chore: use in memory wallet in most tests Signed-off-by: Timo Glastra --- .../action-menu/tests/action-menu.e2e.test.ts | 8 +- packages/anoncreds-rs/tests/anoncredsSetup.ts | 11 +- .../legacy-indy-format-services.test.ts | 15 +- .../v1-connectionless-proofs.e2e.test.ts | 17 +- .../src/updates/__tests__/0.3.test.ts | 22 +- packages/anoncreds/tests/anoncreds.test.ts | 6 +- .../anoncreds/tests/legacyAnonCredsSetup.ts | 21 +- packages/askar/src/wallet/AskarBaseWallet.ts | 193 +--------- packages/askar/src/wallet/didcommV1.ts | 177 +++++++++ .../askar/tests/askar-inmemory.e2e.test.ts | 6 +- .../askar/tests/askar-postgres.e2e.test.ts | 6 +- packages/askar/tests/askar-sqlite.e2e.test.ts | 6 +- packages/askar/tests/helpers.ts | 4 +- .../tests/bbs-signatures.e2e.test.ts | 3 + ...proof.credentials.propose-offerBbs.test.ts | 1 + .../tests/cheqd-did-registrar.e2e.test.ts | 4 +- .../tests/cheqd-did-resolver.e2e.test.ts | 4 +- .../cheqd-sdk-anoncreds-registry.e2e.test.ts | 20 +- packages/cheqd/tests/setupCheqdModule.ts | 2 - .../core/src/agent/__tests__/Agent.test.ts | 10 +- .../src/crypto/__tests__/JwsService.test.ts | 11 +- .../signature/SignatureDecoratorUtils.test.ts | 11 +- .../__tests__/basic-messages.e2e.test.ts | 25 +- .../__tests__/ConnectionService.test.ts | 10 +- .../__tests__/connection-manual.e2e.test.ts | 12 +- .../__tests__/did-rotate.e2e.test.ts | 9 +- .../__tests__/didexchange-numalgo.e2e.test.ts | 9 +- .../v2-connectionless-credentials.e2e.test.ts | 12 +- .../v2-credentials-auto-accept.e2e.test.ts | 6 +- ...f.credentials.propose-offerED25519.test.ts | 10 +- .../modules/dids/__tests__/DidsApi.test.ts | 15 +- .../dids/__tests__/dids-registrar.e2e.test.ts | 11 +- .../dids/__tests__/dids-resolver.e2e.test.ts | 13 +- .../modules/dids/__tests__/peer-did.test.ts | 11 +- .../v1-discover-features.e2e.test.ts | 29 +- .../v2-discover-features.e2e.test.ts | 29 +- .../message-pickup/__tests__/pickup.test.ts | 37 +- .../oob/__tests__/connect-to-self.e2e.test.ts | 15 +- .../oob/__tests__/implicit.e2e.test.ts | 12 +- ...entationExchangeProofFormatService.test.ts | 4 +- .../v2-indy-connectionless-proofs.e2e.test.ts | 16 +- ...entation-exchange-presentation.e2e.test.ts | 2 +- .../routing/__tests__/mediation.test.ts | 40 +- .../vc/__tests__/W3cCredentialService.test.ts | 14 +- .../vc/__tests__/W3cCredentialsApi.test.ts | 20 +- .../W3cJsonLdCredentialService.test.ts | 12 +- .../__tests__/W3cJwtCredentialService.test.ts | 12 +- .../storage/migration/__tests__/0.1.test.ts | 46 ++- .../storage/migration/__tests__/0.2.test.ts | 36 +- .../storage/migration/__tests__/0.3.test.ts | 11 +- .../__tests__/UpdateAssistant.test.ts | 25 +- .../migration/__tests__/backup-askar.test.ts | 5 +- packages/core/tests/agents.test.ts | 23 +- packages/core/tests/connections.test.ts | 36 +- packages/core/tests/generic-records.test.ts | 13 +- packages/core/tests/helpers.ts | 34 ++ packages/core/tests/jsonld.ts | 18 +- .../core/tests/multi-protocol-version.test.ts | 23 +- .../tests/oob-mediation-provision.test.ts | 22 +- packages/core/tests/oob-mediation.test.ts | 22 +- packages/core/tests/oob.test.ts | 17 +- .../__tests__/IndyVdrIndyDidRegistrar.test.ts | 10 +- .../indy-vdr-anoncreds-registry.e2e.test.ts | 71 ++-- .../tests/indy-vdr-did-registrar.e2e.test.ts | 13 +- .../indy-vdr-indy-did-resolver.e2e.test.ts | 6 +- .../indy-vdr/tests/indy-vdr-pool.e2e.test.ts | 7 +- .../indy-vdr-sov-did-resolver.e2e.test.ts | 6 +- .../tests/openid4vc-client.e2e.test.ts | 13 +- .../__tests__/QuestionAnswerService.test.ts | 7 +- .../tests/question-answer.e2e.test.ts | 8 +- .../src/__tests__/SdJwtVcService.test.ts | 6 +- packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts | 6 +- .../tenants/src/__tests__/TenantAgent.test.ts | 17 +- .../tenants/src/__tests__/TenantsApi.test.ts | 14 +- .../tenants/tests/tenant-sessions.e2e.test.ts | 16 +- packages/tenants/tests/tenants.e2e.test.ts | 19 +- samples/extension-module/package.json | 6 +- tests/InMemoryStorageService.ts | 68 +++- tests/InMemoryWallet.ts | 344 ++++++++++++++++++ tests/InMemoryWalletModule.ts | 22 ++ tests/e2e-askar-indy-vdr-anoncreds-rs.test.ts | 18 +- tests/e2e-http.test.ts | 16 +- tests/e2e-subject.test.ts | 16 +- tests/e2e-ws-pickup-v2.test.ts | 16 +- tests/e2e-ws.test.ts | 16 +- 85 files changed, 1120 insertions(+), 895 deletions(-) create mode 100644 packages/askar/src/wallet/didcommV1.ts create mode 100644 tests/InMemoryWallet.ts create mode 100644 tests/InMemoryWalletModule.ts diff --git a/packages/action-menu/tests/action-menu.e2e.test.ts b/packages/action-menu/tests/action-menu.e2e.test.ts index 55aa034b2e..134887830c 100644 --- a/packages/action-menu/tests/action-menu.e2e.test.ts +++ b/packages/action-menu/tests/action-menu.e2e.test.ts @@ -2,8 +2,7 @@ import type { ConnectionRecord } from '@credo-ts/core' import { Agent } from '@credo-ts/core' -import { askarModule } from '../../askar/tests/helpers' -import { getAgentOptions, makeConnection, testLogger, setupSubjectTransports } from '../../core/tests' +import { makeConnection, testLogger, setupSubjectTransports, getInMemoryAgentOptions } from '../../core/tests' import { waitForActionMenuRecord } from './helpers' @@ -11,10 +10,9 @@ import { ActionMenu, ActionMenuModule, ActionMenuRecord, ActionMenuRole, ActionM const modules = { actionMenu: new ActionMenuModule(), - askar: askarModule, } -const faberAgentOptions = getAgentOptions( +const faberAgentOptions = getInMemoryAgentOptions( 'Faber Action Menu', { endpoints: ['rxjs:faber'], @@ -22,7 +20,7 @@ const faberAgentOptions = getAgentOptions( modules ) -const aliceAgentOptions = getAgentOptions( +const aliceAgentOptions = getInMemoryAgentOptions( 'Alice Action Menu', { endpoints: ['rxjs:alice'], diff --git a/packages/anoncreds-rs/tests/anoncredsSetup.ts b/packages/anoncreds-rs/tests/anoncredsSetup.ts index 797ff51142..aff1d1ccca 100644 --- a/packages/anoncreds-rs/tests/anoncredsSetup.ts +++ b/packages/anoncreds-rs/tests/anoncredsSetup.ts @@ -37,12 +37,10 @@ import { randomUUID } from 'crypto' import { AnonCredsCredentialFormatService, AnonCredsProofFormatService, AnonCredsModule } from '../../anoncreds/src' import { InMemoryAnonCredsRegistry } from '../../anoncreds/tests/InMemoryAnonCredsRegistry' -import { AskarModule } from '../../askar/src' -import { askarModuleConfig } from '../../askar/tests/helpers' import { sleep } from '../../core/src/utils/sleep' import { setupSubjectTransports, setupEventReplaySubjects } from '../../core/tests' import { - getAgentOptions, + getInMemoryAgentOptions, makeConnection, waitForCredentialRecordSubject, waitForProofExchangeRecordSubject, @@ -98,7 +96,6 @@ export const getAnonCredsModules = ({ dids: new DidsModule({ resolvers: [new LocalDidResolver()], }), - askar: new AskarModule(askarModuleConfig), cache: new CacheModule({ cache: new InMemoryLruCache({ limit: 100 }), }), @@ -303,7 +300,7 @@ export async function setupAnonCredsTests< registries?: [AnonCredsRegistry, ...AnonCredsRegistry[]] }): Promise> { const issuerAgent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( issuerName, { endpoints: ['rxjs:issuer'], @@ -317,7 +314,7 @@ export async function setupAnonCredsTests< ) const holderAgent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( holderName, { endpoints: ['rxjs:holder'], @@ -332,7 +329,7 @@ export async function setupAnonCredsTests< const verifierAgent = verifierName ? new Agent( - getAgentOptions( + getInMemoryAgentOptions( verifierName, { endpoints: ['rxjs:verifier'], diff --git a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts index d278015e9c..ecda92dcb8 100644 --- a/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts +++ b/packages/anoncreds/src/formats/__tests__/legacy-indy-format-services.test.ts @@ -3,7 +3,6 @@ import type { AnonCredsCredentialRequest } from '../../models' import { CredentialState, CredentialExchangeRecord, - SigningProviderRegistry, KeyType, CredentialPreviewAttribute, ProofExchangeRecord, @@ -13,6 +12,8 @@ import { } from '@credo-ts/core' import { Subject } from 'rxjs' +import { InMemoryStorageService } from '../../../../../tests/InMemoryStorageService' +import { InMemoryWallet } from '../../../../../tests/InMemoryWallet' import { AnonCredsRsHolderService, AnonCredsRsIssuerService, @@ -20,9 +21,6 @@ import { AnonCredsRsVerifierService, } from '../../../../anoncreds-rs/src' import { anoncreds } from '../../../../anoncreds-rs/tests/helpers' -import { AskarStorageService } from '../../../../askar/src' -import { AskarModuleConfig } from '../../../../askar/src/AskarModuleConfig' -import { askarModuleConfig, RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' import { indyDidFromPublicKeyBase58 } from '../../../../core/src/utils/did' import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' import { InMemoryAnonCredsRegistry } from '../../../tests/InMemoryAnonCredsRegistry' @@ -62,13 +60,9 @@ const agentConfig = getAgentConfig('LegacyIndyFormatServicesTest') const anonCredsVerifierService = new AnonCredsRsVerifierService() const anonCredsHolderService = new AnonCredsRsHolderService() const anonCredsIssuerService = new AnonCredsRsIssuerService() -const wallet = new RegisteredAskarTestWallet( - agentConfig.logger, - new agentDependencies.FileSystem(), - new SigningProviderRegistry([]) -) +const wallet = new InMemoryWallet() // eslint-disable-next-line @typescript-eslint/no-explicit-any -const storageService = new AskarStorageService() +const storageService = new InMemoryStorageService() const eventEmitter = new EventEmitter(agentDependencies, new Subject()) const anonCredsLinkSecretRepository = new AnonCredsLinkSecretRepository(storageService, eventEmitter) const anonCredsCredentialDefinitionRepository = new AnonCredsCredentialDefinitionRepository( @@ -93,7 +87,6 @@ const agentContext = getAgentContext({ [AnonCredsCredentialDefinitionPrivateRepository, anonCredsCredentialDefinitionPrivateRepository], [AnonCredsCredentialRepository, anonCredsCredentialRepository], [AnonCredsKeyCorrectnessProofRepository, anonCredsKeyCorrectnessProofRepository], - [AskarModuleConfig, askarModuleConfig], [InjectionSymbols.StorageService, storageService], [ AnonCredsRsModuleConfig, diff --git a/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts b/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts index b06b6af89b..9b7c86c770 100644 --- a/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts +++ b/packages/anoncreds/src/protocols/proofs/v1/__tests__/v1-connectionless-proofs.e2e.test.ts @@ -5,7 +5,6 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../../tests/transport/SubjectOutboundTransport' -import { askarModule } from '../../../../../../askar/tests/helpers' import { CredentialEventTypes, Agent, @@ -24,12 +23,12 @@ import { uuid } from '../../../../../../core/src/utils/uuid' import { testLogger, waitForProofExchangeRecordSubject, - getAgentOptions, makeConnection, setupEventReplaySubjects, + getInMemoryAgentOptions, } from '../../../../../../core/tests' import { - getAskarAnonCredsIndyModules, + getAnonCredsIndyModules, issueLegacyAnonCredsCredential, prepareForAnonCredsIssuance, setupAnonCredsTests, @@ -62,6 +61,7 @@ describe('V1 Proofs - Connectionless - Indy', () => { attributeNames: ['name', 'age'], }) + // FIXME: We should reuse anoncreds crypto object as it will speed up tests significantly await issueLegacyAnonCredsCredential({ issuerAgent: faberAgent, holderAgent: aliceAgent, @@ -359,13 +359,12 @@ describe('V1 Proofs - Connectionless - Indy', () => { const unique = uuid().substring(0, 4) - const mediatorAgentOptions = getAgentOptions( + const mediatorAgentOptions = getInMemoryAgentOptions( `Connectionless proofs with mediator Mediator-${unique}`, { endpoints: ['rxjs:mediator'], }, { - askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true, }), @@ -391,11 +390,11 @@ describe('V1 Proofs - Connectionless - Indy', () => { handshakeProtocols: [HandshakeProtocol.Connections], }) - const faberAgentOptions = getAgentOptions( + const faberAgentOptions = getInMemoryAgentOptions( `Connectionless proofs with mediator Faber-${unique}`, {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ @@ -407,11 +406,11 @@ describe('V1 Proofs - Connectionless - Indy', () => { } ) - const aliceAgentOptions = getAgentOptions( + const aliceAgentOptions = getInMemoryAgentOptions( `Connectionless proofs with mediator Alice-${unique}`, {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ diff --git a/packages/anoncreds/src/updates/__tests__/0.3.test.ts b/packages/anoncreds/src/updates/__tests__/0.3.test.ts index fe0d4f6f0e..69972503c6 100644 --- a/packages/anoncreds/src/updates/__tests__/0.3.test.ts +++ b/packages/anoncreds/src/updates/__tests__/0.3.test.ts @@ -64,7 +64,12 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(holderRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(holderRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.isUpToDate()).toBe(false) expect(await updateAssistant.getNeededUpdates('0.4')).toEqual([ @@ -80,9 +85,7 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { expect(await updateAssistant.isUpToDate()).toBe(true) expect(await updateAssistant.getNeededUpdates()).toEqual([]) - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() @@ -202,7 +205,12 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(issuerRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(issuerRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.isUpToDate()).toBe(false) expect(await updateAssistant.getNeededUpdates()).toEqual([ @@ -218,9 +226,7 @@ describe('UpdateAssistant | AnonCreds | v0.3.1 - v0.4', () => { expect(await updateAssistant.isUpToDate()).toBe(true) expect(await updateAssistant.getNeededUpdates()).toEqual([]) - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() diff --git a/packages/anoncreds/tests/anoncreds.test.ts b/packages/anoncreds/tests/anoncreds.test.ts index f185813fbc..dc0ce53967 100644 --- a/packages/anoncreds/tests/anoncreds.test.ts +++ b/packages/anoncreds/tests/anoncreds.test.ts @@ -2,8 +2,7 @@ import { Agent, KeyType, TypedArrayEncoder } from '@credo-ts/core' import { AnonCredsRsModule } from '../../anoncreds-rs/src' import { anoncreds } from '../../anoncreds-rs/tests/helpers' -import { askarModule } from '../../askar/tests/helpers' -import { getAgentOptions } from '../../core/tests' +import { getInMemoryAgentOptions } from '../../core/tests' import { AnonCredsModule } from '../src' import { InMemoryAnonCredsRegistry } from './InMemoryAnonCredsRegistry' @@ -73,12 +72,11 @@ const existingRevocationStatusLists = { } const agent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'credo-anoncreds-package', {}, { anoncredsRs: new AnonCredsRsModule({ anoncreds, autoCreateLinkSecret: false }), - askar: askarModule, anoncreds: new AnonCredsModule({ registries: [ new InMemoryAnonCredsRegistry({ diff --git a/packages/anoncreds/tests/legacyAnonCredsSetup.ts b/packages/anoncreds/tests/legacyAnonCredsSetup.ts index a60cc45ab3..f9752c4a7c 100644 --- a/packages/anoncreds/tests/legacyAnonCredsSetup.ts +++ b/packages/anoncreds/tests/legacyAnonCredsSetup.ts @@ -32,12 +32,10 @@ import { randomUUID } from 'crypto' import { AnonCredsRsModule } from '../../anoncreds-rs/src' import { anoncreds } from '../../anoncreds-rs/tests/helpers' -import { AskarModule } from '../../askar/src' -import { askarModuleConfig } from '../../askar/tests/helpers' import { sleep } from '../../core/src/utils/sleep' import { setupSubjectTransports, setupEventReplaySubjects } from '../../core/tests' import { - getAgentOptions, + getInMemoryAgentOptions, importExistingIndyDidFromPrivateKey, makeConnection, publicDidSeed, @@ -68,10 +66,10 @@ import { // Helper type to get the type of the agents (with the custom modules) for the credential tests export type AnonCredsTestsAgent = Agent< // eslint-disable-next-line @typescript-eslint/no-explicit-any - ReturnType & { mediationRecipient?: any; mediator?: any } + ReturnType & { mediationRecipient?: any; mediator?: any } > -export const getAskarAnonCredsIndyModules = ({ +export const getAnonCredsIndyModules = ({ autoAcceptCredentials, autoAcceptProofs, }: { autoAcceptCredentials?: AutoAcceptCredential; autoAcceptProofs?: AutoAcceptProof } = {}) => { @@ -112,7 +110,6 @@ export const getAskarAnonCredsIndyModules = ({ resolvers: [new IndyVdrSovDidResolver(), new IndyVdrIndyDidResolver()], registrars: [new IndyVdrIndyDidRegistrar()], }), - askar: new AskarModule(askarModuleConfig), cache: new CacheModule({ cache: new InMemoryLruCache({ limit: 100 }), }), @@ -303,12 +300,12 @@ export async function setupAnonCredsTests< createConnections?: CreateConnections }): Promise> { const issuerAgent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( issuerName, { endpoints: ['rxjs:issuer'], }, - getAskarAnonCredsIndyModules({ + getAnonCredsIndyModules({ autoAcceptCredentials, autoAcceptProofs, }) @@ -316,12 +313,12 @@ export async function setupAnonCredsTests< ) const holderAgent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( holderName, { endpoints: ['rxjs:holder'], }, - getAskarAnonCredsIndyModules({ + getAnonCredsIndyModules({ autoAcceptCredentials, autoAcceptProofs, }) @@ -330,12 +327,12 @@ export async function setupAnonCredsTests< const verifierAgent = verifierName ? new Agent( - getAgentOptions( + getInMemoryAgentOptions( verifierName, { endpoints: ['rxjs:verifier'], }, - getAskarAnonCredsIndyModules({ + getAnonCredsIndyModules({ autoAcceptCredentials, autoAcceptProofs, }) diff --git a/packages/askar/src/wallet/AskarBaseWallet.ts b/packages/askar/src/wallet/AskarBaseWallet.ts index 90aae49f79..9e3c1383cd 100644 --- a/packages/askar/src/wallet/AskarBaseWallet.ts +++ b/packages/askar/src/wallet/AskarBaseWallet.ts @@ -18,24 +18,21 @@ import { WalletKeyExistsError, isValidSeed, isValidPrivateKey, - JsonTransformer, JsonEncoder, - KeyType, Buffer, AriesFrameworkError, WalletError, Key, TypedArrayEncoder, } from '@credo-ts/core' -import { KeyAlgs, CryptoBox, Store, Key as AskarKey, keyAlgFromString } from '@hyperledger/aries-askar-shared' -// eslint-disable-next-line import/order +import { CryptoBox, Store, Key as AskarKey, keyAlgFromString } from '@hyperledger/aries-askar-shared' import BigNumber from 'bn.js' -const isError = (error: unknown): error is Error => error instanceof Error - import { AskarErrorCode, isAskarError, isKeyTypeSupportedByAskar, keyTypesSupportedByAskar } from '../utils' -import { JweEnvelope, JweRecipient } from './JweEnvelope' +import { didcommV1Pack, didcommV1Unpack } from './didcommV1' + +const isError = (error: unknown): error is Error => error instanceof Error export abstract class AskarBaseWallet implements Wallet { protected _session?: Session @@ -102,7 +99,7 @@ export abstract class AskarBaseWallet implements Wallet { // Create key let key: AskarKey | undefined try { - const key = privateKey + key = privateKey ? AskarKey.fromSecretBytes({ secretKey: privateKey, algorithm }) : seed ? AskarKey.fromSeed({ seed, algorithm }) @@ -216,7 +213,7 @@ export abstract class AskarBaseWallet implements Wallet { throw new WalletError(`Currently not supporting verification of multiple messages`) } - const askarKey = AskarKey.fromPublicBytes({ + askarKey = AskarKey.fromPublicBytes({ algorithm: keyAlgFromString(key.keyType), publicKey: key.publicKey, }) @@ -262,96 +259,18 @@ export abstract class AskarBaseWallet implements Wallet { recipientKeys: string[], senderVerkey?: string // in base58 ): Promise { - let cek: AskarKey | undefined - let senderKey: KeyEntryObject | null | undefined - let senderExchangeKey: AskarKey | undefined + const senderKey = senderVerkey ? await this.session.fetchKey({ name: senderVerkey }) : undefined try { - cek = AskarKey.generate(KeyAlgs.Chacha20C20P) - - senderKey = senderVerkey ? await this.session.fetchKey({ name: senderVerkey }) : undefined if (senderVerkey && !senderKey) { - throw new WalletError(`Unable to pack message. Sender key ${senderVerkey} not found in wallet.`) + throw new WalletError(`Sender key not found`) } - senderExchangeKey = senderKey ? senderKey.key.convertkey({ algorithm: KeyAlgs.X25519 }) : undefined + const envelope = didcommV1Pack(payload, recipientKeys, senderKey?.key) - const recipients: JweRecipient[] = [] - - for (const recipientKey of recipientKeys) { - let targetExchangeKey: AskarKey | undefined - try { - targetExchangeKey = AskarKey.fromPublicBytes({ - publicKey: Key.fromPublicKeyBase58(recipientKey, KeyType.Ed25519).publicKey, - algorithm: KeyAlgs.Ed25519, - }).convertkey({ algorithm: KeyAlgs.X25519 }) - - if (senderVerkey && senderExchangeKey) { - const encryptedSender = CryptoBox.seal({ - recipientKey: targetExchangeKey, - message: Buffer.from(senderVerkey), - }) - const nonce = CryptoBox.randomNonce() - const encryptedCek = CryptoBox.cryptoBox({ - recipientKey: targetExchangeKey, - senderKey: senderExchangeKey, - message: cek.secretBytes, - nonce, - }) - - recipients.push( - new JweRecipient({ - encryptedKey: encryptedCek, - header: { - kid: recipientKey, - sender: TypedArrayEncoder.toBase64URL(encryptedSender), - iv: TypedArrayEncoder.toBase64URL(nonce), - }, - }) - ) - } else { - const encryptedCek = CryptoBox.seal({ - recipientKey: targetExchangeKey, - message: cek.secretBytes, - }) - recipients.push( - new JweRecipient({ - encryptedKey: encryptedCek, - header: { - kid: recipientKey, - }, - }) - ) - } - } finally { - targetExchangeKey?.handle.free() - } - } - - const protectedJson = { - enc: 'xchacha20poly1305_ietf', - typ: 'JWM/1.0', - alg: senderVerkey ? 'Authcrypt' : 'Anoncrypt', - recipients: recipients.map((item) => JsonTransformer.toJSON(item)), - } - - const { ciphertext, tag, nonce } = cek.aeadEncrypt({ - message: Buffer.from(JSON.stringify(payload)), - aad: Buffer.from(JsonEncoder.toBase64URL(protectedJson)), - }).parts - - const envelope = new JweEnvelope({ - ciphertext: TypedArrayEncoder.toBase64URL(ciphertext), - iv: TypedArrayEncoder.toBase64URL(nonce), - protected: JsonEncoder.toBase64URL(protectedJson), - tag: TypedArrayEncoder.toBase64URL(tag), - }).toJson() - - return envelope as EncryptedMessage + return envelope } finally { - cek?.handle.free() senderKey?.key.handle.free() - senderExchangeKey?.handle.free() } } @@ -363,101 +282,21 @@ export abstract class AskarBaseWallet implements Wallet { */ public async unpack(messagePackage: EncryptedMessage): Promise { const protectedJson = JsonEncoder.fromBase64(messagePackage.protected) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const recipientKids: string[] = protectedJson.recipients.map((r: any) => r.header.kid) - const alg = protectedJson.alg - if (!['Anoncrypt', 'Authcrypt'].includes(alg)) { - throw new WalletError(`Unsupported pack algorithm: ${alg}`) - } - - const recipients = [] - - for (const recip of protectedJson.recipients) { - const kid = recip.header.kid - if (!kid) { - throw new WalletError('Blank recipient key') - } - const sender = recip.header.sender ? TypedArrayEncoder.fromBase64(recip.header.sender) : undefined - const iv = recip.header.iv ? TypedArrayEncoder.fromBase64(recip.header.iv) : undefined - if (sender && !iv) { - throw new WalletError('Missing IV') - } else if (!sender && iv) { - throw new WalletError('Unexpected IV') - } - recipients.push({ - kid, - sender, - iv, - encrypted_key: TypedArrayEncoder.fromBase64(recip.encrypted_key), - }) - } - - let payloadKey, senderKey, recipientKey - - for (const recipient of recipients) { - let recipientKeyEntry: KeyEntryObject | null | undefined - let sender_x: AskarKey | undefined - let recip_x: AskarKey | undefined - + for (const recipientKid of recipientKids) { + const recipientKeyEntry = await this.session.fetchKey({ name: recipientKid }) try { - recipientKeyEntry = await this.session.fetchKey({ name: recipient.kid }) if (recipientKeyEntry) { - const recip_x = recipientKeyEntry.key.convertkey({ algorithm: KeyAlgs.X25519 }) - recipientKey = recipient.kid - - if (recipient.sender && recipient.iv) { - senderKey = TypedArrayEncoder.toUtf8String( - CryptoBox.sealOpen({ - recipientKey: recip_x, - ciphertext: recipient.sender, - }) - ) - const sender_x = AskarKey.fromPublicBytes({ - algorithm: KeyAlgs.Ed25519, - publicKey: TypedArrayEncoder.fromBase58(senderKey), - }).convertkey({ algorithm: KeyAlgs.X25519 }) - - payloadKey = CryptoBox.open({ - recipientKey: recip_x, - senderKey: sender_x, - message: recipient.encrypted_key, - nonce: recipient.iv, - }) - } else { - payloadKey = CryptoBox.sealOpen({ ciphertext: recipient.encrypted_key, recipientKey: recip_x }) - } - break + return didcommV1Unpack(messagePackage, recipientKeyEntry.key) } } finally { recipientKeyEntry?.key.handle.free() - sender_x?.handle.free() - recip_x?.handle.free() } } - if (!payloadKey) { - throw new WalletError('No corresponding recipient key found') - } - - if (!senderKey && alg === 'Authcrypt') { - throw new WalletError('Sender public key not provided for Authcrypt') - } - let cek: AskarKey | undefined - try { - cek = AskarKey.fromSecretBytes({ algorithm: KeyAlgs.Chacha20C20P, secretKey: payloadKey }) - const message = cek.aeadDecrypt({ - ciphertext: TypedArrayEncoder.fromBase64(messagePackage.ciphertext), - nonce: TypedArrayEncoder.fromBase64(messagePackage.iv), - tag: TypedArrayEncoder.fromBase64(messagePackage.tag), - aad: TypedArrayEncoder.fromString(messagePackage.protected), - }) - return { - plaintextMessage: JsonEncoder.fromBuffer(message), - senderKey, - recipientKey, - } - } finally { - cek?.handle.free() - } + throw new WalletError('No corresponding recipient key found') } public async generateNonce(): Promise { diff --git a/packages/askar/src/wallet/didcommV1.ts b/packages/askar/src/wallet/didcommV1.ts new file mode 100644 index 0000000000..6ab9a7f76d --- /dev/null +++ b/packages/askar/src/wallet/didcommV1.ts @@ -0,0 +1,177 @@ +import type { EncryptedMessage } from '@credo-ts/core' + +import { WalletError, JsonEncoder, JsonTransformer, Key, KeyType, TypedArrayEncoder, Buffer } from '@credo-ts/core' +import { CryptoBox, Key as AskarKey, KeyAlgs } from '@hyperledger/aries-askar-shared' + +import { JweEnvelope, JweRecipient } from './JweEnvelope' + +export function didcommV1Pack(payload: Record, recipientKeys: string[], senderKey?: AskarKey) { + let cek: AskarKey | undefined + let senderExchangeKey: AskarKey | undefined + + try { + cek = AskarKey.generate(KeyAlgs.Chacha20C20P) + + senderExchangeKey = senderKey ? senderKey.convertkey({ algorithm: KeyAlgs.X25519 }) : undefined + + const recipients: JweRecipient[] = [] + + for (const recipientKey of recipientKeys) { + let targetExchangeKey: AskarKey | undefined + try { + targetExchangeKey = AskarKey.fromPublicBytes({ + publicKey: Key.fromPublicKeyBase58(recipientKey, KeyType.Ed25519).publicKey, + algorithm: KeyAlgs.Ed25519, + }).convertkey({ algorithm: KeyAlgs.X25519 }) + + if (senderKey && senderExchangeKey) { + const encryptedSender = CryptoBox.seal({ + recipientKey: targetExchangeKey, + message: TypedArrayEncoder.fromString(TypedArrayEncoder.toBase58(senderKey.publicBytes)), + }) + const nonce = CryptoBox.randomNonce() + const encryptedCek = CryptoBox.cryptoBox({ + recipientKey: targetExchangeKey, + senderKey: senderExchangeKey, + message: cek.secretBytes, + nonce, + }) + + recipients.push( + new JweRecipient({ + encryptedKey: encryptedCek, + header: { + kid: recipientKey, + sender: TypedArrayEncoder.toBase64URL(encryptedSender), + iv: TypedArrayEncoder.toBase64URL(nonce), + }, + }) + ) + } else { + const encryptedCek = CryptoBox.seal({ + recipientKey: targetExchangeKey, + message: cek.secretBytes, + }) + recipients.push( + new JweRecipient({ + encryptedKey: encryptedCek, + header: { + kid: recipientKey, + }, + }) + ) + } + } finally { + targetExchangeKey?.handle.free() + } + } + + const protectedJson = { + enc: 'xchacha20poly1305_ietf', + typ: 'JWM/1.0', + alg: senderKey ? 'Authcrypt' : 'Anoncrypt', + recipients: recipients.map((item) => JsonTransformer.toJSON(item)), + } + + const { ciphertext, tag, nonce } = cek.aeadEncrypt({ + message: Buffer.from(JSON.stringify(payload)), + aad: Buffer.from(JsonEncoder.toBase64URL(protectedJson)), + }).parts + + const envelope = new JweEnvelope({ + ciphertext: TypedArrayEncoder.toBase64URL(ciphertext), + iv: TypedArrayEncoder.toBase64URL(nonce), + protected: JsonEncoder.toBase64URL(protectedJson), + tag: TypedArrayEncoder.toBase64URL(tag), + }).toJson() + + return envelope as EncryptedMessage + } finally { + cek?.handle.free() + senderExchangeKey?.handle.free() + } +} + +export function didcommV1Unpack(messagePackage: EncryptedMessage, recipientKey: AskarKey) { + const protectedJson = JsonEncoder.fromBase64(messagePackage.protected) + + const alg = protectedJson.alg + if (!['Anoncrypt', 'Authcrypt'].includes(alg)) { + throw new WalletError(`Unsupported pack algorithm: ${alg}`) + } + + const recipient = protectedJson.recipients.find( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (r: any) => r.header.kid === TypedArrayEncoder.toBase58(recipientKey.publicBytes) + ) + + if (!recipient) { + throw new WalletError('No corresponding recipient key found') + } + + const sender = recipient?.header.sender ? TypedArrayEncoder.fromBase64(recipient.header.sender) : undefined + const iv = recipient?.header.iv ? TypedArrayEncoder.fromBase64(recipient.header.iv) : undefined + const encrypted_key = TypedArrayEncoder.fromBase64(recipient.encrypted_key) + + if (sender && !iv) { + throw new WalletError('Missing IV') + } else if (!sender && iv) { + throw new WalletError('Unexpected IV') + } + + let payloadKey, senderKey + + let sender_x: AskarKey | undefined + let recip_x: AskarKey | undefined + + try { + recip_x = recipientKey.convertkey({ algorithm: KeyAlgs.X25519 }) + + if (sender && iv) { + senderKey = TypedArrayEncoder.toUtf8String( + CryptoBox.sealOpen({ + recipientKey: recip_x, + ciphertext: sender, + }) + ) + sender_x = AskarKey.fromPublicBytes({ + algorithm: KeyAlgs.Ed25519, + publicKey: TypedArrayEncoder.fromBase58(senderKey), + }).convertkey({ algorithm: KeyAlgs.X25519 }) + + payloadKey = CryptoBox.open({ + recipientKey: recip_x, + senderKey: sender_x, + message: encrypted_key, + nonce: iv, + }) + } else { + payloadKey = CryptoBox.sealOpen({ ciphertext: encrypted_key, recipientKey: recip_x }) + } + } finally { + sender_x?.handle.free() + recip_x?.handle.free() + } + + if (!senderKey && alg === 'Authcrypt') { + throw new WalletError('Sender public key not provided for Authcrypt') + } + + let cek: AskarKey | undefined + try { + cek = AskarKey.fromSecretBytes({ algorithm: KeyAlgs.Chacha20C20P, secretKey: payloadKey }) + const message = cek.aeadDecrypt({ + ciphertext: TypedArrayEncoder.fromBase64(messagePackage.ciphertext), + nonce: TypedArrayEncoder.fromBase64(messagePackage.iv), + tag: TypedArrayEncoder.fromBase64(messagePackage.tag), + aad: TypedArrayEncoder.fromString(messagePackage.protected), + }) + return { + plaintextMessage: JsonEncoder.fromBuffer(message), + senderKey, + recipientKey: TypedArrayEncoder.toBase58(recipientKey.publicBytes), + } + } finally { + cek?.handle.free() + } +} diff --git a/packages/askar/tests/askar-inmemory.e2e.test.ts b/packages/askar/tests/askar-inmemory.e2e.test.ts index e848602aab..d98e762fa5 100644 --- a/packages/askar/tests/askar-inmemory.e2e.test.ts +++ b/packages/askar/tests/askar-inmemory.e2e.test.ts @@ -7,16 +7,16 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { e2eTest, getSqliteAgentOptions } from './helpers' +import { e2eTest, getAskarSqliteAgentOptions } from './helpers' -const aliceInMemoryAgentOptions = getSqliteAgentOptions( +const aliceInMemoryAgentOptions = getAskarSqliteAgentOptions( 'AgentsAlice', { endpoints: ['rxjs:alice'], }, true ) -const bobInMemoryAgentOptions = getSqliteAgentOptions( +const bobInMemoryAgentOptions = getAskarSqliteAgentOptions( 'AgentsBob', { endpoints: ['rxjs:bob'], diff --git a/packages/askar/tests/askar-postgres.e2e.test.ts b/packages/askar/tests/askar-postgres.e2e.test.ts index ee3a586924..92a7168b5f 100644 --- a/packages/askar/tests/askar-postgres.e2e.test.ts +++ b/packages/askar/tests/askar-postgres.e2e.test.ts @@ -7,12 +7,12 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { askarPostgresStorageConfig, e2eTest, getPostgresAgentOptions } from './helpers' +import { askarPostgresStorageConfig, e2eTest, getAskarPostgresAgentOptions } from './helpers' -const alicePostgresAgentOptions = getPostgresAgentOptions('AgentsAlice', askarPostgresStorageConfig, { +const alicePostgresAgentOptions = getAskarPostgresAgentOptions('AgentsAlice', askarPostgresStorageConfig, { endpoints: ['rxjs:alice'], }) -const bobPostgresAgentOptions = getPostgresAgentOptions('AgentsBob', askarPostgresStorageConfig, { +const bobPostgresAgentOptions = getAskarPostgresAgentOptions('AgentsBob', askarPostgresStorageConfig, { endpoints: ['rxjs:bob'], }) diff --git a/packages/askar/tests/askar-sqlite.e2e.test.ts b/packages/askar/tests/askar-sqlite.e2e.test.ts index 3a3797ec4b..7de1f8408b 100644 --- a/packages/askar/tests/askar-sqlite.e2e.test.ts +++ b/packages/askar/tests/askar-sqlite.e2e.test.ts @@ -15,10 +15,10 @@ import { Store } from '@hyperledger/aries-askar-shared' import { tmpdir } from 'os' import path from 'path' -import { getSqliteAgentOptions } from './helpers' +import { getAskarSqliteAgentOptions } from './helpers' -const aliceAgentOptions = getSqliteAgentOptions('AgentsAlice') -const bobAgentOptions = getSqliteAgentOptions('AgentsBob') +const aliceAgentOptions = getAskarSqliteAgentOptions('AgentsAlice') +const bobAgentOptions = getAskarSqliteAgentOptions('AgentsBob') describe('Askar SQLite agents', () => { let aliceAgent: Agent diff --git a/packages/askar/tests/helpers.ts b/packages/askar/tests/helpers.ts index ecf6c13143..af6fddea15 100644 --- a/packages/askar/tests/helpers.ts +++ b/packages/askar/tests/helpers.ts @@ -39,7 +39,7 @@ export const askarPostgresStorageConfig: AskarWalletPostgresStorageConfig = { }, } -export function getPostgresAgentOptions( +export function getAskarPostgresAgentOptions( name: string, storageConfig: AskarWalletPostgresStorageConfig, extraConfig: Partial = {} @@ -68,7 +68,7 @@ export function getPostgresAgentOptions( } as const } -export function getSqliteAgentOptions(name: string, extraConfig: Partial = {}, inMemory?: boolean) { +export function getAskarSqliteAgentOptions(name: string, extraConfig: Partial = {}, inMemory?: boolean) { const random = utils.uuid().slice(0, 4) const config: InitConfig = { label: `SQLiteAgent: ${name} - ${random}`, diff --git a/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts b/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts index a723effe68..3448d05754 100644 --- a/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts +++ b/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts @@ -69,6 +69,9 @@ describeSkipNode18('BBS W3cCredentialService', () => { const privateKey = TypedArrayEncoder.fromString('testseed000000000000000000000001') beforeAll(async () => { + // Use askar wallet so we can use the signing provider registry + // TODO: support signing provider registry in memory wallet + // so we don't have to use askar here wallet = new RegisteredAskarTestWallet( agentConfig.logger, new agentDependencies.FileSystem(), diff --git a/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts b/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts index feaead2f3e..fea00fcc68 100644 --- a/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts +++ b/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts @@ -63,6 +63,7 @@ describeSkipNode18('credentials, BBS+ signature', () => { } = await setupJsonLdTests({ issuerName: 'Faber Agent Credentials LD BBS+', holderName: 'Alice Agent Credentials LD BBS+', + useBbs: true, })) await faberAgent.context.wallet.createKey({ diff --git a/packages/cheqd/tests/cheqd-did-registrar.e2e.test.ts b/packages/cheqd/tests/cheqd-did-registrar.e2e.test.ts index 69f0f524c2..d86a9c7f77 100644 --- a/packages/cheqd/tests/cheqd-did-registrar.e2e.test.ts +++ b/packages/cheqd/tests/cheqd-did-registrar.e2e.test.ts @@ -4,12 +4,12 @@ import type { DidDocument } from '@credo-ts/core' import { Agent, TypedArrayEncoder } from '@credo-ts/core' import { generateKeyPairFromSeed } from '@stablelib/ed25519' -import { getAgentOptions } from '../../core/tests/helpers' +import { getInMemoryAgentOptions } from '../../core/tests/helpers' import { validService } from './setup' import { getCheqdModules } from './setupCheqdModule' -const agentOptions = getAgentOptions('Faber Dids Registrar', {}, getCheqdModules()) +const agentOptions = getInMemoryAgentOptions('Faber Dids Registrar', {}, getCheqdModules()) describe('Cheqd DID registrar', () => { let agent: Agent> diff --git a/packages/cheqd/tests/cheqd-did-resolver.e2e.test.ts b/packages/cheqd/tests/cheqd-did-resolver.e2e.test.ts index 4a11e53ed5..498cd6e4ec 100644 --- a/packages/cheqd/tests/cheqd-did-resolver.e2e.test.ts +++ b/packages/cheqd/tests/cheqd-did-resolver.e2e.test.ts @@ -1,13 +1,13 @@ import { Agent, JsonTransformer } from '@credo-ts/core' -import { getAgentOptions } from '../../core/tests/helpers' +import { getInMemoryAgentOptions } from '../../core/tests/helpers' import { getClosestResourceVersion } from '../src/dids/didCheqdUtil' import { DefaultRPCUrl } from '../src/ledger/CheqdLedgerService' import { getCheqdModules } from './setupCheqdModule' export const resolverAgent = new Agent( - getAgentOptions('Cheqd resolver', {}, getCheqdModules(undefined, DefaultRPCUrl.Testnet)) + getInMemoryAgentOptions('Cheqd resolver', {}, getCheqdModules(undefined, DefaultRPCUrl.Testnet)) ) describe('Cheqd DID resolver', () => { diff --git a/packages/cheqd/tests/cheqd-sdk-anoncreds-registry.e2e.test.ts b/packages/cheqd/tests/cheqd-sdk-anoncreds-registry.e2e.test.ts index 77c6caaf6c..39802bb20e 100644 --- a/packages/cheqd/tests/cheqd-sdk-anoncreds-registry.e2e.test.ts +++ b/packages/cheqd/tests/cheqd-sdk-anoncreds-registry.e2e.test.ts @@ -2,21 +2,21 @@ import type { CheqdDidCreateOptions } from '../src' import { Agent, JsonTransformer, TypedArrayEncoder } from '@credo-ts/core' -import { agentDependencies, getAgentConfig } from '../../core/tests/helpers' +import { getInMemoryAgentOptions } from '../../core/tests/helpers' import { CheqdAnonCredsRegistry } from '../src/anoncreds' import { resolverAgent } from './cheqd-did-resolver.e2e.test' import { getCheqdModules } from './setupCheqdModule' -const agentConfig = getAgentConfig('cheqdAnonCredsRegistry') - -const agent = new Agent({ - config: agentConfig, - dependencies: agentDependencies, - modules: getCheqdModules( - 'ugly dirt sorry girl prepare argue door man that manual glow scout bomb pigeon matter library transfer flower clown cat miss pluck drama dizzy' - ), -}) +const agent = new Agent( + getInMemoryAgentOptions( + 'cheqdAnonCredsRegistry', + {}, + getCheqdModules( + 'ugly dirt sorry girl prepare argue door man that manual glow scout bomb pigeon matter library transfer flower clown cat miss pluck drama dizzy' + ) + ) +) const cheqdAnonCredsRegistry = new CheqdAnonCredsRegistry() diff --git a/packages/cheqd/tests/setupCheqdModule.ts b/packages/cheqd/tests/setupCheqdModule.ts index f04283276e..b4a6f39fea 100644 --- a/packages/cheqd/tests/setupCheqdModule.ts +++ b/packages/cheqd/tests/setupCheqdModule.ts @@ -2,7 +2,6 @@ import type { CheqdModuleConfigOptions } from '../src' import { DidsModule } from '@credo-ts/core' -import { askarModule } from '../../askar/tests/helpers' import { CheqdModule, CheqdDidRegistrar, CheqdDidResolver } from '../src' export const getCheqdModuleConfig = (seed?: string, rpcUrl?: string) => @@ -24,5 +23,4 @@ export const getCheqdModules = (seed?: string, rpcUrl?: string) => ({ registrars: [new CheqdDidRegistrar()], resolvers: [new CheqdDidResolver()], }), - askarModule, }) diff --git a/packages/core/src/agent/__tests__/Agent.test.ts b/packages/core/src/agent/__tests__/Agent.test.ts index 803741a0db..662dd2ccc6 100644 --- a/packages/core/src/agent/__tests__/Agent.test.ts +++ b/packages/core/src/agent/__tests__/Agent.test.ts @@ -2,8 +2,8 @@ import type { DependencyManager, Module } from '../../plugins' import { injectable } from 'tsyringe' -import { askarModule } from '../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../tests/helpers' +import { InMemoryWalletModule } from '../../../../../tests/InMemoryWalletModule' +import { getInMemoryAgentOptions } from '../../../tests/helpers' import { InjectionSymbols } from '../../constants' import { BasicMessageRepository, BasicMessageService } from '../../modules/basic-messages' import { BasicMessagesApi } from '../../modules/basic-messages/BasicMessagesApi' @@ -34,7 +34,7 @@ import { FeatureRegistry } from '../FeatureRegistry' import { MessageReceiver } from '../MessageReceiver' import { MessageSender } from '../MessageSender' -const agentOptions = getAgentOptions('Agent Class Test', {}, { askar: askarModule }) +const agentOptions = getInMemoryAgentOptions('Agent Class Test') const myModuleMethod = jest.fn() @injectable() @@ -62,7 +62,7 @@ describe('Agent', () => { ...agentOptions, modules: { myModule: new MyModule(), - askar: askarModule, + inMemory: new InMemoryWalletModule(), }, }) @@ -80,7 +80,7 @@ describe('Agent', () => { mediationRecipient: new MediationRecipientModule({ maximumMessagePickup: 42, }), - askar: askarModule, + inMemory: new InMemoryWalletModule(), }, }) diff --git a/packages/core/src/crypto/__tests__/JwsService.test.ts b/packages/core/src/crypto/__tests__/JwsService.test.ts index f43de829a1..d6654aaa0d 100644 --- a/packages/core/src/crypto/__tests__/JwsService.test.ts +++ b/packages/core/src/crypto/__tests__/JwsService.test.ts @@ -1,15 +1,14 @@ import type { AgentContext } from '../../agent' import type { Key, Wallet } from '@credo-ts/core' -import { RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' -import { agentDependencies, getAgentConfig, getAgentContext } from '../../../tests/helpers' +import { InMemoryWallet } from '../../../../../tests/InMemoryWallet' +import { getAgentConfig, getAgentContext } from '../../../tests/helpers' import { DidKey } from '../../modules/dids' import { JsonEncoder, TypedArrayEncoder } from '../../utils' import { JwsService } from '../JwsService' import { KeyType } from '../KeyType' import { JwaSignatureAlgorithm } from '../jose/jwa' import { getJwkFromKey } from '../jose/jwk' -import { SigningProviderRegistry } from '../signing-provider' import * as didJwsz6Mkf from './__fixtures__/didJwsz6Mkf' import * as didJwsz6Mkv from './__fixtures__/didJwsz6Mkv' @@ -25,11 +24,7 @@ describe('JwsService', () => { beforeAll(async () => { const config = getAgentConfig('JwsService') - wallet = new RegisteredAskarTestWallet( - config.logger, - new agentDependencies.FileSystem(), - new SigningProviderRegistry([]) - ) + wallet = new InMemoryWallet() agentContext = getAgentContext({ wallet, }) diff --git a/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts b/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts index c4b943a5e1..e3fbdbfe11 100644 --- a/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts +++ b/packages/core/src/decorators/signature/SignatureDecoratorUtils.test.ts @@ -1,9 +1,8 @@ import type { Wallet } from '../../wallet' -import { RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' -import { agentDependencies, getAgentConfig } from '../../../tests/helpers' +import { InMemoryWallet } from '../../../../../tests/InMemoryWallet' +import { getAgentConfig } from '../../../tests/helpers' import { KeyType } from '../../crypto' -import { SigningProviderRegistry } from '../../crypto/signing-provider' import { TypedArrayEncoder } from '../../utils' import { SignatureDecorator } from './SignatureDecorator' @@ -46,11 +45,7 @@ describe('Decorators | Signature | SignatureDecoratorUtils', () => { beforeAll(async () => { const config = getAgentConfig('SignatureDecoratorUtilsTest') - wallet = new RegisteredAskarTestWallet( - config.logger, - new agentDependencies.FileSystem(), - new SigningProviderRegistry([]) - ) + wallet = new InMemoryWallet() // eslint-disable-next-line @typescript-eslint/no-non-null-assertion await wallet.createAndOpen(config.walletConfig!) }) diff --git a/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts b/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts index ae6ca1a29c..57ceae6bb5 100644 --- a/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts +++ b/packages/core/src/modules/basic-messages/__tests__/basic-messages.e2e.test.ts @@ -6,29 +6,20 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions, makeConnection, waitForBasicMessage } from '../../../../tests/helpers' +import { getInMemoryAgentOptions, makeConnection, waitForBasicMessage } from '../../../../tests/helpers' import testLogger from '../../../../tests/logger' import { Agent } from '../../../agent/Agent' import { MessageSendingError, RecordNotFoundError } from '../../../error' import { BasicMessage } from '../messages' import { BasicMessageRecord } from '../repository' -const faberConfig = getAgentOptions( - 'Faber Basic Messages', - { - endpoints: ['rxjs:faber'], - }, - { askar: askarModule } -) - -const aliceConfig = getAgentOptions( - 'Alice Basic Messages', - { - endpoints: ['rxjs:alice'], - }, - { askar: askarModule } -) +const faberConfig = getInMemoryAgentOptions('Faber Basic Messages', { + endpoints: ['rxjs:faber'], +}) + +const aliceConfig = getInMemoryAgentOptions('Alice Basic Messages', { + endpoints: ['rxjs:alice'], +}) describe('Basic Messages E2E', () => { let faberAgent: Agent diff --git a/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts b/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts index 78ff3c9b7d..6ec32e78c3 100644 --- a/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts +++ b/packages/core/src/modules/connections/__tests__/ConnectionService.test.ts @@ -5,9 +5,8 @@ import type { Routing } from '../services/ConnectionService' import { Subject } from 'rxjs' -import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' +import { InMemoryWallet } from '../../../../../../tests/InMemoryWallet' import { - agentDependencies, getAgentConfig, getAgentContext, getMockConnection, @@ -18,7 +17,6 @@ import { AgentMessage } from '../../../agent/AgentMessage' import { EventEmitter } from '../../../agent/EventEmitter' import { InboundMessageContext } from '../../../agent/models/InboundMessageContext' import { Key, KeyType } from '../../../crypto' -import { SigningProviderRegistry } from '../../../crypto/signing-provider' import { signData, unpackAndVerifySignatureDecorator } from '../../../decorators/signature/SignatureDecoratorUtils' import { JsonTransformer } from '../../../utils/JsonTransformer' import { indyDidFromPublicKeyBase58 } from '../../../utils/did' @@ -92,11 +90,7 @@ describe('ConnectionService', () => { let agentContext: AgentContext beforeAll(async () => { - wallet = new RegisteredAskarTestWallet( - agentConfig.logger, - new agentDependencies.FileSystem(), - new SigningProviderRegistry([]) - ) + wallet = new InMemoryWallet() agentContext = getAgentContext({ wallet, agentConfig, diff --git a/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts b/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts index e784c6983e..fe519c8950 100644 --- a/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts +++ b/packages/core/src/modules/connections/__tests__/connection-manual.e2e.test.ts @@ -4,9 +4,8 @@ import type { ConnectionStateChangedEvent } from '../ConnectionEvents' import { firstValueFrom } from 'rxjs' import { filter, first, map, timeout } from 'rxjs/operators' -import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' -import { getAgentOptions } from '../../../../tests/helpers' +import { getInMemoryAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { ConnectionEventTypes } from '../ConnectionEvents' import { ConnectionsModule } from '../ConnectionsModule' @@ -46,39 +45,36 @@ describe('Manual Connection Flow', () => { // This test was added to reproduce a bug where all connections based on a reusable invitation would use the same keys // This was only present in the manual flow, which is almost never used. it('can connect multiple times using the same reusable invitation without manually using the connections api', async () => { - const aliceAgentOptions = getAgentOptions( + const aliceAgentOptions = getInMemoryAgentOptions( 'Manual Connection Flow Alice', { label: 'alice', endpoints: ['rxjs:alice'], }, { - askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, }), } ) - const bobAgentOptions = getAgentOptions( + const bobAgentOptions = getInMemoryAgentOptions( 'Manual Connection Flow Bob', { label: 'bob', endpoints: ['rxjs:bob'], }, { - askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, }), } ) - const faberAgentOptions = getAgentOptions( + const faberAgentOptions = getInMemoryAgentOptions( 'Manual Connection Flow Faber', { endpoints: ['rxjs:faber'], }, { - askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, }), diff --git a/packages/core/src/modules/connections/__tests__/did-rotate.e2e.test.ts b/packages/core/src/modules/connections/__tests__/did-rotate.e2e.test.ts index 14c8496094..a6f885cb5f 100644 --- a/packages/core/src/modules/connections/__tests__/did-rotate.e2e.test.ts +++ b/packages/core/src/modules/connections/__tests__/did-rotate.e2e.test.ts @@ -5,10 +5,9 @@ import type { ConnectionRecord } from '../repository' import { ReplaySubject, first, firstValueFrom, timeout } from 'rxjs' import { MessageSender } from '../../..//agent/MessageSender' -import { getIndySdkModules } from '../../../../../indy-sdk/tests/setupIndySdkModule' import { setupSubjectTransports, testLogger } from '../../../../tests' import { - getAgentOptions, + getInMemoryAgentOptions, makeConnection, waitForAgentMessageProcessedEvent, waitForBasicMessage, @@ -32,7 +31,7 @@ describe('Rotation E2E tests', () => { let bobAliceConnection: ConnectionRecord | undefined beforeEach(async () => { - const aliceAgentOptions = getAgentOptions( + const aliceAgentOptions = getInMemoryAgentOptions( 'DID Rotate Alice', { label: 'alice', @@ -40,13 +39,12 @@ describe('Rotation E2E tests', () => { logger: testLogger, }, { - ...getIndySdkModules(), connections: new ConnectionsModule({ autoAcceptConnections: true, }), } ) - const bobAgentOptions = getAgentOptions( + const bobAgentOptions = getInMemoryAgentOptions( 'DID Rotate Bob', { label: 'bob', @@ -54,7 +52,6 @@ describe('Rotation E2E tests', () => { logger: testLogger, }, { - ...getIndySdkModules(), connections: new ConnectionsModule({ autoAcceptConnections: true, }), diff --git a/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts b/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts index 8f7912e02e..3edcc48d0f 100644 --- a/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts +++ b/packages/core/src/modules/connections/__tests__/didexchange-numalgo.e2e.test.ts @@ -4,9 +4,8 @@ import type { ConnectionStateChangedEvent } from '../ConnectionEvents' import { firstValueFrom } from 'rxjs' import { filter, first, map, timeout } from 'rxjs/operators' -import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' -import { getAgentOptions } from '../../../../tests/helpers' +import { getInMemoryAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { uuid } from '../../../utils/uuid' import { DidsModule, PeerDidNumAlgo, createPeerDidDocumentFromServices } from '../../dids' @@ -96,14 +95,13 @@ async function didExchangeNumAlgoBaseTest(options: { // Make a common in-memory did registry for both agents const didRegistry = new InMemoryDidRegistry() - const aliceAgentOptions = getAgentOptions( + const aliceAgentOptions = getInMemoryAgentOptions( 'DID Exchange numalgo settings Alice', { label: 'alice', endpoints: ['rxjs:alice'], }, { - askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, peerNumAlgoForDidExchangeRequests: options.requesterNumAlgoSetting, @@ -111,13 +109,12 @@ async function didExchangeNumAlgoBaseTest(options: { dids: new DidsModule({ registrars: [didRegistry], resolvers: [didRegistry] }), } ) - const faberAgentOptions = getAgentOptions( + const faberAgentOptions = getInMemoryAgentOptions( 'DID Exchange numalgo settings Alice', { endpoints: ['rxjs:faber'], }, { - askar: askarModule, connections: new ConnectionsModule({ autoAcceptConnections: false, peerNumAlgoForDidExchangeRequests: options.responderNumAlgoSetting, diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts index 9e1c5a7f0c..2a90d4ec88 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-connectionless-credentials.e2e.test.ts @@ -8,10 +8,10 @@ import { ReplaySubject, Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../../../tests/transport/SubjectOutboundTransport' import { - getAskarAnonCredsIndyModules, + getAnonCredsIndyModules, prepareForAnonCredsIssuance, } from '../../../../../../../anoncreds/tests/legacyAnonCredsSetup' -import { waitForCredentialRecordSubject, getAgentOptions } from '../../../../../../tests/helpers' +import { waitForCredentialRecordSubject, getInMemoryAgentOptions } from '../../../../../../tests/helpers' import testLogger from '../../../../../../tests/logger' import { Agent } from '../../../../../agent/Agent' import { CredentialEventTypes } from '../../../CredentialEvents' @@ -20,20 +20,20 @@ import { CredentialState } from '../../../models/CredentialState' import { CredentialExchangeRecord } from '../../../repository/CredentialExchangeRecord' import { V2CredentialPreview } from '../messages' -const faberAgentOptions = getAgentOptions( +const faberAgentOptions = getInMemoryAgentOptions( 'Faber connection-less Credentials V2', { endpoints: ['rxjs:faber'], }, - getAskarAnonCredsIndyModules() + getAnonCredsIndyModules() ) -const aliceAgentOptions = getAgentOptions( +const aliceAgentOptions = getInMemoryAgentOptions( 'Alice connection-less Credentials V2', { endpoints: ['rxjs:alice'], }, - getAskarAnonCredsIndyModules() + getAnonCredsIndyModules() ) const credentialPreview = V2CredentialPreview.fromRecord({ diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts index 0fb3cf3e78..5e909c1457 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2-credentials-auto-accept.e2e.test.ts @@ -5,7 +5,7 @@ import { setupAnonCredsTests } from '../../../../../../../anoncreds/tests/legacy import { waitForCredentialRecord, waitForCredentialRecordSubject, - waitForMessageProcessedSubject, + waitForAgentMessageProcessedEventSubject, } from '../../../../../../tests/helpers' import testLogger from '../../../../../../tests/logger' import { AutoAcceptCredential } from '../../../models/CredentialAutoAcceptType' @@ -443,9 +443,9 @@ describe('V2 Credentials Auto Accept', () => { // ProposalReceived is emitted before the whole message is finished processing // So to not get errors when shutting down the agent, we wait for the message to be processed - await waitForMessageProcessedSubject(faberReplay, { + await waitForAgentMessageProcessedEventSubject(faberReplay, { threadId: aliceCredentialRecord.threadId, - messageClass: V2ProposeCredentialMessage, + messageType: V2ProposeCredentialMessage.type.messageTypeUri, }) }) }) diff --git a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts index 296e2bc863..bde3f9def5 100644 --- a/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts +++ b/packages/core/src/modules/credentials/protocol/v2/__tests__/v2.ldproof.credentials.propose-offerED25519.test.ts @@ -7,13 +7,13 @@ import { V1ProofProtocol, } from '../../../../../../../anoncreds/src' import { - getAskarAnonCredsIndyModules, + getAnonCredsIndyModules, prepareForAnonCredsIssuance, } from '../../../../../../../anoncreds/tests/legacyAnonCredsSetup' import { + getInMemoryAgentOptions, setupEventReplaySubjects, setupSubjectTransports, - getAgentOptions, waitForCredentialRecordSubject, testLogger, makeConnection, @@ -76,7 +76,7 @@ const indyProofFormat = new LegacyIndyProofFormatService() const getIndyJsonLdModules = () => ({ - ...getAskarAnonCredsIndyModules(), + ...getAnonCredsIndyModules(), credentials: new CredentialsModule({ credentialProtocols: [ new V1CredentialProtocol({ indyCredentialFormat }), @@ -112,7 +112,7 @@ describe('V2 Credentials - JSON-LD - Ed25519', () => { beforeAll(async () => { faberAgent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'Faber Agent Indy/JsonLD', { endpoints: ['rxjs:faber'], @@ -121,7 +121,7 @@ describe('V2 Credentials - JSON-LD - Ed25519', () => { ) ) aliceAgent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'Alice Agent Indy/JsonLD', { endpoints: ['rxjs:alice'], diff --git a/packages/core/src/modules/dids/__tests__/DidsApi.test.ts b/packages/core/src/modules/dids/__tests__/DidsApi.test.ts index c5351ea012..274a5bc031 100644 --- a/packages/core/src/modules/dids/__tests__/DidsApi.test.ts +++ b/packages/core/src/modules/dids/__tests__/DidsApi.test.ts @@ -1,5 +1,4 @@ -import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests/helpers' +import { getInMemoryAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { isLongFormDidPeer4, isShortFormDidPeer4 } from '../methods/peer/peerDidNumAlgo4' @@ -12,13 +11,7 @@ import { createPeerDidDocumentFromServices, } from '@credo-ts/core' -const agentOptions = getAgentOptions( - 'DidsApi', - {}, - { - askar: askarModule, - } -) +const agentOptions = getInMemoryAgentOptions('DidsApi') const agent = new Agent(agentOptions) @@ -67,6 +60,8 @@ describe('DidsApi', () => { method: 'key', methodSpecificIdentifier: 'z6MkjEayvPpjVJKFLirX8SomBTPDboHm1XSCkUev2M4siQty', role: 'created', + alternativeDids: undefined, + recipientKeyFingerprints: [], }) expect(createdDids[0].toJSON()).toMatchObject({ @@ -150,6 +145,8 @@ describe('DidsApi', () => { method: 'peer', methodSpecificIdentifier: '0z6Mkhu3G8viiebsWmCiSgWiQoCZrTeuX76oLDow81YNYvJQM', role: 'created', + alternativeDids: undefined, + recipientKeyFingerprints: [], }) expect(createdDids[0].toJSON()).toMatchObject({ diff --git a/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts b/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts index e09ebb8f1e..457cb2d73d 100644 --- a/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts +++ b/packages/core/src/modules/dids/__tests__/dids-registrar.e2e.test.ts @@ -1,21 +1,14 @@ import type { KeyDidCreateOptions } from '../methods/key/KeyDidRegistrar' import type { PeerDidNumAlgo0CreateOptions } from '../methods/peer/PeerDidRegistrar' -import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests/helpers' +import { getInMemoryAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { KeyType } from '../../../crypto' import { PeerDidNumAlgo } from '../methods/peer/didPeer' import { JsonTransformer, TypedArrayEncoder } from '@credo-ts/core' -const agentOptions = getAgentOptions( - 'Faber Dids Registrar', - {}, - { - askar: askarModule, - } -) +const agentOptions = getInMemoryAgentOptions('Faber Dids Registrar') describe('dids', () => { let agent: Agent diff --git a/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts b/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts index dcb6f8ff20..feba6ee688 100644 --- a/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts +++ b/packages/core/src/modules/dids/__tests__/dids-resolver.e2e.test.ts @@ -1,17 +1,8 @@ -import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests/helpers' +import { getInMemoryAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { JsonTransformer } from '../../../utils' -const agent = new Agent( - getAgentOptions( - 'Faber Dids', - {}, - { - askar: askarModule, - } - ) -) +const agent = new Agent(getInMemoryAgentOptions('Faber Dids')) describe('dids', () => { beforeAll(async () => { diff --git a/packages/core/src/modules/dids/__tests__/peer-did.test.ts b/packages/core/src/modules/dids/__tests__/peer-did.test.ts index 67a873c5ca..6f5afc193b 100644 --- a/packages/core/src/modules/dids/__tests__/peer-did.test.ts +++ b/packages/core/src/modules/dids/__tests__/peer-did.test.ts @@ -4,12 +4,11 @@ import type { Wallet } from '../../../wallet' import { Subject } from 'rxjs' import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' -import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' -import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../tests/helpers' +import { InMemoryWallet } from '../../../../../../tests/InMemoryWallet' +import { getAgentConfig, getAgentContext } from '../../../../tests/helpers' import { EventEmitter } from '../../../agent/EventEmitter' import { InjectionSymbols } from '../../../constants' import { Key, KeyType } from '../../../crypto' -import { SigningProviderRegistry } from '../../../crypto/signing-provider' import { JsonTransformer, TypedArrayEncoder } from '../../../utils' import { DidsModuleConfig } from '../DidsModuleConfig' import { @@ -40,11 +39,7 @@ describe('peer dids', () => { let eventEmitter: EventEmitter beforeEach(async () => { - wallet = new RegisteredAskarTestWallet( - config.logger, - new agentDependencies.FileSystem(), - new SigningProviderRegistry([]) - ) + wallet = new InMemoryWallet() const storageService = new InMemoryStorageService() eventEmitter = new EventEmitter(config.agentDependencies, new Subject()) didRepository = new DidRepository(storageService, eventEmitter) diff --git a/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts b/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts index 4b5ddd9fb3..9ca14efd37 100644 --- a/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts +++ b/packages/core/src/modules/discover-features/__tests__/v1-discover-features.e2e.test.ts @@ -6,33 +6,20 @@ import type { import { ReplaySubject } from 'rxjs' -import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' -import { getAgentOptions, makeConnection } from '../../../../tests/helpers' +import { getInMemoryAgentOptions, makeConnection } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { DiscoverFeaturesEventTypes } from '../DiscoverFeaturesEvents' import { waitForDisclosureSubject, waitForQuerySubject } from './helpers' -const faberAgentOptions = getAgentOptions( - 'Faber Discover Features V1 E2E', - { - endpoints: ['rxjs:faber'], - }, - { - askar: askarModule, - } -) - -const aliceAgentOptions = getAgentOptions( - 'Alice Discover Features V1 E2E', - { - endpoints: ['rxjs:alice'], - }, - { - askar: askarModule, - } -) +const faberAgentOptions = getInMemoryAgentOptions('Faber Discover Features V1 E2E', { + endpoints: ['rxjs:faber'], +}) + +const aliceAgentOptions = getInMemoryAgentOptions('Alice Discover Features V1 E2E', { + endpoints: ['rxjs:alice'], +}) describe('v1 discover features', () => { let faberAgent: Agent diff --git a/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts b/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts index 00f0c5cfb1..c76a574992 100644 --- a/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts +++ b/packages/core/src/modules/discover-features/__tests__/v2-discover-features.e2e.test.ts @@ -6,34 +6,21 @@ import type { import { ReplaySubject } from 'rxjs' -import { askarModule } from '../../../../../askar/tests/helpers' import { setupSubjectTransports } from '../../../../tests' -import { getAgentOptions, makeConnection } from '../../../../tests/helpers' +import { getInMemoryAgentOptions, makeConnection } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { GoalCode, Feature } from '../../../agent/models' import { DiscoverFeaturesEventTypes } from '../DiscoverFeaturesEvents' import { waitForDisclosureSubject, waitForQuerySubject } from './helpers' -const faberAgentOptions = getAgentOptions( - 'Faber Discover Features V2 E2E', - { - endpoints: ['rxjs:faber'], - }, - { - askar: askarModule, - } -) - -const aliceAgentOptions = getAgentOptions( - 'Alice Discover Features V2 E2E', - { - endpoints: ['rxjs:alice'], - }, - { - askar: askarModule, - } -) +const faberAgentOptions = getInMemoryAgentOptions('Faber Discover Features V2 E2E', { + endpoints: ['rxjs:faber'], +}) + +const aliceAgentOptions = getInMemoryAgentOptions('Alice Discover Features V2 E2E', { + endpoints: ['rxjs:alice'], +}) describe('v2 discover features', () => { let faberAgent: Agent diff --git a/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts b/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts index c035dd63fe..beb622c7fd 100644 --- a/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts +++ b/packages/core/src/modules/message-pickup/__tests__/pickup.test.ts @@ -5,37 +5,15 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { askarModule } from '../../../../../askar/tests/helpers' -import { - getAgentOptions, - getAskarWalletConfig, - waitForBasicMessage, - waitForTrustPingReceivedEvent, -} from '../../../../tests/helpers' +import { getInMemoryAgentOptions, waitForBasicMessage, waitForTrustPingReceivedEvent } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { HandshakeProtocol } from '../../connections' -const recipientOptions = getAgentOptions( - 'Mediation: Recipient Pickup', - { - // Agent is shutdown during test, so we can't use in-memory wallet - walletConfig: getAskarWalletConfig('Mediation: Recipient Pickup', { inMemory: false }), - }, - { - askar: askarModule, - } -) -const mediatorOptions = getAgentOptions( - 'Mediation: Mediator Pickup', - { - // Agent is shutdown during test, so we can't use in-memory wallet - walletConfig: getAskarWalletConfig('Mediation: Mediator Pickup', { inMemory: false }), - endpoints: ['wss://mediator'], - }, - { - askar: askarModule, - } -) +const recipientOptions = getInMemoryAgentOptions('Mediation: Recipient Pickup') +const mediatorOptions = getInMemoryAgentOptions('Mediation: Mediator Pickup', { + // Agent is shutdown during test, so we can't use in-memory wallet + endpoints: ['wss://mediator'], +}) describe('E2E Pick Up protocol', () => { let recipientAgent: Agent @@ -90,9 +68,6 @@ describe('E2E Pick Up protocol', () => { // Now they are connected, reinitialize recipient agent in order to lose the session (as with SubjectTransport it remains open) await recipientAgent.shutdown() - - recipientAgent = new Agent(recipientOptions) - recipientAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) await recipientAgent.initialize() const message = 'hello pickup V1' diff --git a/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts b/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts index 00253af4cd..2e6f5ef429 100644 --- a/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts +++ b/packages/core/src/modules/oob/__tests__/connect-to-self.e2e.test.ts @@ -5,22 +5,15 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests/helpers' +import { getInMemoryAgentOptions } from '../../../../tests/helpers' import { HandshakeProtocol, DidExchangeState } from '../../connections' import { OutOfBandState } from '../domain/OutOfBandState' import { Agent } from '@credo-ts/core' -const faberAgentOptions = getAgentOptions( - 'Faber Agent OOB Connect to Self', - { - endpoints: ['rxjs:faber'], - }, - { - askar: askarModule, - } -) +const faberAgentOptions = getInMemoryAgentOptions('Faber Agent OOB Connect to Self', { + endpoints: ['rxjs:faber'], +}) describe('out of band', () => { let faberAgent: Agent diff --git a/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts b/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts index 862c82001a..41535e27ae 100644 --- a/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts +++ b/packages/core/src/modules/oob/__tests__/implicit.e2e.test.ts @@ -1,10 +1,10 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { IndyVdrDidCreateOptions } from '@credo-ts/indy-vdr' -import { getAskarAnonCredsIndyModules } from '../../../../../anoncreds/tests/legacyAnonCredsSetup' +import { getAnonCredsIndyModules } from '../../../../../anoncreds/tests/legacyAnonCredsSetup' import { setupSubjectTransports } from '../../../../tests' import { - getAgentOptions, + getInMemoryAgentOptions, importExistingIndyDidFromPrivateKey, publicDidSeed, waitForConnectionRecord, @@ -15,19 +15,19 @@ import { sleep } from '../../../utils/sleep' import { DidExchangeState, HandshakeProtocol } from '../../connections' import { DidCommV1Service, DidCommV2Service, DidDocumentService } from '../../dids' -const faberAgentOptions = getAgentOptions( +const faberAgentOptions = getInMemoryAgentOptions( 'Faber Agent OOB Implicit', { endpoints: ['rxjs:faber'], }, - getAskarAnonCredsIndyModules() + getAnonCredsIndyModules() ) -const aliceAgentOptions = getAgentOptions( +const aliceAgentOptions = getInMemoryAgentOptions( 'Alice Agent OOB Implicit', { endpoints: ['rxjs:alice'], }, - getAskarAnonCredsIndyModules() + getAnonCredsIndyModules() ) describe('out of band implicit', () => { diff --git a/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts b/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts index 316927aaf8..cd2738efbe 100644 --- a/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts +++ b/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts @@ -4,7 +4,6 @@ import type { DifPresentationExchangeProofFormat } from '../DifPresentationExcha import { PresentationSubmissionLocation } from '@sphereon/pex' -import { getIndySdkModules } from '../../../../../../../indy-sdk/tests/setupIndySdkModule' import { agentDependencies, getAgentConfig } from '../../../../../../tests' import { Agent } from '../../../../../agent/Agent' import { DifPresentationExchangeModule, DifPresentationExchangeService } from '../../../../dif-presentation-exchange' @@ -95,11 +94,10 @@ describe('Presentation Exchange ProofFormatService', () => { agent = new Agent({ config: getAgentConfig('PresentationExchangeProofFormatService'), modules: { - someModule: new DifPresentationExchangeModule(), + pex: new DifPresentationExchangeModule(), proofs: new ProofsModule({ proofProtocols: [new V2ProofProtocol({ proofFormats: [new PresentationExchangeProofFormatService()] })], }), - ...getIndySdkModules(), }, dependencies: agentDependencies, }) diff --git a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts index db1bbbe965..4fecad52ea 100644 --- a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts +++ b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-indy-connectionless-proofs.e2e.test.ts @@ -7,18 +7,18 @@ import { SubjectInboundTransport } from '../../../../../../../../tests/transport import { SubjectOutboundTransport } from '../../../../../../../../tests/transport/SubjectOutboundTransport' import { V1CredentialPreview } from '../../../../../../../anoncreds/src' import { - getAskarAnonCredsIndyModules, + getAnonCredsIndyModules, issueLegacyAnonCredsCredential, prepareForAnonCredsIssuance, setupAnonCredsTests, } from '../../../../../../../anoncreds/tests/legacyAnonCredsSetup' import { waitForProofExchangeRecordSubject, - getAgentOptions, makeConnection, testLogger, setupEventReplaySubjects, waitForProofExchangeRecord, + getInMemoryAgentOptions, } from '../../../../../../tests' import { Agent } from '../../../../../agent/Agent' import { Attachment, AttachmentData } from '../../../../../decorators/attachment/Attachment' @@ -265,13 +265,13 @@ describe('V2 Connectionless Proofs - Indy', () => { const unique = uuid().substring(0, 4) - const mediatorOptions = getAgentOptions( + const mediatorOptions = getInMemoryAgentOptions( `Connectionless proofs with mediator Mediator-${unique}`, { endpoints: ['rxjs:mediator'], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediator: new MediatorModule({ @@ -299,11 +299,11 @@ describe('V2 Connectionless Proofs - Indy', () => { handshakeProtocols: [HandshakeProtocol.Connections], }) - const faberOptions = getAgentOptions( + const faberOptions = getInMemoryAgentOptions( `Connectionless proofs with mediator Faber-${unique}`, {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ @@ -315,11 +315,11 @@ describe('V2 Connectionless Proofs - Indy', () => { } ) - const aliceOptions = getAgentOptions( + const aliceOptions = getInMemoryAgentOptions( `Connectionless proofs with mediator Alice-${unique}`, {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptProofs: AutoAcceptProof.Always, }), mediationRecipient: new MediationRecipientModule({ diff --git a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-presentation-exchange-presentation.e2e.test.ts b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-presentation-exchange-presentation.e2e.test.ts index a0901029a6..fdea6b6698 100644 --- a/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-presentation-exchange-presentation.e2e.test.ts +++ b/packages/core/src/modules/proofs/protocol/v2/__tests__/v2-presentation-exchange-presentation.e2e.test.ts @@ -110,7 +110,7 @@ describe('Present Proof', () => { const verifierProofExchangeRecord = await verifierPresentationRecordPromise const didCommMessageRepository = - proverAgent.dependencyManager.resolve(DidCommMessageRepository) + verifierAgent.dependencyManager.resolve(DidCommMessageRepository) const proposal = await didCommMessageRepository.findAgentMessage(verifierAgent.context, { associatedRecordId: verifierProofExchangeRecord.id, diff --git a/packages/core/src/modules/routing/__tests__/mediation.test.ts b/packages/core/src/modules/routing/__tests__/mediation.test.ts index ae29aaf80b..cd5b284cdf 100644 --- a/packages/core/src/modules/routing/__tests__/mediation.test.ts +++ b/packages/core/src/modules/routing/__tests__/mediation.test.ts @@ -8,8 +8,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../../../../tests/transport/SubjectOutboundTransport' -import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions, getAskarWalletConfig, waitForBasicMessage } from '../../../../tests/helpers' +import { getInMemoryAgentOptions, waitForBasicMessage } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { sleep } from '../../../utils/sleep' import { ConnectionRecord, HandshakeProtocol } from '../../connections' @@ -18,35 +17,22 @@ import { MediatorModule } from '../MediatorModule' import { MediatorPickupStrategy } from '../MediatorPickupStrategy' import { MediationState } from '../models/MediationState' -const recipientAgentOptions = getAgentOptions( - 'Mediation: Recipient', - { - walletConfig: getAskarWalletConfig('Mediation: Recipient', { inMemory: false }), - }, - { askar: askarModule } -) -const mediatorAgentOptions = getAgentOptions( +const recipientAgentOptions = getInMemoryAgentOptions('Mediation: Recipient') +const mediatorAgentOptions = getInMemoryAgentOptions( 'Mediation: Mediator', { endpoints: ['rxjs:mediator'], - walletConfig: getAskarWalletConfig('Mediation: Mediator', { inMemory: false }), }, { - askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true, }), } ) -const senderAgentOptions = getAgentOptions( - 'Mediation: Sender', - { - endpoints: ['rxjs:sender'], - walletConfig: getAskarWalletConfig('Mediation: Sender', { inMemory: false }), - }, - { askar: askarModule } -) +const senderAgentOptions = getInMemoryAgentOptions('Mediation: Sender', { + endpoints: ['rxjs:sender'], +}) describe('mediator establishment', () => { let recipientAgent: Agent @@ -257,20 +243,6 @@ describe('mediator establishment', () => { // Restart recipient agent await recipientAgent.shutdown() - recipientAgent = new Agent({ - ...recipientAgentOptions, - modules: { - ...recipientAgentOptions.modules, - mediationRecipient: new MediationRecipientModule({ - mediatorInvitationUrl: mediatorOutOfBandRecord.outOfBandInvitation.toUrl({ - domain: 'https://example.com/ssi', - }), - mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, - }), - }, - }) - recipientAgent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)) - recipientAgent.registerInboundTransport(new SubjectInboundTransport(recipientMessages)) await recipientAgent.initialize() // Initialize sender agent diff --git a/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts b/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts index 99c73e17c5..f708a56e96 100644 --- a/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts +++ b/packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts @@ -1,9 +1,9 @@ import type { AgentContext } from '../../../agent' import type { Wallet } from '../../../wallet' -import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' -import { agentDependencies, getAgentConfig, getAgentContext, mockFunction } from '../../../../tests' -import { SigningProviderRegistry, JwsService } from '../../../crypto' +import { InMemoryWallet } from '../../../../../../tests/InMemoryWallet' +import { getAgentConfig, getAgentContext, mockFunction } from '../../../../tests' +import { JwsService } from '../../../crypto' import { JsonTransformer, asArray } from '../../../utils' import { W3cCredentialService } from '../W3cCredentialService' import { W3cCredentialsModuleConfig } from '../W3cCredentialsModuleConfig' @@ -17,8 +17,6 @@ import { W3cJwtCredentialService } from '../jwt-vc' import { W3cPresentation } from '../models' import { W3cCredentialRepository, W3cCredentialRecord } from '../repository' -const signingProviderRegistry = new SigningProviderRegistry([]) - jest.mock('../repository/W3cCredentialRepository') const W3cCredentialsRepositoryMock = W3cCredentialRepository as jest.Mock @@ -48,11 +46,7 @@ describe('W3cCredentialsService', () => { let w3cCredentialsRepository: W3cCredentialRepository beforeAll(async () => { - wallet = new RegisteredAskarTestWallet( - agentConfig.logger, - new agentDependencies.FileSystem(), - signingProviderRegistry - ) + wallet = new InMemoryWallet() await wallet.createAndOpen(agentConfig.walletConfig) agentContext = getAgentContext({ agentConfig, diff --git a/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts b/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts index f374f09593..c39f408452 100644 --- a/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts +++ b/packages/core/src/modules/vc/__tests__/W3cCredentialsApi.test.ts @@ -1,5 +1,4 @@ -import { askarModule } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests' +import { getInMemoryAgentOptions } from '../../../../tests' import { Agent } from '../../../agent/Agent' import { JsonTransformer } from '../../../utils' import { W3cCredentialService } from '../W3cCredentialService' @@ -9,14 +8,15 @@ import { Ed25519Signature2018Fixtures } from '../data-integrity/__tests__/fixtur import { W3cJsonLdVerifiableCredential } from '../data-integrity/models' import { W3cCredentialRepository } from '../repository' -const modules = { - askar: askarModule, - w3cCredentials: new W3cCredentialsModule({ - documentLoader: customDocumentLoader, - }), -} - -const agentOptions = getAgentOptions('W3cCredentialsApi', {}, modules) +const agentOptions = getInMemoryAgentOptions( + 'W3cCredentialsApi', + {}, + { + w3cCredentials: new W3cCredentialsModule({ + documentLoader: customDocumentLoader, + }), + } +) const agent = new Agent(agentOptions) diff --git a/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts b/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts index 72a4c9037d..b6170844f7 100644 --- a/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts +++ b/packages/core/src/modules/vc/data-integrity/__tests__/W3cJsonLdCredentialService.test.ts @@ -1,10 +1,9 @@ import type { AgentContext } from '../../../../agent' import type { Wallet } from '../../../../wallet' -import { RegisteredAskarTestWallet } from '../../../../../../askar/tests/helpers' -import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../../tests/helpers' +import { InMemoryWallet } from '../../../../../../../tests/InMemoryWallet' +import { getAgentConfig, getAgentContext } from '../../../../../tests/helpers' import { KeyType } from '../../../../crypto' -import { SigningProviderRegistry } from '../../../../crypto/signing-provider' import { asArray, TypedArrayEncoder } from '../../../../utils' import { JsonTransformer } from '../../../../utils/JsonTransformer' import { WalletError } from '../../../../wallet/error' @@ -40,7 +39,6 @@ const signatureSuiteRegistry = new SignatureSuiteRegistry([ }, ]) -const signingProviderRegistry = new SigningProviderRegistry([]) const agentConfig = getAgentConfig('W3cJsonLdCredentialServiceTest') describe('W3cJsonLdCredentialsService', () => { @@ -50,11 +48,7 @@ describe('W3cJsonLdCredentialsService', () => { const privateKey = TypedArrayEncoder.fromString('testseed000000000000000000000001') beforeAll(async () => { - wallet = new RegisteredAskarTestWallet( - agentConfig.logger, - new agentDependencies.FileSystem(), - signingProviderRegistry - ) + wallet = new InMemoryWallet() await wallet.createAndOpen(agentConfig.walletConfig) agentContext = getAgentContext({ agentConfig, diff --git a/packages/core/src/modules/vc/jwt-vc/__tests__/W3cJwtCredentialService.test.ts b/packages/core/src/modules/vc/jwt-vc/__tests__/W3cJwtCredentialService.test.ts index 42fb659cb0..51aa0706b0 100644 --- a/packages/core/src/modules/vc/jwt-vc/__tests__/W3cJwtCredentialService.test.ts +++ b/packages/core/src/modules/vc/jwt-vc/__tests__/W3cJwtCredentialService.test.ts @@ -1,7 +1,7 @@ -import { RegisteredAskarTestWallet } from '../../../../../../askar/tests/helpers' -import { agentDependencies, getAgentConfig, getAgentContext, testLogger } from '../../../../../tests' +import { InMemoryWallet } from '../../../../../../../tests/InMemoryWallet' +import { getAgentConfig, getAgentContext, testLogger } from '../../../../../tests' import { InjectionSymbols } from '../../../../constants' -import { JwsService, KeyType, SigningProviderRegistry } from '../../../../crypto' +import { JwsService, KeyType } from '../../../../crypto' import { JwaSignatureAlgorithm } from '../../../../crypto/jose/jwa' import { getJwkFromKey } from '../../../../crypto/jose/jwk' import { AriesFrameworkError, ClassValidationError } from '../../../../error' @@ -23,11 +23,7 @@ import { didIonJwtVcPresentationProfileJwtVc } from './fixtures/jwt-vc-presentat import { didKeyTransmuteJwtVc, didKeyTransmuteJwtVp } from './fixtures/transmute-verifiable-data' const config = getAgentConfig('W3cJwtCredentialService') -const wallet = new RegisteredAskarTestWallet( - config.logger, - new agentDependencies.FileSystem(), - new SigningProviderRegistry([]) -) +const wallet = new InMemoryWallet() const agentContext = getAgentContext({ wallet, registerInstances: [ diff --git a/packages/core/src/storage/migration/__tests__/0.1.test.ts b/packages/core/src/storage/migration/__tests__/0.1.test.ts index 67c9aabed0..deaf622249 100644 --- a/packages/core/src/storage/migration/__tests__/0.1.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.1.test.ts @@ -59,7 +59,12 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceMediationRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceMediationRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([ { @@ -74,9 +79,9 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { expect(await updateAssistant.isUpToDate('0.2')).toBe(true) expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([]) - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot(mediationRoleUpdateStrategy) + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot( + mediationRoleUpdateStrategy + ) await agent.shutdown() await agent.wallet.delete() @@ -117,7 +122,12 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceCredentialRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceCredentialRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.isUpToDate('0.2')).toBe(false) expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([ @@ -133,9 +143,7 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { expect(await updateAssistant.isUpToDate('0.2')).toBe(true) expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([]) - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() @@ -177,7 +185,12 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceCredentialRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceCredentialRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.isUpToDate('0.2')).toBe(false) expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([ @@ -193,9 +206,7 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { expect(await updateAssistant.isUpToDate('0.2')).toBe(true) expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([]) - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() @@ -241,7 +252,12 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceConnectionRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceConnectionRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.isUpToDate('0.2')).toBe(false) expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([ @@ -257,9 +273,7 @@ describe('UpdateAssistant | v0.1 - v0.2', () => { expect(await updateAssistant.isUpToDate('0.2')).toBe(true) expect(await updateAssistant.getNeededUpdates('0.2')).toEqual([]) - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() diff --git a/packages/core/src/storage/migration/__tests__/0.2.test.ts b/packages/core/src/storage/migration/__tests__/0.2.test.ts index 95ed841a1b..2e5c0647a5 100644 --- a/packages/core/src/storage/migration/__tests__/0.2.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.2.test.ts @@ -56,7 +56,12 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceCredentialRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceCredentialRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.isUpToDate()).toBe(false) expect(await updateAssistant.getNeededUpdates('0.3.1')).toEqual([ @@ -76,10 +81,7 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { expect(await updateAssistant.isUpToDate()).toBe(true) expect(await updateAssistant.getNeededUpdates()).toEqual([]) - - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() @@ -123,13 +125,15 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceCredentialRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceCredentialRecordsString), + creationDate: new Date(), + }, + } await agent.initialize() - - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() @@ -170,14 +174,16 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceDidRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceDidRecordsString), + creationDate: new Date(), + }, + } await agent.initialize() - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() diff --git a/packages/core/src/storage/migration/__tests__/0.3.test.ts b/packages/core/src/storage/migration/__tests__/0.3.test.ts index 25f0a2a219..7cef8aafd7 100644 --- a/packages/core/src/storage/migration/__tests__/0.3.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.3.test.ts @@ -56,7 +56,12 @@ describe('UpdateAssistant | v0.3.1 - v0.4', () => { // Set storage after initialization. This mimics as if this wallet // is opened as an existing wallet instead of a new wallet - storageService.records = JSON.parse(aliceDidRecordsString) + storageService.contextCorrelationIdToRecords = { + default: { + records: JSON.parse(aliceDidRecordsString), + creationDate: new Date(), + }, + } expect(await updateAssistant.isUpToDate()).toBe(false) expect(await updateAssistant.getNeededUpdates('0.4')).toEqual([ @@ -72,9 +77,7 @@ describe('UpdateAssistant | v0.3.1 - v0.4', () => { expect(await updateAssistant.isUpToDate()).toBe(true) expect(await updateAssistant.getNeededUpdates()).toEqual([]) - // MEDIATOR_ROUTING_RECORD recipientKeys will be different every time, and is not what we're testing here - delete storageService.records.MEDIATOR_ROUTING_RECORD - expect(storageService.records).toMatchSnapshot() + expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() await agent.wallet.delete() diff --git a/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts b/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts index e437b36c6b..eac4d95755 100644 --- a/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts +++ b/packages/core/src/storage/migration/__tests__/UpdateAssistant.test.ts @@ -1,15 +1,13 @@ +import type { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' import type { BaseRecord } from '../../BaseRecord' -import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' -import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' -import { getAgentOptions } from '../../../../tests/helpers' +import { getInMemoryAgentOptions } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { InjectionSymbols } from '../../../constants' -import { DependencyManager } from '../../../plugins' import { UpdateAssistant } from '../UpdateAssistant' import { CURRENT_FRAMEWORK_STORAGE_VERSION } from '../updates' -const agentOptions = getAgentOptions('UpdateAssistant', {}) +const agentOptions = getInMemoryAgentOptions('UpdateAssistant', {}) describe('UpdateAssistant', () => { let updateAssistant: UpdateAssistant @@ -17,13 +15,7 @@ describe('UpdateAssistant', () => { let storageService: InMemoryStorageService beforeEach(async () => { - const dependencyManager = new DependencyManager() - storageService = new InMemoryStorageService() - // If we register the AskarModule it will register the storage service, but we use in memory storage here - dependencyManager.registerContextScoped(InjectionSymbols.Wallet, RegisteredAskarTestWallet) - dependencyManager.registerInstance(InjectionSymbols.StorageService, storageService) - - agent = new Agent(agentOptions, dependencyManager) + agent = new Agent(agentOptions) updateAssistant = new UpdateAssistant(agent, { v0_1ToV0_2: { @@ -31,6 +23,8 @@ describe('UpdateAssistant', () => { }, }) + storageService = agent.dependencyManager.resolve(InjectionSymbols.StorageService) + await updateAssistant.initialize() }) @@ -41,10 +35,13 @@ describe('UpdateAssistant', () => { describe('upgrade()', () => { it('should not upgrade records when upgrading after a new wallet is created', async () => { - const beforeStorage = JSON.stringify(storageService.records) + const beforeStorage = JSON.stringify(storageService.contextCorrelationIdToRecords) await updateAssistant.update() - expect(JSON.parse(beforeStorage)).toEqual(storageService.records) + // We parse and stringify so the dates are equal (both string) + expect(JSON.parse(beforeStorage)).toEqual( + JSON.parse(JSON.stringify(storageService.contextCorrelationIdToRecords)) + ) }) }) diff --git a/packages/core/src/storage/migration/__tests__/backup-askar.test.ts b/packages/core/src/storage/migration/__tests__/backup-askar.test.ts index 97f5450983..3db486adc1 100644 --- a/packages/core/src/storage/migration/__tests__/backup-askar.test.ts +++ b/packages/core/src/storage/migration/__tests__/backup-askar.test.ts @@ -4,8 +4,7 @@ import type { StorageUpdateError } from '../error/StorageUpdateError' import { readFileSync, unlinkSync } from 'fs' import path from 'path' -import { AskarModule } from '../../../../../askar/src' -import { askarModuleConfig } from '../../../../../askar/tests/helpers' +import { askarModule } from '../../../../../askar/tests/helpers' import { getAgentOptions, getAskarWalletConfig } from '../../../../tests/helpers' import { Agent } from '../../../agent/Agent' import { InjectionSymbols } from '../../../constants' @@ -21,7 +20,7 @@ const agentOptions = getAgentOptions( walletConfig: getAskarWalletConfig('UpdateAssistant | Backup | Aries Askar', { inMemory: false }), }, { - askar: new AskarModule(askarModuleConfig), + askar: askarModule, } ) diff --git a/packages/core/tests/agents.test.ts b/packages/core/tests/agents.test.ts index 9f8dd40b97..6a8a7b23b4 100644 --- a/packages/core/tests/agents.test.ts +++ b/packages/core/tests/agents.test.ts @@ -1,27 +1,18 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { ConnectionRecord } from '../src/modules/connections' -import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { HandshakeProtocol } from '../src/modules/connections' -import { waitForBasicMessage, getAgentOptions } from './helpers' +import { waitForBasicMessage, getInMemoryAgentOptions } from './helpers' import { setupSubjectTransports } from './transport' -const aliceAgentOptions = getAgentOptions( - 'Agents Alice', - { - endpoints: ['rxjs:alice'], - }, - { askar: askarModule } -) -const bobAgentOptions = getAgentOptions( - 'Agents Bob', - { - endpoints: ['rxjs:bob'], - }, - { askar: askarModule } -) +const aliceAgentOptions = getInMemoryAgentOptions('Agents Alice', { + endpoints: ['rxjs:alice'], +}) +const bobAgentOptions = getInMemoryAgentOptions('Agents Bob', { + endpoints: ['rxjs:bob'], +}) describe('agents', () => { let aliceAgent: Agent diff --git a/packages/core/tests/connections.test.ts b/packages/core/tests/connections.test.ts index 09760187a8..d158acc272 100644 --- a/packages/core/tests/connections.test.ts +++ b/packages/core/tests/connections.test.ts @@ -3,7 +3,6 @@ import type { AgentMessageProcessedEvent, KeylistUpdate } from '../src' import { filter, firstValueFrom, map, timeout } from 'rxjs' -import { askarModule } from '../../askar/tests/helpers' import { MediatorModule, Key, @@ -17,7 +16,7 @@ import { Agent } from '../src/agent/Agent' import { didKeyToVerkey } from '../src/modules/dids/helpers' import { OutOfBandState } from '../src/modules/oob/domain/OutOfBandState' -import { getAgentOptions, waitForTrustPingResponseReceivedEvent } from './helpers' +import { getInMemoryAgentOptions, waitForTrustPingResponseReceivedEvent } from './helpers' import { setupSubjectTransports } from './transport' describe('connections', () => { @@ -27,34 +26,21 @@ describe('connections', () => { let mediatorAgent: Agent beforeEach(async () => { - const faberAgentOptions = getAgentOptions( - 'Faber Agent Connections', - { - endpoints: ['rxjs:faber'], - }, - { askar: askarModule } - ) - const aliceAgentOptions = getAgentOptions( - 'Alice Agent Connections', - { - endpoints: ['rxjs:alice'], - }, - { askar: askarModule } - ) - const acmeAgentOptions = getAgentOptions( - 'Acme Agent Connections', - { - endpoints: ['rxjs:acme'], - }, - { askar: askarModule } - ) - const mediatorAgentOptions = getAgentOptions( + const faberAgentOptions = getInMemoryAgentOptions('Faber Agent Connections', { + endpoints: ['rxjs:faber'], + }) + const aliceAgentOptions = getInMemoryAgentOptions('Alice Agent Connections', { + endpoints: ['rxjs:alice'], + }) + const acmeAgentOptions = getInMemoryAgentOptions('Acme Agent Connections', { + endpoints: ['rxjs:acme'], + }) + const mediatorAgentOptions = getInMemoryAgentOptions( 'Mediator Agent Connections', { endpoints: ['rxjs:mediator'], }, { - askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true, }), diff --git a/packages/core/tests/generic-records.test.ts b/packages/core/tests/generic-records.test.ts index 6da9f6f8ce..bdf605d517 100644 --- a/packages/core/tests/generic-records.test.ts +++ b/packages/core/tests/generic-records.test.ts @@ -1,18 +1,13 @@ import type { GenericRecord } from '../src/modules/generic-records/repository/GenericRecord' -import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { RecordNotFoundError } from '../src/error' -import { getAgentOptions } from './helpers' +import { getInMemoryAgentOptions } from './helpers' -const aliceAgentOptions = getAgentOptions( - 'Generic Records Alice', - { - endpoints: ['rxjs:alice'], - }, - { askar: askarModule } -) +const aliceAgentOptions = getInMemoryAgentOptions('Generic Records Alice', { + endpoints: ['rxjs:alice'], +}) describe('genericRecords', () => { let aliceAgent: Agent diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts index 4989d499d6..6372d3caaa 100644 --- a/packages/core/tests/helpers.ts +++ b/packages/core/tests/helpers.ts @@ -29,6 +29,7 @@ import path from 'path' import { lastValueFrom, firstValueFrom, ReplaySubject } from 'rxjs' import { catchError, filter, map, take, timeout } from 'rxjs/operators' +import { InMemoryWalletModule } from '../../../tests/InMemoryWalletModule' import { agentDependencies } from '../../node/src' import { AgentEventTypes, @@ -124,6 +125,39 @@ export function getAgentOptions( + name: string, + extraConfig: Partial = {}, + inputModules?: AgentModules +): { config: InitConfig; modules: AgentModules; dependencies: AgentDependencies } { + const random = uuid().slice(0, 4) + const config: InitConfig = { + label: `Agent: ${name} - ${random}`, + walletConfig: { + id: `Wallet: ${name} - ${random}`, + key: `Wallet: ${name}`, + }, + // TODO: determine the log level based on an environment variable. This will make it + // possible to run e.g. failed github actions in debug mode for extra logs + logger: TestLogger.fromLogger(testLogger, name), + ...extraConfig, + } + + const m = (inputModules ?? {}) as AgentModulesInput + const modules = { + ...m, + inMemory: new InMemoryWalletModule(), + // Make sure connections module is always defined so we can set autoAcceptConnections + connections: + m.connections ?? + new ConnectionsModule({ + autoAcceptConnections: true, + }), + } + + return { config, modules: modules as unknown as AgentModules, dependencies: agentDependencies } as const +} + export async function importExistingIndyDidFromPrivateKey(agent: Agent, privateKey: Buffer) { const key = await agent.wallet.createKey({ keyType: KeyType.Ed25519, diff --git a/packages/core/tests/jsonld.ts b/packages/core/tests/jsonld.ts index 6e06541cec..9dd4760296 100644 --- a/packages/core/tests/jsonld.ts +++ b/packages/core/tests/jsonld.ts @@ -1,6 +1,7 @@ import type { EventReplaySubject } from './events' import type { AutoAcceptCredential, AutoAcceptProof, ConnectionRecord } from '../src' +import { InMemoryWalletModule } from '../../../tests/InMemoryWalletModule' import { askarModule } from '../../askar/tests/helpers' import { BbsModule } from '../../bbs-signatures/src/BbsModule' import { @@ -28,7 +29,8 @@ export type JsonLdTestsAgent = Agent> export const getJsonLdModules = ({ autoAcceptCredentials, autoAcceptProofs, -}: { autoAcceptCredentials?: AutoAcceptCredential; autoAcceptProofs?: AutoAcceptProof } = {}) => + useBbs = false, +}: { autoAcceptCredentials?: AutoAcceptCredential; autoAcceptProofs?: AutoAcceptProof; useBbs?: boolean } = {}) => ({ credentials: new CredentialsModule({ credentialProtocols: [new V2CredentialProtocol({ credentialFormats: [new JsonLdCredentialFormatService()] })], @@ -44,8 +46,15 @@ export const getJsonLdModules = ({ cache: new CacheModule({ cache: new InMemoryLruCache({ limit: 100 }), }), - askar: askarModule, - bbs: new BbsModule(), + // We don't support signing provider in in memory wallet yet, so if BBS is used we need to use Askar + ...(useBbs + ? { + askar: askarModule, + bbs: new BbsModule(), + } + : { + inMemory: new InMemoryWalletModule(), + }), } as const) interface SetupJsonLdTestsReturn { @@ -85,6 +94,7 @@ export async function setupJsonLdTests< autoAcceptCredentials, autoAcceptProofs, createConnections, + useBbs = false, }: { issuerName: string holderName: string @@ -92,10 +102,12 @@ export async function setupJsonLdTests< autoAcceptCredentials?: AutoAcceptCredential autoAcceptProofs?: AutoAcceptProof createConnections?: CreateConnections + useBbs?: boolean }): Promise> { const modules = getJsonLdModules({ autoAcceptCredentials, autoAcceptProofs, + useBbs, }) const issuerAgent = new Agent( diff --git a/packages/core/tests/multi-protocol-version.test.ts b/packages/core/tests/multi-protocol-version.test.ts index b14db97215..1f9fa3c915 100644 --- a/packages/core/tests/multi-protocol-version.test.ts +++ b/packages/core/tests/multi-protocol-version.test.ts @@ -2,29 +2,20 @@ import type { AgentMessageProcessedEvent } from '../src/agent/Events' import { filter, firstValueFrom, timeout } from 'rxjs' -import { askarModule } from '../../askar/tests/helpers' import { parseMessageType, MessageSender, AgentMessage, IsValidMessageType } from '../src' import { Agent } from '../src/agent/Agent' import { AgentEventTypes } from '../src/agent/Events' import { OutboundMessageContext } from '../src/agent/models' -import { getAgentOptions } from './helpers' +import { getInMemoryAgentOptions } from './helpers' import { setupSubjectTransports } from './transport' -const aliceAgentOptions = getAgentOptions( - 'Multi Protocol Versions - Alice', - { - endpoints: ['rxjs:alice'], - }, - { askar: askarModule } -) -const bobAgentOptions = getAgentOptions( - 'Multi Protocol Versions - Bob', - { - endpoints: ['rxjs:bob'], - }, - { askar: askarModule } -) +const aliceAgentOptions = getInMemoryAgentOptions('Multi Protocol Versions - Alice', { + endpoints: ['rxjs:alice'], +}) +const bobAgentOptions = getInMemoryAgentOptions('Multi Protocol Versions - Bob', { + endpoints: ['rxjs:bob'], +}) describe('multi version protocols', () => { let aliceAgent: Agent diff --git a/packages/core/tests/oob-mediation-provision.test.ts b/packages/core/tests/oob-mediation-provision.test.ts index 610f27fdfd..3bf27ba9eb 100644 --- a/packages/core/tests/oob-mediation-provision.test.ts +++ b/packages/core/tests/oob-mediation-provision.test.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { OutOfBandInvitation } from '../src/modules/oob/messages' -import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { DidExchangeState, HandshakeProtocol } from '../src/modules/connections' import { @@ -11,36 +10,29 @@ import { MediationRecipientModule, } from '../src/modules/routing' -import { getAgentOptions, waitForBasicMessage } from './helpers' +import { getInMemoryAgentOptions, waitForBasicMessage } from './helpers' import { setupSubjectTransports } from './transport' -const faberAgentOptions = getAgentOptions( - 'OOB mediation provision - Faber Agent', - { - endpoints: ['rxjs:faber'], - }, - { askar: askarModule } -) -const aliceAgentOptions = getAgentOptions( +const faberAgentOptions = getInMemoryAgentOptions('OOB mediation provision - Faber Agent', { + endpoints: ['rxjs:faber'], +}) +const aliceAgentOptions = getInMemoryAgentOptions( 'OOB mediation provision - Alice Recipient Agent', { endpoints: ['rxjs:alice'], }, { - askar: askarModule, mediationRecipient: new MediationRecipientModule({ - // FIXME: discover features returns that we support this protocol, but we don't support all roles - // we should return that we only support the mediator role so we don't have to explicitly declare this mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, }), } ) -const mediatorAgentOptions = getAgentOptions( +const mediatorAgentOptions = getInMemoryAgentOptions( 'OOB mediation provision - Mediator Agent', { endpoints: ['rxjs:mediator'], }, - { askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } + { mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } ) describe('out of band with mediation set up with provision method', () => { diff --git a/packages/core/tests/oob-mediation.test.ts b/packages/core/tests/oob-mediation.test.ts index ea39333bc2..3372ccc8cf 100644 --- a/packages/core/tests/oob-mediation.test.ts +++ b/packages/core/tests/oob-mediation.test.ts @@ -7,7 +7,6 @@ import { filter, firstValueFrom, map, Subject, timeout } from 'rxjs' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { askarModule } from '../../askar/tests/helpers' import { Agent } from '../src/agent/Agent' import { AgentEventTypes } from '../src/agent/Events' import { DidExchangeState, HandshakeProtocol } from '../src/modules/connections' @@ -22,35 +21,28 @@ import { MediatorModule, } from '../src/modules/routing' -import { getAgentOptions, waitForBasicMessage } from './helpers' +import { getInMemoryAgentOptions, waitForBasicMessage } from './helpers' -const faberAgentOptions = getAgentOptions( - 'OOB mediation - Faber Agent', - { - endpoints: ['rxjs:faber'], - }, - { askar: askarModule } -) -const aliceAgentOptions = getAgentOptions( +const faberAgentOptions = getInMemoryAgentOptions('OOB mediation - Faber Agent', { + endpoints: ['rxjs:faber'], +}) +const aliceAgentOptions = getInMemoryAgentOptions( 'OOB mediation - Alice Recipient Agent', { endpoints: ['rxjs:alice'], }, { - askar: askarModule, mediationRecipient: new MediationRecipientModule({ - // FIXME: discover features returns that we support this protocol, but we don't support all roles - // we should return that we only support the mediator role so we don't have to explicitly declare this mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, }), } ) -const mediatorAgentOptions = getAgentOptions( +const mediatorAgentOptions = getInMemoryAgentOptions( 'OOB mediation - Mediator Agent', { endpoints: ['rxjs:mediator'], }, - { askar: askarModule, mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } + { mediator: new MediatorModule({ autoAcceptMediationRequests: true }) } ) describe('out of band with mediation', () => { diff --git a/packages/core/tests/oob.test.ts b/packages/core/tests/oob.test.ts index b8faf9ccac..3721635e23 100644 --- a/packages/core/tests/oob.test.ts +++ b/packages/core/tests/oob.test.ts @@ -8,7 +8,7 @@ import { Subject } from 'rxjs' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { getAskarAnonCredsIndyModules, prepareForAnonCredsIssuance } from '../../anoncreds/tests/legacyAnonCredsSetup' +import { getAnonCredsIndyModules, prepareForAnonCredsIssuance } from '../../anoncreds/tests/legacyAnonCredsSetup' import { Agent } from '../src/agent/Agent' import { Key } from '../src/crypto' import { DidExchangeState, HandshakeProtocol } from '../src/modules/connections' @@ -20,25 +20,26 @@ import { OutOfBandInvitation } from '../src/modules/oob/messages' import { JsonEncoder, JsonTransformer } from '../src/utils' import { TestMessage } from './TestMessage' -import { getAgentOptions, waitForCredentialRecord } from './helpers' +import { getInMemoryAgentOptions, waitForCredentialRecord } from './helpers' import { AgentEventTypes, AriesFrameworkError, AutoAcceptCredential, CredentialState } from '@credo-ts/core' -const faberAgentOptions = getAgentOptions( +// FIXME: oob.test doesn't need heavy AnonCreds / indy dependencies +const faberAgentOptions = getInMemoryAgentOptions( 'Faber Agent OOB', { endpoints: ['rxjs:faber'], }, - getAskarAnonCredsIndyModules({ + getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }) ) -const aliceAgentOptions = getAgentOptions( +const aliceAgentOptions = getInMemoryAgentOptions( 'Alice Agent OOB', { endpoints: ['rxjs:alice'], }, - getAskarAnonCredsIndyModules({ + getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }) ) @@ -63,8 +64,8 @@ describe('out of band', () => { autoAcceptConnection: false, } - let faberAgent: Agent> - let aliceAgent: Agent> + let faberAgent: Agent> + let aliceAgent: Agent> let credentialTemplate: CreateCredentialOfferOptions<[V1CredentialProtocol]> beforeAll(async () => { diff --git a/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts b/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts index 567afcfa31..866f8e7880 100644 --- a/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts +++ b/packages/indy-vdr/src/dids/__tests__/IndyVdrIndyDidRegistrar.test.ts @@ -14,14 +14,13 @@ import { Key, KeyType, RepositoryEventTypes, - SigningProviderRegistry, TypedArrayEncoder, VerificationMethod, } from '@credo-ts/core' import { Subject } from 'rxjs' import { InMemoryStorageService } from '../../../../../tests/InMemoryStorageService' -import { RegisteredAskarTestWallet } from '../../../../askar/tests/helpers' +import { InMemoryWallet } from '../../../../../tests/InMemoryWallet' import { agentDependencies, getAgentConfig, getAgentContext, mockProperty } from '../../../../core/tests' import { IndyVdrPool, IndyVdrPoolService } from '../../pool' import { IndyVdrIndyDidRegistrar } from '../IndyVdrIndyDidRegistrar' @@ -32,12 +31,7 @@ const poolMock = new IndyVdrPoolMock() mockProperty(poolMock, 'indyNamespace', 'ns1') const agentConfig = getAgentConfig('IndyVdrIndyDidRegistrar') - -const wallet = new RegisteredAskarTestWallet( - agentConfig.logger, - new agentDependencies.FileSystem(), - new SigningProviderRegistry([]) -) +const wallet = new InMemoryWallet() jest .spyOn(wallet, 'createKey') diff --git a/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts index 6c66771c35..211066e7f6 100644 --- a/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-anoncreds-registry.e2e.test.ts @@ -8,8 +8,7 @@ import { import { Agent, DidsModule, TypedArrayEncoder } from '@credo-ts/core' import { indyVdr } from '@hyperledger/indy-vdr-nodejs' -import { askarModule } from '../../askar/tests/helpers' -import { agentDependencies, getAgentConfig, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' +import { getInMemoryAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' import { IndyVdrIndyDidResolver, IndyVdrModule, IndyVdrSovDidResolver } from '../src' import { IndyVdrAnonCredsRegistry } from '../src/anoncreds/IndyVdrAnonCredsRegistry' import { IndyVdrIndyDidRegistrar } from '../src/dids/IndyVdrIndyDidRegistrar' @@ -18,45 +17,45 @@ import { IndyVdrPoolService } from '../src/pool' import { credentialDefinitionValue, revocationRegistryDefinitionValue } from './__fixtures__/anoncreds' import { indyVdrModuleConfig } from './helpers' -const endorserConfig = getAgentConfig('IndyVdrAnonCredsRegistryEndorser') -const agentConfig = getAgentConfig('IndyVdrAnonCredsRegistryAgent') - const indyVdrAnonCredsRegistry = new IndyVdrAnonCredsRegistry() -const endorser = new Agent({ - config: endorserConfig, - dependencies: agentDependencies, - modules: { - indyVdr: new IndyVdrModule({ - indyVdr, - networks: indyVdrModuleConfig.networks, - }), - askar: askarModule, - dids: new DidsModule({ - registrars: [new IndyVdrIndyDidRegistrar()], - resolvers: [new IndyVdrSovDidResolver(), new IndyVdrIndyDidResolver()], - }), - }, -}) - -const agent = new Agent({ - config: agentConfig, - dependencies: agentDependencies, - modules: { - indyVdr: new IndyVdrModule({ - indyVdr, - networks: indyVdrModuleConfig.networks, - }), - asakar: askarModule, - dids: new DidsModule({ - registrars: [new IndyVdrIndyDidRegistrar()], - resolvers: [new IndyVdrSovDidResolver(), new IndyVdrIndyDidResolver()], - }), - }, -}) +const endorser = new Agent( + getInMemoryAgentOptions( + 'IndyVdrAnonCredsRegistryEndorser', + {}, + { + indyVdr: new IndyVdrModule({ + indyVdr, + networks: indyVdrModuleConfig.networks, + }), + dids: new DidsModule({ + registrars: [new IndyVdrIndyDidRegistrar()], + resolvers: [new IndyVdrSovDidResolver(), new IndyVdrIndyDidResolver()], + }), + } + ) +) + +const agent = new Agent( + getInMemoryAgentOptions( + 'IndyVdrAnonCredsRegistryAgent', + {}, + { + indyVdr: new IndyVdrModule({ + indyVdr, + networks: indyVdrModuleConfig.networks, + }), + dids: new DidsModule({ + registrars: [new IndyVdrIndyDidRegistrar()], + resolvers: [new IndyVdrSovDidResolver(), new IndyVdrIndyDidResolver()], + }), + } + ) +) const indyVdrPoolService = endorser.dependencyManager.resolve(IndyVdrPoolService) +// FIXME: this test is very slow, probably due to the sleeps. Can we speed it up? describe('IndyVdrAnonCredsRegistry', () => { let endorserDid: string beforeAll(async () => { diff --git a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts index 85182d3add..d59607fdc8 100644 --- a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts @@ -15,8 +15,11 @@ import { import { indyVdr } from '@hyperledger/indy-vdr-nodejs' import { convertPublicKeyToX25519, generateKeyPairFromSeed } from '@stablelib/ed25519' -import { askarModule } from '../../askar/tests/helpers' -import { getAgentOptions, importExistingIndyDidFromPrivateKey, retryUntilResult } from '../../core/tests/helpers' +import { + getInMemoryAgentOptions, + importExistingIndyDidFromPrivateKey, + retryUntilResult, +} from '../../core/tests/helpers' import { IndyVdrModule, IndyVdrSovDidResolver } from '../src' import { IndyVdrIndyDidRegistrar } from '../src/dids/IndyVdrIndyDidRegistrar' import { IndyVdrIndyDidResolver } from '../src/dids/IndyVdrIndyDidResolver' @@ -25,7 +28,7 @@ import { indyDidFromNamespaceAndInitialKey } from '../src/dids/didIndyUtil' import { indyVdrModuleConfig } from './helpers' const endorser = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'Indy VDR Indy DID Registrar', {}, { @@ -33,7 +36,6 @@ const endorser = new Agent( networks: indyVdrModuleConfig.networks, indyVdr, }), - askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], @@ -42,7 +44,7 @@ const endorser = new Agent( ) ) const agent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'Indy VDR Indy DID Registrar', {}, { @@ -50,7 +52,6 @@ const agent = new Agent( indyVdr, networks: indyVdrModuleConfig.networks, }), - askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], diff --git a/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts index 4229cd7a27..1d7a8f9373 100644 --- a/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-indy-did-resolver.e2e.test.ts @@ -1,15 +1,14 @@ import { DidsModule, Agent, TypedArrayEncoder, JsonTransformer } from '@credo-ts/core' import { indyVdr } from '@hyperledger/indy-vdr-nodejs' -import { askarModule } from '../../askar/tests/helpers' -import { getAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' +import { getInMemoryAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' import { IndyVdrModule } from '../src' import { IndyVdrIndyDidRegistrar, IndyVdrIndyDidResolver, IndyVdrSovDidResolver } from '../src/dids' import { createDidOnLedger, indyVdrModuleConfig } from './helpers' const agent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'Indy VDR Indy DID resolver', {}, { @@ -17,7 +16,6 @@ const agent = new Agent( indyVdr, networks: indyVdrModuleConfig.networks, }), - askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], 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 869bd2d413..ba23c7b384 100644 --- a/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-pool.e2e.test.ts @@ -1,12 +1,11 @@ import type { Key } from '@credo-ts/core' -import { TypedArrayEncoder, KeyType, SigningProviderRegistry } from '@credo-ts/core' +import { TypedArrayEncoder, KeyType } from '@credo-ts/core' import { GetNymRequest, NymRequest, SchemaRequest, CredentialDefinitionRequest } from '@hyperledger/indy-vdr-shared' -import { RegisteredAskarTestWallet } from '../../askar/tests/helpers' +import { InMemoryWallet } from '../../../tests/InMemoryWallet' import { genesisTransactions, getAgentConfig, getAgentContext } from '../../core/tests/helpers' import testLogger from '../../core/tests/logger' -import { NodeFileSystem } from '../../node/src/NodeFileSystem' import { IndyVdrPool } from '../src/pool' import { IndyVdrPoolService } from '../src/pool/IndyVdrPoolService' import { indyDidFromPublicKeyBase58 } from '../src/utils/did' @@ -14,7 +13,7 @@ import { indyDidFromPublicKeyBase58 } from '../src/utils/did' import { indyVdrModuleConfig } from './helpers' const indyVdrPoolService = new IndyVdrPoolService(testLogger, indyVdrModuleConfig) -const wallet = new RegisteredAskarTestWallet(testLogger, new NodeFileSystem(), new SigningProviderRegistry([])) +const wallet = new InMemoryWallet() const agentConfig = getAgentConfig('IndyVdrPoolService') const agentContext = getAgentContext({ wallet, agentConfig }) diff --git a/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts index e554eb0bfc..2088c50d51 100644 --- a/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-sov-did-resolver.e2e.test.ts @@ -2,15 +2,14 @@ import { parseIndyDid } from '@credo-ts/anoncreds' import { DidsModule, Agent, TypedArrayEncoder, JsonTransformer } from '@credo-ts/core' import { indyVdr } from '@hyperledger/indy-vdr-nodejs' -import { askarModule } from '../../askar/tests/helpers' -import { getAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' +import { getInMemoryAgentOptions, importExistingIndyDidFromPrivateKey } from '../../core/tests/helpers' import { IndyVdrModule } from '../src' import { IndyVdrIndyDidRegistrar, IndyVdrIndyDidResolver, IndyVdrSovDidResolver } from '../src/dids' import { createDidOnLedger, indyVdrModuleConfig } from './helpers' const agent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'Indy VDR Sov DID resolver', {}, { @@ -18,7 +17,6 @@ const agent = new Agent( indyVdr, networks: indyVdrModuleConfig.networks, }), - askar: askarModule, dids: new DidsModule({ registrars: [new IndyVdrIndyDidRegistrar()], resolvers: [new IndyVdrIndyDidResolver(), new IndyVdrSovDidResolver()], diff --git a/packages/openid4vc-client/tests/openid4vc-client.e2e.test.ts b/packages/openid4vc-client/tests/openid4vc-client.e2e.test.ts index c4089e2a37..b0a19263af 100644 --- a/packages/openid4vc-client/tests/openid4vc-client.e2e.test.ts +++ b/packages/openid4vc-client/tests/openid4vc-client.e2e.test.ts @@ -12,10 +12,9 @@ import { } from '@credo-ts/core' import nock, { cleanAll, enableNetConnect } from 'nock' -import { AskarModule } from '../../askar/src' -import { askarModuleConfig } from '../../askar/tests/helpers' +import { InMemoryWalletModule } from '../../../tests/InMemoryWalletModule' import { customDocumentLoader } from '../../core/src/modules/vc/data-integrity/__tests__/documentLoader' -import { getAgentOptions } from '../../core/tests' +import { getInMemoryAgentOptions } from '../../core/tests' import { mattrLaunchpadJsonLd, waltIdJffJwt } from './fixtures' @@ -26,23 +25,21 @@ const modules = { w3cCredentials: new W3cCredentialsModule({ documentLoader: customDocumentLoader, }), - askar: new AskarModule(askarModuleConfig), + inMemory: new InMemoryWalletModule(), } describe('OpenId4VcClient', () => { let agent: Agent beforeEach(async () => { - const agentOptions = getAgentOptions('OpenId4VcClient Agent', {}, modules) - + const agentOptions = getInMemoryAgentOptions('OpenId4VcClient Agent', {}, modules) agent = new Agent(agentOptions) - await agent.initialize() }) afterEach(async () => { - await agent.shutdown() await agent.wallet.delete() + await agent.shutdown() }) describe('Pre-authorized flow', () => { diff --git a/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts b/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts index cba2704247..1a45b7c173 100644 --- a/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts +++ b/packages/question-answer/src/__tests__/QuestionAnswerService.test.ts @@ -1,13 +1,12 @@ import type { AgentConfig, AgentContext, Repository, Wallet } from '@credo-ts/core' import type { QuestionAnswerStateChangedEvent, ValidResponse } from '@credo-ts/question-answer' -import { EventEmitter, SigningProviderRegistry, InboundMessageContext, DidExchangeState } from '@credo-ts/core' +import { EventEmitter, InboundMessageContext, DidExchangeState } from '@credo-ts/core' import { agentDependencies } from '@credo-ts/node' import { Subject } from 'rxjs' -import { RegisteredAskarTestWallet } from '../../../askar/tests/helpers' +import { InMemoryWallet } from '../../../../tests/InMemoryWallet' import { getAgentConfig, getAgentContext, getMockConnection, mockFunction } from '../../../core/tests/helpers' -import { NodeFileSystem } from '../../../node/src/NodeFileSystem' import { QuestionAnswerRecord, @@ -61,7 +60,7 @@ describe('QuestionAnswerService', () => { beforeAll(async () => { agentConfig = getAgentConfig('QuestionAnswerServiceTest') - wallet = new RegisteredAskarTestWallet(agentConfig.logger, new NodeFileSystem(), new SigningProviderRegistry([])) + wallet = new InMemoryWallet() agentContext = getAgentContext() // eslint-disable-next-line @typescript-eslint/no-non-null-assertion await wallet.createAndOpen(agentConfig.walletConfig!) diff --git a/packages/question-answer/tests/question-answer.e2e.test.ts b/packages/question-answer/tests/question-answer.e2e.test.ts index 9d386afc6d..dafbc55cdd 100644 --- a/packages/question-answer/tests/question-answer.e2e.test.ts +++ b/packages/question-answer/tests/question-answer.e2e.test.ts @@ -2,8 +2,7 @@ import type { ConnectionRecord } from '@credo-ts/core' import { Agent } from '@credo-ts/core' -import { askarModule } from '../../askar/tests/helpers' -import { setupSubjectTransports, testLogger, getAgentOptions, makeConnection } from '../../core/tests' +import { setupSubjectTransports, testLogger, makeConnection, getInMemoryAgentOptions } from '../../core/tests' import { waitForQuestionAnswerRecord } from './helpers' @@ -11,10 +10,9 @@ import { QuestionAnswerModule, QuestionAnswerRole, QuestionAnswerState } from '@ const modules = { questionAnswer: new QuestionAnswerModule(), - askar: askarModule, } -const bobAgentOptions = getAgentOptions( +const bobAgentOptions = getInMemoryAgentOptions( 'Bob Question Answer', { endpoints: ['rxjs:bob'], @@ -22,7 +20,7 @@ const bobAgentOptions = getAgentOptions( modules ) -const aliceAgentOptions = getAgentOptions( +const aliceAgentOptions = getInMemoryAgentOptions( 'Alice Question Answer', { endpoints: ['rxjs:alice'], diff --git a/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts b/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts index bc0b9b5c97..f21a5510c6 100644 --- a/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts +++ b/packages/sd-jwt-vc/src/__tests__/SdJwtVcService.test.ts @@ -11,8 +11,7 @@ import { TypedArrayEncoder, } from '@credo-ts/core' -import { askarModule } from '../../../askar/tests/helpers' -import { getAgentOptions } from '../../../core/tests' +import { getInMemoryAgentOptions } from '../../../core/tests' import { SdJwtVcService } from '../SdJwtVcService' import { SdJwtVcRepository } from '../repository' @@ -26,11 +25,10 @@ import { } from './sdjwtvc.fixtures' const agent = new Agent( - getAgentOptions( + getInMemoryAgentOptions( 'sdjwtvcserviceagent', {}, { - askar: askarModule, dids: new DidsModule({ resolvers: [new KeyDidResolver()], registrars: [new KeyDidRegistrar()], diff --git a/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts b/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts index a2bb7ac9bd..89aae8ad85 100644 --- a/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts +++ b/packages/sd-jwt-vc/tests/sdJwtVc.e2e.test.ts @@ -2,18 +2,16 @@ import type { Key } from '@credo-ts/core' import { Agent, DidKey, DidsModule, KeyDidRegistrar, KeyDidResolver, KeyType, TypedArrayEncoder } from '@credo-ts/core' -import { askarModule } from '../../askar/tests/helpers' -import { getAgentOptions } from '../../core/tests' +import { getInMemoryAgentOptions } from '../../core/tests' import { SdJwtVcModule } from '../src' const getAgent = (label: string) => new Agent( - getAgentOptions( + getInMemoryAgentOptions( label, {}, { sdJwt: new SdJwtVcModule(), - askar: askarModule, dids: new DidsModule({ resolvers: [new KeyDidResolver()], registrars: [new KeyDidRegistrar()], diff --git a/packages/tenants/src/__tests__/TenantAgent.test.ts b/packages/tenants/src/__tests__/TenantAgent.test.ts index d04a3a864a..6989bfc47c 100644 --- a/packages/tenants/src/__tests__/TenantAgent.test.ts +++ b/packages/tenants/src/__tests__/TenantAgent.test.ts @@ -1,24 +1,11 @@ import { Agent, AgentContext } from '@credo-ts/core' -import { askarModule } from '../../../askar/tests/helpers' -import { agentDependencies, getAgentConfig, getAgentContext } from '../../../core/tests/helpers' +import { getAgentConfig, getAgentContext, getInMemoryAgentOptions } from '../../../core/tests/helpers' import { TenantAgent } from '../TenantAgent' describe('TenantAgent', () => { test('possible to construct a TenantAgent instance', () => { - const agent = new Agent({ - config: { - label: 'test', - walletConfig: { - id: 'Wallet: TenantAgentRoot', - key: 'Wallet: TenantAgentRoot', - }, - }, - dependencies: agentDependencies, - modules: { - askar: askarModule, - }, - }) + const agent = new Agent(getInMemoryAgentOptions('TenantAgentRoot')) const tenantDependencyManager = agent.dependencyManager.createChild() diff --git a/packages/tenants/src/__tests__/TenantsApi.test.ts b/packages/tenants/src/__tests__/TenantsApi.test.ts index 241933655e..baf4f2fc69 100644 --- a/packages/tenants/src/__tests__/TenantsApi.test.ts +++ b/packages/tenants/src/__tests__/TenantsApi.test.ts @@ -1,7 +1,6 @@ import { Agent, AgentContext, InjectionSymbols } from '@credo-ts/core' -import { askarModule } from '../../../askar/tests/helpers' -import { getAgentContext, getAgentOptions, mockFunction } from '../../../core/tests' +import { getAgentContext, getInMemoryAgentOptions, mockFunction } from '../../../core/tests' import { TenantAgent } from '../TenantAgent' import { TenantsApi } from '../TenantsApi' import { TenantAgentContextProvider } from '../context/TenantAgentContextProvider' @@ -16,7 +15,7 @@ const AgentContextProviderMock = TenantAgentContextProvider as jest.Mock { expect(tenantAgent.wallet.walletConfig).toEqual({ id: 'Wallet: TenantsApi: tenant-id', key: 'Wallet: TenantsApi: tenant-id', - storage: { - type: 'sqlite', - }, }) expect(agentContextProvider.getAgentContextForContextCorrelationId).toBeCalledWith('tenant-id') @@ -88,9 +84,6 @@ describe('TenantsApi', () => { expect(tenantAgent.wallet.walletConfig).toEqual({ id: 'Wallet: TenantsApi: tenant-id', key: 'Wallet: TenantsApi: tenant-id', - storage: { - type: 'sqlite', - }, }) expect(agentContextProvider.getAgentContextForContextCorrelationId).toBeCalledWith('tenant-id') @@ -130,9 +123,6 @@ describe('TenantsApi', () => { expect(tenantAgent.wallet.walletConfig).toEqual({ id: 'Wallet: TenantsApi: tenant-id', key: 'Wallet: TenantsApi: tenant-id', - storage: { - type: 'sqlite', - }, }) expect(agentContextProvider.getAgentContextForContextCorrelationId).toBeCalledWith('tenant-id') diff --git a/packages/tenants/tests/tenant-sessions.e2e.test.ts b/packages/tenants/tests/tenant-sessions.e2e.test.ts index 737af0089b..a434141bea 100644 --- a/packages/tenants/tests/tenant-sessions.e2e.test.ts +++ b/packages/tenants/tests/tenant-sessions.e2e.test.ts @@ -3,15 +3,18 @@ import type { InitConfig } from '@credo-ts/core' import { ConnectionsModule, Agent } from '@credo-ts/core' import { agentDependencies } from '@credo-ts/node' -import { AskarModule, AskarMultiWalletDatabaseScheme } from '../../askar/src' -import { ariesAskar } from '../../askar/tests/helpers' -import { getAskarWalletConfig, testLogger } from '../../core/tests' +import { InMemoryWalletModule } from '../../../tests/InMemoryWalletModule' +import { uuid } from '../../core/src/utils/uuid' +import { testLogger } from '../../core/tests' import { TenantsModule } from '@credo-ts/tenants' const agentConfig: InitConfig = { label: 'Tenant Agent 1', - walletConfig: getAskarWalletConfig('tenant sessions e2e agent 1', { inMemory: false, maxConnections: 100 }), + walletConfig: { + id: `tenant sessions e2e agent 1 - ${uuid().slice(0, 4)}`, + key: `tenant sessions e2e agent 1`, + }, logger: testLogger, endpoints: ['rxjs:tenant-agent1'], } @@ -22,10 +25,7 @@ const agent = new Agent({ dependencies: agentDependencies, modules: { tenants: new TenantsModule({ sessionAcquireTimeout: 10000 }), - askar: new AskarModule({ - ariesAskar, - multiWalletDatabaseScheme: AskarMultiWalletDatabaseScheme.ProfilePerWallet, - }), + inMemory: new InMemoryWalletModule(), connections: new ConnectionsModule({ autoAcceptConnections: true, }), diff --git a/packages/tenants/tests/tenants.e2e.test.ts b/packages/tenants/tests/tenants.e2e.test.ts index 8791676a4c..c55c5bb95c 100644 --- a/packages/tenants/tests/tenants.e2e.test.ts +++ b/packages/tenants/tests/tenants.e2e.test.ts @@ -3,23 +3,30 @@ import type { InitConfig } from '@credo-ts/core' import { ConnectionsModule, OutOfBandRecord, Agent, CacheModule, InMemoryLruCache } from '@credo-ts/core' import { agentDependencies } from '@credo-ts/node' +import { InMemoryWalletModule } from '../../../tests/InMemoryWalletModule' import { SubjectInboundTransport } from '../../../tests/transport/SubjectInboundTransport' import { SubjectOutboundTransport } from '../../../tests/transport/SubjectOutboundTransport' -import { askarModule } from '../../askar/tests/helpers' -import { getAskarWalletConfig, testLogger } from '../../core/tests' +import { uuid } from '../../core/src/utils/uuid' +import { testLogger } from '../../core/tests' import { TenantsModule } from '@credo-ts/tenants' const agent1Config: InitConfig = { label: 'Tenant Agent 1', - walletConfig: getAskarWalletConfig('tenants e2e agent 1'), + walletConfig: { + id: `tenants e2e agent 1 - ${uuid().slice(0, 4)}`, + key: `tenants e2e agent 1`, + }, logger: testLogger, endpoints: ['rxjs:tenant-agent1'], } const agent2Config: InitConfig = { label: 'Tenant Agent 2', - walletConfig: getAskarWalletConfig('tenants e2e agent 2'), + walletConfig: { + id: `tenants e2e agent 2 - ${uuid().slice(0, 4)}`, + key: `tenants e2e agent 2`, + }, logger: testLogger, endpoints: ['rxjs:tenant-agent2'], } @@ -29,7 +36,7 @@ const agent1 = new Agent({ config: agent1Config, modules: { tenants: new TenantsModule(), - askar: askarModule, + inMemory: new InMemoryWalletModule(), connections: new ConnectionsModule({ autoAcceptConnections: true, }), @@ -44,7 +51,7 @@ const agent2 = new Agent({ config: agent2Config, modules: { tenants: new TenantsModule(), - askar: askarModule, + inMemory: new InMemoryWalletModule(), connections: new ConnectionsModule({ autoAcceptConnections: true, }), diff --git a/samples/extension-module/package.json b/samples/extension-module/package.json index d0b68ecb81..76016ac980 100644 --- a/samples/extension-module/package.json +++ b/samples/extension-module/package.json @@ -13,15 +13,15 @@ "responder": "ts-node responder.ts" }, "devDependencies": { - "@credo-ts/core": "*", - "@credo-ts/node": "*", "ts-node": "^10.4.0", - "@credo-ts/askar": "*", "@types/express": "^4.17.13", "@types/uuid": "^9.0.1", "@types/ws": "^8.5.4" }, "dependencies": { + "@credo-ts/core": "*", + "@credo-ts/node": "*", + "@credo-ts/askar": "*", "class-validator": "0.14.0", "rxjs": "^7.2.0", "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5" diff --git a/tests/InMemoryStorageService.ts b/tests/InMemoryStorageService.ts index 40f48c8406..2fb57419c3 100644 --- a/tests/InMemoryStorageService.ts +++ b/tests/InMemoryStorageService.ts @@ -2,6 +2,8 @@ import type { AgentContext } from '../packages/core/src/agent' import type { BaseRecord, TagsBase } from '../packages/core/src/storage/BaseRecord' import type { StorageService, BaseRecordConstructor, Query } from '../packages/core/src/storage/StorageService' +import { InMemoryWallet } from './InMemoryWallet' + import { RecordNotFoundError, RecordDuplicateError, JsonTransformer, injectable } from '@credo-ts/core' interface StorageRecord { @@ -15,16 +17,19 @@ interface InMemoryRecords { [id: string]: StorageRecord } +interface ContextCorrelationIdToRecords { + [contextCorrelationId: string]: { + records: InMemoryRecords + creationDate: Date + } +} + @injectable() // eslint-disable-next-line @typescript-eslint/no-explicit-any export class InMemoryStorageService = BaseRecord> implements StorageService { - public records: InMemoryRecords - - public constructor(records: InMemoryRecords = {}) { - this.records = records - } + public contextCorrelationIdToRecords: ContextCorrelationIdToRecords = {} private recordToInstance(record: StorageRecord, recordClass: BaseRecordConstructor): T { const instance = JsonTransformer.fromJSON(record.value, recordClass) @@ -34,16 +39,43 @@ export class InMemoryStorageService = BaseRe return instance } + private getRecordsForContext(agentContext: AgentContext): InMemoryRecords { + const contextCorrelationId = agentContext.contextCorrelationId + + if (!this.contextCorrelationIdToRecords[contextCorrelationId]) { + this.contextCorrelationIdToRecords[contextCorrelationId] = { + records: {}, + creationDate: new Date(), + } + } else if (agentContext.wallet instanceof InMemoryWallet && agentContext.wallet.activeWalletId) { + const walletCreationDate = agentContext.wallet.inMemoryWallets[agentContext.wallet.activeWalletId].creationDate + const storageCreationDate = this.contextCorrelationIdToRecords[contextCorrelationId].creationDate + + // If the storage was created before the wallet, it means the wallet has been deleted in the meantime + // and thus we need to recreate the storage as we don't want to serve records from the previous wallet + // FIXME: this is a flaw in our wallet/storage model. I think wallet should be for keys, and storage + // for records and you can create them separately. But that's a bigger change. + if (storageCreationDate < walletCreationDate) { + this.contextCorrelationIdToRecords[contextCorrelationId] = { + records: {}, + creationDate: new Date(), + } + } + } + + return this.contextCorrelationIdToRecords[contextCorrelationId].records + } + /** @inheritDoc */ public async save(agentContext: AgentContext, record: T) { record.updatedAt = new Date() const value = JsonTransformer.toJSON(record) - if (this.records[record.id]) { + if (this.getRecordsForContext(agentContext)[record.id]) { throw new RecordDuplicateError(`Record with id ${record.id} already exists`, { recordType: record.type }) } - this.records[record.id] = { + this.getRecordsForContext(agentContext)[record.id] = { value, id: record.id, type: record.type, @@ -57,13 +89,13 @@ export class InMemoryStorageService = BaseRe const value = JsonTransformer.toJSON(record) delete value._tags - if (!this.records[record.id]) { + if (!this.getRecordsForContext(agentContext)[record.id]) { throw new RecordNotFoundError(`record with id ${record.id} not found.`, { recordType: record.type, }) } - this.records[record.id] = { + this.getRecordsForContext(agentContext)[record.id] = { value, id: record.id, type: record.type, @@ -73,13 +105,13 @@ export class InMemoryStorageService = BaseRe /** @inheritDoc */ public async delete(agentContext: AgentContext, record: T) { - if (!this.records[record.id]) { + if (!this.getRecordsForContext(agentContext)[record.id]) { throw new RecordNotFoundError(`record with id ${record.id} not found.`, { recordType: record.type, }) } - delete this.records[record.id] + delete this.getRecordsForContext(agentContext)[record.id] } /** @inheritDoc */ @@ -88,18 +120,18 @@ export class InMemoryStorageService = BaseRe recordClass: BaseRecordConstructor, id: string ): Promise { - if (!this.records[id]) { + if (!this.getRecordsForContext(agentContext)[id]) { throw new RecordNotFoundError(`record with id ${id} not found.`, { recordType: recordClass.type, }) } - delete this.records[id] + delete this.getRecordsForContext(agentContext)[id] } /** @inheritDoc */ public async getById(agentContext: AgentContext, recordClass: BaseRecordConstructor, id: string): Promise { - const record = this.records[id] + const record = this.getRecordsForContext(agentContext)[id] if (!record) { throw new RecordNotFoundError(`record with id ${id} not found.`, { @@ -112,7 +144,7 @@ export class InMemoryStorageService = BaseRe /** @inheritDoc */ public async getAll(agentContext: AgentContext, recordClass: BaseRecordConstructor): Promise { - const records = Object.values(this.records) + const records = Object.values(this.getRecordsForContext(agentContext)) .filter((record) => record.type === recordClass.type) .map((record) => this.recordToInstance(record, recordClass)) @@ -125,7 +157,7 @@ export class InMemoryStorageService = BaseRe recordClass: BaseRecordConstructor, query: Query ): Promise { - const records = Object.values(this.records) + const records = Object.values(this.getRecordsForContext(agentContext)) .filter((record) => record.type === recordClass.type) .filter((record) => filterByQuery(record, query)) .map((record) => this.recordToInstance(record, recordClass)) @@ -165,6 +197,10 @@ function matchSimpleQuery>(record: StorageRe const tags = record.tags as TagsBase for (const [key, value] of Object.entries(query)) { + // We don't query for value undefined, the value should be null in that case + if (value === undefined) continue + + // TODO: support null if (Array.isArray(value)) { const tagValue = tags[key] if (!Array.isArray(tagValue) || !value.every((v) => tagValue.includes(v))) { diff --git a/tests/InMemoryWallet.ts b/tests/InMemoryWallet.ts new file mode 100644 index 0000000000..bfc539eff3 --- /dev/null +++ b/tests/InMemoryWallet.ts @@ -0,0 +1,344 @@ +import type { + EncryptedMessage, + WalletConfig, + WalletCreateKeyOptions, + WalletSignOptions, + UnpackedMessageContext, + WalletVerifyOptions, + Wallet, +} from '@credo-ts/core' + +import { CryptoBox, Store, Key as AskarKey, keyAlgFromString } from '@hyperledger/aries-askar-nodejs' +import BigNumber from 'bn.js' + +import { didcommV1Pack, didcommV1Unpack } from '../packages/askar/src/wallet/didcommV1' + +import { + JsonEncoder, + WalletNotFoundError, + injectable, + isValidSeed, + isValidPrivateKey, + KeyType, + Buffer, + AriesFrameworkError, + WalletError, + Key, + TypedArrayEncoder, +} from '@credo-ts/core' + +const isError = (error: unknown): error is Error => error instanceof Error + +interface InMemoryKey { + publicKeyBytes: Uint8Array + secretKeyBytes: Uint8Array + keyType: KeyType +} + +interface InMemoryKeys { + [id: string]: InMemoryKey +} + +interface InMemoryWallets { + [id: string]: { + keys: InMemoryKeys + creationDate: Date + } +} + +@injectable() +export class InMemoryWallet implements Wallet { + // activeWalletId can be set even if wallet is closed. So make sure to also look at + // isInitialized to see if the wallet is actually open + public activeWalletId?: string + + public inMemoryWallets: InMemoryWallets = {} + /** + * Abstract methods that need to be implemented by subclasses + */ + public isInitialized = false + public isProvisioned = false + + public get supportedKeyTypes() { + return [KeyType.Ed25519, KeyType.P256] + } + + private get inMemoryKeys(): InMemoryKeys { + if (!this.activeWalletId || !this.isInitialized) { + throw new WalletError('No active wallet') + } + + if (!this.inMemoryWallets[this.activeWalletId]) { + throw new WalletError('wallet does not exist') + } + + return this.inMemoryWallets[this.activeWalletId].keys + } + + public async create(walletConfig: WalletConfig) { + if (this.inMemoryWallets[walletConfig.id]) { + throw new WalletError('Wallet already exists') + } + + this.inMemoryWallets[walletConfig.id] = { + keys: {}, + creationDate: new Date(), + } + } + + public async createAndOpen(walletConfig: WalletConfig) { + await this.create(walletConfig) + await this.open(walletConfig) + } + + public async open(walletConfig: WalletConfig) { + if (this.isInitialized) { + throw new WalletError('A wallet is already open') + } + + if (!this.inMemoryWallets[walletConfig.id]) { + throw new WalletNotFoundError('Wallet does not exist', { walletType: 'InMemoryWallet' }) + } + + this.activeWalletId = walletConfig.id + this.isProvisioned = true + this.isInitialized = true + } + + public rotateKey(): Promise { + throw new Error('Method not implemented.') + } + + public async close() { + this.isInitialized = false + } + + public async delete() { + if (!this.activeWalletId) { + throw new WalletError('wallet is not provisioned') + } + + delete this.inMemoryWallets[this.activeWalletId] + this.activeWalletId = undefined + this.isProvisioned = false + } + + public async export() { + throw new Error('Method not implemented.') + } + + public async import() { + throw new Error('Method not implemented.') + } + + public async dispose() { + this.isInitialized = false + } + + /** + * Create a key with an optional seed and keyType. + * The keypair is also automatically stored in the wallet afterwards + */ + public async createKey({ seed, privateKey, keyType }: WalletCreateKeyOptions): Promise { + try { + if (seed && privateKey) { + throw new WalletError('Only one of seed and privateKey can be set') + } + + if (seed && !isValidSeed(seed, keyType)) { + throw new WalletError('Invalid seed provided') + } + + if (privateKey && !isValidPrivateKey(privateKey, keyType)) { + throw new WalletError('Invalid private key provided') + } + + if (!this.supportedKeyTypes.includes(keyType)) { + throw new WalletError(`Unsupported key type: '${keyType}'`) + } + + const algorithm = keyAlgFromString(keyType) + + // Create key + let key: AskarKey | undefined + try { + key = privateKey + ? AskarKey.fromSecretBytes({ secretKey: privateKey, algorithm }) + : seed + ? AskarKey.fromSeed({ seed, algorithm }) + : AskarKey.generate(algorithm) + + const keyPublicBytes = key.publicBytes + // Store key + this.inMemoryKeys[TypedArrayEncoder.toBase58(keyPublicBytes)] = { + publicKeyBytes: keyPublicBytes, + secretKeyBytes: key.secretBytes, + keyType, + } + + key.handle.free() + return Key.fromPublicKey(keyPublicBytes, keyType) + } finally { + key?.handle.free() + } + } catch (error) { + // If already instance of `WalletError`, re-throw + if (error instanceof WalletError) throw error + + if (!isError(error)) { + throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) + } + throw new WalletError(`Error creating key with key type '${keyType}': ${error.message}`, { cause: error }) + } + } + + /** + * sign a Buffer with an instance of a Key class + * + * @param data Buffer The data that needs to be signed + * @param key Key The key that is used to sign the data + * + * @returns A signature for the data + */ + public async sign({ data, key }: WalletSignOptions): Promise { + const inMemoryKey = this.inMemoryKeys[key.publicKeyBase58] + if (!inMemoryKey) { + throw new WalletError(`Key not found in wallet`) + } + + if (!TypedArrayEncoder.isTypedArray(data)) { + throw new WalletError(`Currently not supporting signing of multiple messages`) + } + + let askarKey: AskarKey | undefined + try { + const inMemoryKey = this.inMemoryKeys[key.publicKeyBase58] + askarKey = AskarKey.fromSecretBytes({ + algorithm: keyAlgFromString(inMemoryKey.keyType), + secretKey: inMemoryKey.secretKeyBytes, + }) + + const signed = askarKey.signMessage({ message: data as Buffer }) + + return Buffer.from(signed) + } finally { + askarKey?.handle.free() + } + } + + /** + * Verify the signature with the data and the used key + * + * @param data Buffer The data that has to be confirmed to be signed + * @param key Key The key that was used in the signing process + * @param signature Buffer The signature that was created by the signing process + * + * @returns A boolean whether the signature was created with the supplied data and key + * + * @throws {WalletError} When it could not do the verification + * @throws {WalletError} When an unsupported keytype is used + */ + public async verify({ data, key, signature }: WalletVerifyOptions): Promise { + if (!TypedArrayEncoder.isTypedArray(data)) { + throw new WalletError(`Currently not supporting signing of multiple messages`) + } + + let askarKey: AskarKey | undefined + try { + askarKey = AskarKey.fromPublicBytes({ + algorithm: keyAlgFromString(key.keyType), + publicKey: key.publicKey, + }) + return askarKey.verifySignature({ message: data as Buffer, signature }) + } finally { + askarKey?.handle.free() + } + } + + /** + * Pack a message using DIDComm V1 algorithm + * + * @param payload message to send + * @param recipientKeys array containing recipient keys in base58 + * @param senderVerkey sender key in base58 + * @returns JWE Envelope to send + */ + public async pack( + payload: Record, + recipientKeys: string[], + senderVerkey?: string // in base58 + ): Promise { + const senderKey = senderVerkey ? this.inMemoryKeys[senderVerkey] : undefined + + if (senderVerkey && !senderKey) { + throw new WalletError(`Sender key not found`) + } + + const askarSenderKey = senderKey + ? AskarKey.fromSecretBytes({ + algorithm: keyAlgFromString(senderKey.keyType), + secretKey: senderKey.secretKeyBytes, + }) + : undefined + + try { + const envelope = didcommV1Pack(payload, recipientKeys, askarSenderKey) + return envelope + } finally { + askarSenderKey?.handle.free() + } + } + + /** + * Unpacks a JWE Envelope coded using DIDComm V1 algorithm + * + * @param messagePackage JWE Envelope + * @returns UnpackedMessageContext with plain text message, sender key and recipient key + */ + public async unpack(messagePackage: EncryptedMessage): Promise { + const protectedJson = JsonEncoder.fromBase64(messagePackage.protected) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const recipientKids: string[] = protectedJson.recipients.map((r: any) => r.header.kid) + + for (const recipientKid of recipientKids) { + const recipientKey = this.inMemoryKeys[recipientKid] + const recipientAskarKey = recipientKey + ? AskarKey.fromSecretBytes({ + algorithm: keyAlgFromString(recipientKey.keyType), + secretKey: recipientKey.secretKeyBytes, + }) + : undefined + try { + if (recipientAskarKey) { + const unpacked = didcommV1Unpack(messagePackage, recipientAskarKey) + return unpacked + } + } finally { + recipientAskarKey?.handle.free() + } + } + + throw new WalletError('No corresponding recipient key found') + } + + public async generateNonce(): Promise { + try { + // generate an 80-bit nonce suitable for AnonCreds proofs + const nonce = CryptoBox.randomNonce().slice(0, 10) + return new BigNumber(nonce).toString() + } catch (error) { + if (!isError(error)) { + throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) + } + throw new WalletError('Error generating nonce', { cause: error }) + } + } + + public async generateWalletKey() { + try { + return Store.generateRawKey() + } catch (error) { + throw new WalletError('Error generating wallet key', { cause: error }) + } + } +} diff --git a/tests/InMemoryWalletModule.ts b/tests/InMemoryWalletModule.ts new file mode 100644 index 0000000000..c33326b79f --- /dev/null +++ b/tests/InMemoryWalletModule.ts @@ -0,0 +1,22 @@ +import type { DependencyManager, Module } from '@credo-ts/core' + +import { InMemoryStorageService } from './InMemoryStorageService' +import { InMemoryWallet } from './InMemoryWallet' + +import { AriesFrameworkError, InjectionSymbols } from '@credo-ts/core' + +export class InMemoryWalletModule implements Module { + public register(dependencyManager: DependencyManager) { + if (dependencyManager.isRegistered(InjectionSymbols.Wallet)) { + throw new AriesFrameworkError('There is an instance of Wallet already registered') + } else { + dependencyManager.registerContextScoped(InjectionSymbols.Wallet, InMemoryWallet) + } + + if (dependencyManager.isRegistered(InjectionSymbols.StorageService)) { + throw new AriesFrameworkError('There is an instance of StorageService already registered') + } else { + dependencyManager.registerSingleton(InjectionSymbols.StorageService, InMemoryStorageService) + } + } +} diff --git a/tests/e2e-askar-indy-vdr-anoncreds-rs.test.ts b/tests/e2e-askar-indy-vdr-anoncreds-rs.test.ts index 11eef06dd6..4d948dd281 100644 --- a/tests/e2e-askar-indy-vdr-anoncreds-rs.test.ts +++ b/tests/e2e-askar-indy-vdr-anoncreds-rs.test.ts @@ -3,7 +3,8 @@ import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnon import { Subject } from 'rxjs' -import { getAskarAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' +import { getAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' +import { askarModule } from '../packages/askar/tests/helpers' import { getAgentOptions } from '../packages/core/tests/helpers' import { e2eTest } from './e2e-test' @@ -22,12 +23,13 @@ const recipientAgentOptions = getAgentOptions( 'E2E Askar Subject Recipient', {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, }), + askar: askarModule, } ) const mediatorAgentOptions = getAgentOptions( @@ -36,10 +38,11 @@ const mediatorAgentOptions = getAgentOptions( endpoints: ['rxjs:mediator'], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediator: new MediatorModule({ autoAcceptMediationRequests: true }), + askar: askarModule, } ) const senderAgentOptions = getAgentOptions( @@ -48,13 +51,14 @@ const senderAgentOptions = getAgentOptions( endpoints: ['rxjs:sender'], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ mediatorPollingInterval: 1000, mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, }), + askar: askarModule, } ) @@ -64,9 +68,9 @@ describe('E2E Askar-AnonCredsRS-IndyVDR Subject tests', () => { let senderAgent: AnonCredsTestsAgent beforeEach(async () => { - recipientAgent = new Agent(recipientAgentOptions) as AnonCredsTestsAgent - mediatorAgent = new Agent(mediatorAgentOptions) as AnonCredsTestsAgent - senderAgent = new Agent(senderAgentOptions) as AnonCredsTestsAgent + recipientAgent = new Agent(recipientAgentOptions) as unknown as AnonCredsTestsAgent + mediatorAgent = new Agent(mediatorAgentOptions) as unknown as AnonCredsTestsAgent + senderAgent = new Agent(senderAgentOptions) as unknown as AnonCredsTestsAgent }) afterEach(async () => { diff --git a/tests/e2e-http.test.ts b/tests/e2e-http.test.ts index 7a92f5adea..d4cc8eb163 100644 --- a/tests/e2e-http.test.ts +++ b/tests/e2e-http.test.ts @@ -1,7 +1,7 @@ import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getAskarAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getAgentOptions } from '../packages/core/tests/helpers' +import { getAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' +import { getInMemoryAgentOptions } from '../packages/core/tests/helpers' import { e2eTest } from './e2e-test' @@ -15,11 +15,11 @@ import { } from '@credo-ts/core' import { HttpInboundTransport } from '@credo-ts/node' -const recipientAgentOptions = getAgentOptions( +const recipientAgentOptions = getInMemoryAgentOptions( 'E2E HTTP Recipient', {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ @@ -29,13 +29,13 @@ const recipientAgentOptions = getAgentOptions( ) const mediatorPort = 3000 -const mediatorAgentOptions = getAgentOptions( +const mediatorAgentOptions = getInMemoryAgentOptions( 'E2E HTTP Mediator', { endpoints: [`http://localhost:${mediatorPort}`], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediator: new MediatorModule({ @@ -45,13 +45,13 @@ const mediatorAgentOptions = getAgentOptions( ) const senderPort = 3001 -const senderAgentOptions = getAgentOptions( +const senderAgentOptions = getInMemoryAgentOptions( 'E2E HTTP Sender', { endpoints: [`http://localhost:${senderPort}`], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ diff --git a/tests/e2e-subject.test.ts b/tests/e2e-subject.test.ts index b3e2bac5d5..cc9670abbf 100644 --- a/tests/e2e-subject.test.ts +++ b/tests/e2e-subject.test.ts @@ -3,8 +3,8 @@ import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnon import { Subject } from 'rxjs' -import { getAskarAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getAgentOptions } from '../packages/core/tests/helpers' +import { getAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' +import { getInMemoryAgentOptions } from '../packages/core/tests/helpers' import { e2eTest } from './e2e-test' import { SubjectInboundTransport } from './transport/SubjectInboundTransport' @@ -18,11 +18,11 @@ import { MediationRecipientModule, } from '@credo-ts/core' -const recipientAgentOptions = getAgentOptions( +const recipientAgentOptions = getInMemoryAgentOptions( 'E2E Subject Recipient', {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ @@ -30,25 +30,25 @@ const recipientAgentOptions = getAgentOptions( }), } ) -const mediatorAgentOptions = getAgentOptions( +const mediatorAgentOptions = getInMemoryAgentOptions( 'E2E Subject Mediator', { endpoints: ['rxjs:mediator'], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediator: new MediatorModule({ autoAcceptMediationRequests: true }), } ) -const senderAgentOptions = getAgentOptions( +const senderAgentOptions = getInMemoryAgentOptions( 'E2E Subject Sender', { endpoints: ['rxjs:sender'], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ diff --git a/tests/e2e-ws-pickup-v2.test.ts b/tests/e2e-ws-pickup-v2.test.ts index 6f4b535847..8dc1ace83a 100644 --- a/tests/e2e-ws-pickup-v2.test.ts +++ b/tests/e2e-ws-pickup-v2.test.ts @@ -1,7 +1,7 @@ import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getAskarAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getAgentOptions } from '../packages/core/tests/helpers' +import { getAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' +import { getInMemoryAgentOptions } from '../packages/core/tests/helpers' import { e2eTest } from './e2e-test' @@ -15,11 +15,11 @@ import { } from '@credo-ts/core' import { WsInboundTransport } from '@credo-ts/node' -const recipientOptions = getAgentOptions( +const recipientOptions = getInMemoryAgentOptions( 'E2E WS Pickup V2 Recipient ', {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ @@ -30,13 +30,13 @@ const recipientOptions = getAgentOptions( // FIXME: port numbers should not depend on availability from other test suites that use web sockets const mediatorPort = 4100 -const mediatorOptions = getAgentOptions( +const mediatorOptions = getInMemoryAgentOptions( 'E2E WS Pickup V2 Mediator', { endpoints: [`ws://localhost:${mediatorPort}`], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediator: new MediatorModule({ autoAcceptMediationRequests: true }), @@ -44,13 +44,13 @@ const mediatorOptions = getAgentOptions( ) const senderPort = 4101 -const senderOptions = getAgentOptions( +const senderOptions = getInMemoryAgentOptions( 'E2E WS Pickup V2 Sender', { endpoints: [`ws://localhost:${senderPort}`], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ diff --git a/tests/e2e-ws.test.ts b/tests/e2e-ws.test.ts index 588754c43d..c2d83e0c78 100644 --- a/tests/e2e-ws.test.ts +++ b/tests/e2e-ws.test.ts @@ -1,7 +1,7 @@ import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getAskarAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getAgentOptions } from '../packages/core/tests/helpers' +import { getAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' +import { getInMemoryAgentOptions } from '../packages/core/tests/helpers' import { e2eTest } from './e2e-test' @@ -15,11 +15,11 @@ import { } from '@credo-ts/core' import { WsInboundTransport } from '@credo-ts/node' -const recipientAgentOptions = getAgentOptions( +const recipientAgentOptions = getInMemoryAgentOptions( 'E2E WS Recipient ', {}, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ @@ -29,13 +29,13 @@ const recipientAgentOptions = getAgentOptions( ) const mediatorPort = 4000 -const mediatorAgentOptions = getAgentOptions( +const mediatorAgentOptions = getInMemoryAgentOptions( 'E2E WS Mediator', { endpoints: [`ws://localhost:${mediatorPort}`], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediator: new MediatorModule({ autoAcceptMediationRequests: true }), @@ -43,13 +43,13 @@ const mediatorAgentOptions = getAgentOptions( ) const senderPort = 4001 -const senderAgentOptions = getAgentOptions( +const senderAgentOptions = getInMemoryAgentOptions( 'E2E WS Sender', { endpoints: [`ws://localhost:${senderPort}`], }, { - ...getAskarAnonCredsIndyModules({ + ...getAnonCredsIndyModules({ autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediationRecipient: new MediationRecipientModule({ From fb94f61d15d5cabda43091d0693b9db9d5b5eb97 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Wed, 31 Jan 2024 19:11:07 +0700 Subject: [PATCH 16/19] chore: fix tests Signed-off-by: Timo Glastra --- package.json | 4 +-- .../__tests__/AnonCredsRsServices.test.ts | 3 ++ .../anoncreds-rs/tests/anoncreds-flow.test.ts | 2 +- packages/core/src/agent/Dispatcher.ts | 6 +--- packages/core/src/agent/MessageSender.ts | 6 ++-- .../src/agent/__tests__/MessageSender.test.ts | 8 ++--- ...entationExchangeProofFormatService.test.ts | 24 ++++++++------- .../storage/migration/__tests__/0.2.test.ts | 4 ++- .../tests/indy-vdr-did-registrar.e2e.test.ts | 7 +++++ tests/InMemoryWallet.ts | 1 - yarn.lock | 30 +++++++++---------- 11 files changed, 51 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index 69df9e8a2c..6ce3769f1f 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@types/cors": "^2.8.10", "@types/eslint": "^8.21.2", "@types/express": "^4.17.13", - "@types/jest": "^29.5.5", + "@types/jest": "^29.5.11", "@types/node": "^18.18.8", "@types/uuid": "^9.0.1", "@types/varint": "^6.0.0", @@ -52,7 +52,7 @@ "lerna": "^6.5.1", "prettier": "^2.3.1", "rxjs": "^7.8.0", - "ts-jest": "^29.0.5", + "ts-jest": "^29.1.2", "ts-node": "^10.0.0", "tsconfig-paths": "^4.1.2", "tsyringe": "^4.8.0", diff --git a/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts b/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts index 477187920d..f23ff1f230 100644 --- a/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts +++ b/packages/anoncreds-rs/src/services/__tests__/AnonCredsRsServices.test.ts @@ -25,6 +25,7 @@ import { anoncreds } from '@hyperledger/anoncreds-nodejs' import { Subject } from 'rxjs' import { InMemoryStorageService } from '../../../../../tests/InMemoryStorageService' +import { InMemoryWallet } from '../../../../../tests/InMemoryWallet' import { encodeCredentialValue } from '../../../../anoncreds/src/utils/credential' import { InMemoryAnonCredsRegistry } from '../../../../anoncreds/tests/InMemoryAnonCredsRegistry' import { agentDependencies, getAgentConfig, getAgentContext } from '../../../../core/tests/helpers' @@ -37,9 +38,11 @@ const anonCredsVerifierService = new AnonCredsRsVerifierService() const anonCredsHolderService = new AnonCredsRsHolderService() const anonCredsIssuerService = new AnonCredsRsIssuerService() const storageService = new InMemoryStorageService() +const wallet = new InMemoryWallet() const registry = new InMemoryAnonCredsRegistry() const agentContext = getAgentContext({ + wallet, registerInstances: [ [InjectionSymbols.Stop$, new Subject()], [InjectionSymbols.AgentDependencies, agentDependencies], diff --git a/packages/anoncreds-rs/tests/anoncreds-flow.test.ts b/packages/anoncreds-rs/tests/anoncreds-flow.test.ts index 0ccfe96d21..4f4dece3c0 100644 --- a/packages/anoncreds-rs/tests/anoncreds-flow.test.ts +++ b/packages/anoncreds-rs/tests/anoncreds-flow.test.ts @@ -83,7 +83,7 @@ const indyDid = 'did:indy:local:LjgpST2rjsoxYegQDRm7EL' describe('AnonCreds format services using anoncreds-rs', () => { afterEach(() => { - inMemoryStorageService.records = {} + inMemoryStorageService.contextCorrelationIdToRecords = {} }) test('issuance and verification flow starting from proposal without negotiation and without revocation', async () => { diff --git a/packages/core/src/agent/Dispatcher.ts b/packages/core/src/agent/Dispatcher.ts index 5301745040..4a2bf62a38 100644 --- a/packages/core/src/agent/Dispatcher.ts +++ b/packages/core/src/agent/Dispatcher.ts @@ -89,11 +89,7 @@ class Dispatcher { outboundMessage.inboundMessageContext = messageContext } - if (outboundMessage.isOutboundServiceMessage()) { - await this.messageSender.sendMessageToService(outboundMessage) - } else { - await this.messageSender.sendMessage(outboundMessage) - } + await this.messageSender.sendMessage(outboundMessage) } // Emit event that allows to hook into received messages this.eventEmitter.emit(agentContext, { diff --git a/packages/core/src/agent/MessageSender.ts b/packages/core/src/agent/MessageSender.ts index 215aba845e..82efd2129d 100644 --- a/packages/core/src/agent/MessageSender.ts +++ b/packages/core/src/agent/MessageSender.ts @@ -219,6 +219,7 @@ export class MessageSender { if (session) { this.logger.debug(`Found session with return routing for message '${message.id}' (connection '${connection.id}'`) + try { await this.sendMessageToSession(agentContext, session, message) this.emitMessageSentEvent(outboundMessageContext, OutboundMessageSendStatus.SentToSession) @@ -348,10 +349,7 @@ export class MessageSender { ) } - /** - * @deprecated Use `sendMessage` directly instead. Will be made private in 0.5.0 - */ - public async sendMessageToService(outboundMessageContext: OutboundMessageContext) { + private async sendMessageToService(outboundMessageContext: OutboundMessageContext) { const session = this.findSessionForOutboundContext(outboundMessageContext) if (session) { diff --git a/packages/core/src/agent/__tests__/MessageSender.test.ts b/packages/core/src/agent/__tests__/MessageSender.test.ts index 6c96bf1008..711e59c14e 100644 --- a/packages/core/src/agent/__tests__/MessageSender.test.ts +++ b/packages/core/src/agent/__tests__/MessageSender.test.ts @@ -521,7 +521,7 @@ describe('MessageSender', () => { service, }, }) - await expect(messageSender.sendMessageToService(outboundMessageContext)).rejects.toThrow( + await expect(messageSender.sendMessage(outboundMessageContext)).rejects.toThrow( `Agent has no outbound transport!` ) @@ -549,7 +549,7 @@ describe('MessageSender', () => { }, }) - await messageSender.sendMessageToService(outboundMessageContext) + await messageSender.sendMessage(outboundMessageContext) expect(eventListenerMock).toHaveBeenCalledWith({ type: AgentEventTypes.AgentMessageSent, @@ -585,7 +585,7 @@ describe('MessageSender', () => { }, }) - await messageSender.sendMessageToService(outboundMessageContext) + await messageSender.sendMessage(outboundMessageContext) expect(eventListenerMock).toHaveBeenCalledWith({ type: AgentEventTypes.AgentMessageSent, @@ -616,7 +616,7 @@ describe('MessageSender', () => { }, }) - await expect(messageSender.sendMessageToService(outboundMessageContext)).rejects.toThrow( + await expect(messageSender.sendMessage(outboundMessageContext)).rejects.toThrow( /Unable to send message to service/ ) expect(eventListenerMock).toHaveBeenCalledWith({ diff --git a/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts b/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts index cd2738efbe..f2b82f120c 100644 --- a/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts +++ b/packages/core/src/modules/proofs/formats/dif-presentation-exchange/__tests__/PresentationExchangeProofFormatService.test.ts @@ -4,7 +4,7 @@ import type { DifPresentationExchangeProofFormat } from '../DifPresentationExcha import { PresentationSubmissionLocation } from '@sphereon/pex' -import { agentDependencies, getAgentConfig } from '../../../../../../tests' +import { getInMemoryAgentOptions } from '../../../../../../tests' import { Agent } from '../../../../../agent/Agent' import { DifPresentationExchangeModule, DifPresentationExchangeService } from '../../../../dif-presentation-exchange' import { @@ -91,16 +91,18 @@ describe('Presentation Exchange ProofFormatService', () => { let agent: Agent beforeAll(async () => { - agent = new Agent({ - config: getAgentConfig('PresentationExchangeProofFormatService'), - modules: { - pex: new DifPresentationExchangeModule(), - proofs: new ProofsModule({ - proofProtocols: [new V2ProofProtocol({ proofFormats: [new PresentationExchangeProofFormatService()] })], - }), - }, - dependencies: agentDependencies, - }) + agent = new Agent( + getInMemoryAgentOptions( + 'PresentationExchangeProofFormatService', + {}, + { + pex: new DifPresentationExchangeModule(), + proofs: new ProofsModule({ + proofProtocols: [new V2ProofProtocol({ proofFormats: [new PresentationExchangeProofFormatService()] })], + }), + } + ) + ) await agent.initialize() diff --git a/packages/core/src/storage/migration/__tests__/0.2.test.ts b/packages/core/src/storage/migration/__tests__/0.2.test.ts index 2e5c0647a5..4ad72fca11 100644 --- a/packages/core/src/storage/migration/__tests__/0.2.test.ts +++ b/packages/core/src/storage/migration/__tests__/0.2.test.ts @@ -3,7 +3,7 @@ import path from 'path' import { InMemoryStorageService } from '../../../../../../tests/InMemoryStorageService' import { RegisteredAskarTestWallet } from '../../../../../askar/tests/helpers' -import { Agent } from '../../../../src' +import { Agent, MediatorRoutingRecord } from '../../../../src' import { agentDependencies } from '../../../../tests/helpers' import { InjectionSymbols } from '../../../constants' import { DependencyManager } from '../../../plugins' @@ -133,6 +133,7 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { } await agent.initialize() + await storageService.deleteById(agent.context, MediatorRoutingRecord, 'MEDIATOR_ROUTING_RECORD') expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() @@ -183,6 +184,7 @@ describe('UpdateAssistant | v0.2 - v0.3.1', () => { await agent.initialize() + await storageService.deleteById(agent.context, MediatorRoutingRecord, 'MEDIATOR_ROUTING_RECORD') expect(storageService.contextCorrelationIdToRecords[agent.context.contextCorrelationId].records).toMatchSnapshot() await agent.shutdown() diff --git a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts index d59607fdc8..9cd8063c7e 100644 --- a/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts +++ b/packages/indy-vdr/tests/indy-vdr-did-registrar.e2e.test.ts @@ -203,6 +203,9 @@ describe('Indy VDR Indy Did Registrar', () => { secret: didState.secret, }) + if (didCreateSubmitResult.didState.state !== 'finished') { + throw new Error(`Unexpected did state, ${JSON.stringify(didCreateSubmitResult.didState, null, 2)}`) + } expect(JsonTransformer.toJSON(didCreateSubmitResult)).toMatchObject({ didDocumentMetadata: {}, didRegistrationMetadata: {}, @@ -585,6 +588,10 @@ describe('Indy VDR Indy Did Registrar', () => { ], } + if (didCreateSubmitResult.didState.state !== 'finished') { + throw new Error(`Unexpected did state, ${JSON.stringify(didCreateSubmitResult.didState, null, 2)}`) + } + expect(JsonTransformer.toJSON(didCreateSubmitResult)).toMatchObject({ didDocumentMetadata: {}, didRegistrationMetadata: {}, diff --git a/tests/InMemoryWallet.ts b/tests/InMemoryWallet.ts index bfc539eff3..fd46f2359e 100644 --- a/tests/InMemoryWallet.ts +++ b/tests/InMemoryWallet.ts @@ -176,7 +176,6 @@ export class InMemoryWallet implements Wallet { keyType, } - key.handle.free() return Key.fromPublicKey(keyPublicBytes, keyType) } finally { key?.handle.free() diff --git a/yarn.lock b/yarn.lock index ac41515b93..d22e5418e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3219,10 +3219,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.5.5": - version "29.5.5" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.5.tgz#727204e06228fe24373df9bae76b90f3e8236a2a" - integrity sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg== +"@types/jest@^29.5.11": + version "29.5.11" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c" + integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ== dependencies: expect "^29.0.0" pretty-format "^29.0.0" @@ -11608,18 +11608,18 @@ semver@7.3.8: dependencies: lru-cache "^6.0.0" -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -12491,10 +12491,10 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -ts-jest@^29.0.5: - version "29.1.0" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.0.tgz#4a9db4104a49b76d2b368ea775b6c9535c603891" - integrity sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA== +ts-jest@^29.1.2: + version "29.1.2" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" + integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g== dependencies: bs-logger "0.x" fast-json-stable-stringify "2.x" @@ -12502,7 +12502,7 @@ ts-jest@^29.0.5: json5 "^2.2.3" lodash.memoize "4.x" make-error "1.x" - semver "7.x" + semver "^7.5.3" yargs-parser "^21.0.1" ts-node@^10.0.0, ts-node@^10.4.0: From d9e39eb58db4a8a89291efebd86c1eb3eb5b532a Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Wed, 31 Jan 2024 19:17:32 +0700 Subject: [PATCH 17/19] fix: use askar in ws tests as otherwise it fails Signed-off-by: Timo Glastra --- packages/core/tests/setup.ts | 3 --- tests/e2e-ws-pickup-v2.test.ts | 20 +++++++++++++------- tests/e2e-ws.test.ts | 20 +++++++++++++------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/core/tests/setup.ts b/packages/core/tests/setup.ts index b1f1d020b2..a2ba1429d2 100644 --- a/packages/core/tests/setup.ts +++ b/packages/core/tests/setup.ts @@ -2,9 +2,6 @@ import 'reflect-metadata' import type { ConnectionRecord } from '../src/modules/connections/repository/ConnectionRecord' -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import { askarModuleConfig } from '../../askar/tests/helpers' - jest.setTimeout(120000) expect.extend({ toBeConnectedWith }) diff --git a/tests/e2e-ws-pickup-v2.test.ts b/tests/e2e-ws-pickup-v2.test.ts index 8dc1ace83a..3a61a0ff2a 100644 --- a/tests/e2e-ws-pickup-v2.test.ts +++ b/tests/e2e-ws-pickup-v2.test.ts @@ -1,7 +1,8 @@ import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnonCredsSetup' import { getAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getInMemoryAgentOptions } from '../packages/core/tests/helpers' +import { askarModule } from '../packages/askar/tests/helpers' +import { getAgentOptions } from '../packages/core/tests/helpers' import { e2eTest } from './e2e-test' @@ -15,7 +16,9 @@ import { } from '@credo-ts/core' import { WsInboundTransport } from '@credo-ts/node' -const recipientOptions = getInMemoryAgentOptions( +// FIXME: somehow if we use the in memory wallet and storage service in the WS test it will fail, +// but it succeeds with Askar. We should look into this at some point +const recipientOptions = getAgentOptions( 'E2E WS Pickup V2 Recipient ', {}, { @@ -25,12 +28,13 @@ const recipientOptions = getInMemoryAgentOptions( mediationRecipient: new MediationRecipientModule({ mediatorPickupStrategy: MediatorPickupStrategy.PickUpV2, }), + askar: askarModule, } ) // FIXME: port numbers should not depend on availability from other test suites that use web sockets const mediatorPort = 4100 -const mediatorOptions = getInMemoryAgentOptions( +const mediatorOptions = getAgentOptions( 'E2E WS Pickup V2 Mediator', { endpoints: [`ws://localhost:${mediatorPort}`], @@ -40,11 +44,12 @@ const mediatorOptions = getInMemoryAgentOptions( autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediator: new MediatorModule({ autoAcceptMediationRequests: true }), + askar: askarModule, } ) const senderPort = 4101 -const senderOptions = getInMemoryAgentOptions( +const senderOptions = getAgentOptions( 'E2E WS Pickup V2 Sender', { endpoints: [`ws://localhost:${senderPort}`], @@ -57,6 +62,7 @@ const senderOptions = getInMemoryAgentOptions( mediatorPollingInterval: 1000, mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, }), + askar: askarModule, } ) @@ -66,9 +72,9 @@ describe('E2E WS Pickup V2 tests', () => { let senderAgent: AnonCredsTestsAgent beforeEach(async () => { - recipientAgent = new Agent(recipientOptions) as AnonCredsTestsAgent - mediatorAgent = new Agent(mediatorOptions) as AnonCredsTestsAgent - senderAgent = new Agent(senderOptions) as AnonCredsTestsAgent + recipientAgent = new Agent(recipientOptions) as unknown as AnonCredsTestsAgent + mediatorAgent = new Agent(mediatorOptions) as unknown as AnonCredsTestsAgent + senderAgent = new Agent(senderOptions) as unknown as AnonCredsTestsAgent }) afterEach(async () => { diff --git a/tests/e2e-ws.test.ts b/tests/e2e-ws.test.ts index c2d83e0c78..f3563ab409 100644 --- a/tests/e2e-ws.test.ts +++ b/tests/e2e-ws.test.ts @@ -1,7 +1,8 @@ import type { AnonCredsTestsAgent } from '../packages/anoncreds/tests/legacyAnonCredsSetup' import { getAnonCredsIndyModules } from '../packages/anoncreds/tests/legacyAnonCredsSetup' -import { getInMemoryAgentOptions } from '../packages/core/tests/helpers' +import { askarModule } from '../packages/askar/tests/helpers' +import { getAgentOptions } from '../packages/core/tests/helpers' import { e2eTest } from './e2e-test' @@ -15,7 +16,9 @@ import { } from '@credo-ts/core' import { WsInboundTransport } from '@credo-ts/node' -const recipientAgentOptions = getInMemoryAgentOptions( +// FIXME: somehow if we use the in memory wallet and storage service in the WS test it will fail, +// but it succeeds with Askar. We should look into this at some point +const recipientAgentOptions = getAgentOptions( 'E2E WS Recipient ', {}, { @@ -25,11 +28,12 @@ const recipientAgentOptions = getInMemoryAgentOptions( mediationRecipient: new MediationRecipientModule({ mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, }), + askar: askarModule, } ) const mediatorPort = 4000 -const mediatorAgentOptions = getInMemoryAgentOptions( +const mediatorAgentOptions = getAgentOptions( 'E2E WS Mediator', { endpoints: [`ws://localhost:${mediatorPort}`], @@ -39,11 +43,12 @@ const mediatorAgentOptions = getInMemoryAgentOptions( autoAcceptCredentials: AutoAcceptCredential.ContentApproved, }), mediator: new MediatorModule({ autoAcceptMediationRequests: true }), + askar: askarModule, } ) const senderPort = 4001 -const senderAgentOptions = getInMemoryAgentOptions( +const senderAgentOptions = getAgentOptions( 'E2E WS Sender', { endpoints: [`ws://localhost:${senderPort}`], @@ -56,6 +61,7 @@ const senderAgentOptions = getInMemoryAgentOptions( mediatorPollingInterval: 1000, mediatorPickupStrategy: MediatorPickupStrategy.PickUpV1, }), + askar: askarModule, } ) @@ -65,9 +71,9 @@ describe('E2E WS tests', () => { let senderAgent: AnonCredsTestsAgent beforeEach(async () => { - recipientAgent = new Agent(recipientAgentOptions) as AnonCredsTestsAgent - mediatorAgent = new Agent(mediatorAgentOptions) as AnonCredsTestsAgent - senderAgent = new Agent(senderAgentOptions) as AnonCredsTestsAgent + recipientAgent = new Agent(recipientAgentOptions) as unknown as AnonCredsTestsAgent + mediatorAgent = new Agent(mediatorAgentOptions) as unknown as AnonCredsTestsAgent + senderAgent = new Agent(senderAgentOptions) as unknown as AnonCredsTestsAgent }) afterEach(async () => { From f6da5329836fe8ade5dc206e903272e77bcc33a1 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Wed, 31 Jan 2024 21:26:09 +0700 Subject: [PATCH 18/19] fix: bbs and askar Signed-off-by: Timo Glastra --- package.json | 2 + packages/askar/src/utils/askarKeyTypes.ts | 43 ++++-- packages/askar/src/wallet/AskarBaseWallet.ts | 124 +++++++++++++----- .../tests/bbs-signatures.e2e.test.ts | 11 +- yarn.lock | 7 + 5 files changed, 143 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index 6ce3769f1f..30e910f3ba 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "@hyperledger/aries-askar-nodejs": "^0.2.0-dev.5", + "@types/bn.js": "^5.1.5", "@types/cors": "^2.8.10", "@types/eslint": "^8.21.2", "@types/express": "^4.17.13", @@ -38,6 +39,7 @@ "@types/ws": "^8.5.4", "@typescript-eslint/eslint-plugin": "^5.48.1", "@typescript-eslint/parser": "^5.48.1", + "bn.js": "^5.2.1", "conventional-changelog-conventionalcommits": "^5.0.0", "conventional-recommended-bump": "^6.1.0", "cors": "^2.8.5", diff --git a/packages/askar/src/utils/askarKeyTypes.ts b/packages/askar/src/utils/askarKeyTypes.ts index 9731618b21..cbbf3713d2 100644 --- a/packages/askar/src/utils/askarKeyTypes.ts +++ b/packages/askar/src/utils/askarKeyTypes.ts @@ -1,15 +1,40 @@ import { KeyType } from '@credo-ts/core' import { KeyAlgs } from '@hyperledger/aries-askar-shared' +export enum AskarKeyTypePurpose { + KeyManagement = 'KeyManagement', + Signing = 'Signing', +} + const keyTypeToAskarAlg = { - [KeyType.Ed25519]: KeyAlgs.Ed25519, - [KeyType.X25519]: KeyAlgs.X25519, - [KeyType.Bls12381g1]: KeyAlgs.Bls12381G1, - [KeyType.Bls12381g2]: KeyAlgs.Bls12381G2, - [KeyType.Bls12381g1g2]: KeyAlgs.Bls12381G1G2, - [KeyType.P256]: KeyAlgs.EcSecp256r1, -} as const - -export const isKeyTypeSupportedByAskar = (keyType: KeyType) => keyType in keyTypeToAskarAlg + [KeyType.Ed25519]: { + keyAlg: KeyAlgs.Ed25519, + purposes: [AskarKeyTypePurpose.KeyManagement, AskarKeyTypePurpose.Signing], + }, + [KeyType.X25519]: { + keyAlg: KeyAlgs.X25519, + purposes: [AskarKeyTypePurpose.KeyManagement, AskarKeyTypePurpose.Signing], + }, + [KeyType.Bls12381g1]: { + keyAlg: KeyAlgs.Bls12381G1, + purposes: [AskarKeyTypePurpose.KeyManagement], + }, + [KeyType.Bls12381g2]: { + keyAlg: KeyAlgs.Bls12381G2, + purposes: [AskarKeyTypePurpose.KeyManagement], + }, + [KeyType.Bls12381g1g2]: { + keyAlg: KeyAlgs.Bls12381G1, + purposes: [AskarKeyTypePurpose.KeyManagement], + }, + [KeyType.P256]: { + keyAlg: KeyAlgs.EcSecp256r1, + purposes: [AskarKeyTypePurpose.KeyManagement], + }, +} + +export const isKeyTypeSupportedByAskarForPurpose = (keyType: KeyType, purpose: AskarKeyTypePurpose) => + keyType in keyTypeToAskarAlg && + keyTypeToAskarAlg[keyType as keyof typeof keyTypeToAskarAlg].purposes.includes(purpose) export const keyTypesSupportedByAskar = Object.keys(keyTypeToAskarAlg) as KeyType[] diff --git a/packages/askar/src/wallet/AskarBaseWallet.ts b/packages/askar/src/wallet/AskarBaseWallet.ts index 9e3c1383cd..70796751e6 100644 --- a/packages/askar/src/wallet/AskarBaseWallet.ts +++ b/packages/askar/src/wallet/AskarBaseWallet.ts @@ -12,7 +12,7 @@ import type { Logger, SigningProviderRegistry, } from '@credo-ts/core' -import type { KeyEntryObject, Session } from '@hyperledger/aries-askar-shared' +import type { Session } from '@hyperledger/aries-askar-shared' import { WalletKeyExistsError, @@ -28,7 +28,13 @@ import { import { CryptoBox, Store, Key as AskarKey, keyAlgFromString } from '@hyperledger/aries-askar-shared' import BigNumber from 'bn.js' -import { AskarErrorCode, isAskarError, isKeyTypeSupportedByAskar, keyTypesSupportedByAskar } from '../utils' +import { + AskarErrorCode, + AskarKeyTypePurpose, + isAskarError, + isKeyTypeSupportedByAskarForPurpose, + keyTypesSupportedByAskar, +} from '../utils' import { didcommV1Pack, didcommV1Unpack } from './didcommV1' @@ -93,7 +99,7 @@ export abstract class AskarBaseWallet implements Wallet { throw new WalletError('Invalid private key provided') } - if (isKeyTypeSupportedByAskar(keyType)) { + if (isKeyTypeSupportedByAskarForPurpose(keyType, AskarKeyTypePurpose.KeyManagement)) { const algorithm = keyAlgFromString(keyType) // Create key @@ -151,32 +157,81 @@ export abstract class AskarBaseWallet implements Wallet { * @returns A signature for the data */ public async sign({ data, key }: WalletSignOptions): Promise { - let keyEntry: KeyEntryObject | null | undefined + let askarKey: AskarKey | null | undefined + let keyPair: KeyPair | null | undefined + try { - if (isKeyTypeSupportedByAskar(key.keyType)) { + if (isKeyTypeSupportedByAskarForPurpose(key.keyType, AskarKeyTypePurpose.KeyManagement)) { + askarKey = (await this.session.fetchKey({ name: key.publicKeyBase58 }))?.key + } + + // FIXME: remove the custom KeyPair record now that we deprecate Indy SDK. + // We can do this in a migration script + + // Fallback to fetching key from the non-askar storage, this is to handle the case + // where a key wasn't supported at first by the wallet, but now is + if (!askarKey) { + keyPair = await this.retrieveKeyPair(key.publicKeyBase58) + + // If we have the key stored in a custom record, but it is now supported by Askar, + // we 'import' the key into askar storage and remove the custom key record + if (keyPair && isKeyTypeSupportedByAskarForPurpose(keyPair.keyType, AskarKeyTypePurpose.KeyManagement)) { + askarKey = AskarKey.fromSecretBytes({ + secretKey: TypedArrayEncoder.fromBase58(keyPair.privateKeyBase58), + algorithm: keyAlgFromString(keyPair.keyType), + }) + await this.session.insertKey({ + name: key.publicKeyBase58, + key: askarKey, + }) + // Now we can remove it from the custom record as we have imported it into Askar + await this.deleteKeyPair(key.publicKeyBase58) + keyPair = undefined + } + } + + if (!askarKey && !keyPair) { + throw new WalletError('Key entry not found') + } + + // Not all keys are supported for signing + if (isKeyTypeSupportedByAskarForPurpose(key.keyType, AskarKeyTypePurpose.Signing)) { if (!TypedArrayEncoder.isTypedArray(data)) { throw new WalletError(`Currently not supporting signing of multiple messages`) } - keyEntry = await this.session.fetchKey({ name: key.publicKeyBase58 }) - if (!keyEntry) { + askarKey = + askarKey ?? + (keyPair + ? AskarKey.fromSecretBytes({ + secretKey: TypedArrayEncoder.fromBase58(keyPair.privateKeyBase58), + algorithm: keyAlgFromString(keyPair.keyType), + }) + : undefined) + + if (!askarKey) { throw new WalletError('Key entry not found') } - const signed = keyEntry.key.signMessage({ message: data as Buffer }) - - keyEntry.key.handle.free() - + const signed = askarKey.signMessage({ message: data as Buffer }) return Buffer.from(signed) } else { // Check if there is a signing key provider for the specified key type. if (this.signingKeyProviderRegistry.hasProviderForKeyType(key.keyType)) { const signingKeyProvider = this.signingKeyProviderRegistry.getProviderForKeyType(key.keyType) - const keyPair = await this.retrieveKeyPair(key.publicKeyBase58) + // It could be that askar supports storing the key, but can't sign with it + // (in case of bls) + const privateKeyBase58 = + keyPair?.privateKeyBase58 ?? + (askarKey?.secretBytes ? TypedArrayEncoder.toBase58(askarKey.secretBytes) : undefined) + + if (!privateKeyBase58) { + throw new WalletError('Key entry not found') + } const signed = await signingKeyProvider.sign({ data, - privateKeyBase58: keyPair.privateKeyBase58, + privateKeyBase58: privateKeyBase58, publicKeyBase58: key.publicKeyBase58, }) @@ -185,11 +240,12 @@ export abstract class AskarBaseWallet implements Wallet { throw new WalletError(`Unsupported keyType: ${key.keyType}`) } } catch (error) { - keyEntry?.key.handle.free() if (!isError(error)) { throw new AriesFrameworkError('Attempted to throw error, but it was not of type Error', { cause: error }) } throw new WalletError(`Error signing data with verkey ${key.publicKeyBase58}. ${error.message}`, { cause: error }) + } finally { + askarKey?.handle.free() } } @@ -208,7 +264,7 @@ export abstract class AskarBaseWallet implements Wallet { public async verify({ data, key, signature }: WalletVerifyOptions): Promise { let askarKey: AskarKey | undefined try { - if (isKeyTypeSupportedByAskar(key.keyType)) { + if (isKeyTypeSupportedByAskarForPurpose(key.keyType, AskarKeyTypePurpose.Signing)) { if (!TypedArrayEncoder.isTypedArray(data)) { throw new WalletError(`Currently not supporting verification of multiple messages`) } @@ -220,19 +276,17 @@ export abstract class AskarBaseWallet implements Wallet { const verified = askarKey.verifySignature({ message: data as Buffer, signature }) askarKey.handle.free() return verified - } else { + } else if (this.signingKeyProviderRegistry.hasProviderForKeyType(key.keyType)) { // Check if there is a signing key provider for the specified key type. - if (this.signingKeyProviderRegistry.hasProviderForKeyType(key.keyType)) { - const signingKeyProvider = this.signingKeyProviderRegistry.getProviderForKeyType(key.keyType) - - const signed = await signingKeyProvider.verify({ - data, - signature, - publicKeyBase58: key.publicKeyBase58, - }) + const signingKeyProvider = this.signingKeyProviderRegistry.getProviderForKeyType(key.keyType) + const signed = await signingKeyProvider.verify({ + data, + signature, + publicKeyBase58: key.publicKeyBase58, + }) - return signed - } + return signed + } else { throw new WalletError(`Unsupported keyType: ${key.keyType}`) } } catch (error) { @@ -320,20 +374,26 @@ export abstract class AskarBaseWallet implements Wallet { } } - private async retrieveKeyPair(publicKeyBase58: string): Promise { + private async retrieveKeyPair(publicKeyBase58: string): Promise { try { const entryObject = await this.session.fetch({ category: 'KeyPairRecord', name: `key-${publicKeyBase58}` }) - if (entryObject?.value) { - return JsonEncoder.fromString(entryObject?.value as string) as KeyPair - } else { - throw new WalletError(`No content found for record with public key: ${publicKeyBase58}`) - } + if (!entryObject) return null + + return JsonEncoder.fromString(entryObject?.value as string) as KeyPair } catch (error) { throw new WalletError('Error retrieving KeyPair record', { cause: error }) } } + private async deleteKeyPair(publicKeyBase58: string): Promise { + try { + await this.session.remove({ category: 'KeyPairRecord', name: `key-${publicKeyBase58}` }) + } catch (error) { + throw new WalletError('Error removing KeyPair record', { cause: error }) + } + } + private async storeKeyPair(keyPair: KeyPair): Promise { try { await this.session.insert({ diff --git a/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts b/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts index 3448d05754..0a6c098624 100644 --- a/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts +++ b/packages/bbs-signatures/tests/bbs-signatures.e2e.test.ts @@ -65,7 +65,6 @@ describeSkipNode18('BBS W3cCredentialService', () => { let agentContext: AgentContext let w3cJsonLdCredentialService: W3cJsonLdCredentialService let w3cCredentialService: W3cCredentialService - const seed = TypedArrayEncoder.fromString('testseed000000000000000000000001') const privateKey = TypedArrayEncoder.fromString('testseed000000000000000000000001') beforeAll(async () => { @@ -130,7 +129,13 @@ describeSkipNode18('BBS W3cCredentialService', () => { let verificationMethod: string beforeAll(async () => { - const key = await wallet.createKey({ keyType: KeyType.Bls12381g2, seed }) + // FIXME: askar doesn't create the same privateKey based on the same seed as when generated used askar BBS library... + // See https://github.com/hyperledger/aries-askar/issues/219 + const key = await wallet.createKey({ + keyType: KeyType.Bls12381g2, + privateKey: TypedArrayEncoder.fromBase58('2szQ7zB4tKLJPsGK3YTp9SNQ6hoWYFG5rGhmgfQM4nb7'), + }) + issuerDidKey = new DidKey(key) verificationMethod = `${issuerDidKey.did}#${issuerDidKey.key.fingerprint}` }) @@ -146,7 +151,7 @@ describeSkipNode18('BBS W3cCredentialService', () => { format: ClaimFormat.LdpVc, credential, proofType: 'BbsBlsSignature2020', - verificationMethod: verificationMethod, + verificationMethod, }) expect(vc).toBeInstanceOf(W3cJsonLdVerifiableCredential) diff --git a/yarn.lock b/yarn.lock index d22e5418e0..6c138fa5ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3121,6 +3121,13 @@ dependencies: "@types/node" "*" +"@types/bn.js@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== + dependencies: + "@types/node" "*" + "@types/body-parser@*": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" From 88416ddebd8dacf594fcf725aa3463c55175e1bb Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Wed, 31 Jan 2024 21:58:50 +0700 Subject: [PATCH 19/19] fix: bbs and askar Signed-off-by: Timo Glastra --- .../tests/bbs-signing-provider.e2e.test.ts | 23 +++++++++++++------ ...proof.credentials.propose-offerBbs.test.ts | 4 +++- .../src/agent/__tests__/MessageSender.test.ts | 1 + 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts b/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts index 4f9662406b..6b8515aed0 100644 --- a/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts +++ b/packages/bbs-signatures/tests/bbs-signing-provider.e2e.test.ts @@ -36,15 +36,24 @@ describeSkipNode18('BBS Signing Provider', () => { }) test('Create bls12381g2 keypair', async () => { - await expect(wallet.createKey({ seed, keyType: KeyType.Bls12381g2 })).resolves.toMatchObject({ - publicKeyBase58: - '25TvGExLTWRTgn9h2wZuohrQmmLafXiacY4dhv66wcbY8pLbuNTBRMTgWVcPKh2wsEyrRPmnhLdc4C7LEcJ2seoxzBkoydJEdQD8aqg5dw8wesBTS9Twg8EjuFG1WPRAiERd', - keyType: KeyType.Bls12381g2, - }) + const key = await wallet.createKey({ seed, keyType: KeyType.Bls12381g2 }) + expect(key.keyType).toStrictEqual(KeyType.Bls12381g2) + expect(key.publicKeyBase58).toStrictEqual( + 'yVLZ92FeZ3AYco43LXtJgtM8kUD1WPUyQPw4VwxZ1iYSak85GYGSJwURhVJM4R6ASRGuM9vjjSU91pKbaqTWQgLjPJjFuK8HdDmAHi3thYun9QUGjarrK7BzC11LurcpYqD' + ) }) - test('Fail to create bls12381g1g2 keypair', async () => { - await expect(wallet.createKey({ seed, keyType: KeyType.Bls12381g1g2 })).rejects.toThrowError(WalletError) + test('Fail to sign with bls12381g1g2 keypair', async () => { + const key = await wallet.createKey({ seed, keyType: KeyType.Bls12381g1g2 }) + + await expect( + wallet.sign({ + data: message, + key, + }) + ).rejects.toThrow( + 'Error signing data with verkey AeAihfn5UFf7y9oesemKE1oLmTwKMRv7fafTepespr3qceF4RUMggAbogkoC8n6rXgtJytq4oGy59DsVHxmNj9WGWwkiRnP3Sz2r924RLVbc2NdP4T7yEPsSFZPsWmLjgnP1vXHpj4bVXNcTmkUmF6mSXinF3HehnQVip14vRFuMzYVxMUh28ofTJzbtUqxMWZQRu. Unsupported keyType: bls12381g1g2' + ) }) test('Create a signature with a bls12381g2 keypair', async () => { diff --git a/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts b/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts index fea00fcc68..f6b1983c15 100644 --- a/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts +++ b/packages/bbs-signatures/tests/v2.ldproof.credentials.propose-offerBbs.test.ts @@ -70,9 +70,11 @@ describeSkipNode18('credentials, BBS+ signature', () => { keyType: KeyType.Ed25519, privateKey: TypedArrayEncoder.fromString('testseed000000000000000000000001'), }) + // FIXME: askar doesn't create the same privateKey based on the same seed as when generated used askar BBS library... + // See https://github.com/hyperledger/aries-askar/issues/219 await faberAgent.context.wallet.createKey({ keyType: KeyType.Bls12381g2, - seed: TypedArrayEncoder.fromString('testseed000000000000000000000001'), + privateKey: TypedArrayEncoder.fromBase58('2szQ7zB4tKLJPsGK3YTp9SNQ6hoWYFG5rGhmgfQM4nb7'), }) }) diff --git a/packages/core/src/agent/__tests__/MessageSender.test.ts b/packages/core/src/agent/__tests__/MessageSender.test.ts index 711e59c14e..4312591684 100644 --- a/packages/core/src/agent/__tests__/MessageSender.test.ts +++ b/packages/core/src/agent/__tests__/MessageSender.test.ts @@ -335,6 +335,7 @@ describe('MessageSender', () => { transportServiceFindSessionByIdMock.mockReturnValue(session) messageSender.registerOutboundTransport(outboundTransport) const sendMessageSpy = jest.spyOn(outboundTransport, 'sendMessage') + // @ts-ignore const sendMessageToServiceSpy = jest.spyOn(messageSender, 'sendMessageToService') const contextWithSessionId = new OutboundMessageContext(outboundMessageContext.message, {