Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • svdh/ocm-engine
1 result
Show changes
Commits on Source (2)
Showing
with 655 additions and 71 deletions
......@@ -3,6 +3,13 @@
All notable changes to this project will be documented in this file. See
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.0](https://code.vereign.com/gaiax/ocm/ocm-engine/compare/v1.8.0...v1.9.0) (2023-09-19)
### Features
* improve proof api ([ab95aac](https://code.vereign.com/gaiax/ocm/ocm-engine/commit/ab95aac816b582c250f3f07a1c0f287a82ef9bff))
## [1.8.0](https://code.vereign.com/gaiax/ocm/ocm-engine/compare/v1.7.1...v1.8.0) (2023-09-12)
......
import {
BadRequestException,
Body,
Controller,
Get,
Param,
Post,
UseFilters,
} from "@nestjs/common";
import { Body, Controller, Get, Param, Post, UseFilters } from "@nestjs/common";
import { AllExceptionsHandler } from "../exception.handler";
import { AttestationManagerClient } from "@ocm-engine/clients";
import {
......
import {
BadRequestException,
Body,
Controller,
Get,
Param,
Post,
UseFilters,
} from "@nestjs/common";
import { Body, Controller, Get, Param, Post, UseFilters } from "@nestjs/common";
import {
AcceptProofRequestDto,
DeclineProofRequestDto,
GatewayAcceptedResponseDto,
GetProofRequestDto,
GetSchemaRequestDto,
IssueProofRequestDto,
PROOF_ACCEPT,
PROOF_DECLINE,
PROOF_GET,
PROOF_ISSUE,
PROOF_LIST,
} from "@ocm-engine/dtos";
......@@ -76,6 +72,55 @@ export class ProofController {
});
}
@Get("/credentials/proof/:proof_record_id")
@ApiResponse({
status: 200,
description:
"Request is accepted for execution, the response id will match the event id received from the web socket",
type: GatewayAcceptedResponseDto,
})
@ApiInternalServerErrorResponse({
description:
"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.",
content: {
"application/json": {
schema: {
type: "object",
properties: {
statusCode: {
type: "number",
example: 500,
},
message: {
type: "string",
example: "connect ECONNREFUSED 0.0.0.0.0:1919",
},
},
},
},
},
})
@ApiOperation({
summary: "Get a single proof record by providing proof record id.",
description:
"Method get proof by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket",
tags: ["Credentials Proof"],
})
getProofById(@Param("proof_record_id") proofRecordId: string) {
const data = new GetProofRequestDto();
data.proofRecordId = proofRecordId;
return this.pmClient.sendPayload<GetProofRequestDto>({
pattern: "proofs",
payload: {
source: "/credentials/proof/:proof_record_id",
data,
type: PROOF_GET,
},
});
}
@Post("/credentials/proof/issue")
@ApiResponse({
status: 201,
......@@ -150,7 +195,7 @@ export class ProofController {
});
}
@Post(`/credentials/proof/:proof_record_id/accept`)
@Post(`/credentials/proof/accept`)
@ApiResponse({
status: 201,
description:
......@@ -185,16 +230,62 @@ export class ProofController {
"Method accept credential proof. The id of the response will be matched when you receive event from the websocket",
tags: ["Credentials Proof"],
})
acceptProof(@Param("proof_record_id") proofRecordId: string) {
const data = new AcceptProofRequestDto();
acceptProof(@Body() acceptProofRequestDto: AcceptProofRequestDto) {
return this.pmClient.sendPayload<AcceptProofRequestDto>({
pattern: "proofs",
payload: {
source: "/credentials/proofs/accept",
data: acceptProofRequestDto,
type: PROOF_ACCEPT,
},
});
}
@Post("/credentials/proof/:proof_record_id/decline")
@ApiResponse({
status: 200,
description:
"Request is accepted for execution, the response id will match the event id received from the web socket",
type: GatewayAcceptedResponseDto,
})
@ApiInternalServerErrorResponse({
description:
"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.",
content: {
"application/json": {
schema: {
type: "object",
properties: {
statusCode: {
type: "number",
example: 500,
},
message: {
type: "string",
example: "connect ECONNREFUSED 0.0.0.0.0:1919",
},
},
},
},
},
})
@ApiOperation({
summary: "Decline a proof request.",
description:
"Method to decline a proof request by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket",
tags: ["Credentials Proof"],
})
declineProofRequest(@Param("proof_record_id") proofRecordId: string) {
const data = new DeclineProofRequestDto();
data.proofRecordId = proofRecordId;
return this.pmClient.sendPayload<AcceptProofRequestDto>({
return this.pmClient.sendPayload<DeclineProofRequestDto>({
pattern: "proofs",
payload: {
source: "/credentials/proofs/:id/accept",
source: "/credentials/proof/:proof_record_id/decline",
data,
type: PROOF_ACCEPT,
type: PROOF_DECLINE,
},
});
}
......
......@@ -3,6 +3,7 @@ import { Body, Controller, Logger } from "@nestjs/common";
import { ProducerService } from "@ocm-engine/nats";
import { MessagePattern, RpcException } from "@nestjs/microservices";
import {
AcceptProofRequestDto,
CloudEventDto,
GatewayAcceptedResponseDto,
makeEvent,
......@@ -19,7 +20,7 @@ export class AppController {
async create(
@Body()
payload: {
data: null;
data: null | AcceptProofRequestDto;
type: ProofEvent;
source: string;
},
......
This diff is collapsed.
......@@ -2,15 +2,18 @@ import {
Agent,
AutoAcceptCredential,
AutoAcceptProof,
BaseEvent,
ConnectionsModule,
ConnectionStateChangedEvent,
CredentialsModule,
DidExchangeRole,
DidsModule,
EncryptedMessage,
Key,
KeyDidResolver,
KeyType,
PeerDidResolver,
ProofEventTypes,
ProofsModule,
ProofState,
ProofStateChangedEvent,
......@@ -40,6 +43,25 @@ import { ariesAskar } from "@hyperledger/aries-askar-nodejs";
import { Key as C, KeyAlgs } from "@hyperledger/aries-askar-shared";
import { IConfAgent } from "@ocm-engine/config";
import axios from "axios";
import {
catchError,
filter,
lastValueFrom,
map,
Observable,
ReplaySubject,
Subject,
take,
timeout,
} from "rxjs";
import { SubjectInboundTransport } from "./askar/transports/agent.subject.inbound.transport";
import { SubjectOutboundTransport } from "./askar/transports/agent.subject.outbound.transport";
export type EventReplaySubject = ReplaySubject<BaseEvent>;
export type SubjectMessage = {
message: EncryptedMessage;
replySubject?: Subject<SubjectMessage>;
};
export const importDidsToWallet = async (
agent: Agent,
......@@ -147,6 +169,36 @@ export const getAskarAnonCredsIndyModules = (networks: any) => {
} as const;
};
export const setupEventReplaySubjects = (
agents: Agent[],
eventTypes: string[],
): ReplaySubject<BaseEvent>[] => {
const replaySubjects: EventReplaySubject[] = [];
for (const agent of agents) {
const replaySubject = new ReplaySubject<BaseEvent>();
for (const eventType of eventTypes) {
agent.events.observable(eventType).subscribe(replaySubject);
}
replaySubjects.push(replaySubject);
}
return replaySubjects;
};
export const setupSubjectTransports = (agents: Agent[]) => {
const subjectMap: Record<string, Subject<SubjectMessage>> = {};
for (const agent of agents) {
const messages = new Subject<SubjectMessage>();
subjectMap[agent.config.endpoints[0]] = messages;
agent.registerInboundTransport(new SubjectInboundTransport(messages));
agent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap));
}
};
export const svdxProofStateChangeHandler = async (
ev: ProofStateChangedEvent,
agent: Agent,
......@@ -272,3 +324,64 @@ export const svdxConnectionStateChangeHandler = async (
console.log("failed to issue credential");
}
};
export const isProofStateChangedEvent = (
e: BaseEvent,
): e is ProofStateChangedEvent => e.type === ProofEventTypes.ProofStateChanged;
export const waitForProofExchangeRecordSubject = (
subject: ReplaySubject<BaseEvent> | Observable<BaseEvent>,
{
threadId,
parentThreadId,
state,
previousState,
timeoutMs = 10000,
count = 1,
}: {
threadId?: string;
parentThreadId?: string;
state?: ProofState;
previousState?: ProofState | null;
timeoutMs?: number;
count?: number;
},
) => {
const observable: Observable<BaseEvent> =
subject instanceof ReplaySubject ? subject.asObservable() : subject;
return lastValueFrom(
observable.pipe(
filter(isProofStateChangedEvent),
filter(
(e) =>
previousState === undefined ||
e.payload.previousState === previousState,
),
filter(
(e) =>
threadId === undefined || e.payload.proofRecord.threadId === threadId,
),
filter(
(e) =>
parentThreadId === undefined ||
e.payload.proofRecord.parentThreadId === parentThreadId,
),
filter(
(e) => state === undefined || e.payload.proofRecord.state === state,
),
timeout(timeoutMs),
catchError(() => {
throw new Error(
`ProofStateChangedEvent event not emitted within specified timeout: ${timeoutMs}
previousState: ${previousState},
threadId: ${threadId},
parentThreadId: ${parentThreadId},
state: ${state}
}`,
);
}),
take(count),
map((e) => e.payload.proofRecord),
),
);
};
......@@ -21,13 +21,17 @@ import {
IssueCredentialRequestDto,
IssueProofRequestDto,
MakeBasicMessageRequestDto,
DeclineProofRequestDto,
MESSAGE_MAKE,
PROOF_ACCEPT,
PROOF_ISSUE,
PROOF_LIST,
PROOF_GET,
SCHEMA_CREATE,
SCHEMA_GET,
SCHEMA_LIST,
GetProofRequestDto,
PROOF_DECLINE,
} from "@ocm-engine/dtos";
import asyncRetry from "async-retry";
......@@ -108,9 +112,22 @@ export class EventHandlerService {
data = await this.agentService.proofs();
break;
case PROOF_GET:
dto = event.data as GetProofRequestDto;
data = await this.agentService.getProofById(dto.proofRecordId);
break;
case PROOF_ACCEPT:
dto = event.data as AcceptProofRequestDto;
data = await this.agentService.acceptProof(dto.proofRecordId);
data = await this.agentService.acceptProof(
event.data as AcceptProofRequestDto,
);
break;
case PROOF_DECLINE:
dto = event.data as DeclineProofRequestDto;
data = await this.agentService.declineProofRequest(
dto.proofRecordId,
);
break;
case MESSAGE_MAKE:
......
......@@ -8,6 +8,8 @@ import {
IssueProofRequestDto,
CreateSchemaRequestDto,
MakeBasicMessageRequestDto,
AcceptProofRequestDto,
GetProofRequestDto,
} from "@ocm-engine/dtos";
import { AllExceptionsHandler } from "./exception.handler";
......@@ -77,9 +79,19 @@ export class RestController {
return this.agentService.issueProof(issueProofDto);
}
@Post(`/credential/proof/:proof_record_id/accept`)
acceptProof(@Param("proof_record_id") proofRecordId: string) {
return this.agentService.acceptProof(proofRecordId);
@Get("credential/proof/:proof_record_id")
getProof(@Param("proof_record_id") data: GetProofRequestDto) {
return this.agentService.getProofById(data.proofRecordId);
}
@Post(`/credential/proof/accept`)
acceptProof(@Body() acceptProofRequestDto: AcceptProofRequestDto) {
return this.agentService.acceptProof(acceptProofRequestDto);
}
@Post(`/credential/proof/:proof_record_id/decline`)
declineProofRequest(@Param("proof_record_id") proofRecordId: string) {
return this.agentService.declineProofRequest(proofRecordId);
}
@Post("/resolve")
......@@ -88,7 +100,7 @@ export class RestController {
}
@Post("/messages")
async sendMeesage(@Body() message: MakeBasicMessageRequestDto) {
sendMeesage(@Body() message: MakeBasicMessageRequestDto) {
return this.agentService.sendMessage(message);
}
}
......@@ -23,9 +23,9 @@ import {
} from "../agent.utils";
@Injectable()
export class AgentEventListenerServce implements OnModuleInit {
export class AgentEventListenerService implements OnModuleInit {
private agentConfig: IConfAgent | undefined;
private readonly logger: Logger = new Logger(AgentEventListenerServce.name);
private readonly logger: Logger = new Logger(AgentEventListenerService.name);
constructor(
private readonly gatewayClient: GatewayClient,
......
......@@ -2,6 +2,7 @@ import { Injectable } from "@nestjs/common";
import { AskarService } from "./askar.service";
import {
AcceptInvitationResponseDto,
AcceptProofRequestDto,
ConnectionNotFoundError,
CreateCredentialDefinitionRequsetDto,
CreateCredentialDefinitionResponseDto,
......@@ -13,16 +14,21 @@ import {
IssueCredentialResponseDto,
IssueProofRequestDto,
IssueProofResponseDto,
GetProofByIdResponseDto,
MakeBasicMessageRequestDto,
MakeBasicMessageResponseDto,
SchemaNotCreatedError,
DeclineProofResponseDto,
} from "@ocm-engine/dtos";
import {
AutoAcceptProof,
CredentialState,
ProofExchangeRecord,
JsonEncoder,
ProofState,
} from "@aries-framework/core";
import { AnonCredsRequestedAttribute } from "@aries-framework/anoncreds";
import { uuid } from "@aries-framework/core/build/utils/uuid";
import { waitForProofExchangeRecordSubject } from "../agent.utils";
@Injectable()
export class AgentService {
......@@ -228,11 +234,11 @@ export class AgentService {
};
issueProof = async (issueProofDto: IssueProofRequestDto) => {
let exchangeRecord: ProofExchangeRecord;
console.log(JSON.stringify(issueProofDto, null, 2));
const requestedAttributes: Record<string, AnonCredsRequestedAttribute> = {};
for (const attr of issueProofDto.attributes) {
requestedAttributes[attr.attributeName] = {
requestedAttributes[uuid()] = {
name: attr.attributeName,
restrictions: [
{
......@@ -244,32 +250,45 @@ export class AgentService {
}
if (!issueProofDto.connectionId) {
const { proofRecord } = await this.askar.agent.proofs.createRequest({
protocolVersion: "v2",
proofFormats: {
anoncreds: {
name: "proof-request",
version: "1.0",
requested_attributes: requestedAttributes,
console.log("connection Id not detected, creating oob proof");
const { proofRecord, message } =
await this.askar.agent.proofs.createRequest({
protocolVersion: "v2",
proofFormats: {
anoncreds: {
name: "proof-request",
version: "1.0",
requested_attributes: requestedAttributes,
},
},
},
});
autoAcceptProof: AutoAcceptProof.ContentApproved,
});
exchangeRecord = proofRecord;
} else {
exchangeRecord = await this.askar.agent.proofs.requestProof({
protocolVersion: "v2",
connectionId: issueProofDto.connectionId,
proofFormats: {
anoncreds: {
name: "proof-request",
version: "1.0",
requested_attributes: requestedAttributes,
},
},
});
console.log({ proofRecord });
const { invitationUrl } =
await this.askar.agent.oob.createLegacyConnectionlessInvitation({
recordId: proofRecord.id,
message,
domain: this.askar.agentConfig.agentPeerAddress,
});
return { proofUrl: invitationUrl };
}
console.log(`${issueProofDto.connectionId} detected, issuing proof`);
const exchangeRecord = await this.askar.agent.proofs.requestProof({
protocolVersion: "v2",
connectionId: issueProofDto.connectionId,
proofFormats: {
anoncreds: {
name: "proof-request",
version: "1.0",
requested_attributes: requestedAttributes,
},
},
});
const response = new IssueProofResponseDto();
response.proofId = exchangeRecord.id;
response.connectionId = exchangeRecord.connectionId;
......@@ -300,25 +319,102 @@ export class AgentService {
return response;
};
acceptProof = async (proofRecordId: string) => {
getProofById = async (proofRecordId: string) => {
const proofRecord = await this.askar.agent.proofs.findById(proofRecordId);
if (!proofRecord) {
return proofRecord;
}
const proofResponse = new GetProofByIdResponseDto();
proofResponse.proofId = proofRecord.id;
proofResponse.connectionId = proofRecord.connectionId;
proofResponse.state = proofRecord.state;
proofResponse.updatedAt = proofRecord.updatedAt;
proofResponse.createdAt = proofRecord.createdAt;
return proofResponse;
};
acceptProof = async (acceptProofDto: AcceptProofRequestDto) => {
if (acceptProofDto.proofUrl) {
return this.acceptOobProof(acceptProofDto.proofUrl);
}
return this.acceptConnectionProof(acceptProofDto.proofId);
};
acceptOobProof = async (url: string) => {
const param = url.split("d_m=")[1];
const t = JsonEncoder.fromBase64(param);
await this.askar.agent.receiveMessage(t);
const record = await waitForProofExchangeRecordSubject(this.askar.agentR, {
state: ProofState.RequestReceived,
});
const requestedCredentials =
await this.askar.agent.proofs.selectCredentialsForRequest({
proofRecordId: record.id,
});
const acceptedRecord = await this.askar.agent.proofs.acceptRequest({
proofRecordId: record.id,
proofFormats: requestedCredentials.proofFormats,
});
const response = new IssueProofResponseDto();
response.proofId = acceptedRecord.id;
response.state = acceptedRecord.state;
response.updatedAt = acceptedRecord.updatedAt;
response.createdAt = acceptedRecord.createdAt;
return acceptedRecord;
};
acceptConnectionProof = async (proofRecordId: string) => {
console.log(`accepting proof request for ${proofRecordId}`);
const requestedCredentials =
await this.askar.agent.proofs.selectCredentialsForRequest({
proofRecordId,
});
console.log(JSON.stringify(requestedCredentials, null, 2));
const proof = await this.askar.agent.proofs.acceptRequest({
proofRecordId,
proofFormats: requestedCredentials.proofFormats,
});
const t = new IssueProofResponseDto();
t.proofId = proof.id;
t.connectionId = proof.connectionId;
t.state = proof.state;
t.updatedAt = proof.updatedAt;
t.createdAt = proof.createdAt;
console.log(JSON.stringify(proof, null, 2));
const response = new IssueProofResponseDto();
response.proofId = proof.id;
response.connectionId = proof.connectionId;
response.state = proof.state;
response.updatedAt = proof.updatedAt;
response.createdAt = proof.createdAt;
return response;
};
declineProofRequest = async (proofRecordId: string) => {
const resultFromDecline = await this.askar.agent.proofs.declineRequest({
proofRecordId,
// sendProblemReport: false, // REVIEW: do we have a use case for this key?
});
const declineResponse = new DeclineProofResponseDto();
declineResponse.proofId = resultFromDecline.id;
declineResponse.connectionId = resultFromDecline.connectionId;
declineResponse.state = resultFromDecline.state;
declineResponse.updatedAt = resultFromDecline.updatedAt;
declineResponse.createdAt = resultFromDecline.createdAt;
return t;
return declineResponse;
};
resolve = async (did: string) => {
......
......@@ -3,7 +3,7 @@ import { AskarService } from "./askar.service";
import { AgentService } from "./agent.service";
import { ConfigModule } from "@nestjs/config";
import { LedgersModule } from "@ocm-engine/ledgers";
import { AgentEventListenerServce } from "./agent.event.listener.servce";
import { AgentEventListenerService } from "./agent-event-listener.service";
import { GatewayClient } from "@ocm-engine/clients";
@Global()
......@@ -12,7 +12,7 @@ import { GatewayClient } from "@ocm-engine/clients";
providers: [
AgentService,
AskarService,
AgentEventListenerServce,
AgentEventListenerService,
GatewayClient,
],
exports: [AgentService, AskarService],
......
......@@ -7,10 +7,12 @@ import {
import {
Agent,
BaseEvent,
ConsoleLogger,
HttpOutboundTransport,
InitConfig,
LogLevel,
ProofEventTypes,
TypedArrayEncoder,
WsOutboundTransport,
} from "@aries-framework/core";
......@@ -22,12 +24,16 @@ import {
generateKey,
getAskarAnonCredsIndyModules,
importDidsToWallet,
setupEventReplaySubjects,
setupSubjectTransports,
} from "../agent.utils";
import { IConfAgent } from "@ocm-engine/config";
import { ReplaySubject } from "rxjs";
@Injectable()
export class AskarService implements OnModuleInit, OnModuleDestroy {
public agent: Agent<ReturnType<typeof getAskarAnonCredsIndyModules>>;
public agentR: ReplaySubject<BaseEvent>;
public agentConfig: IConfAgent;
private readonly logger: Logger = new Logger(AskarService.name);
......@@ -73,6 +79,14 @@ export class AskarService implements OnModuleInit, OnModuleDestroy {
this.agent.registerOutboundTransport(new WsOutboundTransport());
this.agent.registerOutboundTransport(new HttpOutboundTransport());
setupSubjectTransports([this.agent]);
const [agentR] = setupEventReplaySubjects(
[this.agent],
[ProofEventTypes.ProofStateChanged],
);
this.agentR = agentR;
this.logger.log("Agent setup completed");
}
......
import {
Agent,
AgentContext,
EncryptedMessage,
InboundTransport,
MessageReceiver,
TransportService,
TransportSession,
} from "@aries-framework/core";
import { Subject, Subscription } from "rxjs";
import { uuid } from "@aries-framework/core/build/utils/uuid";
import { SubjectMessage } from "../../agent.utils";
class SubjectTransportSession implements TransportSession {
public id: string;
public readonly type = "subject";
private replySubject: Subject<SubjectMessage>;
public constructor(id: string, replySubject: Subject<SubjectMessage>) {
this.id = id;
this.replySubject = replySubject;
}
public async send(
agentContext: AgentContext,
encryptedMessage: EncryptedMessage,
): Promise<void> {
this.replySubject.next({ message: encryptedMessage });
}
public async close(): Promise<void> {
this.replySubject.complete();
}
}
export class SubjectInboundTransport implements InboundTransport {
public readonly ourSubject: Subject<SubjectMessage>;
private subscription?: Subscription;
public constructor(ourSubject = new Subject<SubjectMessage>()) {
this.ourSubject = ourSubject;
}
public async start(agent: Agent) {
this.subscribe(agent);
}
public async stop() {
this.subscription?.unsubscribe();
}
private subscribe(agent: Agent) {
const logger = agent.config.logger;
const transportService = agent.dependencyManager.resolve(TransportService);
const messageReceiver = agent.dependencyManager.resolve(MessageReceiver);
this.subscription = this.ourSubject.subscribe({
next: async ({ message, replySubject }: SubjectMessage) => {
logger.test("Received message");
let session: SubjectTransportSession | undefined;
if (replySubject) {
session = new SubjectTransportSession(
`subject-session-${uuid()}`,
replySubject,
);
// When the subject is completed (e.g. when the session is closed), we need to
// remove the session from the transport service so it won't be used for sending messages
// in the future.
replySubject.subscribe({
complete: () => session && transportService.removeSession(session),
});
}
await messageReceiver.receiveMessage(message, { session });
},
});
}
}
import {
Agent,
AriesFrameworkError,
InjectionSymbols,
MessageReceiver,
OutboundPackage,
OutboundTransport,
} from "@aries-framework/core";
import { Logger } from "@nestjs/common";
import { Subject, take, takeUntil } from "rxjs";
import { SubjectMessage } from "../../agent.utils";
export class SubjectOutboundTransport implements OutboundTransport {
private logger!: Logger;
private subjectMap: { [key: string]: Subject<SubjectMessage> | undefined };
private agent!: Agent;
private stop$!: Subject<boolean>;
public supportedSchemes = ["rxjs", "wss"];
public constructor(subjectMap: {
[key: string]: Subject<SubjectMessage> | undefined;
}) {
this.subjectMap = subjectMap;
}
public async start(agent: Agent): Promise<void> {
this.agent = agent;
this.logger = agent.dependencyManager.resolve(InjectionSymbols.Logger);
this.stop$ = agent.dependencyManager.resolve(InjectionSymbols.Stop$);
}
public async stop(): Promise<void> {
// No logic needed
}
public async sendMessage(outboundPackage: OutboundPackage) {
const messageReceiver =
this.agent.dependencyManager.resolve(MessageReceiver);
this.logger.debug(
`Sending outbound message to endpoint ${outboundPackage.endpoint}`,
{
endpoint: outboundPackage.endpoint,
},
);
const { payload, endpoint } = outboundPackage;
if (!endpoint) {
throw new AriesFrameworkError(
"Cannot send message to subject without endpoint",
);
}
const subject = this.subjectMap[endpoint];
if (!subject) {
throw new AriesFrameworkError(
`No subject found for endpoint ${endpoint}`,
);
}
// Create a replySubject just for this session. Both ends will be able to close it,
// mimicking a transport like http or websocket. Close session automatically when agent stops
const replySubject = new Subject<SubjectMessage>();
this.stop$
.pipe(take(1))
.subscribe(() => !replySubject.closed && replySubject.complete());
replySubject.pipe(takeUntil(this.stop$)).subscribe({
next: async ({ message }: SubjectMessage) => {
this.logger.debug("Received message");
await messageReceiver.receiveMessage(message);
},
});
subject.next({ message: payload, replySubject });
}
}
import { IsNotEmpty, IsString } from "class-validator";
import { IsNotEmpty, IsString, ValidateIf } from "class-validator";
export class AcceptProofRequestDto {
@IsString()
@IsNotEmpty()
proofRecordId: string;
@ValidateIf((o) => o.proofUrl === undefined)
proofId: string;
@IsString()
@IsNotEmpty()
@ValidateIf((o) => o.proofId === undefined)
proofUrl: string;
}
import { IsBoolean, IsNotEmpty, IsString } from "class-validator";
export class DeclineProofRequestDto {
@IsString()
@IsNotEmpty()
proofRecordId: string;
@IsBoolean()
sendProblemReport?: boolean;
}
\ No newline at end of file
import { IsNotEmpty, IsString } from "class-validator";
export class GetProofRequestDto {
@IsString()
@IsNotEmpty()
proofRecordId: string;
}
import {
IsDateString,
IsNotEmpty,
IsString
} from "class-validator";
export class DeclineProofResponseDto {
@IsString()
@IsNotEmpty()
proofId: string;
@IsString()
connectionId?: string;
@IsString()
@IsNotEmpty()
state: string;
@IsDateString()
updatedAt?: Date;
@IsNotEmpty()
@IsDateString()
createdAt: Date;
}
\ No newline at end of file
import {
IsDateString,
IsNotEmpty,
IsString
} from "class-validator";
export class GetProofByIdResponseDto {
@IsString()
@IsNotEmpty()
proofId: string;
@IsString()
connectionId?: string;
@IsString()
@IsNotEmpty()
state: string;
@IsDateString()
updatedAt?: Date;
@IsNotEmpty()
@IsDateString()
createdAt: Date;
}
......@@ -17,6 +17,10 @@ import { IssueProofRequestDto } from "../dtos/requests/issue.proof.request.dto";
import { AcceptCredentialOfferRequestDto } from "../dtos/requests/accept.credential.offer.request.dto";
import { MakeBasicMessageResponseDto } from "../dtos/responses/make.basic.message.response.dto";
import { MakeBasicMessageRequestDto } from "../dtos/requests/make.basic.message.request.dto";
import { AcceptProofRequestDto } from "../dtos/requests/accept.proof.request.dto";
import { GetProofByIdResponseDto } from "../dtos/responses/get.proof.response.dto";
import { DeclineProofRequestDto } from '../dtos/requests/decline.proof.request.dto';
import { DeclineProofResponseDto } from "../dtos/responses/decline.proof.response.dto";
export const makeEvent = (payload: {
data:
......@@ -26,8 +30,12 @@ export const makeEvent = (payload: {
| CreateInvitationResponseDto
| GetConnectionRequestDto
| CreateSchemaRequestDto
| AcceptProofRequestDto
| DeclineProofRequestDto
| DeclineProofResponseDto
| CreateSchemaRequestDto
| CreateCredentialDefinitionRequsetDto
| GetProofByIdResponseDto
| IssueCredentialRequestDto
| MakeBasicMessageResponseDto
| MakeBasicMessageRequestDto;
......