Skip to content

Commit

Permalink
feat: Proof Negotiation
Browse files Browse the repository at this point in the history
Signed-off-by: Łukasz Przytuła <lprzytula@gmail.com>
  • Loading branch information
Przytua committed Dec 1, 2022
1 parent c4e9679 commit 1188d03
Show file tree
Hide file tree
Showing 8 changed files with 2,568 additions and 2 deletions.
97 changes: 96 additions & 1 deletion packages/core/src/modules/proofs/ProofsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import type {
ProposeProofOptions,
RequestProofOptions,
ProofServiceMap,
ProposeProofAsResponseOptions,
RequestProofAsResponseOptions,
} from './ProofsApiOptions'
import type { ProofFormat } from './formats/ProofFormat'
import type { IndyProofFormat } from './formats/indy/IndyProofFormat'
Expand All @@ -28,6 +30,7 @@ import type {
FormatRetrievedCredentialOptions,
DeleteProofOptions,
GetFormatDataReturn,
CreateProposalAsResponseOptions,
} from './models/ProofServiceOptions'
import type { ProofExchangeRecord } from './repository/ProofExchangeRecord'

Expand Down Expand Up @@ -57,11 +60,13 @@ export interface ProofsApi<PFs extends ProofFormat[], PSs extends ProofService<P
// Proposal methods
proposeProof(options: ProposeProofOptions<PFs, PSs>): Promise<ProofExchangeRecord>
acceptProposal(options: AcceptProofProposalOptions): Promise<ProofExchangeRecord>
negotiateProposal(options: RequestProofAsResponseOptions<PFs>): Promise<ProofExchangeRecord>

// Request methods
requestProof(options: RequestProofOptions<PFs, PSs>): Promise<ProofExchangeRecord>
acceptRequest(options: AcceptProofPresentationOptions<PFs>): Promise<ProofExchangeRecord>
declineRequest(proofRecordId: string): Promise<ProofExchangeRecord>
negotiateRequest(options: ProposeProofAsResponseOptions<PFs>): Promise<ProofExchangeRecord>

// Present
acceptPresentation(proofRecordId: string): Promise<ProofExchangeRecord>
Expand Down Expand Up @@ -204,13 +209,14 @@ export class ProofsApi<
*/
public async acceptProposal(options: AcceptProofProposalOptions): Promise<ProofExchangeRecord> {
const { proofRecordId } = options

const proofRecord = await this.getById(proofRecordId)

const service = this.getService(proofRecord.protocolVersion)

if (!proofRecord.connectionId) {
throw new AriesFrameworkError(
`No connectionId found for credential record '${proofRecord.id}'. Connection-less issuance does not support presentation proposal or negotiation.`
`No connectionId found for proof record '${proofRecord.id}'. Connection-less issuance does not support presentation proposal or negotiation.`
)
}

Expand Down Expand Up @@ -248,6 +254,50 @@ export class ProofsApi<
return proofRecord
}

/**
* Answer with a new presentation request in response to received presentation proposal message
* to the connection associated with the proof record.
*
* @param options multiple properties like proof record id, proof formats to accept requested credentials object
* specifying which credentials to use for the proof
* @returns Proof record associated with the sent request message
*/
public async negotiateProposal(options: RequestProofAsResponseOptions<PFs>): Promise<ProofExchangeRecord> {
const { proofRecordId } = options

const proofRecord = await this.getById(proofRecordId)

const service = this.getService(proofRecord.protocolVersion)

if (!proofRecord.connectionId) {
throw new AriesFrameworkError(
`No connectionId found for proof record '${proofRecord.id}'. Connection-less issuance does not support negotiation.`
)
}

const connection = await this.connectionService.getById(this.agentContext, proofRecord.connectionId)

// Assert
connection.assertReady()

const requestOptions: CreateRequestAsResponseOptions<PFs> = {
proofRecord,
proofFormats: options.proofFormats,
autoAcceptProof: options.autoAcceptProof,
comment: options.comment,
}
const { message } = await service.createRequestAsResponse(this.agentContext, requestOptions)

const outboundMessageContext = new OutboundMessageContext(message, {
agentContext: this.agentContext,
connection,
associatedRecord: proofRecord,
})
await this.messageSender.sendMessage(outboundMessageContext)

return proofRecord
}

/**
* Initiate a new presentation exchange as verifier by sending a presentation request message
* to the connection with the specified connection id
Expand Down Expand Up @@ -398,6 +448,51 @@ export class ProofsApi<
return proofRecord
}

/**
* Answer with a new presentation proposal in response to received presentation request message
* to the connection associated with the proof record.
*
* @param options multiple properties like proof record id, proof format (indy/ presentation exchange)
* to include in the message
* @returns Proof record associated with the sent proposal message
*/
public async negotiateRequest(options: ProposeProofAsResponseOptions<PFs>): Promise<ProofExchangeRecord> {
const { proofRecordId } = options
const proofRecord = await this.getById(proofRecordId)

const service = this.getService(proofRecord.protocolVersion)

if (!proofRecord.connectionId) {
throw new AriesFrameworkError(
`No connectionId found for proof record '${proofRecord.id}'. Connection-less issuance does not support presentation proposal or negotiation.`
)
}

const connection = await this.connectionService.getById(this.agentContext, proofRecord.connectionId)

// Assert
connection.assertReady()

const proposalOptions: CreateProposalAsResponseOptions<PFs> = {
proofRecord,
proofFormats: options.proofFormats,
autoAcceptProof: options.autoAcceptProof,
goalCode: options.goalCode,
comment: options.comment,
}

const { message } = await service.createProposalAsResponse(this.agentContext, proposalOptions)

const outboundMessageContext = new OutboundMessageContext(message, {
agentContext: this.agentContext,
connection,
associatedRecord: proofRecord,
})
await this.messageSender.sendMessage(outboundMessageContext)

return proofRecord
}

/**
* Accept a presentation as prover (by sending a presentation acknowledgement message) to the connection
* associated with the proof record.
Expand Down
17 changes: 17 additions & 0 deletions packages/core/src/modules/proofs/ProofsApiOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ export interface ProposeProofOptions<
autoAcceptProof?: AutoAcceptProof
parentThreadId?: string
}

export interface ProposeProofAsResponseOptions<PFs extends ProofFormat[] = ProofFormat[]> {
proofRecordId: string
proofFormats: ProofFormatPayload<PFs, 'createProposalAsResponse'>
comment?: string
goalCode?: string
autoAcceptProof?: AutoAcceptProof
}

export interface AcceptProofPresentationOptions<PFs extends ProofFormat[] = ProofFormat[]> {
proofRecordId: string
comment?: string
Expand All @@ -68,6 +77,14 @@ export interface RequestProofOptions<
parentThreadId?: string
}

export interface RequestProofAsResponseOptions<PFs extends ProofFormat[] = ProofFormat[]> {
proofRecordId: string
proofFormats: ProofFormatPayload<PFs, 'createRequestAsResponse'>
comment?: string
autoAcceptProof?: AutoAcceptProof
parentThreadId?: string
}

export interface CreateProofRequestOptions<
PFs extends ProofFormat[] = ProofFormat[],
PSs extends ProofService[] = ProofService[]
Expand Down
Loading

0 comments on commit 1188d03

Please sign in to comment.