Skip to content

Commit

Permalink
feat!: updating DIDComm presentation protocols (#383)
Browse files Browse the repository at this point in the history
BREAKING CHANGES:

Presentation.makePresentationFromRequest removed
ProposePresentation.makeProposalFromRequest removed
RequestPresentation.makeRequestFromProposal removed
ProofTypes interface removed

Signed-off-by: Curtish <[email protected]>
  • Loading branch information
curtis-h authored Feb 26, 2025
1 parent accb2c7 commit fc9b17b
Show file tree
Hide file tree
Showing 12 changed files with 317 additions and 357 deletions.
2 changes: 1 addition & 1 deletion src/edge-agent/didcomm/CreatePresentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class CreatePresentation extends Task<Presentation, Args> {
const presentation = new Presentation(
{
comment: request.body.comment,
goalCode: request.body.goalCode
goal_code: request.body.goal_code
},
[
presentationAttachment,
Expand Down
4 changes: 1 addition & 3 deletions src/edge-agent/didcomm/CreatePresentationRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ export class CreatePresentationRequest extends Task<RequestPresentation, Args> {
: "anoncreds/[email protected]";

return new RequestPresentation(
{
proofTypes: [],
},
{},
[
Domain.AttachmentDescriptor.build(
{ json: definition },
Expand Down
93 changes: 2 additions & 91 deletions src/edge-agent/helpers/ProtocolHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { AttachmentDescriptor, Message } from "../../domain";
import { AgentError } from "../../domain/models/Errors";
import { isArray, isEmpty, isNil, isString, notEmptyString, notNil } from "../../utils";
import { isArray, isEmpty, isNil, notEmptyString } from "../../utils";
import { CredentialFormat } from "../protocols/issueCredential/CredentialFormat";
import {
MediationGrantBody,
PresentationBody,
RequestPresentationBody,
ProposePresentationBody,
BasicMessageBody,
ProblemReportBody,
} from "../protocols/types";
import { MediationGrantBody, BasicMessageBody, ProblemReportBody } from "../protocols/types";

export const parseCredentialAttachments = (credentials: Map<string, any>) => {
const initialValue = {
Expand Down Expand Up @@ -70,85 +63,3 @@ export const parseMediationGrantMessage = (msg: Message): MediationGrantBody =>
routing_did: msg.body.routing_did,
};
};

export const parsePresentationMessage = (msg: Message): PresentationBody => {
if (notNil(msg.body.goalCode) && !isString(msg.body.goalCode)) {
throw new AgentError.InvalidPresentationBodyError("Invalid goalCode");
}
if (notNil(msg.body.comment) && !isString(msg.body.comment)) {
throw new AgentError.InvalidPresentationBodyError("Invalid comment");
}
return {
comment: msg.body.comment,
goalCode: msg.body.goalCode,
};
};

const parseSomePresentationMessage = (msg: Message): RequestPresentationBody | ProposePresentationBody => {
if (notNil(msg.body.goalCode) && !isString(msg.body.goalCode)) {
throw new Error("Invalid goalCode");
}

if (notNil(msg.body.comment) && !isString(msg.body.comment)) {
throw new Error("Invalid comment");
}

if (notNil(msg.body.willConfirm) && typeof msg.body.willConfirm !== "boolean") {
throw new Error("Invalid willConfirm");
}

if (notNil(msg.body.proofTypes)) {
const invalidProofType = !isArray(msg.body.proofTypes) || msg.body.proofTypes.some((x: any) => {
if (notNil(x.schema) && !isString(x.schema)) {
return true;
}

if (notNil(x.requiredFields) && (
!isArray(x.requiredFields) ||
x.requiredFields.some((f: any) => !isString(f))
)) {
return true;
}

if (notNil(x.trustIssuers) && (
!isArray(x.trustIssuers) ||
x.trustIssuers.some((f: any) => !isString(f)))
) {
return true;
}

return false;
});

if (invalidProofType) {
throw new Error("Invalid proofTypes");
}
}

return {
comment: msg.body.comment,
goalCode: msg.body.goalCode,
proofTypes: msg.body.proofTypes,
willConfirm: notNil(msg.body.willConfirm) ? msg.body.willConfirm : false,
};
};

export const parseProposePresentationMessage = (msg: Message): ProposePresentationBody => {
try {
return parseSomePresentationMessage(msg);
}
catch (e) {
const err = e instanceof Error ? e.message : "Invalid propose presentation message";
throw new AgentError.InvalidProposePresentationBodyError(err);
}
};

export const parseRequestPresentationMessage = (msg: Message): RequestPresentationBody => {
try {
return parseSomePresentationMessage(msg);
}
catch (e) {
const err = e instanceof Error ? e.message : "Invalid request presentation message";
throw new AgentError.InvalidPresentationBodyError(err);
}
};
47 changes: 27 additions & 20 deletions src/edge-agent/protocols/proofPresentation/Presentation.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { uuid } from "@stablelib/uuid";

import { AttachmentDescriptor, DID, Message } from "../../../domain";
import { AgentError } from "../../../domain/models/Errors";
import { parsePresentationMessage } from "../../helpers/ProtocolHelpers";
import { ProtocolType } from "../ProtocolTypes";
import { PresentationBody } from "../types";
import { RequestPresentation } from "./RequestPresentation";
import { isString, notNil } from "../../../utils";

/**
* Specification:
* https://github.com/decentralized-identity/waci-didcomm/blob/main/present_proof/present-proof-v3.md#presentation
*/

export interface PresentationBody {
// optional field that indicates the goal of the message sender
goal_code?: string;
// a field that provides some human readable information about this presentation
comment?: string;
}

export class Presentation {
public static type = ProtocolType.DidcommPresentation;
Expand All @@ -17,7 +26,19 @@ export class Presentation {
public to: DID,
public thid?: string,
public id: string = uuid()
) {}
) {
this.validate();
}

private validate() {
if (notNil(this.body.goal_code) && !isString(this.body.goal_code)) {
throw new AgentError.InvalidPresentationBodyError("Invalid goalCode");
}

if (notNil(this.body.comment) && !isString(this.body.comment)) {
throw new AgentError.InvalidPresentationBodyError("Invalid comment");
}
}

makeMessage(): Message {
const body = JSON.stringify(this.body);
Expand All @@ -40,28 +61,14 @@ export class Presentation {
) {
throw new AgentError.InvalidPresentationMessageError();
}
const issueCredentialBody = parsePresentationMessage(fromMessage);

return new Presentation(
issueCredentialBody,
fromMessage.body,
fromMessage.attachments,
fromMessage.from,
fromMessage.to,
fromMessage.thid,
fromMessage.id
);
}

static makePresentationFromRequest(message: Message): Presentation {
const request = RequestPresentation.fromMessage(message);
const presentationBody = parsePresentationMessage(message);

return new Presentation(
presentationBody,
request.attachments,
request.to,
request.from,
message.id
);
}
}
55 changes: 27 additions & 28 deletions src/edge-agent/protocols/proofPresentation/ProposePresentation.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
import { uuid } from "@stablelib/uuid";

import { AttachmentDescriptor, DID, Message } from "../../../domain";
import { AgentError } from "../../../domain/models/Errors";
import { parseProposePresentationMessage } from "../../helpers/ProtocolHelpers";
import { ProtocolType } from "../ProtocolTypes";
import { ProposePresentationBody } from "../types";
import { RequestPresentation } from "./RequestPresentation";
import { isString, notNil } from "../../../utils";

/**
* Specification:
* https://github.com/decentralized-identity/waci-didcomm/blob/main/present_proof/present-proof-v3.md#propose-presentation
*/

export interface ProposePresentationBody {
// optional field that indicates the goal of the message sender
goal_code?: string;
// a field that provides some human readable information about the proposed presentation
comment?: string;
}

export class ProposePresentation {
public static type = ProtocolType.DidcommProposePresentation;
public body: ProposePresentationBody;

constructor(
body: ProposePresentationBody,
public body: ProposePresentationBody,
public attachments: AttachmentDescriptor[],
public from: DID,
public to: DID,
public thid?: string,
public id: string = uuid()
) {
this.body = {
willConfirm: body.willConfirm !== undefined ? body.willConfirm : false,
proofTypes: body.proofTypes,
goalCode: body.goalCode,
comment: body.comment,
};
this.validate();
}

private validate() {
if (notNil(this.body.goal_code) && !isString(this.body.goal_code)) {
throw new Error("Invalid goalCode");
}

if (notNil(this.body.comment) && !isString(this.body.comment)) {
throw new Error("Invalid comment");
}
}

makeMessage(): Message {
Expand All @@ -48,28 +62,13 @@ export class ProposePresentation {
throw new AgentError.InvalidProposePresentationMessageError();
}

const requestPresentationBody = parseProposePresentationMessage(fromMessage);

return new ProposePresentation(
requestPresentationBody,
fromMessage.body,
fromMessage.attachments,
fromMessage.from,
fromMessage.to,
fromMessage.thid,
fromMessage.id
);
}

static makeProposalFromRequest(message: Message): ProposePresentation {
const request = RequestPresentation.fromMessage(message);
const proposePresentationBody = parseProposePresentationMessage(message);

return new ProposePresentation(
proposePresentationBody,
request.attachments,
request.to,
request.from,
message.id
);
}
}
59 changes: 32 additions & 27 deletions src/edge-agent/protocols/proofPresentation/RequestPresentation.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,55 @@
import { uuid } from "@stablelib/uuid";

import { AttachmentDescriptor, DID, Message } from "../../../domain";
import { AgentError } from "../../../domain/models/Errors";
import { parseRequestPresentationMessage } from "../../helpers/ProtocolHelpers";
import { ProtocolType } from "../ProtocolTypes";
import { RequestPresentationBody } from "../types";
import { ProposePresentation } from "./ProposePresentation";
import { isString, notNil } from "../../../utils";

/**
* Specification:
* https://github.com/decentralized-identity/waci-didcomm/blob/main/present_proof/present-proof-v3.md#request-presentation
*/

export interface RequestPresentationBody {
// optional field that indicates the goal of the message sender
goal_code?: string;
// a field that provides some human readable information about this request for a presentation
comment?: string;
// an optional field that defaults to false to indicate that the verifier will or will not send a post-presentation confirmation ack message
will_confirm?: boolean;
}

export class RequestPresentation {
public static type = ProtocolType.DidcommRequestPresentation;
public body: RequestPresentationBody;

constructor(
body: RequestPresentationBody,
public body: RequestPresentationBody,
public attachments: AttachmentDescriptor[],
public from: DID,
public to: DID,
public thid?: string,
public id: string = uuid()
) {
this.body = {
willConfirm: body.willConfirm !== undefined ? body.willConfirm : false,
proofTypes: body.proofTypes,
goalCode: body.goalCode,
comment: body.comment,
};
this.validate();
}

get decodedAttachments() {
return this.attachments.map((attachment) => attachment.payload);
}

private validate() {
if (notNil(this.body.goal_code) && !isString(this.body.goal_code)) {
throw new Error("Invalid goalCode");
}

if (notNil(this.body.comment) && !isString(this.body.comment)) {
throw new Error("Invalid comment");
}

if (notNil(this.body.will_confirm) && typeof this.body.will_confirm !== "boolean") {
throw new Error("Invalid willConfirm");
}
}

makeMessage(): Message {
const body = JSON.stringify(this.body);
return new Message(
Expand All @@ -52,28 +71,14 @@ export class RequestPresentation {
) {
throw new AgentError.InvalidRequestPresentationMessageError();
}
const requestPresentationBody = parseRequestPresentationMessage(fromMessage);

return new RequestPresentation(
requestPresentationBody,
fromMessage.body,
fromMessage.attachments,
fromMessage.from,
fromMessage.to,
fromMessage.thid,
fromMessage.id
);
}

static makeRequestFromProposal(message: Message): RequestPresentation {
const request = ProposePresentation.fromMessage(message);
const requestPresentationBody = parseRequestPresentationMessage(message);

return new RequestPresentation(
requestPresentationBody,
request.attachments,
request.to,
request.from,
message.id
);
}
}
Loading

0 comments on commit fc9b17b

Please sign in to comment.