Skip to content

Commit

Permalink
Directives V2
Browse files Browse the repository at this point in the history
  • Loading branch information
Kolezhniuk committed Sep 25, 2024
1 parent db11c72 commit 4d09303
Show file tree
Hide file tree
Showing 21 changed files with 485 additions and 33 deletions.
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
publishState: async () => {
return '0xc837f95c984892dbcc3ac41812ecb145fedc26d7003202c50e1b87e226a9b33c';
},
getRpcProvider: () => {
return {};
},
publishStateGeneric: async () => {
return '0xc837f95c984892dbcc3ac41812ecb145fedc26d7003202c50e1b87e226a9b33c';
},
Expand Down
3 changes: 3 additions & 0 deletions src/iden3comm/handlers/contract-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ export class ContractRequestHandler
request: ContractInvokeRequest,
txHashToZkpResponseMap: Map<string, ZeroKnowledgeProofResponse[]>
): Promise<ContractInvokeResponse> {
if (!request.to) {
throw new Error('Invalid contract invoke request. Missing to field');
}
const contractInvokeResponse: ContractInvokeResponse = {
id: request.id,
thid: request.thid,
Expand Down
104 changes: 99 additions & 5 deletions src/iden3comm/handlers/credential-proposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
BasicMessage,
CredentialOffer,
CredentialsOfferMessage,
Iden3Directive,
Iden3DirectiveType,
IPackageManager,
JsonDocumentObject,
PackerParams
Expand All @@ -18,15 +20,19 @@ import {
ProposalMessage
} from '../types/protocol/proposal-request';
import { IIdentityWallet } from '../../identity';
import { byteEncoder } from '../../utils';
import { byteDecoder, byteEncoder } from '../../utils';
import { W3CCredential } from '../../verifiable';
import { AbstractMessageHandler, IProtocolMessageHandler } from './message-handler';

/** @beta ProposalRequestCreationOptions represents proposal-request creation options */
export type ProposalRequestCreationOptions = {
credentials: ProposalRequestCredential[];
metadata?: { type: string; data?: JsonDocumentObject };
metadata?: {
type: string;
data: JsonDocumentObject | JsonDocumentObject[];
};
did_doc?: JsonDocumentObject;
thid?: string;
};

/**
Expand All @@ -45,7 +51,7 @@ export function createProposalRequest(
const uuidv4 = uuid.v4();
const request: ProposalRequestMessage = {
id: uuidv4,
thid: uuidv4,
thid: opts.thid ?? uuidv4,
from: sender.string(),
to: receiver.string(),
typ: MediaType.PlainMessage,
Expand Down Expand Up @@ -98,6 +104,21 @@ export interface ICredentialProposalHandler {
*/
parseProposalRequest(request: Uint8Array): Promise<ProposalRequestMessage>;

/**
* @beta
* creates proposal-request
* @param {ProposalRequestCreationOptions} params - creation options
* @returns `Promise<ProposalRequestMessage>`
*/
createProposalRequestPacked(
params: {
thid: string;
sender: DID;
receiver: DID;
directives?: Iden3Directive[];
} & ProposalRequestCreationOptions
): Promise<{ request: ProposalRequestMessage; token: string }>;

/**
* @beta
* handle proposal-request
Expand Down Expand Up @@ -138,7 +159,11 @@ export type ProposalHandlerOptions = {
/** @beta CredentialProposalHandlerParams represents credential proposal handler params */
export type CredentialProposalHandlerParams = {
agentUrl: string;
proposalResolverFn: (context: string, type: string) => Promise<Proposal>;
proposalResolverFn: (
context: string,
type: string,
request?: ProposalRequestMessage
) => Promise<Proposal>;
packerParams: PackerParams;
};

Expand Down Expand Up @@ -169,6 +194,71 @@ export class CredentialProposalHandler
super();
}

/**
* @inheritdoc ICredentialProposalHandler#createProposalRequest
*/
async createProposalRequestPacked(
params: {
thid: string;
sender: DID;
receiver: DID;
directives?: Iden3Directive[];
} & ProposalRequestCreationOptions
): Promise<{ request: ProposalRequestMessage; token: string }> {
const thid = uuid.v4();

const directives = (params.directives ?? []).filter(
(directive) => directive.purpose === PROTOCOL_MESSAGE_TYPE.PROPOSAL_REQUEST_MESSAGE_TYPE
);

const credentialsToRequest: ProposalRequestCredential[] = [...params.credentials];

const result = directives.reduce<{
metadata: {
type: string;
data: JsonDocumentObject[];
};
credentialsToRequest: ProposalRequestCredential[];
}>(
(acc, directive) => {
if (directive.type !== Iden3DirectiveType.TransparentPaymentDirective) {
return acc;
}
const directiveCredentials: ProposalRequestCredential[] = directive.credentials ?? [];
acc.credentialsToRequest = [...acc.credentialsToRequest, ...directiveCredentials];
delete directive.purpose;
const meta = Array.isArray(acc.metadata.data) ? acc.metadata.data : [acc.metadata.data];
acc.metadata.data = [...meta, directive];
return acc;
},
{
metadata: {
type: 'Iden3Metadata',
data: []
},
credentialsToRequest
}
);

const msg = createProposalRequest(params.sender, params.receiver, {
credentials: result.credentialsToRequest,
metadata: result.metadata,
did_doc: params.did_doc,
thid
});

const msgBytes = byteEncoder.encode(JSON.stringify(msg));

const token = byteDecoder.decode(
await this._packerMgr.pack(msg.typ ?? MediaType.PlainMessage, msgBytes, {
senderDID: params.sender,
...this._params.packerParams
})
);

return { request: msg, token };
}

public async handle(
message: BasicMessage,
context: ProposalRequestHandlerOptions
Expand Down Expand Up @@ -266,7 +356,11 @@ export class CredentialProposalHandler
}

// credential not found in the wallet, prepare proposal protocol message
const proposal = await this._params.proposalResolverFn(cred.context, cred.type);
const proposal = await this._params.proposalResolverFn(
cred.context,
cred.type,
proposalRequest
);
if (!proposal) {
throw new Error(`can't resolve Proposal for type: ${cred.type}, context: ${cred.context}`);
}
Expand Down
35 changes: 34 additions & 1 deletion src/iden3comm/handlers/message-handler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { BasicMessage, IPackageManager } from '../types';
import { BasicMessage, Iden3Directive, IPackageManager } from '../types';
import { AuthMessageHandlerOptions } from './auth';
import { RevocationStatusMessageHandlerOptions } from './revocation-status';
import { ContractMessageHandlerOptions } from './contract-request';
import { PaymentHandlerOptions, PaymentRequestMessageHandlerOptions } from './payment';
import { MediaType } from '../constants';
import { proving } from '@iden3/js-jwz';
import { DID } from '@iden3/js-iden3-core';
import { extractDirectiveFromMessage } from '../utils';
import { Iden3AttachmentType } from '../types/protocol/directives';
/**
* iden3 Protocol message handler interface
*/
Expand Down Expand Up @@ -150,4 +152,35 @@ export class MessageHandler {

return this._params.packageManager.packMessage(MediaType.PlainMessage, response, packerParams);
}

protected propagateDirective(request: BasicMessage, response: BasicMessage): BasicMessage {
const directives = extractDirectiveFromMessage(request);
const attachedDirectives = (response.attachments ?? [])
.filter((att) => att.data.type === Iden3AttachmentType.Iden3Directives)
.reduce((acc: Iden3Directive[], att) => {
const dir = att.data.directives;
return [...acc, ...dir];
}, directives);

if (!attachedDirectives.length) {
return response;
}

const resultedAttachments = [
...(response.attachments ?? []).filter(
(att) => att.data.type !== Iden3AttachmentType.Iden3Directives
),
{
data: {
type: Iden3AttachmentType.Iden3Directives,
directives: attachedDirectives
}
}
];

return {
...response,
attachments: resultedAttachments
};
}
}
3 changes: 2 additions & 1 deletion src/iden3comm/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { extractDirectiveFromMessage, propagateDirectiveIntoMessage } from './utils/message';
export * from './packageManager';
export * from './packers';
export * from './types';
export * from './handlers';
export * from './utils/did';

