diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index bef4bf47..a85c2bb1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,13 +2,12 @@ name: Deploy on: push: - branches: ["develop", "master"] + branches: ['develop', 'master'] pull_request: - branches: ["develop", "master"] jobs: cancel-previous: - name: "Cancel Previous Runs" + name: 'Cancel Previous Runs' runs-on: ubuntu-latest timeout-minutes: 3 steps: @@ -26,7 +25,7 @@ jobs: token: ${{ secrets.SECRET_NAME }} - uses: actions/setup-node@v2-beta with: - node-version: "16.10.0" + node-version: '16.10.0' registry-url: https://registry.npmjs.org/ - name: Configure Git diff --git a/docs/api/README.md b/docs/api/README.md index db4d5729..44cf3763 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -58,6 +58,8 @@ Prerelease version npm i iam-client-lib@canary ``` +Some library dependencies require Node.js built-ins. Therefore when library is used in browser make sure they are polyfilled. If application is bundled with Webpack dependencies can be polyfilled with [node-polyfill-webpack-plugin](https://www.npmjs.com/package/node-polyfill-webpack-plugin) + ### Initialization Because of dependencies between modules they should be initialized in right order. This is achieved by accessing module initializer from initialization function of required module. diff --git a/docs/api/classes/DomainsService.md b/docs/api/classes/DomainsService.md index fff75e8e..ca5cce2c 100644 --- a/docs/api/classes/DomainsService.md +++ b/docs/api/classes/DomainsService.md @@ -80,7 +80,7 @@ ___ ### changeOrgOwnership -▸ **changeOrgOwnership**(`__namedParameters`): `Promise`<`undefined` \| { `info`: `string` ; `tx`: `EncodedCall` ; `next`: (`__namedParameters?`: { `retryCheck?`: `boolean` }) => `Promise`<`undefined` \| `TransactionReceipt`\> }[]\> +▸ **changeOrgOwnership**(`__namedParameters`): `Promise`<`undefined` \| [`MulticallTx`](../modules.md#multicalltx)\> changeOrgOwnership @@ -98,7 +98,7 @@ changeOrgOwnership #### Returns -`Promise`<`undefined` \| { `info`: `string` ; `tx`: `EncodedCall` ; `next`: (`__namedParameters?`: { `retryCheck?`: `boolean` }) => `Promise`<`undefined` \| `TransactionReceipt`\> }[]\> +`Promise`<`undefined` \| [`MulticallTx`](../modules.md#multicalltx)\> return array of steps needed to change ownership diff --git a/docs/api/classes/VerifiableCredentialsServiceBase.md b/docs/api/classes/VerifiableCredentialsServiceBase.md index 09b5e031..b6e1a553 100644 --- a/docs/api/classes/VerifiableCredentialsServiceBase.md +++ b/docs/api/classes/VerifiableCredentialsServiceBase.md @@ -6,16 +6,12 @@ - [constructor](VerifiableCredentialsServiceBase.md#constructor) -### Properties - -- [completeIssueCredential](VerifiableCredentialsServiceBase.md#completeissuecredential) -- [prepareIssueCredential](VerifiableCredentialsServiceBase.md#prepareissuecredential) -- [verifyCredential](VerifiableCredentialsServiceBase.md#verifycredential) - ### Methods -- [signVerifiableCredential](VerifiableCredentialsServiceBase.md#signverifiablecredential) -- [verifyVerifiableCredential](VerifiableCredentialsServiceBase.md#verifyverifiablecredential) +- [createPresentation](VerifiableCredentialsServiceBase.md#createpresentation) +- [createRoleVC](VerifiableCredentialsServiceBase.md#createrolevc) +- [createVerifiablePresentation](VerifiableCredentialsServiceBase.md#createverifiablepresentation) +- [verify](VerifiableCredentialsServiceBase.md#verify) - [create](VerifiableCredentialsServiceBase.md#create) ## Constructors @@ -30,116 +26,79 @@ | :------ | :------ | | `_signerService` | [`SignerService`](SignerService.md) | -## Properties - -### completeIssueCredential - -• `Abstract` **completeIssueCredential**: (`credential`: `string`, `preparation`: `string`, `signature`: `string`) => `Promise`<`string`\> +## Methods -#### Type declaration +### createPresentation -▸ (`credential`, `preparation`, `signature`): `Promise`<`string`\> +▸ **createPresentation**(`verifiableCredential`, `options?`): `Presentation` -##### Parameters +#### Parameters | Name | Type | | :------ | :------ | -| `credential` | `string` | -| `preparation` | `string` | -| `signature` | `string` | +| `verifiableCredential` | `VerifiableCredential`<[`RoleCredentialSubject`](../interfaces/RoleCredentialSubject.md)\>[] | +| `options?` | [`CreatePresentationParams`](../interfaces/CreatePresentationParams.md) | -##### Returns +#### Returns -`Promise`<`string`\> +`Presentation` ___ -### prepareIssueCredential +### createRoleVC -• `Abstract` **prepareIssueCredential**: (`credential`: `string`, `linked_data_proof_options`: `string`, `public_key`: `string`) => `Promise`<`string`\> +▸ **createRoleVC**(`credentialParams`, `proofOptions?`): `Promise`<`VerifiableCredential`<[`RoleCredentialSubject`](../interfaces/RoleCredentialSubject.md)\>\> -#### Type declaration - -▸ (`credential`, `linked_data_proof_options`, `public_key`): `Promise`<`string`\> - -##### Parameters +#### Parameters | Name | Type | | :------ | :------ | -| `credential` | `string` | -| `linked_data_proof_options` | `string` | -| `public_key` | `string` | +| `credentialParams` | [`RoleCredentialSubjectParams`](../interfaces/RoleCredentialSubjectParams.md) | +| `proofOptions?` | [`ProofOptions`](../interfaces/ProofOptions.md) | -##### Returns +#### Returns -`Promise`<`string`\> +`Promise`<`VerifiableCredential`<[`RoleCredentialSubject`](../interfaces/RoleCredentialSubject.md)\>\> ___ -### verifyCredential - -• `Abstract` **verifyCredential**: (`vc`: `string`, `proof_options`: `string`) => `Promise`<`string`\> - -#### Type declaration - -▸ (`vc`, `proof_options`): `Promise`<`string`\> +### createVerifiablePresentation -##### Parameters - -| Name | Type | -| :------ | :------ | -| `vc` | `string` | -| `proof_options` | `string` | - -##### Returns - -`Promise`<`string`\> - -## Methods - -### signVerifiableCredential - -▸ **signVerifiableCredential**<`T`\>(`credential`, `options?`): `Promise`<[`SignedVerifiableCredential`](../interfaces/SignedVerifiableCredential.md)<`T`\>\> - -#### Type parameters - -| Name | -| :------ | -| `T` | +▸ **createVerifiablePresentation**(`verifiableCredential`, `options?`): `Promise`<`VerifiablePresentation`\> #### Parameters | Name | Type | | :------ | :------ | -| `credential` | [`VerifiableCredential`](../interfaces/VerifiableCredential.md)<`T`\> | -| `options?` | [`SignVerifiableCredentialOptions`](../interfaces/SignVerifiableCredentialOptions.md) | +| `verifiableCredential` | `VerifiableCredential`<[`RoleCredentialSubject`](../interfaces/RoleCredentialSubject.md)\>[] | +| `options?` | [`ProofOptions`](../interfaces/ProofOptions.md) | #### Returns -`Promise`<[`SignedVerifiableCredential`](../interfaces/SignedVerifiableCredential.md)<`T`\>\> +`Promise`<`VerifiablePresentation`\> ___ -### verifyVerifiableCredential +### verify -▸ **verifyVerifiableCredential**<`T`\>(`vc`, `options?`): `Promise`<`boolean`\> +▸ **verify**<`T`\>(`vp`, `options?`): `any` #### Type parameters -| Name | -| :------ | -| `T` | +| Name | Type | +| :------ | :------ | +| `T` | extends `ICredentialSubject` | #### Parameters | Name | Type | | :------ | :------ | -| `vc` | [`SignedVerifiableCredential`](../interfaces/SignedVerifiableCredential.md)<`T`\> | -| `options?` | [`VerifyVerifiableCredentialOptions`](../interfaces/VerifyVerifiableCredentialOptions.md) | +| `vp` | `VerifiablePresentation` \| `VerifiableCredential`<`T`\> | +| `options?` | [`ProofOptions`](../interfaces/ProofOptions.md) | #### Returns -`Promise`<`boolean`\> +`any` ___ diff --git a/docs/api/interfaces/CreatePresentationParams.md b/docs/api/interfaces/CreatePresentationParams.md new file mode 100644 index 00000000..802b72c9 --- /dev/null +++ b/docs/api/interfaces/CreatePresentationParams.md @@ -0,0 +1,13 @@ +# Interface: CreatePresentationParams + +## Table of contents + +### Properties + +- [presentationDefinition](CreatePresentationParams.md#presentationdefinition) + +## Properties + +### presentationDefinition + +• `Optional` **presentationDefinition**: `IPresentationDefinition` diff --git a/docs/api/interfaces/IssuerFields.md b/docs/api/interfaces/IssuerFields.md new file mode 100644 index 00000000..b1e56506 --- /dev/null +++ b/docs/api/interfaces/IssuerFields.md @@ -0,0 +1,20 @@ +# Interface: IssuerFields + +## Table of contents + +### Properties + +- [key](IssuerFields.md#key) +- [value](IssuerFields.md#value) + +## Properties + +### key + +• **key**: `string` + +___ + +### value + +• **value**: `string` \| `number` diff --git a/docs/api/interfaces/ProofOptions.md b/docs/api/interfaces/ProofOptions.md new file mode 100644 index 00000000..5f0f429b --- /dev/null +++ b/docs/api/interfaces/ProofOptions.md @@ -0,0 +1,20 @@ +# Interface: ProofOptions + +## Table of contents + +### Properties + +- [proofPurpose](ProofOptions.md#proofpurpose) +- [verificationMethod](ProofOptions.md#verificationmethod) + +## Properties + +### proofPurpose + +• `Optional` **proofPurpose**: `string` + +___ + +### verificationMethod + +• `Optional` **verificationMethod**: `string` diff --git a/docs/api/interfaces/RoleCredentialSubject.md b/docs/api/interfaces/RoleCredentialSubject.md new file mode 100644 index 00000000..ac0e1917 --- /dev/null +++ b/docs/api/interfaces/RoleCredentialSubject.md @@ -0,0 +1,44 @@ +# Interface: RoleCredentialSubject + +## Hierarchy + +- `CredentialSubject` + + ↳ **`RoleCredentialSubject`** + +## Table of contents + +### Properties + +- [id](RoleCredentialSubject.md#id) +- [issuerFields](RoleCredentialSubject.md#issuerfields) +- [role](RoleCredentialSubject.md#role) + +## Properties + +### id + +• **id**: `string` + +#### Overrides + +CredentialSubject.id + +___ + +### issuerFields + +• **issuerFields**: [`IssuerFields`](IssuerFields.md)[] + +___ + +### role + +• **role**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `namespace` | `string` | +| `version` | `string` | diff --git a/docs/api/interfaces/RoleCredentialSubjectParams.md b/docs/api/interfaces/RoleCredentialSubjectParams.md new file mode 100644 index 00000000..b94c079c --- /dev/null +++ b/docs/api/interfaces/RoleCredentialSubjectParams.md @@ -0,0 +1,34 @@ +# Interface: RoleCredentialSubjectParams + +## Table of contents + +### Properties + +- [id](RoleCredentialSubjectParams.md#id) +- [issuerFields](RoleCredentialSubjectParams.md#issuerfields) +- [namespace](RoleCredentialSubjectParams.md#namespace) +- [version](RoleCredentialSubjectParams.md#version) + +## Properties + +### id + +• **id**: `string` + +___ + +### issuerFields + +• `Optional` **issuerFields**: [`IssuerFields`](IssuerFields.md)[] + +___ + +### namespace + +• **namespace**: `string` + +___ + +### version + +• **version**: `string` diff --git a/docs/api/interfaces/SignVerifiableCredentialOptions.md b/docs/api/interfaces/SignVerifiableCredentialOptions.md deleted file mode 100644 index 43f17e86..00000000 --- a/docs/api/interfaces/SignVerifiableCredentialOptions.md +++ /dev/null @@ -1,27 +0,0 @@ -# Interface: SignVerifiableCredentialOptions - -## Table of contents - -### Properties - -- [domain](SignVerifiableCredentialOptions.md#domain) -- [proofPurpose](SignVerifiableCredentialOptions.md#proofpurpose) -- [verificationMethod](SignVerifiableCredentialOptions.md#verificationmethod) - -## Properties - -### domain - -• `Optional` **domain**: `Partial`<`TypedDataDomain`\> - -___ - -### proofPurpose - -• `Optional` **proofPurpose**: `string` - -___ - -### verificationMethod - -• `Optional` **verificationMethod**: `string` diff --git a/docs/api/interfaces/SignedVerifiableCredential.md b/docs/api/interfaces/SignedVerifiableCredential.md deleted file mode 100644 index 2b11a19d..00000000 --- a/docs/api/interfaces/SignedVerifiableCredential.md +++ /dev/null @@ -1,99 +0,0 @@ -# Interface: SignedVerifiableCredential - -## Type parameters - -| Name | -| :------ | -| `T` | - -## Hierarchy - -- [`VerifiableCredential`](VerifiableCredential.md)<`T`\> - - ↳ **`SignedVerifiableCredential`** - -## Table of contents - -### Properties - -- [@context](SignedVerifiableCredential.md#@context) -- [credentialSubject](SignedVerifiableCredential.md#credentialsubject) -- [id](SignedVerifiableCredential.md#id) -- [issuer](SignedVerifiableCredential.md#issuer) -- [proof](SignedVerifiableCredential.md#proof) -- [type](SignedVerifiableCredential.md#type) - -## Properties - -### @context - -• **@context**: `string` \| `string`[] - -#### Inherited from - -[VerifiableCredential](VerifiableCredential.md).[@context](VerifiableCredential.md#@context) - -___ - -### credentialSubject - -• **credentialSubject**: `T` - -#### Inherited from - -[VerifiableCredential](VerifiableCredential.md).[credentialSubject](VerifiableCredential.md#credentialsubject) - -___ - -### id - -• `Optional` **id**: `string` - -#### Inherited from - -[VerifiableCredential](VerifiableCredential.md).[id](VerifiableCredential.md#id) - -___ - -### issuer - -• **issuer**: `string` - -#### Inherited from - -[VerifiableCredential](VerifiableCredential.md).[issuer](VerifiableCredential.md#issuer) - -___ - -### proof - -• **proof**: `Object` - -#### Type declaration - -| Name | Type | -| :------ | :------ | -| `@context` | `string` \| `string`[] | -| `created` | `string` | -| `eip712Domain` | { `domain`: `TypedDataDomain` ; `messageSchema`: { `CredentialSubject`: `TypedDataField`[] ; `EIP712Domain`: `TypedDataField`[] ; `Proof`: `TypedDataField`[] ; `VerifiableCredential`: `TypedDataField`[] } ; `primaryType`: `string` } | -| `eip712Domain.domain` | `TypedDataDomain` | -| `eip712Domain.messageSchema` | { `CredentialSubject`: `TypedDataField`[] ; `EIP712Domain`: `TypedDataField`[] ; `Proof`: `TypedDataField`[] ; `VerifiableCredential`: `TypedDataField`[] } | -| `eip712Domain.messageSchema.CredentialSubject` | `TypedDataField`[] | -| `eip712Domain.messageSchema.EIP712Domain` | `TypedDataField`[] | -| `eip712Domain.messageSchema.Proof` | `TypedDataField`[] | -| `eip712Domain.messageSchema.VerifiableCredential` | `TypedDataField`[] | -| `eip712Domain.primaryType` | `string` | -| `proofPurpose` | `string` | -| `proofValue` | `string` | -| `type` | `string` | -| `verificationMethod` | `string` | - -___ - -### type - -• **type**: `string`[] - -#### Inherited from - -[VerifiableCredential](VerifiableCredential.md).[type](VerifiableCredential.md#type) diff --git a/docs/api/interfaces/VerifiableCredential.md b/docs/api/interfaces/VerifiableCredential.md deleted file mode 100644 index 6566ccf8..00000000 --- a/docs/api/interfaces/VerifiableCredential.md +++ /dev/null @@ -1,53 +0,0 @@ -# Interface: VerifiableCredential - -## Type parameters - -| Name | -| :------ | -| `T` | - -## Hierarchy - -- **`VerifiableCredential`** - - ↳ [`SignedVerifiableCredential`](SignedVerifiableCredential.md) - -## Table of contents - -### Properties - -- [@context](VerifiableCredential.md#@context) -- [credentialSubject](VerifiableCredential.md#credentialsubject) -- [id](VerifiableCredential.md#id) -- [issuer](VerifiableCredential.md#issuer) -- [type](VerifiableCredential.md#type) - -## Properties - -### @context - -• **@context**: `string` \| `string`[] - -___ - -### credentialSubject - -• **credentialSubject**: `T` - -___ - -### id - -• `Optional` **id**: `string` - -___ - -### issuer - -• **issuer**: `string` - -___ - -### type - -• **type**: `string`[] diff --git a/docs/api/interfaces/VerifyVerifiableCredentialOptions.md b/docs/api/interfaces/VerifyVerifiableCredentialOptions.md deleted file mode 100644 index fecc4b11..00000000 --- a/docs/api/interfaces/VerifyVerifiableCredentialOptions.md +++ /dev/null @@ -1,20 +0,0 @@ -# Interface: VerifyVerifiableCredentialOptions - -## Table of contents - -### Properties - -- [proofPurpose](VerifyVerifiableCredentialOptions.md#proofpurpose) -- [verificationMethod](VerifyVerifiableCredentialOptions.md#verificationmethod) - -## Properties - -### proofPurpose - -• `Optional` **proofPurpose**: `string` - -___ - -### verificationMethod - -• `Optional` **verificationMethod**: `string` diff --git a/docs/api/modules.md b/docs/api/modules.md index f2849689..8f6a0626 100644 --- a/docs/api/modules.md +++ b/docs/api/modules.md @@ -47,6 +47,7 @@ - [ChainConfig](interfaces/ChainConfig.md) - [Claim](interfaces/Claim.md) - [ClaimData](interfaces/ClaimData.md) +- [CreatePresentationParams](interfaces/CreatePresentationParams.md) - [IApp](interfaces/IApp.md) - [ICacheClient](interfaces/ICacheClient.md) - [IClaimIssuance](interfaces/IClaimIssuance.md) @@ -56,12 +57,12 @@ - [IOrganization](interfaces/IOrganization.md) - [IPubKeyAndIdentityToken](interfaces/IPubKeyAndIdentityToken.md) - [IRole](interfaces/IRole.md) +- [IssuerFields](interfaces/IssuerFields.md) - [MessagingConfig](interfaces/MessagingConfig.md) - [Profile](interfaces/Profile.md) -- [SignVerifiableCredentialOptions](interfaces/SignVerifiableCredentialOptions.md) -- [SignedVerifiableCredential](interfaces/SignedVerifiableCredential.md) -- [VerifiableCredential](interfaces/VerifiableCredential.md) -- [VerifyVerifiableCredentialOptions](interfaces/VerifyVerifiableCredentialOptions.md) +- [ProofOptions](interfaces/ProofOptions.md) +- [RoleCredentialSubject](interfaces/RoleCredentialSubject.md) +- [RoleCredentialSubjectParams](interfaces/RoleCredentialSubjectParams.md) - [VerifyVerifiableCredentialResults](interfaces/VerifyVerifiableCredentialResults.md) ### Type aliases @@ -71,6 +72,7 @@ - [ChainId](modules.md#chainid) - [ClaimsFilter](modules.md#claimsfilter) - [IssueClaim](modules.md#issueclaim) +- [MulticallTx](modules.md#multicalltx) - [RejectClaim](modules.md#rejectclaim) - [RequestClaim](modules.md#requestclaim) - [Service](modules.md#service) @@ -95,6 +97,9 @@ - [erc712\_type\_hash](modules.md#erc712_type_hash) - [proof\_type\_hash](modules.md#proof_type_hash) - [typedMsgPrefix](modules.md#typedmsgprefix) +- [verifiableCredentialEIP712Types](modules.md#verifiablecredentialeip712types) +- [verifiablePresentationEIP712Types](modules.md#verifiablepresentationeip712types) +- [verifiablePresentationWithCredentialEIP712Types](modules.md#verifiablepresentationwithcredentialeip712types) ### Functions @@ -190,6 +195,12 @@ ___ ___ +### MulticallTx + +Ƭ **MulticallTx**: { `info`: `string` ; `tx`: `EncodedCall` ; `next`: (`opts?`: { `retryCheck?`: `boolean` }) => `Promise`<`undefined` \| `TransactionReceipt`\> }[] + +___ + ### RejectClaim Ƭ **RejectClaim**: `Object` @@ -353,6 +364,60 @@ ___ • `Const` **typedMsgPrefix**: ``"1901"`` +___ + +### verifiableCredentialEIP712Types + +• `Const` **verifiableCredentialEIP712Types**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `CredentialSubject` | { `name`: `string` = 'id'; `type`: `string` = 'string' }[] | +| `EIP712Domain` | `never`[] | +| `EWFRole` | { `name`: `string` = 'namespace'; `type`: `string` = 'string' }[] | +| `IssuerFields` | { `name`: `string` = 'key'; `type`: `string` = 'string' }[] | +| `Proof` | { `name`: `string` = '@context'; `type`: `string` = 'string' }[] | +| `VerifiableCredential` | { `name`: `string` = '@context'; `type`: `string` = 'string[]' }[] | + +___ + +### verifiablePresentationEIP712Types + +• `Const` **verifiablePresentationEIP712Types**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `EIP712Domain` | `never`[] | +| `Proof` | { `name`: `string` = '@context'; `type`: `string` = 'string' }[] | +| `VerifiablePresentation` | { `name`: `string` = '@context'; `type`: `string` = 'string[]' }[] | + +___ + +### verifiablePresentationWithCredentialEIP712Types + +• `Const` **verifiablePresentationWithCredentialEIP712Types**: `Object` + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `CredentialSubject` | { `name`: `string` = 'id'; `type`: `string` = 'string' }[] | +| `EIP712Domain` | `never`[] | +| `EWFRole` | { `name`: `string` = 'namespace'; `type`: `string` = 'string' }[] | +| `IssuerFields` | { `name`: `string` = 'key'; `type`: `string` = 'string' }[] | +| `Proof` | { `name`: `string` = '@context'; `type`: `string` = 'string' }[] | +| `VC712Domain` | { `name`: `string` = 'domain'; `type`: `string` = 'VC712DomainData' }[] | +| `VC712DomainData` | `never`[] | +| `VC712DomainSchema` | { `name`: `string` = 'CredentialSubject'; `type`: `string` = 'VC712DomainTypedDataField[]' }[] | +| `VC712DomainTypedDataField` | { `name`: `string` = 'name'; `type`: `string` = 'string' }[] | +| `VCProof` | { `name`: `string` = '@context'; `type`: `string` = 'string' }[] | +| `VerifiableCredential` | { `name`: `string` = '@context'; `type`: `string` = 'string[]' }[] | +| `VerifiablePresentation` | { `name`: `string` = '@context'; `type`: `string` = 'string[]' }[] | + ## Functions ### addSupportedDID diff --git a/e2e/fixtures/externalVC.ts b/e2e/fixtures/externalVC.ts index 5aec1220..9063e6ea 100644 --- a/e2e/fixtures/externalVC.ts +++ b/e2e/fixtures/externalVC.ts @@ -88,7 +88,7 @@ export const validExampleExternalVC = { }, }; -export const invalidExampleExternalVC = { +export const exampleExternalVCWithInvalidSubjectId = { '@context': ['https://www.w3.org/2018/credentials/v1'], type: ['VerifiableCredential'], credentialSubject: { diff --git a/e2e/verifiable-credentials.service.e2e.ts b/e2e/verifiable-credentials.service.e2e.ts new file mode 100644 index 00000000..408dee7d --- /dev/null +++ b/e2e/verifiable-credentials.service.e2e.ts @@ -0,0 +1,223 @@ +import { Wallet } from 'ethers'; +import { v4 as uuid } from 'uuid'; +import { + exampleExternalVCWithInvalidSubjectId, + validExampleExternalVC, +} from './fixtures'; +import { replenish, rpcUrl, setupENS } from './utils/setup_contracts'; +import { fromPrivateKey } from '../src'; +import { + getVerifiableCredentialsService, + IssuerFields, + VerifiableCredentialsServiceBase, +} from '../src/modules/verifiable-credentials'; + +describe('Verifiable credentials tests', () => { + let verifiableCredentialsService: VerifiableCredentialsServiceBase; + let rootOwnerDid: string; + const rootOwnerWallet = Wallet.createRandom(); + const rootOwnerAddress = rootOwnerWallet.address; + + const createExampleSignedCredential = async ( + issuerFields: IssuerFields[] + ) => { + return await verifiableCredentialsService.createRoleVC({ + id: rootOwnerDid, + namespace: 'test.iam.ewc', + version: '1', + issuerFields, + }); + }; + + beforeEach(async () => { + jest.clearAllMocks(); + await replenish(rootOwnerAddress); + await setupENS(rootOwnerAddress); + const signerService = await fromPrivateKey( + rootOwnerWallet.privateKey, + rpcUrl + ); + + await signerService.publicKeyAndIdentityToken(); + + rootOwnerDid = signerService.didHex; + verifiableCredentialsService = await getVerifiableCredentialsService( + signerService + ); + }); + + describe('Verifiable credentials', () => { + test('should create a VC proof', async () => { + const vc = await createExampleSignedCredential([]); + + expect(vc).toBeDefined(); + expect(vc.proof).toStrictEqual( + expect.objectContaining({ + '@context': 'https://w3id.org/security/suites/eip712sig-2021/v1', + type: 'EthereumEip712Signature2021', + proofPurpose: 'assertionMethod', + proofValue: expect.any(String), + verificationMethod: `${rootOwnerDid}#controller`, + created: expect.any(String), + eip712Domain: expect.anything(), + }) + ); + }); + + test('should verify a valid VC', async () => { + const vc = await createExampleSignedCredential([]); + + expect(vc).toBeDefined(); + + const result = await verifiableCredentialsService.verify(vc); + expect(result).toBe(true); + }); + + test('should create a VC proof with issuer fields', async () => { + const issuerFields = [{ key: 'foo', value: 'bar' }]; + const vc = await createExampleSignedCredential(issuerFields); + + expect(vc).toBeDefined(); + + expect(vc.credentialSubject.issuerFields).toBeDefined(); + expect(vc.credentialSubject.issuerFields).toStrictEqual(issuerFields); + expect(vc.proof).toStrictEqual( + expect.objectContaining({ + '@context': 'https://w3id.org/security/suites/eip712sig-2021/v1', + type: 'EthereumEip712Signature2021', + proofPurpose: 'assertionMethod', + proofValue: expect.any(String), + verificationMethod: `${rootOwnerDid}#controller`, + created: expect.any(String), + eip712Domain: expect.anything(), + }) + ); + }); + + test('should verify a valid VC with issuer fields', async () => { + const vc = await createExampleSignedCredential([ + { key: 'foo', value: 'bar' }, + ]); + + expect(vc).toBeDefined(); + + const result = await verifiableCredentialsService.verify(vc); + expect(result).toBe(true); + }); + + test('should throw an error for invalid VC during verification', async () => { + const vc = await createExampleSignedCredential([]); + + vc.id = 'urn:uuid:' + uuid(); + + expect(vc).toBeDefined(); + + await expect( + verifiableCredentialsService.verify(vc) + ).rejects.toMatchObject({ + message: expect.stringContaining( + 'Verifiable Credential or Presentation is invalid' + ), + }); + }); + + test('should verify valid external VC', async () => { + const isValid = await verifiableCredentialsService.verify( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + validExampleExternalVC as any + ); + + expect(isValid).toBe(true); + }); + + test('should throw an error for invalid external VC', async () => { + await expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + verifiableCredentialsService.verify( + exampleExternalVCWithInvalidSubjectId as never + ) + ).rejects.toMatchObject({ + message: expect.stringContaining( + 'Verifiable Credential or Presentation is invalid' + ), + }); + }); + }); + + describe('Verifiable presentations', () => { + test('should create a unsigned VP', async () => { + const vc = await createExampleSignedCredential([]); + + const vp = await verifiableCredentialsService.createPresentation([vc]); + + expect(vp).toBeDefined(); + expect(vp['proof']).toBeUndefined(); + expect(vp.verifiableCredential).toStrictEqual([vc]); + }); + + test('should create a VP proof', async () => { + const vc = await createExampleSignedCredential([]); + + const vp = + await verifiableCredentialsService.createVerifiablePresentation([vc]); + + expect(vp).toBeDefined(); + expect(vp.proof).toEqual( + expect.objectContaining({ + '@context': 'https://w3id.org/security/suites/eip712sig-2021/v1', + type: 'EthereumEip712Signature2021', + proofPurpose: 'authentication', + proofValue: expect.any(String), + verificationMethod: `${rootOwnerDid}#controller`, + created: expect.any(String), + eip712Domain: expect.any(Object), + }) + ); + }); + + test('should verify a valid VP', async () => { + const vc = await createExampleSignedCredential([]); + const vp = + await verifiableCredentialsService.createVerifiablePresentation([vc]); + + await verifiableCredentialsService.verify(vp); + }); + + test('should verify a valid VP with issuer fields', async () => { + const vc = await createExampleSignedCredential([ + { key: 'foo', value: 'bar' }, + ]); + const vp = + await verifiableCredentialsService.createVerifiablePresentation([vc]); + + await verifiableCredentialsService.verify(vp); + }); + + test('should verify a valid VP without verifiable credentials', async () => { + const vp = + await verifiableCredentialsService.createVerifiablePresentation([]); + await verifiableCredentialsService.verify(vp); + }); + + test('should throw an error when one of the VC is invalid', async () => { + const vc = await createExampleSignedCredential([ + { key: 'foo', value: 'bar' }, + ]); + + vc.id = 'urn:uuid:' + uuid(); + + expect(vc).toBeDefined(); + + const vp = + await verifiableCredentialsService.createVerifiablePresentation([vc]); + + await expect( + verifiableCredentialsService.verify(vp) + ).rejects.toMatchObject({ + message: expect.stringContaining( + 'Verifiable Credential or Presentation is invalid' + ), + }); + }); + }); +}); diff --git a/e2e/verifiableCredentials.service.e2e.ts b/e2e/verifiableCredentials.service.e2e.ts deleted file mode 100644 index 6400ef8a..00000000 --- a/e2e/verifiableCredentials.service.e2e.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { Wallet } from 'ethers'; -import { v4 as uuid } from 'uuid'; -import { invalidExampleExternalVC, validExampleExternalVC } from './fixtures'; -import { replenish, rpcUrl, setupENS } from './utils/setup_contracts'; -import { fromPrivateKey } from '../src'; -import { - getVerifiableCredentialsService, - VerifiableCredentialsServiceBase, -} from '../src/modules/verifiableCredentials'; - -describe('Verifiable credentials tests', () => { - let verifiableCredentialsService: VerifiableCredentialsServiceBase; - let rootOwnerDid: string; - const rootOwnerWallet = Wallet.createRandom(); - const rootOwnerAddress = rootOwnerWallet.address; - - beforeEach(async () => { - jest.clearAllMocks(); - await replenish(rootOwnerAddress); - await setupENS(rootOwnerAddress); - const signerService = await fromPrivateKey( - rootOwnerWallet.privateKey, - rpcUrl - ); - - await signerService.publicKeyAndIdentityToken(); - - rootOwnerDid = signerService.didHex; - verifiableCredentialsService = await getVerifiableCredentialsService( - signerService - ); - }); - - test('should create a VC proof', async () => { - const credential = { - '@context': [ - 'https://www.w3.org/2018/credentials/v1', - 'https://tzprofiles.com/2021/ethereum-address-control-v1.jsonld', - ], - id: 'urn:uuid:' + uuid(), - issuer: rootOwnerDid, - issuanceDate: new Date().toISOString(), - type: ['VerifiableCredential', 'EthereumAddressControl'], - credentialSubject: { - address: rootOwnerAddress, - sameAs: rootOwnerDid, - }, - }; - - const vc = await verifiableCredentialsService.signVerifiableCredential( - credential - ); - - expect(vc).toBeDefined(); - expect(vc.proof).toStrictEqual( - expect.objectContaining({ - '@context': 'https://w3id.org/security/suites/eip712sig-2021/v1', - type: 'EthereumEip712Signature2021', - proofPurpose: 'assertionMethod', - proofValue: expect.any(String), - verificationMethod: `${rootOwnerDid}#controller`, - created: expect.any(String), - eip712Domain: expect.anything(), - }) - ); - }); - - test('should verify a valid VC', async () => { - const credential = { - '@context': [ - 'https://www.w3.org/2018/credentials/v1', - 'https://tzprofiles.com/2021/ethereum-address-control-v1.jsonld', - ], - id: 'urn:uuid:' + uuid(), - issuer: rootOwnerDid, - issuanceDate: new Date().toISOString(), - type: ['VerifiableCredential', 'EthereumAddressControl'], - credentialSubject: { - address: rootOwnerAddress, - sameAs: rootOwnerDid, - }, - }; - - const vc = await verifiableCredentialsService.signVerifiableCredential( - credential - ); - - expect(vc).toBeDefined(); - - await verifiableCredentialsService.verifyVerifiableCredential(vc); - }); - - test('should throw an error for invalid VC during verification', async () => { - const credential = { - '@context': [ - 'https://www.w3.org/2018/credentials/v1', - 'https://tzprofiles.com/2021/ethereum-address-control-v1.jsonld', - ], - id: 'urn:uuid:' + uuid(), - issuer: rootOwnerDid, - issuanceDate: new Date().toISOString(), - type: ['VerifiableCredential', 'EthereumAddressControl'], - credentialSubject: { - address: rootOwnerAddress, - sameAs: rootOwnerDid, - }, - }; - - const vc = await verifiableCredentialsService.signVerifiableCredential( - credential - ); - - vc.id = 'urn:uuid:' + uuid(); - - expect(vc).toBeDefined(); - - await expect( - verifiableCredentialsService.verifyVerifiableCredential(vc) - ).rejects.toMatchObject({ - message: expect.stringContaining('Verifiable Credential is invalid'), - }); - }); - - test('should verify valid external VC', async () => { - const isValid = - await verifiableCredentialsService.verifyVerifiableCredential( - validExampleExternalVC - ); - - expect(isValid).toBe(true); - }); - - test('should throw an error for invalid external VC', async () => { - await expect( - verifiableCredentialsService.verifyVerifiableCredential( - invalidExampleExternalVC - ) - ).rejects.toMatchObject({ - message: expect.stringContaining('Verifiable Credential is invalid'), - }); - }); -}); diff --git a/package-lock.json b/package-lock.json index 364cb337..803377c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@energyweb/staking-pool": "^1.0.0-rc.14", "@ensdomains/ens": "^0.6.2", "@ew-did-registry/claims": "^0.6.3-alpha.531.0", + "@ew-did-registry/credentials-interface": "^0.6.3-alpha.531.0", "@ew-did-registry/did": "^0.6.3-alpha.531.0", "@ew-did-registry/did-document": "^0.6.3-alpha.531.0", "@ew-did-registry/did-ethr-resolver": "^0.6.3-alpha.531.0", @@ -26,6 +27,9 @@ "@gnosis.pm/safe-apps-provider": "0.8.0", "@gnosis.pm/safe-apps-sdk": "4.3.0", "@metamask/detect-provider": "^1.2.0", + "@sphereon/pex": "^1.0.2", + "@spruceid/didkit-wasm": "^0.2.1", + "@spruceid/didkit-wasm-node": "^0.2.1", "@walletconnect/ethereum-provider": "1.7.1", "axios": "^0.26.0", "base64url": "^3.0.1", @@ -2559,6 +2563,22 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2592,6 +2612,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -3308,6 +3334,17 @@ "sjcl": "npm:sjcl-complete@1.0.0" } }, + "node_modules/@ew-did-registry/credentials-interface": { + "version": "0.6.3-alpha.531.0", + "resolved": "https://registry.npmjs.org/@ew-did-registry/credentials-interface/-/credentials-interface-0.6.3-alpha.531.0.tgz", + "integrity": "sha512-D4FsZyGpdxA3oyX2uHaPlDMTGbESym//gHX39HTk/d4Kc2OpxmKuHXq+VrkIPSpW+VMuvT7nFoXTvnGHJRxAbQ==", + "dependencies": { + "@ethersproject/abstract-signer": "5.6.0", + "@sphereon/pex": "^1.0.2", + "@types/lodash": "^4.14.181", + "lodash": "^4.17.21" + } + }, "node_modules/@ew-did-registry/did": { "version": "0.6.3-alpha.531.0", "resolved": "https://registry.npmjs.org/@ew-did-registry/did/-/did-0.6.3-alpha.531.0.tgz", @@ -4783,6 +4820,37 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@sphereon/pex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@sphereon/pex/-/pex-1.0.2.tgz", + "integrity": "sha512-uwXZt0CQc/0qVyxEREu4mhz9HhvxGirw0L2pxwXT13mpYS5p61maUaF1Dl/G5tV9XyU1CrhaXKdCw9GRNPgzmA==", + "dependencies": { + "@sphereon/pex-models": "^1.1.0", + "ajv": "^8.8.2", + "ajv-formats": "^2.1.1", + "jsonpath": "^1.1.1", + "nanoid": "^3.1.32", + "string.prototype.matchall": "^4.0.6" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@sphereon/pex-models": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sphereon/pex-models/-/pex-models-1.1.0.tgz", + "integrity": "sha512-kMslWspdqwuXGBFxOPXTAK8HlIHycBR/locYHMlYmyvdnau6bp40JXk2zviBRVOPfe8N3Dv2p5IPAjMk3pT77A==" + }, + "node_modules/@spruceid/didkit-wasm": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@spruceid/didkit-wasm/-/didkit-wasm-0.2.1.tgz", + "integrity": "sha512-Qi0ZVS2vNA6iVwOzfIdyVQSj1Q88DgV0HyjnQGZ84YsrjaxbCSPwyhZs3TBzUGKwvoyiGCvWohYnL0G3BsPEMQ==" + }, + "node_modules/@spruceid/didkit-wasm-node": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@spruceid/didkit-wasm-node/-/didkit-wasm-node-0.2.1.tgz", + "integrity": "sha512-c8e3u5FIRS/2Gf6UHnRPnfRozgKgby4avZzlvIiaJRDVLl1LaX1SE13vEvKV2rAq6NMfZrV4YG908M4uVlT90Q==" + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -4942,8 +5010,7 @@ "node_modules/@types/lodash": { "version": "4.14.181", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.181.tgz", - "integrity": "sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==", - "dev": true + "integrity": "sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==" }, "node_modules/@types/lodash.difference": { "version": "4.5.6", @@ -5641,14 +5708,13 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -5656,6 +5722,22 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/alphanum-sort": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", @@ -7176,9 +7258,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001325", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz", - "integrity": "sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==", + "version": "1.0.30001327", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz", + "integrity": "sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==", "dev": true, "funding": [ { @@ -8863,8 +8945,7 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/deepmerge": { "version": "4.2.2", @@ -9621,6 +9702,22 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9746,6 +9843,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -9854,7 +9957,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -9869,7 +9971,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -10336,8 +10437,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.2.0", @@ -10385,8 +10485,7 @@ "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "node_modules/fastparse": { "version": "1.1.2", @@ -12180,6 +12279,28 @@ "node": ">=6" } }, + "node_modules/har-validator/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/har-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -15955,10 +16076,9 @@ "dev": true }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -16015,6 +16135,28 @@ "node >= 0.2.0" ] }, + "node_modules/jsonpath": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", + "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "dependencies": { + "esprima": "1.2.2", + "static-eval": "2.0.2", + "underscore": "1.12.1" + } + }, + "node_modules/jsonpath/node_modules/esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs=", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -16637,9 +16779,9 @@ } }, "node_modules/lru-cache": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.3.tgz", - "integrity": "sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.0.tgz", + "integrity": "sha512-AmXqneQZL3KZMIgBpaPTeI6pfwh+xQ2vutMsyqOu1TBdEXFZgpG/80wuJ531w2ZN7TI0/oc8CPxzh/DKQudZqg==", "dev": true, "engines": { "node": ">=12" @@ -16723,9 +16865,9 @@ } }, "node_modules/marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.13.tgz", + "integrity": "sha512-lS/ZCa4X0gsRcfWs1eoh6dLnHr9kVH3K1t2X4M/tTtNouhZ7anS1Csb6464VGLQHv8b2Tw1cLeZQs58Jav8Rzw==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -22504,6 +22646,21 @@ "node": ">=0.10.0" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", + "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -22692,9 +22849,9 @@ } }, "node_modules/require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "engines": { "node": ">=0.10.0" } @@ -24356,6 +24513,14 @@ "node": ">=0.10.0" } }, + "node_modules/solc/node_modules/require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/solc/node_modules/require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", @@ -24727,6 +24892,91 @@ "node": ">=8" } }, + "node_modules/static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "dependencies": { + "escodegen": "^1.8.1" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -24942,6 +25192,24 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", @@ -25948,6 +26216,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -26137,7 +26410,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -26433,7 +26705,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -28466,6 +28737,18 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -28490,6 +28773,12 @@ "argparse": "^2.0.1" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -28908,6 +29197,17 @@ "sjcl": "npm:sjcl-complete@1.0.0" } }, + "@ew-did-registry/credentials-interface": { + "version": "0.6.3-alpha.531.0", + "resolved": "https://registry.npmjs.org/@ew-did-registry/credentials-interface/-/credentials-interface-0.6.3-alpha.531.0.tgz", + "integrity": "sha512-D4FsZyGpdxA3oyX2uHaPlDMTGbESym//gHX39HTk/d4Kc2OpxmKuHXq+VrkIPSpW+VMuvT7nFoXTvnGHJRxAbQ==", + "requires": { + "@ethersproject/abstract-signer": "5.6.0", + "@sphereon/pex": "^1.0.2", + "@types/lodash": "^4.14.181", + "lodash": "^4.17.21" + } + }, "@ew-did-registry/did": { "version": "0.6.3-alpha.531.0", "resolved": "https://registry.npmjs.org/@ew-did-registry/did/-/did-0.6.3-alpha.531.0.tgz", @@ -30115,6 +30415,34 @@ "@sinonjs/commons": "^1.7.0" } }, + "@sphereon/pex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@sphereon/pex/-/pex-1.0.2.tgz", + "integrity": "sha512-uwXZt0CQc/0qVyxEREu4mhz9HhvxGirw0L2pxwXT13mpYS5p61maUaF1Dl/G5tV9XyU1CrhaXKdCw9GRNPgzmA==", + "requires": { + "@sphereon/pex-models": "^1.1.0", + "ajv": "^8.8.2", + "ajv-formats": "^2.1.1", + "jsonpath": "^1.1.1", + "nanoid": "^3.1.32", + "string.prototype.matchall": "^4.0.6" + } + }, + "@sphereon/pex-models": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sphereon/pex-models/-/pex-models-1.1.0.tgz", + "integrity": "sha512-kMslWspdqwuXGBFxOPXTAK8HlIHycBR/locYHMlYmyvdnau6bp40JXk2zviBRVOPfe8N3Dv2p5IPAjMk3pT77A==" + }, + "@spruceid/didkit-wasm": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@spruceid/didkit-wasm/-/didkit-wasm-0.2.1.tgz", + "integrity": "sha512-Qi0ZVS2vNA6iVwOzfIdyVQSj1Q88DgV0HyjnQGZ84YsrjaxbCSPwyhZs3TBzUGKwvoyiGCvWohYnL0G3BsPEMQ==" + }, + "@spruceid/didkit-wasm-node": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@spruceid/didkit-wasm-node/-/didkit-wasm-node-0.2.1.tgz", + "integrity": "sha512-c8e3u5FIRS/2Gf6UHnRPnfRozgKgby4avZzlvIiaJRDVLl1LaX1SE13vEvKV2rAq6NMfZrV4YG908M4uVlT90Q==" + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -30263,8 +30591,7 @@ "@types/lodash": { "version": "4.14.181", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.181.tgz", - "integrity": "sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==", - "dev": true + "integrity": "sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==" }, "@types/lodash.difference": { "version": "4.5.6", @@ -30828,17 +31155,24 @@ } }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "requires": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + } + }, "alphanum-sort": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", @@ -32001,9 +32335,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001325", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz", - "integrity": "sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==", + "version": "1.0.30001327", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz", + "integrity": "sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==", "dev": true }, "capture-exit": { @@ -33346,8 +33680,7 @@ "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "deepmerge": { "version": "4.2.2", @@ -33898,6 +34231,18 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -33984,6 +34329,12 @@ "argparse": "^2.0.1" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -34111,8 +34462,7 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "estree-walker": { "version": "1.0.1", @@ -34123,8 +34473,7 @@ "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "eth-ens-namehash": { "version": "2.0.8", @@ -34511,8 +34860,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-diff": { "version": "1.2.0", @@ -34556,8 +34904,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fastparse": { "version": "1.1.2", @@ -35918,6 +36265,26 @@ "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } } }, "hard-rejection": { @@ -38793,10 +39160,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -38844,6 +39210,23 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "jsonpath": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", + "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "requires": { + "esprima": "1.2.2", + "static-eval": "2.0.2", + "underscore": "1.12.1" + }, + "dependencies": { + "esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs=" + } + } + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -39358,9 +39741,9 @@ } }, "lru-cache": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.3.tgz", - "integrity": "sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.0.tgz", + "integrity": "sha512-AmXqneQZL3KZMIgBpaPTeI6pfwh+xQ2vutMsyqOu1TBdEXFZgpG/80wuJ531w2ZN7TI0/oc8CPxzh/DKQudZqg==", "dev": true }, "lunr": { @@ -39423,9 +39806,9 @@ } }, "marked": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", - "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.13.tgz", + "integrity": "sha512-lS/ZCa4X0gsRcfWs1eoh6dLnHr9kVH3K1t2X4M/tTtNouhZ7anS1Csb6464VGLQHv8b2Tw1cLeZQs58Jav8Rzw==", "dev": true }, "marked-terminal": { @@ -43783,6 +44166,15 @@ "safe-regex": "^1.1.0" } }, + "regexp.prototype.flags": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", + "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -43928,9 +44320,9 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, "require-main-filename": { "version": "2.0.0", @@ -45252,6 +45644,11 @@ "read-pkg": "^1.0.0" } }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", @@ -45575,6 +45972,69 @@ } } }, + "static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "requires": { + "escodegen": "^1.8.1" + }, + "dependencies": { + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -45762,6 +46222,21 @@ "strip-ansi": "^6.0.1" } }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + } + }, "string.prototype.trimend": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", @@ -46531,6 +47006,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -46684,7 +47164,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -46928,8 +47407,7 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "wordwrap": { "version": "1.0.0", diff --git a/package.json b/package.json index 6689c099..c38dc121 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@energyweb/staking-pool": "^1.0.0-rc.14", "@ensdomains/ens": "^0.6.2", "@ew-did-registry/claims": "^0.6.3-alpha.531.0", + "@ew-did-registry/credentials-interface": "^0.6.3-alpha.531.0", "@ew-did-registry/did": "^0.6.3-alpha.531.0", "@ew-did-registry/did-document": "^0.6.3-alpha.531.0", "@ew-did-registry/did-ethr-resolver": "^0.6.3-alpha.531.0", @@ -76,6 +77,9 @@ "@gnosis.pm/safe-apps-provider": "0.8.0", "@gnosis.pm/safe-apps-sdk": "4.3.0", "@metamask/detect-provider": "^1.2.0", + "@sphereon/pex": "^1.0.2", + "@spruceid/didkit-wasm": "^0.2.1", + "@spruceid/didkit-wasm-node": "^0.2.1", "@walletconnect/ethereum-provider": "1.7.1", "axios": "^0.26.0", "base64url": "^3.0.1", diff --git a/src/index.ts b/src/index.ts index 8536f910..0dbe8205 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,7 +23,7 @@ export * from './modules/domains'; export * from './modules/messaging'; export * from './modules/signer'; export * from './modules/staking'; -export * from './modules/verifiableCredentials'; +export * from './modules/verifiable-credentials'; export * from './errors'; export * from './config'; export * from './utils'; diff --git a/src/init.ts b/src/init.ts index 492f3f9c..a6fde3da 100644 --- a/src/init.ts +++ b/src/init.ts @@ -22,7 +22,7 @@ import { defaultKmsServerUrl, } from './utils'; import { chainConfigs } from './config'; -import { getVerifiableCredentialsService } from './modules/verifiableCredentials'; +import { getVerifiableCredentialsService } from './modules/verifiable-credentials'; export async function initWithPrivateKeySigner( privateKey: string, diff --git a/src/modules/verifiableCredentials/index.ts b/src/modules/verifiable-credentials/index.ts similarity index 63% rename from src/modules/verifiableCredentials/index.ts rename to src/modules/verifiable-credentials/index.ts index 931c2370..5335b809 100644 --- a/src/modules/verifiableCredentials/index.ts +++ b/src/modules/verifiable-credentials/index.ts @@ -1,8 +1,8 @@ -export * from './verifiableCredentials.types'; -export * from './verifiableCredentialsBase.service'; +export * from './types'; +export * from './verifiable-credentials-base.service'; import { SignerService } from '../signer'; -import { VerifiableCredentialsServiceBase } from './verifiableCredentialsBase.service'; +import { VerifiableCredentialsServiceBase } from './verifiable-credentials-base.service'; import { ExecutionEnvironment, executionEnvironment } from '../../utils'; export const getVerifiableCredentialsService = async ( @@ -10,11 +10,11 @@ export const getVerifiableCredentialsService = async ( ): Promise => { let service: VerifiableCredentialsServiceBase; if (executionEnvironment() === ExecutionEnvironment.NODE) { - service = await import('./verifiableCredentialsNode.service').then( + service = await import('./verifiable-credentials-node.service').then( (module) => module.VerifiableCredentialsServiceNode.create(signerService) ); } else { - service = await import('./verifiableCredentialsWeb.service').then( + service = await import('./verifiable-credentials-web.service').then( (module) => module.VerifiableCredentialsServiceWeb.create(signerService) ); } diff --git a/src/modules/verifiable-credentials/types/eip712.types.ts b/src/modules/verifiable-credentials/types/eip712.types.ts new file mode 100644 index 00000000..a4343fb1 --- /dev/null +++ b/src/modules/verifiable-credentials/types/eip712.types.ts @@ -0,0 +1,92 @@ +export const verifiableCredentialEIP712Types = { + EIP712Domain: [], + VerifiableCredential: [ + { name: '@context', type: 'string[]' }, + { name: 'id', type: 'string' }, + { name: 'type', type: 'string[]' }, + { name: 'issuer', type: 'string' }, + { name: 'issuanceDate', type: 'string' }, + { name: 'credentialSubject', type: 'CredentialSubject' }, + { name: 'proof', type: 'Proof' }, + ], + EWFRole: [ + { name: 'namespace', type: 'string' }, + { name: 'version', type: 'string' }, + ], + IssuerFields: [ + { name: 'key', type: 'string' }, + { name: 'value', type: 'string' }, + ], + CredentialSubject: [ + { name: 'id', type: 'string' }, + { name: 'role', type: 'EWFRole' }, + { name: 'issuerFields', type: 'IssuerFields[]' }, + ], + Proof: [ + { name: '@context', type: 'string' }, + { name: 'verificationMethod', type: 'string' }, + { name: 'created', type: 'string' }, + { name: 'proofPurpose', type: 'string' }, + { name: 'type', type: 'string' }, + ], +}; + +export const verifiablePresentationEIP712Types = { + Proof: verifiableCredentialEIP712Types.Proof, + VerifiablePresentation: [ + { type: 'string[]', name: '@context' }, + { type: 'string', name: 'id' }, + { type: 'string[]', name: 'type' }, + { type: 'string', name: 'holder' }, + { type: 'Proof', name: 'proof' }, + ], + EIP712Domain: [], +}; + +export const verifiablePresentationWithCredentialEIP712Types = { + VC712DomainTypedDataField: [ + { name: 'name', type: 'string' }, + { name: 'type', type: 'string' }, + ], + VC712DomainData: [], + VC712DomainSchema: [ + { name: 'CredentialSubject', type: 'VC712DomainTypedDataField[]' }, + { name: 'EIP712Domain', type: 'VC712DomainTypedDataField[]' }, + { name: 'EWFRole', type: 'VC712DomainTypedDataField[]' }, + { name: 'IssuerFields', type: 'VC712DomainTypedDataField[]' }, + { name: 'Proof', type: 'VC712DomainTypedDataField[]' }, + { name: 'VerifiableCredential', type: 'VC712DomainTypedDataField[]' }, + ], + VC712Domain: [ + { name: 'domain', type: 'VC712DomainData' }, + { name: 'messageSchema', type: 'VC712DomainSchema' }, + { name: 'primaryType', type: 'string' }, + ], + EWFRole: verifiableCredentialEIP712Types.EWFRole, + IssuerFields: verifiableCredentialEIP712Types.IssuerFields, + CredentialSubject: verifiableCredentialEIP712Types.CredentialSubject, + VCProof: [ + ...verifiableCredentialEIP712Types.Proof, + { type: 'string', name: 'proofValue' }, + { type: 'VC712Domain', name: 'eip712Domain' }, + ], + VerifiableCredential: [ + { type: 'string[]', name: '@context' }, + { type: 'string', name: 'id' }, + { type: 'string[]', name: 'type' }, + { type: 'string', name: 'issuer' }, + { type: 'string', name: 'issuanceDate' }, + { type: 'CredentialSubject', name: 'credentialSubject' }, + { type: 'VCProof', name: 'proof' }, + ], + Proof: verifiableCredentialEIP712Types.Proof, + VerifiablePresentation: [ + { type: 'string[]', name: '@context' }, + { type: 'string', name: 'id' }, + { type: 'string[]', name: 'type' }, + { type: 'string', name: 'holder' }, + { type: 'VerifiableCredential[]', name: 'verifiableCredential' }, + { type: 'Proof', name: 'proof' }, + ], + EIP712Domain: [], +}; diff --git a/src/modules/verifiable-credentials/types/index.ts b/src/modules/verifiable-credentials/types/index.ts new file mode 100644 index 00000000..b9b34788 --- /dev/null +++ b/src/modules/verifiable-credentials/types/index.ts @@ -0,0 +1,3 @@ +export * from './eip712.types'; +export * from './role-credential.types'; +export * from './verifiable-credentials.types'; diff --git a/src/modules/verifiable-credentials/types/role-credential.types.ts b/src/modules/verifiable-credentials/types/role-credential.types.ts new file mode 100644 index 00000000..fbd82157 --- /dev/null +++ b/src/modules/verifiable-credentials/types/role-credential.types.ts @@ -0,0 +1,19 @@ +import { CredentialSubject } from '@ew-did-registry/credentials-interface'; + +export interface IssuerFields { + key: string; + value: string | number; +} + +export interface RoleCredentialSubject extends CredentialSubject { + /* + * https://www.w3.org/TR/vc-data-model/#identifiers + */ + id: string; + + role: { + namespace: string; + version: string; + }; + issuerFields: IssuerFields[]; +} diff --git a/src/modules/verifiable-credentials/types/verifiable-credentials.types.ts b/src/modules/verifiable-credentials/types/verifiable-credentials.types.ts new file mode 100644 index 00000000..7228f75e --- /dev/null +++ b/src/modules/verifiable-credentials/types/verifiable-credentials.types.ts @@ -0,0 +1,31 @@ +import { IPresentationDefinition } from '@sphereon/pex'; +import { IssuerFields } from './role-credential.types'; + +/* + * Parameters required to construct the subject for a role credential + * https://www.w3.org/TR/vc-data-model/#credential-subject + */ +export interface RoleCredentialSubjectParams { + /* + * https://www.w3.org/TR/vc-data-model/#identifiers + */ + id: string; + namespace: string; + version: string; + issuerFields?: IssuerFields[]; +} + +export interface ProofOptions { + verificationMethod?: string; + proofPurpose?: string; +} + +export interface CreatePresentationParams { + presentationDefinition?: IPresentationDefinition; +} + +export interface VerifyVerifiableCredentialResults { + checks: string[]; + warnings: string[]; + errors: string[]; +} diff --git a/src/modules/verifiable-credentials/verifiable-credentials-base.service.ts b/src/modules/verifiable-credentials/verifiable-credentials-base.service.ts new file mode 100644 index 00000000..d398b3a5 --- /dev/null +++ b/src/modules/verifiable-credentials/verifiable-credentials-base.service.ts @@ -0,0 +1,315 @@ +import { ICredentialSubject, PEX } from '@sphereon/pex'; +import { v4 as uuid } from 'uuid'; +import { + VerifiableCredential, + VerifiablePresentation, + Credential, + Presentation, +} from '@ew-did-registry/credentials-interface'; +import { SignerService } from '../signer'; +import { + ProofOptions, + VerifyVerifiableCredentialResults, + RoleCredentialSubjectParams, + RoleCredentialSubject, + CreatePresentationParams, + verifiableCredentialEIP712Types, + verifiablePresentationEIP712Types, + verifiablePresentationWithCredentialEIP712Types, +} from './types'; + +export abstract class VerifiableCredentialsServiceBase { + /** + * @param {string} credential - The credential object in JSON format + * @param {string} linked_data_proof_options - The proof options in JSON format + * @param {string} public_key - Information about public key that credential will be signed in JSON format + * @description get prepared data for signing a credential + * @returns {Promise} JSON stringified prepared data (including EIP712 types and credential with proof ready for signing) + */ + protected abstract prepareIssueCredential( + credential: string, + linked_data_proof_options: string, + public_key: string + ): Promise; + + /** + * @param {string} credential - The credential object in JSON format + * @param {string} preparation - Output of `prepareIssueCredential` method + * @param {string} signature - Signature of the credential + * @description get verifiable credential object + * @returns {Promise} verifiable credential object in JSON format + */ + protected abstract completeIssueCredential( + credential: string, + preparation: string, + signature: string + ): Promise; + + /** + * @param {string} vc - The verifiable credential object in JSON format + * @param {string} proof_options - The proof options in JSON format + * @description verify given verifiable credential + * @returns {Promise} object with results of verification in JSON format + */ + protected abstract verifyCredential( + vc: string, + proof_options: string + ): Promise; + + /** + * @param {string} presentation - The presentation object in JSON format + * @param {string} linked_data_proof_options - The proof options in JSON format + * @param {string} public_key - Information about public key that presentation will be signed in JSON format + * @description get prepared data for signing a presentation + * @returns {Promise} JSON stringified prepared data (including EIP712 types and presentation with proof ready for signing) + */ + protected abstract prepareIssuePresentation( + presentation: string, + linked_data_proof_options: string, + public_key: string + ): Promise; + + /** + * @param {string} presentation - The presentation object in JSON format + * @param {string} preparation - Output of `prepareIssuePresentation` method + * @param {string} signature - Signature of the presentation + * @description get verifiable presentation object + * @returns {Promise} verifiable presentation object in JSON format + */ + protected abstract completeIssuePresentation( + presentation: string, + preparation: string, + signature: string + ): Promise; + + /** + * @param {string} vp - The verifiable presentation object in JSON format + * @param {string} proof_options - The proof options in JSON format + * @description verify given verifiable presentation (included verifiable credentials are not verified) + * @returns {Promise} object with results of verification in JSON format + */ + protected abstract verifyPresentation( + vp: string, + proof_options: string + ): Promise; + + constructor(protected readonly _signerService: SignerService) {} + + // * Should be overridden by the implementation + static async create( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + signerService: SignerService + ): Promise { + throw new Error('Not implemented'); + } + + // TODO: Host EWF VC Context and Vocab + private createCredential( + params: RoleCredentialSubjectParams + ): Credential { + const credential = { + '@context': ['https://www.w3.org/2018/credentials/v1'], + id: 'urn:uuid:' + uuid(), + type: ['VerifiableCredential', 'EWFRole'], + issuer: this._signerService.didHex, + issuanceDate: new Date().toISOString(), + credentialSubject: { + role: { + namespace: params.namespace, + version: params.version, + }, + issuerFields: params.issuerFields + ? [ + ...params.issuerFields.map((field) => ({ + ...field, + value: field.value.toString(), + })), + ] + : [], + id: params.id, + }, + }; + return credential; + } + + public async createRoleVC( + credentialParams: RoleCredentialSubjectParams, + proofOptions?: ProofOptions + ): Promise> { + const did = this._signerService.didHex; + + const credentialObject = this.createCredential(credentialParams); + const proofOptionsObject = { + verificationMethod: + proofOptions?.verificationMethod || did + '#controller', + proofPurpose: proofOptions?.proofPurpose || 'assertionMethod', + eip712Domain: { + primaryType: 'VerifiableCredential', + domain: {}, + messageSchema: { + // TODO: generate types from the credential + ...verifiableCredentialEIP712Types, + EIP712Domain: [], + }, + }, + }; + + const keyType = { + kty: 'EC', + crv: 'secp256k1', + alg: 'ES256K-R', + key_ops: ['signTypedData'], + }; + + const stringifyCredential = JSON.stringify(credentialObject); + const preparedVC = await this.prepareIssueCredential( + stringifyCredential, + JSON.stringify(proofOptionsObject), + JSON.stringify(keyType) + ); + const preparation = JSON.parse(preparedVC); + + const typedData = preparation.signingInput; + if (!typedData || !typedData.primaryType) { + throw new Error('Expected EIP-712 TypedData'); + } + + delete typedData.types['EIP712Domain']; + + const signature = await this._signerService.signTypedData( + typedData.domain, + typedData.types, + typedData.message + ); + + const signedCredential = await this.completeIssueCredential( + stringifyCredential, + preparedVC, + signature + ); + + return JSON.parse( + signedCredential + ) as VerifiableCredential; + } + + public createPresentation( + verifiableCredential: VerifiableCredential[], + options?: CreatePresentationParams + ): Presentation { + const did = this._signerService.didHex; + const pex = new PEX(); + + if (options?.presentationDefinition) { + return { + ...pex.presentationFrom( + options.presentationDefinition, + verifiableCredential, + did + ), + id: 'urn:uuid:' + uuid(), + } as Presentation; + } + + return { + '@context': ['https://www.w3.org/2018/credentials/v1'], + id: 'urn:uuid:' + uuid(), + type: ['VerifiablePresentation'], + holder: did, + verifiableCredential, + }; + } + + public async createVerifiablePresentation( + verifiableCredential: VerifiableCredential[], + options?: ProofOptions + ): Promise { + const did = this._signerService.didHex; + + // TODO: generate types from the presentation + const types = verifiableCredential + ? verifiablePresentationWithCredentialEIP712Types + : verifiablePresentationEIP712Types; + + const presentationTemplate = { + ...this.createPresentation(verifiableCredential), + proof: { + '@context': 'https://w3id.org/security/suites/eip712sig-2021/v1', + type: 'EthereumEip712Signature2021', + created: new Date().toISOString(), + verificationMethod: options?.verificationMethod || did + '#controller', + proofPurpose: options?.proofPurpose || 'authentication', + }, + }; + + const signature = await this._signerService.signTypedData( + {}, + { ...types }, + presentationTemplate + ); + + return { + ...presentationTemplate, + proof: { + ...presentationTemplate.proof, + proofValue: signature, + eip712Domain: { + domain: {}, + messageSchema: types, + primaryType: 'VerifiablePresentation', + }, + }, + }; + } + + public async verify( + vp: VerifiablePresentation | VerifiableCredential, + options?: ProofOptions + ) { + let verifyFunc: (vp: string, proof_options: string) => Promise; + switch (vp.type.includes('VerifiablePresentation')) { + case true: + verifyFunc = this.verifyPresentation; + break; + case false: + verifyFunc = this.verifyCredential; + break; + default: + throw new Error( + 'Unsupported verifiable credential or presentation type' + ); + } + + const verifyResultsString = await verifyFunc( + JSON.stringify(vp), + JSON.stringify(options || {}) + ); + + const verifyResults = JSON.parse( + verifyResultsString + ) as VerifyVerifiableCredentialResults; + + if (verifyResults.errors.length) { + throw new Error( + `Verifiable Credential or Presentation is invalid, errors: ${verifyResults.errors.join( + ', ' + )}` + ); + } + + if ( + vp.type.includes('VerifiablePresentation') && + 'verifiableCredential' in vp && + vp.verifiableCredential && + Array.isArray(vp.verifiableCredential) + ) { + const vcsVerification = await Promise.all([ + ...vp.verifiableCredential.map((vc) => this.verify(vc)), + ]); + + return vcsVerification.every(Boolean); + } + + return true; + } +} diff --git a/src/modules/verifiable-credentials/verifiable-credentials-node.service.ts b/src/modules/verifiable-credentials/verifiable-credentials-node.service.ts new file mode 100644 index 00000000..07625537 --- /dev/null +++ b/src/modules/verifiable-credentials/verifiable-credentials-node.service.ts @@ -0,0 +1,61 @@ +import { + prepareIssueCredential, + completeIssueCredential, + verifyCredential, + verifyPresentation, +} from 'didkit-wasm-node'; +import { + prepareIssuePresentation, + completeIssuePresentation, +} from '@spruceid/didkit-wasm-node'; +import { SignerService } from '../signer'; +import { VerifiableCredentialsServiceBase } from './verifiable-credentials-base.service'; + +export class VerifiableCredentialsServiceNode extends VerifiableCredentialsServiceBase { + protected prepareIssueCredential: ( + credential: string, + linked_data_proof_options: string, + public_key: string + ) => Promise; + protected completeIssueCredential: ( + credential: string, + preparation: string, + signature: string + ) => Promise; + protected verifyCredential: ( + vc: string, + proof_options: string + ) => Promise; + + protected prepareIssuePresentation: ( + presentation: string, + linked_data_proof_options: string, + public_key: string + ) => Promise; + protected completeIssuePresentation: ( + presentation: string, + preparation: string, + signature: string + ) => Promise; + protected verifyPresentation: ( + vp: string, + proof_options: string + ) => Promise; + + constructor(_signerService: SignerService) { + super(_signerService); + + this.completeIssueCredential = completeIssueCredential; + this.prepareIssueCredential = prepareIssueCredential; + this.verifyCredential = verifyCredential; + + this.prepareIssuePresentation = prepareIssuePresentation; + this.completeIssuePresentation = completeIssuePresentation; + this.verifyPresentation = verifyPresentation; + } + + static async create(signerService: SignerService) { + const service = new VerifiableCredentialsServiceNode(signerService); + return service; + } +} diff --git a/src/modules/verifiable-credentials/verifiable-credentials-web.service.ts b/src/modules/verifiable-credentials/verifiable-credentials-web.service.ts new file mode 100644 index 00000000..ff73d9e3 --- /dev/null +++ b/src/modules/verifiable-credentials/verifiable-credentials-web.service.ts @@ -0,0 +1,61 @@ +import { + prepareIssueCredential, + completeIssueCredential, + verifyCredential, + verifyPresentation, +} from 'didkit-wasm'; +import { + prepareIssuePresentation, + completeIssuePresentation, +} from '@spruceid/didkit-wasm'; +import { SignerService } from '../signer'; +import { VerifiableCredentialsServiceBase } from './verifiable-credentials-base.service'; + +export class VerifiableCredentialsServiceWeb extends VerifiableCredentialsServiceBase { + protected prepareIssueCredential: ( + credential: string, + linked_data_proof_options: string, + public_key: string + ) => Promise; + protected completeIssueCredential: ( + credential: string, + preparation: string, + signature: string + ) => Promise; + protected verifyCredential: ( + vc: string, + proof_options: string + ) => Promise; + + protected prepareIssuePresentation: ( + presentation: string, + linked_data_proof_options: string, + public_key: string + ) => Promise; + protected completeIssuePresentation: ( + presentation: string, + preparation: string, + signature: string + ) => Promise; + protected verifyPresentation: ( + vp: string, + proof_options: string + ) => Promise; + + constructor(_signerService: SignerService) { + super(_signerService); + + this.completeIssueCredential = completeIssueCredential; + this.prepareIssueCredential = prepareIssueCredential; + this.verifyCredential = verifyCredential; + + this.prepareIssuePresentation = prepareIssuePresentation; + this.completeIssuePresentation = completeIssuePresentation; + this.verifyPresentation = verifyPresentation; + } + + static async create(signerService: SignerService) { + const service = new VerifiableCredentialsServiceWeb(signerService); + return service; + } +} diff --git a/src/modules/verifiableCredentials/verifiableCredentials.types.ts b/src/modules/verifiableCredentials/verifiableCredentials.types.ts deleted file mode 100644 index 626a63be..00000000 --- a/src/modules/verifiableCredentials/verifiableCredentials.types.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { - TypedDataDomain, - TypedDataField, -} from '@ethersproject/abstract-signer'; - -export interface VerifiableCredential { - '@context': string | string[]; - id?: string; - issuer: string; - type: string[]; - credentialSubject: T; -} - -export interface SignedVerifiableCredential extends VerifiableCredential { - proof: { - '@context': string | string[]; - type: string; - proofPurpose: string; - proofValue: string; - verificationMethod: string; - created: string; - eip712Domain: { - domain: TypedDataDomain; - messageSchema: { - CredentialSubject: TypedDataField[]; - EIP712Domain: TypedDataField[]; - Proof: TypedDataField[]; - VerifiableCredential: TypedDataField[]; - }; - primaryType: string; - }; - }; -} - -export interface SignVerifiableCredentialOptions { - verificationMethod?: string; - proofPurpose?: string; - domain?: Partial; -} - -export interface VerifyVerifiableCredentialOptions { - proofPurpose?: string; - verificationMethod?: string; -} - -export interface VerifyVerifiableCredentialResults { - checks: string[]; - warnings: string[]; - errors: string[]; -} diff --git a/src/modules/verifiableCredentials/verifiableCredentialsBase.service.ts b/src/modules/verifiableCredentials/verifiableCredentialsBase.service.ts deleted file mode 100644 index 85800163..00000000 --- a/src/modules/verifiableCredentials/verifiableCredentialsBase.service.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { SignerService } from '../signer'; -import { - SignedVerifiableCredential, - SignVerifiableCredentialOptions, - VerifiableCredential, - VerifyVerifiableCredentialOptions, - VerifyVerifiableCredentialResults, -} from './verifiableCredentials.types'; - -export abstract class VerifiableCredentialsServiceBase { - abstract prepareIssueCredential: ( - credential: string, - linked_data_proof_options: string, - public_key: string - ) => Promise; - abstract completeIssueCredential: ( - credential: string, - preparation: string, - signature: string - ) => Promise; - abstract verifyCredential: ( - vc: string, - proof_options: string - ) => Promise; - - constructor(protected readonly _signerService: SignerService) {} - - static async create( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - signerService: SignerService - ): Promise { - throw new Error('Not implemented'); - } - - public async verifyVerifiableCredential( - vc: SignedVerifiableCredential, - options?: VerifyVerifiableCredentialOptions - ) { - const verifyResultsString = await this.verifyCredential( - JSON.stringify(vc), - JSON.stringify(options || {}) - ); - - const verifyResults = JSON.parse( - verifyResultsString - ) as VerifyVerifiableCredentialResults; - - if (verifyResults.errors.length) { - throw new Error( - `Verifiable Credential is invalid, errors: ${verifyResults.errors.join( - ', ' - )}` - ); - } - - return true; - } - - public async signVerifiableCredential( - credential: VerifiableCredential, - options?: SignVerifiableCredentialOptions - ) { - const did = credential.issuer; - - const proofOptions = { - verificationMethod: options?.verificationMethod || did + '#controller', - proofPurpose: options?.proofPurpose || 'assertionMethod', - eip712Domain: { - primaryType: 'VerifiableCredential', - domain: { - name: 'EWF Verifiable Credential', - ...options?.domain, - }, - messageSchema: { - EIP712Domain: [{ name: 'name', type: 'string' }], - VerifiableCredential: [ - { name: '@context', type: 'string[]' }, - { name: 'id', type: 'string' }, - { name: 'type', type: 'string[]' }, - { name: 'issuer', type: 'string' }, - { name: 'issuanceDate', type: 'string' }, - { name: 'credentialSubject', type: 'CredentialSubject' }, - { name: 'proof', type: 'Proof' }, - ], - CredentialSubject: [ - { name: 'address', type: 'string' }, - { name: 'sameAs', type: 'string' }, - ], - Proof: [ - { name: '@context', type: 'string' }, - { name: 'verificationMethod', type: 'string' }, - { name: 'created', type: 'string' }, - { name: 'proofPurpose', type: 'string' }, - { name: 'type', type: 'string' }, - ], - }, - }, - }; - - const keyType = { - kty: 'EC', - crv: 'secp256k1', - alg: 'ES256K-R', - key_ops: ['signTypedData'], - }; - - const stringifyCredential = JSON.stringify(credential); - const preparedVC = await this.prepareIssueCredential( - stringifyCredential, - JSON.stringify(proofOptions), - JSON.stringify(keyType) - ); - const preparation = JSON.parse(preparedVC); - - const typedData = preparation.signingInput; - if (!typedData || !typedData.primaryType) { - throw new Error('Expected EIP-712 TypedData'); - } - - delete typedData.types['EIP712Domain']; - - const signature = await this._signerService.signTypedData( - typedData.domain, - typedData.types, - typedData.message - ); - - const signedCredential = await this.completeIssueCredential( - stringifyCredential, - preparedVC, - signature - ); - - return JSON.parse(signedCredential) as SignedVerifiableCredential; - } -} diff --git a/src/modules/verifiableCredentials/verifiableCredentialsNode.service.ts b/src/modules/verifiableCredentials/verifiableCredentialsNode.service.ts deleted file mode 100644 index 9fe110c7..00000000 --- a/src/modules/verifiableCredentials/verifiableCredentialsNode.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { - prepareIssueCredential, - completeIssueCredential, - verifyCredential, -} from 'didkit-wasm-node'; -import { SignerService } from '../signer'; -import { VerifiableCredentialsServiceBase } from './verifiableCredentialsBase.service'; - -export class VerifiableCredentialsServiceNode extends VerifiableCredentialsServiceBase { - prepareIssueCredential: ( - credential: string, - linked_data_proof_options: string, - public_key: string - ) => Promise; - completeIssueCredential: ( - credential: string, - preparation: string, - signature: string - ) => Promise; - verifyCredential: (vc: string, proof_options: string) => Promise; - - constructor(_signerService: SignerService) { - super(_signerService); - - this.completeIssueCredential = completeIssueCredential; - this.prepareIssueCredential = prepareIssueCredential; - this.verifyCredential = verifyCredential; - } - - static async create(signerService: SignerService) { - const service = new VerifiableCredentialsServiceNode(signerService); - return service; - } -} diff --git a/src/modules/verifiableCredentials/verifiableCredentialsWeb.service.ts b/src/modules/verifiableCredentials/verifiableCredentialsWeb.service.ts deleted file mode 100644 index 58c32b48..00000000 --- a/src/modules/verifiableCredentials/verifiableCredentialsWeb.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { - prepareIssueCredential, - completeIssueCredential, - verifyCredential, -} from 'didkit-wasm'; -import { SignerService } from '../signer'; -import { VerifiableCredentialsServiceBase } from './verifiableCredentialsBase.service'; - -export class VerifiableCredentialsServiceWeb extends VerifiableCredentialsServiceBase { - prepareIssueCredential: ( - credential: string, - linked_data_proof_options: string, - public_key: string - ) => Promise; - completeIssueCredential: ( - credential: string, - preparation: string, - signature: string - ) => Promise; - verifyCredential: (vc: string, proof_options: string) => Promise; - - constructor(_signerService: SignerService) { - super(_signerService); - - this.completeIssueCredential = completeIssueCredential; - this.prepareIssueCredential = prepareIssueCredential; - this.verifyCredential = verifyCredential; - } - - static async create(signerService: SignerService) { - const service = new VerifiableCredentialsServiceWeb(signerService); - return service; - } -} diff --git a/src/utils/updateLegacyIssuers.ts b/src/utils/updateLegacyIssuers.ts index 16007c4c..aeb51e22 100644 --- a/src/utils/updateLegacyIssuers.ts +++ b/src/utils/updateLegacyIssuers.ts @@ -18,15 +18,6 @@ import { SignerT } from '../modules/signer'; const { JsonRpcProvider } = providers; -// TODO: implement this function -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const updateLegacyIssuers = (a: string, b: Wallet, c: number): any[] => { - a; - b; - c; - throw new Error('Method not implemented.'); -}; - /** * @description - Checks that role issuers of all roles under `rootDomain` contains method-specific-id and adds it if missing * `signer` must own `rootDomain` on `targetChain`