Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(anoncreds): add anoncreds API #1232

Merged
merged 10 commits into from
Feb 6, 2023
428 changes: 428 additions & 0 deletions packages/anoncreds/src/AnonCredsApi.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/anoncreds/src/AnonCredsApiOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface AnonCredsCreateLinkSecretOptions {
linkSecretId?: string
setAsDefault?: boolean
}
16 changes: 16 additions & 0 deletions packages/anoncreds/src/AnonCredsModule.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import type { AnonCredsModuleConfigOptions } from './AnonCredsModuleConfig'
import type { DependencyManager, Module } from '@aries-framework/core'

import { AnonCredsApi } from './AnonCredsApi'
import { AnonCredsModuleConfig } from './AnonCredsModuleConfig'
import {
AnonCredsCredentialDefinitionPrivateRepository,
AnonCredsKeyCorrectnessProofRepository,
AnonCredsLinkSecretRepository,
} from './repository'
import { AnonCredsCredentialDefinitionRepository } from './repository/AnonCredsCredentialDefinitionRepository'
import { AnonCredsSchemaRepository } from './repository/AnonCredsSchemaRepository'
import { AnonCredsRegistryService } from './services/registry/AnonCredsRegistryService'

/**
* @public
*/
export class AnonCredsModule implements Module {
public readonly config: AnonCredsModuleConfig
public api = AnonCredsApi

public constructor(config: AnonCredsModuleConfigOptions) {
this.config = new AnonCredsModuleConfig(config)
Expand All @@ -19,5 +28,12 @@ export class AnonCredsModule implements Module {
dependencyManager.registerInstance(AnonCredsModuleConfig, this.config)

dependencyManager.registerSingleton(AnonCredsRegistryService)

// Repositories
dependencyManager.registerSingleton(AnonCredsSchemaRepository)
dependencyManager.registerSingleton(AnonCredsCredentialDefinitionRepository)
dependencyManager.registerSingleton(AnonCredsCredentialDefinitionPrivateRepository)
dependencyManager.registerSingleton(AnonCredsKeyCorrectnessProofRepository)
dependencyManager.registerSingleton(AnonCredsLinkSecretRepository)
}
}
14 changes: 13 additions & 1 deletion packages/anoncreds/src/__tests__/AnonCredsModule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import type { DependencyManager } from '@aries-framework/core'

import { AnonCredsModule } from '../AnonCredsModule'
import { AnonCredsModuleConfig } from '../AnonCredsModuleConfig'
import {
AnonCredsSchemaRepository,
AnonCredsCredentialDefinitionRepository,
AnonCredsCredentialDefinitionPrivateRepository,
AnonCredsKeyCorrectnessProofRepository,
AnonCredsLinkSecretRepository,
} from '../repository'
import { AnonCredsRegistryService } from '../services/registry/AnonCredsRegistryService'

const dependencyManager = {
Expand All @@ -19,8 +26,13 @@ describe('AnonCredsModule', () => {
})
anonCredsModule.register(dependencyManager)

expect(dependencyManager.registerSingleton).toHaveBeenCalledTimes(1)
expect(dependencyManager.registerSingleton).toHaveBeenCalledTimes(6)
expect(dependencyManager.registerSingleton).toHaveBeenCalledWith(AnonCredsRegistryService)
expect(dependencyManager.registerSingleton).toHaveBeenCalledWith(AnonCredsSchemaRepository)
expect(dependencyManager.registerSingleton).toHaveBeenCalledWith(AnonCredsCredentialDefinitionRepository)
expect(dependencyManager.registerSingleton).toHaveBeenCalledWith(AnonCredsCredentialDefinitionPrivateRepository)
expect(dependencyManager.registerSingleton).toHaveBeenCalledWith(AnonCredsKeyCorrectnessProofRepository)
expect(dependencyManager.registerSingleton).toHaveBeenCalledWith(AnonCredsLinkSecretRepository)

expect(dependencyManager.registerInstance).toHaveBeenCalledTimes(1)
expect(dependencyManager.registerInstance).toHaveBeenCalledWith(AnonCredsModuleConfig, anonCredsModule.config)
Expand Down
7 changes: 7 additions & 0 deletions packages/anoncreds/src/error/AnonCredsStoreRecordError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { AnonCredsError } from './AnonCredsError'

export class AnonCredsStoreRecordError extends AnonCredsError {
public constructor(message: string, { cause }: { cause?: Error } = {}) {
super(message, { cause })
}
}
1 change: 1 addition & 0 deletions packages/anoncreds/src/error/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './AnonCredsError'
export * from './AnonCredsStoreRecordError'
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe('LegacyIndyCredentialFormatService', () => {
options: {},
})

const credentialDefinition = await anonCredsIssuerService.createCredentialDefinition(
const { credentialDefinition } = await anonCredsIssuerService.createCredentialDefinition(
agentContext,
{
issuerId: indyDid,
Expand Down
4 changes: 4 additions & 0 deletions packages/anoncreds/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export * from './models'
export * from './services'
export * from './error'
export * from './repository'
export { AnonCredsModule } from './AnonCredsModule'
export { AnonCredsModuleConfig, AnonCredsModuleConfigOptions } from './AnonCredsModuleConfig'
export { AnonCredsApi } from './AnonCredsApi'
export { LegacyIndyCredentialFormatService } from './formats/LegacyIndyCredentialFormatService'
export { AnonCredsRegistryService } from './services/registry/AnonCredsRegistryService'
2 changes: 1 addition & 1 deletion packages/anoncreds/src/models/exchange.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface AnonCredsProofRequestRestriction {
export interface AnonCredsProofRequestRestriction {
schema_id?: string
schema_issuer_id?: string
schema_name?: string
Expand Down
2 changes: 1 addition & 1 deletion packages/anoncreds/src/models/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface AnonCredsRevocationRegistryDefinition {
tailsHash: string
}

export interface AnonCredsRevocationList {
export interface AnonCredsRevocationStatusList {
issuerId: string
revRegId: string
revocationList: number[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { TagsBase } from '@aries-framework/core'

import { BaseRecord, utils } from '@aries-framework/core'

export interface AnonCredsCredentialDefinitionPrivateRecordProps {
id?: string
credentialDefinitionId: string
value: Record<string, unknown>
}

export type DefaultAnonCredsCredentialDefinitionPrivateTags = {
credentialDefinitionId: string
}

export class AnonCredsCredentialDefinitionPrivateRecord extends BaseRecord<
DefaultAnonCredsCredentialDefinitionPrivateTags,
TagsBase
> {
public static readonly type = 'AnonCredsCredentialDefinitionPrivateRecord'
public readonly type = AnonCredsCredentialDefinitionPrivateRecord.type

public readonly credentialDefinitionId!: string
public readonly value!: Record<string, unknown> // TODO: Define structure

public constructor(props: AnonCredsCredentialDefinitionPrivateRecordProps) {
super()

if (props) {
this.id = props.id ?? utils.uuid()
this.credentialDefinitionId = props.credentialDefinitionId
this.value = props.value
}
}

public getTags() {
return {
...this._tags,
credentialDefinitionId: this.credentialDefinitionId,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { AgentContext } from '@aries-framework/core'

import { Repository, InjectionSymbols, StorageService, EventEmitter, injectable, inject } from '@aries-framework/core'

import { AnonCredsCredentialDefinitionPrivateRecord } from './AnonCredsCredentialDefinitionPrivateRecord'

@injectable()
export class AnonCredsCredentialDefinitionPrivateRepository extends Repository<AnonCredsCredentialDefinitionPrivateRecord> {
public constructor(
@inject(InjectionSymbols.StorageService) storageService: StorageService<AnonCredsCredentialDefinitionPrivateRecord>,
eventEmitter: EventEmitter
) {
super(AnonCredsCredentialDefinitionPrivateRecord, storageService, eventEmitter)
}

public async getByCredentialDefinitionId(agentContext: AgentContext, credentialDefinitionId: string) {
return this.getSingleByQuery(agentContext, { credentialDefinitionId })
}

public async findByCredentialDefinitionId(agentContext: AgentContext, credentialDefinitionId: string) {
return this.findSingleByQuery(agentContext, { credentialDefinitionId })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { AnonCredsCredentialDefinitionRecordMetadata } from './anonCredsCredentialDefinitionRecordMetadataTypes'
import type { AnonCredsCredentialDefinition } from '../models'
import type { TagsBase } from '@aries-framework/core'

import { BaseRecord, utils } from '@aries-framework/core'

export interface AnonCredsCredentialDefinitionRecordProps {
id?: string
credentialDefinitionId: string
credentialDefinition: AnonCredsCredentialDefinition
}

export type DefaultAnonCredsCredentialDefinitionTags = {
schemaId: string
credentialDefinitionId: string
issuerId: string
tag: string
}

export class AnonCredsCredentialDefinitionRecord extends BaseRecord<
DefaultAnonCredsCredentialDefinitionTags,
TagsBase,
AnonCredsCredentialDefinitionRecordMetadata
> {
public static readonly type = 'AnonCredsCredentialDefinitionRecord'
public readonly type = AnonCredsCredentialDefinitionRecord.type

public readonly credentialDefinitionId!: string
public readonly credentialDefinition!: AnonCredsCredentialDefinition

public constructor(props: AnonCredsCredentialDefinitionRecordProps) {
super()

if (props) {
this.id = props.id ?? utils.uuid()
this.credentialDefinitionId = props.credentialDefinitionId
this.credentialDefinition = props.credentialDefinition
}
}

public getTags() {
return {
...this._tags,
credentialDefinitionId: this.credentialDefinitionId,
schemaId: this.credentialDefinition.schemaId,
issuerId: this.credentialDefinition.issuerId,
tag: this.credentialDefinition.tag,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { AgentContext } from '@aries-framework/core'

import { Repository, InjectionSymbols, StorageService, EventEmitter, injectable, inject } from '@aries-framework/core'

import { AnonCredsCredentialDefinitionRecord } from './AnonCredsCredentialDefinitionRecord'

@injectable()
export class AnonCredsCredentialDefinitionRepository extends Repository<AnonCredsCredentialDefinitionRecord> {
public constructor(
@inject(InjectionSymbols.StorageService) storageService: StorageService<AnonCredsCredentialDefinitionRecord>,
eventEmitter: EventEmitter
) {
super(AnonCredsCredentialDefinitionRecord, storageService, eventEmitter)
}

public async getByCredentialDefinitionId(agentContext: AgentContext, credentialDefinitionId: string) {
return this.getSingleByQuery(agentContext, { credentialDefinitionId })
}

public async findByCredentialDefinitionId(agentContext: AgentContext, credentialDefinitionId: string) {
return this.findSingleByQuery(agentContext, { credentialDefinitionId })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { TagsBase } from '@aries-framework/core'

import { BaseRecord, utils } from '@aries-framework/core'

export interface AnonCredsKeyCorrectnessProofRecordProps {
id?: string
credentialDefinitionId: string
value: Record<string, unknown>
}

export type DefaultAnonCredsKeyCorrectnessProofPrivateTags = {
credentialDefinitionId: string
}

export class AnonCredsKeyCorrectnessProofRecord extends BaseRecord<
DefaultAnonCredsKeyCorrectnessProofPrivateTags,
TagsBase
> {
public static readonly type = 'AnonCredsKeyCorrectnessProofRecord'
public readonly type = AnonCredsKeyCorrectnessProofRecord.type

public readonly credentialDefinitionId!: string
public readonly value!: Record<string, unknown> // TODO: Define structure

public constructor(props: AnonCredsKeyCorrectnessProofRecordProps) {
super()

if (props) {
this.id = props.id ?? utils.uuid()
this.credentialDefinitionId = props.credentialDefinitionId
this.value = props.value
}
}

public getTags() {
return {
...this._tags,
credentialDefinitionId: this.credentialDefinitionId,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { AgentContext } from '@aries-framework/core'

import { Repository, InjectionSymbols, StorageService, EventEmitter, injectable, inject } from '@aries-framework/core'

import { AnonCredsKeyCorrectnessProofRecord } from './AnonCredsKeyCorrectnessProofRecord'

@injectable()
export class AnonCredsKeyCorrectnessProofRepository extends Repository<AnonCredsKeyCorrectnessProofRecord> {
public constructor(
@inject(InjectionSymbols.StorageService) storageService: StorageService<AnonCredsKeyCorrectnessProofRecord>,
eventEmitter: EventEmitter
) {
super(AnonCredsKeyCorrectnessProofRecord, storageService, eventEmitter)
}

public async getByCredentialDefinitionId(agentContext: AgentContext, credentialDefinitionId: string) {
return this.getSingleByQuery(agentContext, { credentialDefinitionId })
}

public async findByCredentialDefinitionId(agentContext: AgentContext, credentialDefinitionId: string) {
return this.findSingleByQuery(agentContext, { credentialDefinitionId })
}
}
42 changes: 42 additions & 0 deletions packages/anoncreds/src/repository/AnonCredsLinkSecretRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { TagsBase } from '@aries-framework/core'

import { BaseRecord, utils } from '@aries-framework/core'

export interface AnonCredsLinkSecretRecordProps {
id?: string
linkSecretId: string
value?: string // If value is not provided, only reference to link secret is stored in regular storage
}

export type DefaultAnonCredsLinkSecretTags = {
linkSecretId: string
}

export type CustomAnonCredsLinkSecretTags = TagsBase & {
isDefault?: boolean
}

export class AnonCredsLinkSecretRecord extends BaseRecord<DefaultAnonCredsLinkSecretTags, TagsBase> {
public static readonly type = 'AnonCredsLinkSecretRecord'
public readonly type = AnonCredsLinkSecretRecord.type

public readonly linkSecretId!: string
public readonly value?: string

public constructor(props: AnonCredsLinkSecretRecordProps) {
super()

if (props) {
this.id = props.id ?? utils.uuid()
this.linkSecretId = props.linkSecretId
this.value = props.value
}
}

public getTags() {
return {
...this._tags,
linkSecretId: this.linkSecretId,
}
}
}
31 changes: 31 additions & 0 deletions packages/anoncreds/src/repository/AnonCredsLinkSecretRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { AgentContext } from '@aries-framework/core'

import { Repository, InjectionSymbols, StorageService, EventEmitter, injectable, inject } from '@aries-framework/core'

import { AnonCredsLinkSecretRecord } from './AnonCredsLinkSecretRecord'

@injectable()
export class AnonCredsLinkSecretRepository extends Repository<AnonCredsLinkSecretRecord> {
public constructor(
@inject(InjectionSymbols.StorageService) storageService: StorageService<AnonCredsLinkSecretRecord>,
eventEmitter: EventEmitter
) {
super(AnonCredsLinkSecretRecord, storageService, eventEmitter)
}

public async getDefault(agentContext: AgentContext) {
return this.getSingleByQuery(agentContext, { isDefault: true })
}

public async findDefault(agentContext: AgentContext) {
return this.findSingleByQuery(agentContext, { isDefault: true })
}

public async getByLinkSecretId(agentContext: AgentContext, linkSecretId: string) {
return this.getSingleByQuery(agentContext, { linkSecretId })
}

public async findByLinkSecretId(agentContext: AgentContext, linkSecretId: string) {
return this.findSingleByQuery(agentContext, { linkSecretId })
}
}
Loading