Skip to content

Commit

Permalink
feat(anoncreds): add anoncreds API (#1232)
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
  • Loading branch information
TimoGlastra authored Feb 6, 2023
1 parent f1e4937 commit 3a4c5ec
Show file tree
Hide file tree
Showing 44 changed files with 1,370 additions and 80 deletions.
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

0 comments on commit 3a4c5ec

Please sign in to comment.