diff --git a/demos/next/src/components/Message.tsx b/demos/next/src/components/Message.tsx
index dc2e25673..eb631ecb1 100644
--- a/demos/next/src/components/Message.tsx
+++ b/demos/next/src/components/Message.tsx
@@ -27,6 +27,12 @@ const InputFields: React.FC<{ fields: SDK.Domain.InputField[]; }> = props => {
>;
};
+function replacePlaceholders(text: string, args: any[]): string {
+ return text.replace(/\{(\d+)\}/g, (match, index) => {
+ const idx = parseInt(index) - 1; // Adjust for zero-based array index
+ return args[idx] !== undefined ? args[idx] : match; // Replace or keep original if undefined
+ });
+}
export function Message({ message }) {
const app = useMountedApp();
@@ -370,8 +376,36 @@ export function Message({ message }) {
;
}
-
-
+ if (message.piuri === SDK.ProtocolType.ProblemReporting) {
+ const content = replacePlaceholders(message.body.comment, message.body.args);
+
+ return
+
+
+
+
An error ocurred, {content}, CODE {message.body.code}
+
+
+
+ }
if (message.piuri === "https://didcomm.atalaprism.io/present-proof/3.0/request-presentation") {
const requestPresentationMessage = SDK.RequestPresentation.fromMessage(message);
diff --git a/src/domain/models/errors/Agent.ts b/src/domain/models/errors/Agent.ts
index fb38435e0..ab288b9f3 100644
--- a/src/domain/models/errors/Agent.ts
+++ b/src/domain/models/errors/Agent.ts
@@ -161,6 +161,11 @@ export class InvalidPresentationBodyError extends Error {
super(message || "Invalid Presentation body Error");
}
}
+export class InvalidProblemReportBodyError extends Error {
+ constructor(message?: string) {
+ super(message || "Invalid Problem reporting body Error");
+ }
+}
export class InvalidProposeCredentialBodyError extends Error {
constructor(message?: string) {
super(message || "Invalid Propose CredentialBody Error");
diff --git a/src/edge-agent/connectionsManager/ConnectionsManager.ts b/src/edge-agent/connectionsManager/ConnectionsManager.ts
index 24a88b32c..398a7d09b 100644
--- a/src/edge-agent/connectionsManager/ConnectionsManager.ts
+++ b/src/edge-agent/connectionsManager/ConnectionsManager.ts
@@ -170,7 +170,6 @@ export class ConnectionsManager implements ConnectionsManagerClass {
}
}
}
-
if (messageIds.length) {
await this.mediationHandler.registerMessagesAsRead(messageIds);
}
diff --git a/src/edge-agent/helpers/ProtocolHelpers.ts b/src/edge-agent/helpers/ProtocolHelpers.ts
index 4f5a4ec88..739d3125d 100644
--- a/src/edge-agent/helpers/ProtocolHelpers.ts
+++ b/src/edge-agent/helpers/ProtocolHelpers.ts
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { AttachmentDescriptor, Message } from "../../domain";
import { AgentError } from "../../domain/models/Errors";
-import { asArray, isArray, isNil, isObject, isString, notEmptyString, notNil } from "../../utils";
+import { asArray, isArray, isEmpty, isNil, isObject, isString, notEmptyString, notNil } from "../../utils";
import { ProtocolType } from "../protocols/ProtocolTypes";
import { CredentialFormat } from "../protocols/issueCredential/CredentialFormat";
import {
@@ -14,6 +14,7 @@ import {
RequestPresentationBody,
ProposePresentationBody,
BasicMessageBody,
+ ProblemReportBody,
} from "../protocols/types";
export const parseCredentialAttachments = (credentials: Map) => {
@@ -60,6 +61,18 @@ export const parseBasicMessageBody = (msg: Message): BasicMessageBody => {
throw new AgentError.InvalidBasicMessageBodyError("Invalid content");
};
+export const parseProblemReportBody = (msg: Message): ProblemReportBody => {
+ if (notEmptyString(msg.body.code) &&
+ notEmptyString(msg.body.comment) &&
+ notEmptyString(msg.body.escalate_to) &&
+ isArray(msg.body.args) && isEmpty(msg.body.args)
+ ) {
+ const { code, comment, escalate_to, args } = msg.body;
+ return { code, comment, escalate_to, args }
+ }
+ throw new AgentError.InvalidProblemReportBodyError()
+}
+
export const parseCredentialBody = (msg: Message): CredentialBody => {
if (Object.keys(msg.body).length === 0) {
throw new AgentError.InvalidCredentialBodyError(
diff --git a/src/edge-agent/mediator/BasicMediatorHandler.ts b/src/edge-agent/mediator/BasicMediatorHandler.ts
index cf13465e7..7e43c2b0e 100644
--- a/src/edge-agent/mediator/BasicMediatorHandler.ts
+++ b/src/edge-agent/mediator/BasicMediatorHandler.ts
@@ -179,7 +179,6 @@ export class BasicMediatorHandler implements MediatorHandler {
if (!message) {
return [];
}
-
return new PickupRunner(message, this.mercury).run();
}
diff --git a/src/edge-agent/protocols/ProtocolTypes.ts b/src/edge-agent/protocols/ProtocolTypes.ts
index ef037e421..4ed293dac 100644
--- a/src/edge-agent/protocols/ProtocolTypes.ts
+++ b/src/edge-agent/protocols/ProtocolTypes.ts
@@ -21,7 +21,8 @@ export enum ProtocolType {
PickupStatus = "https://didcomm.org/messagepickup/3.0/status",
PickupReceived = "https://didcomm.org/messagepickup/3.0/messages-received",
LiveDeliveryChange = "https://didcomm.org/messagepickup/3.0/live-delivery-change",
- PrismRevocation = "https://atalaprism.io/revocation_notification/1.0/revoke"
+ PrismRevocation = "https://atalaprism.io/revocation_notification/1.0/revoke",
+ ProblemReporting = "https://didcomm.org/report-problem/2.0/problem-report"
}
export function findProtocolTypeByValue(string: string): ProtocolType {
diff --git a/src/edge-agent/protocols/other/ProblemReport.ts b/src/edge-agent/protocols/other/ProblemReport.ts
new file mode 100644
index 000000000..d0225c804
--- /dev/null
+++ b/src/edge-agent/protocols/other/ProblemReport.ts
@@ -0,0 +1,50 @@
+import { AgentError, DID, Message } from "../../../domain/models";
+import { parseProblemReportBody } from "../../helpers/ProtocolHelpers";
+import { ProtocolType } from "../ProtocolTypes";
+import { ProblemReportBody } from "../types";
+
+
+
+
+
+export class ProblemReport {
+ public static type = ProtocolType.ProblemReporting;
+
+ constructor(
+ public body: ProblemReportBody,
+ public from: DID,
+ public to: DID,
+ public thid?: string,
+ ) { }
+
+ makeMessage(): Message {
+ const body = JSON.stringify(this.body);
+ return new Message(
+ body,
+ undefined,
+ ProblemReport.type,
+ this.from,
+ this.to,
+ [],
+ this.thid
+ );
+ }
+
+ static fromMessage(fromMessage: Message): ProblemReport {
+ if (
+ fromMessage.piuri !== ProtocolType.DidcommBasicMessage ||
+ !fromMessage.from ||
+ !fromMessage.to
+ ) {
+ throw new AgentError.InvalidBasicMessageBodyError(
+ "Invalid BasicMessage body error."
+ );
+ }
+ const problemReportBody = parseProblemReportBody(fromMessage);
+ return new ProblemReport(
+ problemReportBody,
+ fromMessage.from,
+ fromMessage.to
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/edge-agent/protocols/pickup/PickupRunner.ts b/src/edge-agent/protocols/pickup/PickupRunner.ts
index aae4722cd..defae0b8f 100644
--- a/src/edge-agent/protocols/pickup/PickupRunner.ts
+++ b/src/edge-agent/protocols/pickup/PickupRunner.ts
@@ -6,7 +6,8 @@ import { PickupAttachment } from "../types";
type PickupResponse =
| { type: "status"; message: Message }
- | { type: "delivery"; message: Message };
+ | { type: "delivery"; message: Message }
+ | { type: 'report', message: Message };
export class PickupRunner {
private message: PickupResponse;
@@ -20,6 +21,9 @@ export class PickupRunner {
case ProtocolType.PickupDelivery:
this.message = { type: "delivery", message: message };
break;
+ case ProtocolType.ProblemReporting:
+ this.message = { type: "report", message: message };
+ break;
default:
throw new AgentError.InvalidPickupDeliveryMessageError();
}
@@ -63,6 +67,13 @@ export class PickupRunner {
message: await this.mercury.unpackMessage(attachment.data),
}))
);
+ } else if (this.message.type === "report") {
+ return [
+ {
+ attachmentId: this.message.message.id,
+ message: this.message.message
+ }
+ ]
}
return [];
diff --git a/src/edge-agent/protocols/types.ts b/src/edge-agent/protocols/types.ts
index 3947c5abf..b74fe9c69 100644
--- a/src/edge-agent/protocols/types.ts
+++ b/src/edge-agent/protocols/types.ts
@@ -70,6 +70,14 @@ export interface BasicMessageBody {
content: string;
}
+
+export interface ProblemReportBody {
+ code: string,
+ comment: string,
+ args: string[],
+ escalate_to: string
+}
+
export interface RequestPresentationBody extends PresentationBody {
willConfirm?: boolean;
proofTypes: ProofTypes[];
diff --git a/tests/agent/protocols/pickup/PickupRunner.test.ts b/tests/agent/protocols/pickup/PickupRunner.test.ts
index e30e521b9..055e21585 100644
--- a/tests/agent/protocols/pickup/PickupRunner.test.ts
+++ b/tests/agent/protocols/pickup/PickupRunner.test.ts
@@ -45,6 +45,27 @@ describe("PickupRunner Tests", () => {
expect(response).to.be.an("array").with.length(0);
});
+ test(`${ProtocolType.PickupDelivery} - 1 problem report message`, async () => {
+ const runner = new PickupRunner(Messages.Reporting, mercury);
+ const response = await runner.run();
+ expect(response).to.be.an("array").with.length(1);
+ expect(response[0].message.ack).to.deep.eq(Messages.Reporting.ack);
+ expect(response[0].message.attachments).to.deep.eq(Messages.Reporting.attachments);
+ expect(response[0].message.body).to.deep.eq(Messages.Reporting.body);
+ expect(response[0].message.createdTime).to.deep.eq(Messages.Reporting.createdTime);
+ expect(response[0].message.direction).to.deep.eq(Messages.Reporting.direction);
+ expect(response[0].message.extraHeaders).to.deep.eq(Messages.Reporting.extraHeaders);
+ expect(response[0].message.from).to.deep.eq(Messages.Reporting.from);
+ expect(response[0].message.fromPrior).to.deep.eq(Messages.Reporting.fromPrior);
+ expect(response[0].message.id).to.deep.eq(Messages.Reporting.id);
+ expect(response[0].message.piuri).to.deep.eq(Messages.Reporting.piuri);
+ expect(response[0].message.pthid).to.deep.eq(Messages.Reporting.pthid);
+ expect(response[0].message.thid).to.deep.eq(Messages.Reporting.thid);
+ expect(response[0].message.to).to.deep.eq(Messages.Reporting.to);
+ });
+
+
+
test(`${ProtocolType.PickupDelivery} - 1 message`, async () => {
const runner = new PickupRunner(Messages.PickupDelivery, mercury);
const response = await runner.run();
diff --git a/tests/fixtures/messages/index.ts b/tests/fixtures/messages/index.ts
index c24faf7e8..3813eecad 100644
--- a/tests/fixtures/messages/index.ts
+++ b/tests/fixtures/messages/index.ts
@@ -1,5 +1,6 @@
import { base64 } from "multiformats/bases/base64";
import * as Domain from "../../../src/domain";
+import { ProtocolType } from "../../../src/edge-agent/protocols/ProtocolTypes";
// convert raw DIDComm message to domain, handles parsing idiosyncrasies
const convertDidcomm = (value: any) => new Domain.Message(
@@ -238,3 +239,23 @@ const pickupStatusRaw: any = {
};
export const PickupStatus = convertDidcomm(pickupStatusRaw);
+
+
+export const Reporting = convertDidcomm({
+ "id": "033642e4-9064-4da2-ac84-6be20b3ec8b8",
+ "typ": "application/didcomm-plain+json",
+ "type": ProtocolType.ProblemReporting,
+ "body": {
+ "args": [
+ 'did:peer:2.Ez6LSmEZPCeaFeA1vwBTZeLvXi6F24ZdEQgmzJCqHaQQojBj8.Vz6MktyGjB1ogYgsu3nt9ncjzXM4mBBGJSU5cPrCScDcC2GrN.SW10'
+ ],
+ "comment": "The DID '{1}' is not enroled",
+ "code": "e.p.req.not_enroll",
+ "escalate_to": "email@email.com"
+ },
+ "from": "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vc2l0LXByaXNtLW1lZGlhdG9yLmF0YWxhcHJpc20uaW8iLCJhIjpbImRpZGNvbW0vdjIiXX19.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6IndzczovL3NpdC1wcmlzbS1tZWRpYXRvci5hdGFsYXByaXNtLmlvL3dzIiwiYSI6WyJkaWRjb21tL3YyIl19fQ",
+ "to": [
+ "did:peer:2.Ez6LSrjn3NUEgFDY2wKnxbNfbXLozs8Em5RX6xWkTJn3kqpsL.Vz6MkuK1KvyssRGvzYuerJQQaTANA9hAe3dXt2X31d6Ef9xee.SW10"
+ ],
+ "thid": "dcc4af0e-0a9c-4082-98d1-bbdc582002b7"
+})
\ No newline at end of file