import * as PROTOCOL_CONSTANTS from './constants';
export { PROTOCOL_CONSTANTS };
export { PROTOCOL_CONSTANTS, extractDirectiveFromMessage, propagateDirectiveIntoMessage };
1 change: 1 addition & 0 deletions src/iden3comm/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './protocol/revocation';
export * from './protocol/contract-request';
export * from './protocol/proposal-request';
export * from './protocol/payment';
export * from './protocol/directives';

export * from './packer';
export * from './models';
Expand Down
4 changes: 3 additions & 1 deletion src/iden3comm/types/packer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CircuitId } from '../../circuits';
import { MediaType, PROTOCOL_MESSAGE_TYPE } from '../constants';
import { DIDDocument, VerificationMethod } from 'did-resolver';
import { StateVerificationOpts } from './models';
import { Attachment } from './protocol/directives';

/**
* Protocol message type
Expand Down Expand Up @@ -44,8 +45,9 @@ export type BasicMessage = {
type: ProtocolMessage;
thid?: string;
body?: unknown;
from?: string;
from: string;
to?: string;
attachments?: Attachment[];
};

/**
Expand Down
12 changes: 5 additions & 7 deletions src/iden3comm/types/protocol/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,30 @@ import { PROTOCOL_MESSAGE_TYPE } from '../../constants';
/** AuthorizationResponseMessage is struct the represents iden3message authorization response */
export type AuthorizationResponseMessage = BasicMessage & {
body: AuthorizationMessageResponseBody;
from: string;
to: string;
type: typeof PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE;
to: string;
};

/** AuthorizationMessageResponseBody is struct the represents authorization response data */
export type AuthorizationMessageResponseBody = {
export type AuthorizationMessageResponseBody = BasicMessage['body'] & {
did_doc?: JsonDocumentObject;
message?: string;
scope: Array<ZeroKnowledgeProofResponse>;
scope: ZeroKnowledgeProofResponse[];
};

/** AuthorizationRequestMessage is struct the represents iden3message authorization request */
export type AuthorizationRequestMessage = BasicMessage & {
body: AuthorizationRequestMessageBody;
from: string;
type: typeof PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE;
};

/** AuthorizationRequestMessageBody is body for authorization request */
export type AuthorizationRequestMessageBody = {
export type AuthorizationRequestMessageBody = BasicMessage['body'] & {
callbackUrl: string;
reason?: string;
message?: string;
did_doc?: JsonDocumentObject;
scope: Array<ZeroKnowledgeProofRequest>;
scope: ZeroKnowledgeProofRequest[];
};

/** ZeroKnowledgeProofRequest represents structure of zkp request object */
Expand Down
16 changes: 11 additions & 5 deletions src/iden3comm/types/protocol/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ export type CredentialIssuanceRequestMessageBody = {
};

/** CredentialIssuanceRequestMessage represent Iden3message for credential request */
export type CredentialIssuanceRequestMessage = Required<BasicMessage> & {
export type CredentialIssuanceRequestMessage = BasicMessage & {
body: CredentialIssuanceRequestMessageBody;
type: typeof PROTOCOL_MESSAGE_TYPE.CREDENTIAL_ISSUANCE_REQUEST_MESSAGE_TYPE;
to: string;
};

/** CredentialsOfferMessage represent Iden3message for credential offer */
export type CredentialsOfferMessage = Required<BasicMessage> & {
export type CredentialsOfferMessage = BasicMessage & {
body: CredentialsOfferMessageBody;
type: typeof PROTOCOL_MESSAGE_TYPE.CREDENTIAL_OFFER_MESSAGE_TYPE;
to: string;
};

/** CredentialsOfferMessageBody is struct the represents offer message */
Expand All @@ -29,9 +31,10 @@ export type CredentialsOfferMessageBody = {
};

/** CredentialsOnchainOfferMessage represent Iden3message for credential onchain offer message */
export type CredentialsOnchainOfferMessage = Required<BasicMessage> & {
export type CredentialsOnchainOfferMessage = BasicMessage & {
body: CredentialsOnchainOfferMessageBody;
type: typeof PROTOCOL_MESSAGE_TYPE.CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE;
to: string;
};

/** CredentialsOnchainOfferMessageBody is struct the represents onchain offer message body */
Expand All @@ -55,9 +58,10 @@ export type CredentialOffer = {
};

/** CredentialIssuanceMessage represent Iden3message for credential issuance */
export type CredentialIssuanceMessage = Required<BasicMessage> & {
export type CredentialIssuanceMessage = BasicMessage & {
body: IssuanceMessageBody;
type: typeof PROTOCOL_MESSAGE_TYPE.CREDENTIAL_ISSUANCE_RESPONSE_MESSAGE_TYPE;
to: string;
};

/** IssuanceMessageBody is struct the represents message when credential is issued */
Expand All @@ -69,6 +73,7 @@ export type IssuanceMessageBody = {
export type CredentialFetchRequestMessage = BasicMessage & {
body: CredentialFetchRequestMessageBody;
type: typeof PROTOCOL_MESSAGE_TYPE.CREDENTIAL_FETCH_REQUEST_MESSAGE_TYPE;
to: string;
};

/** CredentialFetchRequestMessageBody is msg body for fetch request */
Expand All @@ -84,9 +89,10 @@ export type Schema = {
};

/** CredentialRefreshMessage represent Iden3message for credential refresh request */
export type CredentialRefreshMessage = Required<BasicMessage> & {
export type CredentialRefreshMessage = BasicMessage & {
body: CredentialRefreshMessageBody;
type: typeof PROTOCOL_MESSAGE_TYPE.CREDENTIAL_REFRESH_MESSAGE_TYPE;
to: string;
};

/** CredentialRefreshMessageBody is msg body for refresh request */
Expand Down
Loading

0 comments on commit 4d09303

Please sign in to comment.